Re: __cyg_profile_func_enter is not called with correct address ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



robert song wrote:
> Hello, everyone. I used -finstrument-functions option to trace some
> program, and I found that address past to __cyg_profile_func_{enter,
> exit} is not so precise.
> 
> The example is as below.
> 
> foo.c :
>   int foo()
>   {
>     return 1;
>   }
>   int bar()
>   {
>     return 2;
>   }
> 
> main.c :
>   #include <stdio.h>
>   extern int foo(), bar();
>   void *ptr = foo;
> 
>   int main(int argc, char *argv[])
>   {
>     foo();
>     bar();
>     return 0 ;
>   }
> 
> tracer.c :
>   #define _GNU_SOURCE
>   #include <stdio.h>
> 
>   void __cyg_profile_func_enter(void *this_fn, void *call_site)
>   __attribute__((no_instrument_function));
>   void __cyg_profile_func_exit(void *this_fn, void *call_site)
>   __attribute__((no_instrument_function));
> 
>   void __cyg_profile_func_enter(void *this_fn, void *call_site)
>   {
>     printf("addr:%lx\n", this_fn);
>   }
> 
>   void __cyg_profile_func_exit(void *this_fn, void *call_site)
>   {
>     printf("addr:%lx\n", this_fn);
>   }
> 
> $ cc -fPIC -finstrument-functions -g -shared -o foo.so foo.c
> $ cc -finstrument-functions -g -o main main.c tracer.c foo.so -Wl,-rpath `pwd`
> 
> The addresses past to __cyg_profile_func_{enter,exit} are as below:
> addr:8048514 <- main
> addr:8048418 <- foo
> addr:8048418 <- foo
> addr:37b4b7  <- bar
> addr:37b4b7  <- bar
> addr:8048514 <- main
> 
> $ readelf -s main | grep foo
>      7: 08048418    75 FUNC    GLOBAL DEFAULT  UND foo
>     69: 08048418    75 FUNC    GLOBAL DEFAULT  UND foo
> 
> As you can see, foo is undefined symbol but has the value of
> 0x08048418, and I think the relocated address (0x37b46c) of foo
> should be more reasonable, just like bar() function.
> 
> Now I don't have a good method to deal with the problem, Can anyone
> give me some advise to do the trick in __cyg_profile_func_enter() to
> get the correct address ?

The shared library loader is trying to make the code as efficient as possible.
When you take the address of a symbol in main, the loader is forced to fix up
the reloc with a pointer into the PLT.  This happens because at the time the
fixup is made, the symbol foo has not been resolved: it'll only be resolved
later when the first call to foo happens.  So, we have to use the PLT address
because we don't yet know where foo is.

Because of C's rule that the address of a function must be unique, every subsequent
reference to that symbol will return the PLT address, including the one used
in the call to __cyg_profile_func_enter().

You can get around this by compiling main with -fpic and not globally initializing
ptr.

void *ptr;

int
main (int argc, char *argv[])
{
  ptr = foo;

cc -fpic -finstrument-functions -g -o main main.c tracer.c foo.so -Wl,-rpath `pwd`

 $  ./main
addr:40073c
addr:110634
addr:110634
addr:11066b
addr:11066b
addr:40073c

Andrew.


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux