I am trying to process the output of a nm or readelf -s on an executable. However, I am having trouble differentiating static functions from each other in the output.
Here is what I am working with:
test.c
static int foo() {
int x = 6;
}
main() {}
other.c
static int foo() {
int x = 5;
}
I compile these like so:
gcc -o test test.c other.c
And then run a nm command to get all the symbols:
nm test
Among which the following two symbols (for my static functions) appear:
00000000004004ed t foo
0000000000400500 t foo
Is there a method to be able to distinguish which file the specific foo function appeared from? Or will I need to do some magic before compiling to get this to work?
I should add that for my use case, I have access to the final binary and the object files used by it, but I cannot actually build it myself to ensure that it has a symbol table.
Thanks!
Your question assumes that, given an executable, you can always discover
the names of the static
(local) functions that were compiled into it,
using nm
or another tool. Thus you will be able to see when two or
more such names are the same and to raise the question of how to discover
what source files they were compiled from.
However, that assumption is false. In the case of gcc, if files are compiled
with optimization -O0
then local symbols will be emitted in the object
file symbol table. -O0
is the default, so it applies in the case of your:
gcc -o test test.c other.c
But if files are compiled at any higher optimization level - as they certainly
will be for a release build - then local symbols are omitted from the object
files symbol table. So the linker never even sees them. So you cannot recover
them from the executable with nm
or anything else.
Compile your sample files with:
gcc -O1 -o test test.c other.c
then nm test
again, and you will observe that the:
00000000004004ed t foo
0000000000400500 t foo
have vanished, together with all of the other static function names.
In that case, if as you say you cannot control how the executable is built, then you cannot ensure that it is even possible for your question to arise.
If you could control how the executable is built to ensure that files are
compiled with -O0
, then there are several ways in which you can tie the
static function names to source files. Two equally simple ones would be:
readelf -s test
and
objdump -t test
each of which will list a source file name at the head of each chunk of symbols that come from it.
(And if it needs saying, the gdb
approach suggested by by @Amol does not escape the restriction that the executable must have been compiled with optimization -O0
)