How can a Solaris process read its own character table?

I have a Solaris process which is a C ++ application which is loaded by ld several .so libraries. This application has a function that gets the return address in the calling function and then tries to determine the name of the specified calling function.

If I use dladdr(3) for this, this does not always mean what I expect to see in Dl_info :: dli_sname. It looks like it returns a function name that is not closer or lower than the pointer value. If I take the pointer value and look at the output of nm , I can match this value with the exact function that I expect.

I am wondering if there is a way to get the character map for the process and let it look for the function name without using dladdr(3) . I am particularly interested in getting a character map not only for the executable file itself, but for all the .so libraries that it downloaded.

I am working on Solaris10 / SPARC and I am using gcc 4.2.x.

Thanks!

+7
source share
2 answers

I tried a simple test using dladdr() on Solaris 10 / SPARC (but caveats: GCC 3.4, direct C), and this works fine for me:

 #include <dlfcn.h> #include <stdio.h> void print_name(char *name, void *addr); void print_name_by_dladdr(void *addr); int main(int argc, const char *argv[]) { print_name("main", (void *)&main); print_name("print_name", (void *)&print_name); print_name("printf", (void *)&printf); return 0; } void print_name(char *name, void *addr) { (void)printf("Getting name of function %s() at 0x%x\n", name, addr); print_name_by_dladdr(addr); } void print_name_by_dladdr(void *addr) { Dl_info dli; if(!dladdr(addr, &dli)) { perror("dladdr()"); exit(1); } (void)printf(" %s\n", dli.dli_sname); } 

Output:

 Getting name of function main() at 0x10714 main Getting name of function print_name() at 0x10778 print_name Getting name of function printf() at 0x209b8 _PROCEDURE_LINKAGE_TABLE_ 

This also works correctly if I write (for example)

  print_name("main", (void *)&main + 4); 

You say that you can correctly resolve nm output, so the possibilities seem limited ... are you sure that the return address is output or correctly passed to your recognizer function? You probably use the GCC built-in for this? I tested __builtin_return_address(0) and it also works great for me. If you use the built-in GCC consoles, will you call __builtin_extract_return_address() (see above on the page for details, explicitly mentions SPARC)? Can you post your code?

Can you stretch a bit to "reprogram your own binary / shared object files"? If so, libelf may be a way forward. This is exactly what some of the utilities you mentioned use, for example nm : http://cr.opensolaris.org/~devnull/6515400/usr/src/cmd/sgs/nm/common/nm.c.html

This introductory article from sun.com may be helpful (warning: 10 year article).

This is not as nice as doing internal introspection, and it is strange that dladdr(3C) does not work: (

Alternative intermediate: did you try the RTLD_DL_SYMENT flag on dladdr1(3C) (and then, perhaps, borrowed from nm.c , as indicated above on the returned ELF element)?

+4
source

a bit late, but maybe more help: elf-files usually have 2 symbol tables: .symtab and .dynsym nm reads .symtab by default, use nm -D to read the .dynsym table. dladdr (as well as the dynamic loader) use the .dynsym table. the .symtab table is more complete. you can force all characters to be in the .dynsym table as well using the -rdynamic linker flag. however it slows down (for example, in my current project approx. 200ms). (nb: the above refers to linux, but character processing works pretty much the same on sunos. command line options may differ)

+3
source

All Articles