- How can I look inside a Linux .so or .a object and see what functions they contain?
- 2 Answers 2
- View the List of Functions Exported by a Linux Shared Library
- 1. Overview
- 2. Exported Symbols in Shared Libraries
- 3. Listing Exported Symbols of a Shared Library
- 3.1. Using readelf
- 3.2. Using objdump
- 3.3. Using nm
- 4. Conclusion
- How do I list the symbols in a .so file
- 11 Answers 11
How can I look inside a Linux .so or .a object and see what functions they contain?
The linker can presumably do this, so is there a command-line tool to list functions in object files and tell me the names of functions and their signatures?
2 Answers 2
For a shared library, you have to use:
Without the -D , nm dumps debug symbols; -D refers to the dynamic symbols that are actually used for dynamic linking. From Ubuntu 12 session:
$ nm /lib/i386-linux-gnu/libc.so.6 nm: /lib/i386-linux-gnu/libc.so.6: no symbols $ nm -D /lib/i386-linux-gnu/libc.so.6 | tail 0011fc20 T xdr_wrapstring 001202c0 T xdrmem_create 00115540 T xdrrec_create 001157f0 T xdrrec_endofrecord 00115740 T xdrrec_eof 00115690 T xdrrec_skiprecord 00120980 T xdrstdio_create 00120c70 T xencrypt 0011d330 T xprt_register 0011d450 T xprt_unregister
On this system libc.so is stripped of debug symbols, so nm shows nothing; but of course there are symbols for the dynamic linking mechanism revealed by nm -D .
For a .a archive or .o object file, just nm . The symbols are the symbols; if these files are stripped, these objects cannot be used for linking.
Exported sumbols are indicated by a T . Required symbols that must be loaded from other shared objects have a U . Note that the symbol table does not include just functions, but exported variables as well.
Or if you only want to see exported symbols, add the —defined-only flag. eg: nm -D —defined-only /lib/libtest.so
View the List of Functions Exported by a Linux Shared Library
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
1. Overview
In this tutorial, we’ll learn about exported symbols in Linux shared libraries and how we can view them.
2. Exported Symbols in Shared Libraries
External programs can only use exported symbols from shared libraries.
Let’s demonstrate this with an example. First, let’s create a shared library called lib.so and export symbols from it:
$ cat lib.c #include void lib_exported1(void) < printf("Hello, this is an exported symbol\n"); >void lib_exported2(void) < printf("Hello, this is another exported symbol\n"); >static void lib_private(void) < printf("This function is static and can't be used from outside\n"); >$ gcc lib.c -shared -o lib.so
We used gcc with the -shared flag to output a shared library. Here, the function lib_private is marked as a static function and will not be exported as static functions can’t be accessed outside of the file they are present in.
Now, let’s try to link to the private symbol:
$ cat program.c // Forward declarations void lib_exported1(void); void lib_exported2(void); void lib_private(void); int main(void) < lib_exported1(); lib_exported2(); lib_private(); >$ cc program.c lib.so /usr/bin/ld: /tmp/ccfZyf8j.o: in function `main': program.c:(.text+0xf): undefined reference to `lib_private' collect2: error: ld returned 1 exit status
As we can see, we can’t link to unexported private symbols.
Additionally, symbol names can be mangled if the library is written in C++. This means that symbol names like lib_exported1 might appear as _Z13lib_exported1v. Most utilities can deal with these symbols with special flags.
3. Listing Exported Symbols of a Shared Library
Now, let’s learn how to view the exported symbols of a library with the help of the library created in the above example.
3.1. Using readelf
We can use the readelf command with the -s flag to view exported symbols:
$ readelf -s lib.so Symbol table '.dynsym' contains 8 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[. ] 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [email protected]_2.2.5 (2) 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[. ] 5: 0000000000000000 0 FUNC WEAK DEFAULT UND [. ]@GLIBC_2.2.5 (2) 6: 000000000000111f 22 FUNC GLOBAL DEFAULT 12 lib_exported2 7: 0000000000001109 22 FUNC GLOBAL DEFAULT 12 lib_exported1 .
Here, we can see the lib_exported1 and lib_exported2 functions, but not the private lib_private function. The other symbols like puts belong to the C library, i.e., glibc. readelf does not support de-mangling of symbol names.
3.2. Using objdump
We can also use the objdump command with the -T flag to view exported symbols:
$ objdump -T lib.so lib.so: file format elf64-x86-64 DYNAMIC SYMBOL TABLE: 0000000000000000 w D *UND* 0000000000000000 Base _ITM_deregisterTMCloneTable 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 puts 0000000000000000 w D *UND* 0000000000000000 Base __gmon_start__ 0000000000000000 w D *UND* 0000000000000000 Base _ITM_registerTMCloneTable 0000000000000000 w DF *UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize 000000000000111f g DF .text 0000000000000016 Base lib_exported2 0000000000001109 g DF .text 0000000000000016 Base lib_exported1
Let’s compile our library as C++ and see how objdump handles mangled symbols:
$ g++ lib.c -shared -o lib.so $ objdump -T lib.so lib.so: file format elf64-x86-64 DYNAMIC SYMBOL TABLE: . 0000000000001109 g DF .text 0000000000000016 Base _Z13lib_exported1v 000000000000111f g DF .text 0000000000000016 Base _Z13lib_exported2v
It doesn’t demangle symbols by default, so we must pass the –demangle flag:
$ objdump -T --demangle lib.so lib.so: file format elf64-x86-64 DYNAMIC SYMBOL TABLE: . 0000000000001109 g DF .text 0000000000000016 Base lib_exported1() 000000000000111f g DF .text 0000000000000016 Base lib_exported2()
3.3. Using nm
Finally, we can also use the nm command with the -D flag to view exported symbols. It can demangle names with the –demangle flag just like objdump:
$ nm -D --demangle lib.so w [email protected]_2.2.5 w __gmon_start__ w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable U [email protected]_2.2.5 0000000000001109 T lib_exported1() 000000000000111f T lib_exported2()
4. Conclusion
In this article, we learned about exported and private symbols in a shared library. We also covered the various commands used for viewing exported symbols.
How do I list the symbols in a .so file
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.
The platform makes a difference. Apple provides a GCC 4.0, but its nm does not respond to some options, like -D and -g (IIRC).
11 Answers 11
The standard tool for listing symbols is nm , you can use it simply like this:
If you want to see symbols of a C++ library, add the «-C» option which demangle the symbols (it’s far more readable demangled).
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
$ 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