Question

It is easy to get the starting address of a function in C, but not its size. So I am currently doing an "nm" over the object file in order to locate my function and THEN locate the starting address of the next function. I need to do the "nm" because compiler could (and actually do, in my case) reorder functions, so source order can be different of object order.

I wonder if there are other ways of doing this. For example, instructing the compiler to preserve source code order in the object file, etc. Maybe some ELF magic?

My compilers are GCC, CLANG and Sun Studio. Platform: Solaris and derivatives, MacOSX, FreeBSD. To expand in the future.

Was it helpful?

Solution

I have found that the output of objdump -t xxx will give definitive function size/length values for program and object files (.o).

For example: (From one of my projects)

objdump -t emma | grep " F .text"

0000000000401674 l F .text 0000000000000376 parse_program_header
00000000004027ce l F .text 0000000000000157 create_segment
00000000004019ea l F .text 000000000000050c parse_section_header
0000000000402660 l F .text 000000000000016e create_section
0000000000401ef6 l F .text 000000000000000a parse_symbol_section
000000000040252c l F .text 0000000000000134 create_symbol
00000000004032e0 g F .text 0000000000000002 __libc_csu_fini
0000000000402240 g F .text 000000000000002e emma_segment_count
00000000004022f1 g F .text 0000000000000055 emma_get_symbol
00000000004021bd g F .text 000000000000002e emma_section_count
0000000000402346 g F .text 00000000000001e6 emma_close
0000000000401f00 g F .text 000000000000002f emma_init
0000000000403270 g F .text 0000000000000065 __libc_csu_init
0000000000400c20 g F .text 0000000000000060 estr
00000000004022c3 g F .text 000000000000002e emma_symbol_count
0000000000400b10 g F .text 0000000000000000 _start
0000000000402925 g F .text 000000000000074f main
0000000000401f2f g F .text 000000000000028e emma_open

I've pruned the list a bit, it was lengthy. You can see that the 5th column (the second wide column with lots of zeros....) gives a length value for every function. main is 0x74f bytes long, emma_close is 0x1e6, parse_symbol_section is a paltry 0x0a bytes... 10 bytes! (wait... is that a stub?)

Additionally, I grep'd for just the 'F'unctions in the .text section, thus limiting the list further. The -t option to objdump shows only the symbol tables, so it omits quite a bit of other information not particularly useful towards function length gathering.

I suppose you could use it like this:

objdump -t MYPROG | grep "MYFUNCTION$" | awk '{print "0x" $(NF-1)}' | xargs -I{} -- python -c 'print {}'

An example:

00000000004019ea l F .text 000000000000050c parse_section_header

$ objdump -t emma | grep "parse_section_header$" | awk '{print "0x" $(NF-1)}' | xargs -I{} -- python -c 'print {}'
1292

Checks out, since 0x50c == 1292.

I used $(NF-1) to grab the column in awk since the second field can vary in content and spaces depending on the identifiers relevant to the symbol involved. Also, note the trailing $ in the grep, causing main to find the main function, not the entry with main.c as its name.

The xargs -I{} -- python -c 'print {}' bit is to convert the value from hex to decimal. If anyone can think of an easier way, please chime in. (You can see where awk is sneaking the 0x prefix in there).

Ah, I just remembered that I have an alias for objdump which presets the demangle option for objdump. It'll make things easier to match if you add --demangle to the objdump invocation. (I also use --wide, much easier to read, but doesn't affect this particular output).

This works on any ELF object, library, program, object file, as long as it's NOT stripped. (I tested with and without debugging symbols too)

Hope this helps.

(I looked, parse_symbol_section IS a stub.)

OTHER TIPS

Here is an all awk answer to this question to see size of all functions in certain section:

# call objdump with -t to get list of symbols
# awk filters out all the columns which are in text section
# awk sums the values in 5th column (prefixed with 0x as they are considered hex and then converted to dec with strtonum function)
objdump -t MYPROG | awk -F ' ' '($4 == ".text") {sum += strtonum("0x"$5)} END {print sum}'

And here is if you want to see only certain functions from certain section

# awk filters out all the columns which are in rom section and all function names which have anywhere in name funcname
# (we convert to lowercase the value in column 6 to avoid case sensitive regex)
# awk sums the values in 5th column (prefixed with 0x as they are considered hex and then converted to dec with strtonum function)
objdump -t MYPROG | awk -F ' ' '($4 == ".rom") && (tolower($6) ~ /_*funcname*/) {sum += strtonum("0x"$5)} END {print sum}'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top