23

Sometimes when I do nm on a .so file (for example, libstdc++.so.6), it says no symbols, and I need to use nm --dynamic. But for some other .so files, I can see the symbols without --dynamic.

The doc says:

Display the dynamic symbols rather than the normal symbols. This is only meaningful for dynamic objects, such as certain types of shared libraries.

But it is confusing... what "types" of shared libraries need --dynamic? How is this determined? During the compilation of the library? I thought all shared libraries are dynamic (I mean, can be dynamically loaded during run time), but seems that my understanding is not quite right.

maxschlepzig
  • 35,645
  • 14
  • 145
  • 182
szli
  • 36,893
  • 11
  • 32
  • 40

2 Answers2

21

It could very well possible that if your symbol is not exported from your shared library, it would end up in the normal symbol table instead of the dynamic symbol table.

There are many types of symbols in ELF files.

  • symbols part of the Normal Symbol table. This is the output from mere nm libabc.so or objdump --syms libabc.so. These symbols are only used during static linking.

  • symbols part of the Dynamic Symbol table. This is the output from nm --dynamic libabc.so or objdump --dynamic-syms libabc.so. Dynamic symbol table is the one used by the run-time linker/loader which binds the symbols between the ELF file which refers them and the ELF file which defines them. It is also used by the static linker, while linking a shared library with an application which requires it. This is the component which helps in showing all the undefined symbol errors during linking.

  • Hidden symbols - these are the symbols which have been marked using _attribute_ ((visibility("hidden"))). These symbols are not exported outside and can only be used within the library. The visibility is checked during the linking step, and hence is enforced only for shared libraries. The default visibility is public, i.e. the symbols are exported unless otherwise specified. The behavior can be modified using the -fvisibility=default|internal|hidden|protected.

Set the default ELF image symbol visibility to the specified option—all symbols will be marked with this unless overridden within the code. Using this feature can very substantially improve linking and load times of shared object libraries, produce more optimized code, provide near-perfect API export and prevent symbol clashes. It is strongly recommended that you use this in any shared objects you distribute. Despite the nomenclature, default always means public ie; available to be linked against from outside the shared object. protected and internal are pretty useless in real-world usage so the only other commonly used option will be hidden. The default if -fvisibility isn't specified is default, i.e., make every symbol public—this causes the same behavior as previous versions of GCC.

An overview of these techniques, their benefits and how to use them is at http://gcc.gnu.org/wiki/Visibility.

To answer your question when would you use the --dynamic option of nm, it would be when you want to list all the symbols exported by your shared library, and the only ones that are available to the ELF images which reference them.

Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • "The visibility is checked during the linking step, and hence is enforced only for shared libraries." What is the logic in this? I guess you meant to say, "dynamic linking step" right? – Hot.PxL Apr 19 '17 at 07:05
  • @Hot.PxL - You could have one shared library refer to symbols exported from other shared libraries (which is actually quite common).What I meant is that symbol visibility makes sense only for shared libraries and not static libraries. IIUC, this check is done both by static linker and the dynamic linker. But I could not find a relevant source to confirm this. Please share if you find any. – Tuxdude Apr 22 '17 at 03:33
  • Where can I read more about the "normal symbol table"? I tried googling, but can't find anything. Are there only 2 symbol tables? I don't think I understand what goes in there. – 425nesp Nov 07 '22 at 23:56
2

You need to use --dynamic or -D option on a shared library if it is stripped and thus only contains a dynamic symbol table.

You may want to use this option for other shared libraries to explicitly display the dynamic symbol table as this is the table that is consulted by the dynamic linker.

The file utility indicates whether a shared library is stripped or not. Example:

$ file /usr/lib64/libcrypt-nss-2.26.so
[..] ELF 64-bit LSB shared object, x86-64 [..], not stripped
$ file /usr/lib64/libxml2.so.2.9.7
[..] ELF 64-bit LSB shared object, x86-64 [..], stripped

Example for how the different symbol tables may contain different symbols:

$ nm -D /usr/lib64/libcrypt-nss-2.26.so | wc -l
39
$ nm /usr/lib64/libcrypt-nss-2.26.so | wc -l 
112
maxschlepzig
  • 35,645
  • 14
  • 145
  • 182