static analysis - How do you include subroutine calls in a control flow graph? -


i idea of control flow graph; involves nodes basic blocks (sequences of operations occur), connected edges represent jumps.

but how represent subroutine call?

if have 2 functions this:

int tweedledee(void) {     int x = 16;     return x + do_something(); }  int tweedledum(int n) {     if (n < 0)        return n;     else        return n + do_something(); } 

with both functions calling do_something(), need way allow jump block in tweedledee do_something , jump tweedledee, , jump block in tweedledum do_something , tweedledum, there's never jump tweedledee do_something , tweedledum. (or tweedledumdo_somethingtweedledee) seems plain directed graph wouldn't suffice define these relationships... maybe i'm missing something.

procedures make cfgs , static analysis in general quite complicated. there different approaches representing routine calls in control flow graphs.

one first , common solution create cfg each routine, , split "call nodes" (the basic block corresponding "call do_something()" in tweedledee example) 2 nodes, actual call block c , block r writing return value.

an edge (normally of special type) inserted between c , initial block of routine being called, , 1 between end block of routine being called , r. simple example:

void foo() { int x = bar(); } int bar() { return 1; } 

might transformed to:

[init::foo] ==> [call bar()]  [x = retval(bar())] ==> [end::foo]                      ||            /\                      \/            ||                 [init::bar] ==> [ret = 1 (end::bar)] 

if there call bar(), e.g. routine

void foo2() { int y = bar(); } 

then following graph might result:

 [init::foo] ==> [call bar()]  [x = retval(bar())] ==> [end::foo]                      ||            /\                      \/            ||                 [init::bar] ==> [ret = 1 (end::bar)]                      /\            ||                      ||            \/  [init::foo2]==> [call bar()]  [x = retval(bar())] ==> [end::foo2] 

the problem here: there paths in graph (e.g. init::foo ==> call bar() ==> init::bar ==> ret = 1 ==> x = retval(bar()) ==> end::foo2) make no sense in program. might mean wondering whether "plain directed graph" suffices. there different approaches problem, e.g.: make copies of routine (here bar) each invocation of it. helps if there no real recursion, , expensive in general. static analysis useful "overapproximate" number of paths using fixed number of such copies.

the slides interprocedural analysis lecture notes (stephen chong) seem introduction. there quite books constructing such graphs, e.g. principles of program analysis nielson et al.


Comments

Popular posts from this blog

python - No exponential form of the z-axis in matplotlib-3D-plots -

php - Best Light server (Linux + Web server + Database) for Raspberry Pi -

c# - "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" error when deserializing class -