[cfe-dev] Static Analyzer : Query regarding how symbols are marked as dead

Karthik Bhat blitz.opensource at gmail.com
Thu Mar 14 23:08:54 PDT 2013


Thanks Jordan. I will try to upload my changes so that you can access the
same.

I have a small doubt. Please excuse me if it sounds a bit silly as i'm new
to clang static analyzer.

How do i load the external AST file in the same ASTContext as the current
compiler instance ASTContext?

I'm currently using LoadFromASTFile to get the ASTUnit. Did you mean i need
to use ASTImporter class to import the Decl in this AST into current AST(
i.e. CI.getASTContext()) ?


Currently the code flow looks like-

1. In getRuntimeDefinition() if a function body is null i'm
using LoadFromASTFile to get the ASTUnit (Unit).
    ( e.g. ASTUnit* Unit1 =
 ASTUnit::LoadFromASTFile(funcDeclFile,Diags1,FileSystemOpt1); )

2. Get the TranslationUnitDecl from ASTUnit and traverse it to get the
appropriate FunctionDecl.

3. Use this FunctionDecl to create and return the RuntimeDefinition object.

4. I'm also storing the corresponding SourceManager and propagating it  so
that the Diagnostic Engine can use this SourceManager to decode the
SourceLocation correctly which might be present in the loaded file.


P.S. I'm able to detect and report double free properly now across TU. I
had made a small mistake in code. But i'm getting a lot of false alarm in
case 1 mentioned above were it is reporting memory leak even though the
allocated memory is freed by the called function. i.e.-

*File2.c has -*

char* mymalloc()
{
  char* kar = (char*) malloc(sizeof(char));
  return kar;
}

*File1.c has-*

extern char* mymalloc();
int main()
{

  char* q = mymalloc();
  free(q);
  return 0;
}

In the above code during processCallExit in ExprEngine Core marks symbol
for variable kar in mymalloc as dead although the MemoryRegion is referred
in File1.c  after aliasing it to q.

Any inputs appreciated and thanks for your prompt replies.

Regards
Karthik


On Thu, Mar 14, 2013 at 11:17 PM, Jordan Rose <jordan_rose at apple.com> wrote:

> I think I'd have to see your code to be sure. One thing that's very
> important is that you load the external AST file in the same ASTContext.
> Other than that, though, your approach does seem reasonable.
>
> Can you post your modifications somewhere? I'll try to look over them when
> I have time and see if I see anything obviously strange.
> Jordan
>
>
> On Mar 13, 2013, at 3:51 , Karthik Bhat <blitz.opensource at gmail.com>
> wrote:
>
> Thanks Jordan. That was useful information. I also found  *"*A memory
> model for static analysis of C programs*" *by Ted also very useful.
>
> I'm trying to implement IPA across TU for my internal project. The
> approach i'm using is i'm dumping .ast of all files using -emit-ast option.
> In case a function body is not found while analyzing i load the
> corresponding ast file having function definition and use this FunctionDecl
> with the current in-lining approach.
>
> For example in the above code myFree()  is implemented in another file and
> i get the FunctionDecl by loading the ast and use this to inline.
>
> In this case though unfortunately region for 'q' does not contain a
> binding with the symbolic value returned from malloc.
>
> Am i doing something wrong here or missing out something?
>
> Any inputs greatly appreciated.
>
> Thanks
>
> On Tue, Mar 12, 2013 at 10:09 PM, Jordan Rose <jordan_rose at apple.com>wrote:
>
>> Hello, Karthik. The analyzer does certain deliberate passes to clean up
>> dead symbols and dead bindings in the state, generally before processing
>> each statement. The top-level function for this is
>> ExprEngine::ExprEngine::removeDead, and most of the high-level
>> implementation is in the SymbolReaper class in ProgramState.h. The basic
>> algorithm is pretty simple, though:
>>
>> (1) Find out which expressions and variables are still live
>> (LiveVariables). This is cached, per-function, context-insensitive
>> information.
>> (2) Ask checkers which symbols are known to be in use, though potentially
>> not live (checkLiveSymbols).
>> (3) Mark live any values associated with live expressions in the
>> Environment. Remove all other bindings.
>> (4) Mark live any values accessible via the live regions in the Store.
>> Remove all other bindings.
>> (5) Remove any constraints on dead symbols.
>> (6) Report dead symbols to the checkers, so that they can stop tracking
>> information dependent on those symbols (checkDeadSymbols).
>>
>>
>> Your second question is easier: parameter-passing is modeled as a bind to
>> the region for the parameter (a VarRegion whose associated declaration is a
>> ParmVarDecl). So your myFree() example is essentially the same as this:
>>
>> char *q = (char *)malloc(sizeof(char);
>> char *p = q;
>> free(p);
>> free(q); // warning
>>
>> This happens in the 'enterStackFrame' method on the StoreManager, which
>> uses CallEvent::getInitialStackFrameContents to figure out the initial
>> bindings. You are correct that both the region for 'q' and the region for
>> 'p' will contain a binding with the symbolic value returned from 'malloc'.
>>
>> Does this help?
>> Jordan
>>
>> P.S. For the record, this model of parameter passing will not be entirely
>> correct once we model the destructors of C++ temporary regions; we will
>> need to be more careful about non-POD objects being passed by value.
>>
>>
>> On Mar 11, 2013, at 1:09 , Karthik Bhat <blitz.opensource at gmail.com>
>> wrote:
>>
>> > Hi All,
>> > I was going through Malloc checker in clang Static analyzer. I had a
>> few doubts-
>> >
>> > 1) How is a symbol marked as dead( How does clang static analyzer
>> detect that a symbol is dead) ?
>> > E.g.
>> >
>> > char* myMalloc()
>> > {
>> >   char* p = (char*) malloc(sizeof(char));
>> >   return p;
>> > }
>> >
>> > int main()
>> > {
>> >   char* q = myMalloc();
>> >   return 0;
>> > }
>> >
>> > In the above example symbol assigned for p in myMalloc is alive till
>> main(caller) exits right?
>> >
>> >
>> > 2) In case of IPA how are symbol propagated form one function to
>> another in case it is passed as a parameter.
>> > E.g.
>> >
>> > void myFree(char* p)
>> > {
>> >    free(p);
>> > }
>> >
>> > int main()
>> > {
>> >
>> >   char* q = (char*) malloc(sizeof(char));
>> >   myFree(q);
>> >   free(q);
>> > }
>> >
>> > In the above example is it true that the parameter p in myFree is
>> assigned the same symbol as that of q being passed to the function? If yes
>> could someone guide me were this assignment of symbol happens?
>> >
>> >
>> > Thanks
>> > Karthik
>> >
>> >
>> > _______________________________________________
>> > cfe-dev mailing list
>> > cfe-dev at cs.uiuc.edu
>> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130315/4687b9ab/attachment.html>


More information about the cfe-dev mailing list