-2

Hi I am trying to find the absolute address of a symbol(like a function name) in a .so file. I tried nm -gDC myLib.so and objdump -TC myLib.so, but I didn't find the address.

Symbol table '.symtab' contains 91 entries:
59: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSolsEi@@GLIBCXX_3.4
60: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZSt16__throw_bad_castv@@GLIBCXX_3.4
61: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSo9_M_insertIlEERSoT_@@GLIBCXX_3.4.9
62: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND close@@GLIBC_2.2.5
63: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
64: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
65: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNKSt5ctypeIcE13_M_widen_initEv@@GLIBCXX_3.4.11
66: 0000000000000fe0   236 FUNC    GLOBAL DEFAULT   10 _ZN4test13overwriteFuncEiml
67: 00000000000013e0     0 FUNC    GLOBAL DEFAULT   11 _fini
68: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
69: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@@GLIBC_2.2.5
70: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4

I got something like this. Could someone tell me how to find the symbol(function name) absolute address in .so file?

Thanks

Tzig
  • 726
  • 5
  • 20
Qiyang Li
  • 109
  • 2
  • 9

2 Answers2

2

I am trying to find the absolute address of a symbol(like a function name) in a .so file

If by "absolute address" you mean the location of the symbol in virtual memory at runtime, then the answer is: you can't possibly find it in the .so file because the .so will be loaded at random address.

For any given execution which uses the .so, you could find that address by adding the address you observe in nm output to the relocation that was applied to the .so when it was loaded. The latter can be obtained from e.g. dl_iterate_phdr(). See this answer.

Update:

when I check /proc/self/maps file, it returns me 0x4000-0x7000 for a specific .so file. After nm that .so file I could get an address 0x780. Does it mean that absolute address is 0x4000+ 0x780?

Maybe.

Details matter, and you aren't very clear on what you mean by "returns me 0x4000-0x7000". Also 0x4000 is an unusually low address to map a .so at, but maybe you are dealing with unusual system on which this is normal.

In any case:

  1. on a Linux system,
  2. with a foo.so linked at address 0 (the vaddr of the first LOAD segment, as displayed with readelf -Wl foo.so)
  3. IF the lowest address belonging to foo.so is 0x4000 in /proc/self/maps and
  4. nm foo.so gives address 0x780 for some symbol, then

yes: that symbols absolute address in virtual memory is 0x4780 in that particular execution.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Hi @Employed Russian. Thanks a lot. I was a little bit confused about the relocation applied to .so file when it was loaded. when I check /proc/self/maps file, it returns me 0x4000-0x7000 for a specific .so file. After nm that .so file I could get an address 0x780. Does it mean that absolute address is 0x4000+ 0x780? or should I call some function to get the relocation of .so file? – Qiyang Li Aug 30 '21 at 03:46
-1

I'm going to use a simple C++ executable I made for this but any elf file works.

I created a very simple C++ program:

int main()
{
    return 0;
}

and compiled it with g++ main.cpp.

Let's say we want to find the address of the main function, we can use nm to see which symbols are in the elf file:

$ nm --defined-only --demangle a.out

000000000000039c r __abi_tag
0000000000004028 B __bss_start
0000000000004028 b completed.0
0000000000004018 D __data_start
0000000000004018 W data_start
0000000000001050 t deregister_tm_clones
00000000000010c0 t __do_global_dtors_aux
0000000000003e00 d __do_global_dtors_aux_fini_array_entry
0000000000004020 D __dso_handle
0000000000003e08 d _DYNAMIC
0000000000004028 D _edata
0000000000004030 B _end
00000000000011a8 T _fini
0000000000001110 t frame_dummy
0000000000003df8 d __frame_dummy_init_array_entry
00000000000020dc r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
0000000000002004 r __GNU_EH_FRAME_HDR
0000000000001000 t _init
0000000000003e00 d __init_array_end
0000000000003df8 d __init_array_start
0000000000002000 R _IO_stdin_used
00000000000011a0 T __libc_csu_fini
0000000000001130 T __libc_csu_init
0000000000001119 T main
0000000000001080 t register_tm_clones
0000000000001020 T _start
0000000000004028 D __TMC_END__

In a very small executable like this it's easy to find it by just looking at the names but let's immagine my elf file is a lot more complicated, in that case I'd use

$ nm --defined-only --demangle a.out | grep main

0000000000001119 T main

which gives me the address instantly.

Note that if you're using simple function names such as "print" with multiple libraries it's possible you will find multiple functions with different addresses, you'll need to remove the --demangle flag to help you find which function is which

Tzig
  • 726
  • 5
  • 20
  • I tried the same thing with you and get the same result. However when it comes to .so file, it's totally different. when I nm .so file I got 00000000000010d0 141 FUNC GLOBAL DEFAULT 10 _ZN4test13overwriteFuncEv for overwriteFunc. But When I use gdb disassemble overwriteFunc, it returns me (gdb) print test::overwriteFunc $1 = {bool (int, size_t, off_t)} 0x7ffff79a8e4a , – Qiyang Li Aug 26 '21 at 11:05
  • @QiyangLi `_ZN4test13overwriteFuncEv` is the mangled version of `overwriteFunc`, you can learn more about mangling [on Wikipedia](https://en.wikipedia.org/wiki/Name_mangling). You can use the `--demangle` flag of nm to get the name you expect – Tzig Aug 26 '21 at 11:56
  • `0x1119` is _not_ the absolute address of `main`. – Employed Russian Aug 27 '21 at 17:49