608

How do I list the symbols being exported from a .so file? If possible, I'd also like to know their source (e.g. if they are pulled in from a static library).

I'm using gcc 4.0.2, if that makes a difference.

Andrey Nikolov
  • 12,967
  • 3
  • 20
  • 32
Moe
  • 28,607
  • 10
  • 51
  • 67

11 Answers11

759

The standard tool for listing symbols is nm, you can use it simply like this:

nm -gD yourLib.so

If you want to see symbols of a C++ library, add the "-C" option which demangle the symbols (it's far more readable demangled).

nm -gDC yourLib.so

If your .so file is in elf format, you have two options:

Either objdump (-C is also useful for demangling C++):

$ objdump -TC libz.so

libz.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000002010 l    d  .init  0000000000000000              .init
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __errno_location
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable

Or use readelf:

$ readelf -Ws libz.so
Symbol table '.dynsym' contains 112 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000002010     0 SECTION LOCAL  DEFAULT   10
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND free@GLIBC_2.2.5 (14)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@GLIBC_2.2.5 (14)
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
Steve Gury
  • 15,158
  • 6
  • 38
  • 42
  • 40
    This doesn't always work with .so files, though, and so you may have to use the "readelf" solution mentioned in another answer. – Brooks Moses Dec 13 '10 at 23:53
  • Great answer - but I don't get the function signatures from nm, objdump or readelf. Do you know how I can get the function signature (parameters) as well? – Kevin Parker Jun 20 '12 at 22:07
  • 9
    Note that OS X versions of nm are missing the '-C' option for demangling symbols. c++filt can be used instead. Example script here: http://v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | c++filt -p -i – fredbaba Jun 12 '13 at 21:13
  • 8
    Note that `readelf -Ws` will show you *all* symbols, and `nm -g` shows only the externally visible symbols. This may be confusing if you are examining multiple symbol files and start interchanging your commands. – Andrew B May 27 '14 at 15:32
  • 3
    I would also add `objectdump -TC` to the list. In contrary to `readelf -Ws`, it doesn't show the mangled names. – Yan Foto Aug 04 '15 at 19:26
  • For those searching for what the numbers in parentheses at the end of each line mean, see [this description](http://www.lightofdawn.org/wiki/wiki.cgi/NewAppsOnOldGlibc). – 0 _ Apr 15 '17 at 12:39
  • 2
    @BrooksMoses For `.so` files you may need to add `--dynamic` to `nm` command line. – user7610 Jan 06 '18 at 00:09
  • Much like `readelf`, `objdump` needs the `-W` flag or it might truncate the symbol but unlike `readelf`, `objdump` can demangle the symbols without an external tool. – nonsensickle Mar 22 '18 at 07:28
  • `nm -g mylib.so` gave `nm: mylib.so: no symbols`. For reference, https://unix.stackexchange.com/questions/282616/why-nm-shows-no-symbols-for-lib-i386-linux-gnu-libc-so-6 – jozxyqk Sep 13 '19 at 18:45
  • This generally *doesn't* work for .so files on Linux -- you need to ad `-D` or `--dynamic` – Chris Dodd Nov 24 '19 at 21:19
99

If your .so file is in elf format, you can use readelf program to extract symbol information from the binary. This command will give you the symbol table:

readelf -Ws /usr/lib/libexample.so

You only should extract those that are defined in this .so file, not in the libraries referenced by it. Seventh column should contain a number in this case. You can extract it by using a simple regex:

readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+'

or, as proposed by Caspin,:

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
Community
  • 1
  • 1
P Shved
  • 96,026
  • 17
  • 121
  • 165
  • 24
    readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}'; regexes are awesome but sometimes a little awk goes a long way. – deft_code Mar 09 '10 at 07:34
57
objdump -TC /usr/lib/libexample.so
Pavel Lapin
  • 726
  • 5
  • 4
44

For shared libraries libNAME.so the -D switch was necessary to see symbols in my Linux

nm -D libNAME.so

and for static library as reported by others

nm -g libNAME.a
cavila
  • 7,834
  • 5
  • 21
  • 19
37

I kept wondering why -fvisibility=hidden and #pragma GCC visibility did not seem to have any influence, as all the symbols were always visible with nm - until I found this post that pointed me to readelf and objdump, which made me realize that there seem to actually be two symbol tables:

  • The one you can list with nm
  • The one you can list with readelf and objdump

I think the former contains debugging symbols that can be stripped with strip or the -s switch that you can give to the linker or the install command. And even if nm does not list anything anymore, your exported symbols are still exported because they are in the ELF "dynamic symbol table", which is the latter.

Peter Remmers
  • 1,273
  • 12
  • 11
31

For C++ .so files, the ultimate nm command is nm --demangle --dynamic --defined-only --extern-only <my.so>

# nm --demangle --dynamic --defined-only --extern-only /usr/lib64/libqpid-proton-cpp.so | grep work | grep add
0000000000049500 T proton::work_queue::add(proton::internal::v03::work)
0000000000049580 T proton::work_queue::add(proton::void_function0&)
000000000002e7b0 W proton::work_queue::impl::add_void(proton::internal::v03::work)
000000000002b1f0 T proton::container::impl::add_work_queue()
000000000002dc50 T proton::container::impl::container_work_queue::add(proton::internal::v03::work)
000000000002db60 T proton::container::impl::connection_work_queue::add(proton::internal::v03::work)

source: https://stackoverflow.com/a/43257338

user7610
  • 25,267
  • 15
  • 124
  • 150
  • No way to see the symbol version though, isn't it? – Treviño Apr 14 '21 at 15:40
  • 2
    @Treviño `nm` has `--with-symbol-versions` on my system. I tried it with `glibc.so`, but the output was the same with it or without it... more investigation needed. eidt: I forgot to use also `--dynamic`. With that, it works. I get e.g. `iswupper` without and `iswupper@@GLIBC_2.2.5` with, in the output. – user7610 Aug 27 '21 at 11:46
18

For Android .so files, the NDK toolchain comes with the required tools mentioned in the other answers: readelf, objdump and nm.

Adi Shavit
  • 16,743
  • 5
  • 67
  • 137
13

You can use the nm -g tool from the binutils toolchain. However, their source is not always readily available. and I'm not actually even sure that this information can always be retrieved. Perhaps objcopy reveals further information.

/EDIT: The tool's name is of course nm. The flag -g is used to show only exported symbols.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
12

Try adding -l to the nm flags in order to get the source of each symbol. If the library is compiled with debugging info (gcc -g) this should be the source file and line number. As Konrad said, the object file / static library is probably unknown at this point.

Adam Mitz
  • 6,025
  • 1
  • 29
  • 28
7

nm -g list the extern variable, which is not necessary exported symbol. Any non-static file scope variable(in C) are all extern variable.

nm -D will list the symbol in the dynamic table, which you can find it's address by dlsym.

nm --version

GNU nm 2.17.50.0.6-12.el5 20061020

zhaorufei
  • 2,045
  • 19
  • 18
2

If you just want to know if there are symbols present you can use

objdump -h /path/to/object

or to list the debug info

objdump -g /path/to/object
Craig Ringer
  • 307,061
  • 76
  • 688
  • 778