How to map function symbol to address range
What is the proper way to determine the address range for a function symbol (string)? I'll be working with statically-linked, non-stripped C programs on Linux.
For example, I'd like to do something like this:
char* func_name = get_string_from_user();
printf("start address: %p \n", get_addr_range(func_name).start);
printf("end address: %p \n", get_addr_range(func_name).end);
Where the start address开发者_运维问答 should be the actual address of the function as layed out currently in memory. I think gdb and objdump perform similar actions, so it should be possible, right?
Thanks.
You could look at the BFD library provided with binutils (with objdump and and the rest). I have used it once briefly and it's not exactly trivial as far as I remember.
There are some usage examples out there (search for "using libbfd" or something like that). I'd recommend reading the binutils utilities source code also.
There is also elfutils which comes with ELF and DWARF routines. Haven't used that one though and documentation looks sparse.
It is not generally possible to get the entire range of a function.
At best, you can get the starting address. Here is an example, it is NOT portable:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("fputs = %p\n", (void *)fputs);
return 0;
}
The reason why this is not possible is because in general, the only information the linker uses about each object, whether function or data, is its address and its name (and a few bits of other data). The linker just doesn't care about how big something is.
Now, you can find out how big a function is by examining the debugging data, if the debugging data is present for the given function. There are libraries you can use to parse the data, as it can be somewhat complicated. Here's a link to some information about DWARF, if that's the format you're using:
- http://wiki.dwarfstd.org/index.php?title=DWARF_FAQ
- http://reality.sgiweb.org/davea/dwarf.html
Note that you can put the debugging data in whatever format you like when you compile the program, or leave it out entirely. STABS and DWARF are common on Linux. However, just because the executable or library isn't stripped doesn't mean that the debugging data is there.
It' possible to get the start address, but difficult to get the end address, for a function. GTK does something similar to what you ask with dynamic Glade bindings.
To do this yourself, you compile your application as a dynamically-loaded image (like a shared library) using libtool, and set the image to have exported names using the libtool -export-dynamic
option.
For more information see this link to Libtool documentation.
The link command to use is:
libtool gcc -export-dynamic -o program main.o
Once you have compiled with the -export-dynamic
switch required, you may call dlopen()
to dynamically open your executable image as a dynamic library, and dlsym()
to obtain the address of specific symbols.
精彩评论