Hi all, I'm trying to write an LLVM pass which would determine whether there is any pointer which ever points to a function. I couldn't figure out if there is any existing pass which does something of the kind (maybe some analysis pass which I'm not aware of?). Of course, I could just iterate over all values, and check whether they point to functions (as in a similar recent post). However, this will not always be sufficient - for example, consider the following C code: #include "stdio.h" int foo(){ printf ("Reached function foo\n"); return 0; } int bar(){ printf("Reached function bar\n"); return 1; } int main(){ int (*f_ptr)() = &foo; (*f_ptr)(); int diff = (int)&bar- (int)&foo; f_ptr = (int (*)()) ( (int)f_ptr + diff); (*f_ptr)(); return 0; } This code changes f_ptr from pointing at the function foo to pointing at the function bar, by explicitly advancing the pointer by the difference in memory addresses between them. What can I do to catch that kind of behavior? Thanks for the help (as usual), Guy -- View this message in context: http://old.nabble.com/Counting-pointers-to-functions-tp31278058p31278058.html Sent from the LLVM - Dev mailing list archive at Nabble.com.
On 3/30/11 10:12 AM, guyadini wrote:> Hi all, > > I'm trying to write an LLVM pass which would determine whether there is any > pointer which ever points to a function. I couldn't figure out if there is > any existing pass which does something of the kind (maybe some analysis pass > which I'm not aware of?).DSA (part of the poolalloc project: https://llvm.org/svn/llvm-project/poolalloc/trunk) is a unification-style points-to analysis that also does call graph construction. In short, it can figure out to which functions a function pointer can point (although I'm not sure how well it does this; points-to analysis is conservative). That said, read below:> Of course, I could just iterate over all values, and check whether they > point to functions (as in a similar recent post). However, this will not > always be sufficient - for example, consider the following C code: > > #include "stdio.h" > > int foo(){ > printf ("Reached function foo\n"); > return 0; > } > int bar(){ > printf("Reached function bar\n"); > return 1; > } > > int main(){ > int (*f_ptr)() =&foo; > (*f_ptr)(); > int diff = (int)&bar- (int)&foo; > f_ptr = (int (*)()) ( (int)f_ptr + diff); > (*f_ptr)(); > > > return 0; > > } > > This code changes f_ptr from pointing at the function foo to pointing at the > function bar, by explicitly advancing the pointer by the difference in > memory addresses between them. > > What can I do to catch that kind of behavior?I am not a language lawyer, but I believe this is considered undefined behavior in C. In C, it is illegal to create a pointer that points within one memory object and advance it past the bounds of one memory object and into another memory object. I can't see taking a function pointer and "walking it" from one function into another to be legal. -- John T.> Thanks for the help (as usual), > Guy
On Wed, Mar 30, 2011 at 8:23 AM, John Criswell <criswell at illinois.edu> wrote:> On 3/30/11 10:12 AM, guyadini wrote: >> Hi all, >> >> I'm trying to write an LLVM pass which would determine whether there is any >> pointer which ever points to a function. I couldn't figure out if there is >> any existing pass which does something of the kind (maybe some analysis pass >> which I'm not aware of?). > > DSA (part of the poolalloc project: > https://llvm.org/svn/llvm-project/poolalloc/trunk) is a > unification-style points-to analysis that also does call graph > construction. In short, it can figure out to which functions a function > pointer can point (although I'm not sure how well it does this; > points-to analysis is conservative). > > That said, read below: > >> Of course, I could just iterate over all values, and check whether they >> point to functions (as in a similar recent post). However, this will not >> always be sufficient - for example, consider the following C code: >> >> #include "stdio.h" >> >> int foo(){ >> printf ("Reached function foo\n"); >> return 0; >> } >> int bar(){ >> printf("Reached function bar\n"); >> return 1; >> } >> >> int main(){ >> int (*f_ptr)() =&foo; >> (*f_ptr)(); >> int diff = (int)&bar- (int)&foo; >> f_ptr = (int (*)()) ( (int)f_ptr + diff); >> (*f_ptr)(); >> >> >> return 0; >> >> } >> >> This code changes f_ptr from pointing at the function foo to pointing at the >> function bar, by explicitly advancing the pointer by the difference in >> memory addresses between them. >> >> What can I do to catch that kind of behavior? > > I am not a language lawyer, but I believe this is considered undefined > behavior in C. In C, it is illegal to create a pointer that points > within one memory object and advance it past the bounds of one memory > object and into another memory object. I can't see taking a function > pointer and "walking it" from one function into another to be legal.Nah, this is legal (if you ignore the integer overflow); it's just computing a-b+b, and all the arithmetic is done on integers. Granted, I'm not sure what the issue is; it's completely obvious if you look at the either the original code or the IR that this code uses the address of bar, and it's impossible for an analysis like this to be perfectly precise. -Eli
Maybe Matching Threads
- [LLVMdev] Counting pointers to functions
- [LLVMdev] Question about using steensgaard's pointer analysis in poolalloc
- [LLVMdev] Question about using steensgaard's pointer analysis in poolalloc
- [LLVMdev] Fwd: Question about using steensgaard's pointer analysis in poolalloc
- [LLVMdev] Question about using steensgaard's pointer analysis in poolalloc