¿Cómo enumero los símbolos en un archivo .so?

¿Cómo se enumeran los símbolos que se exportan desde un archivo .so? Si es posible, también me gustaría saber su fuente (por ejemplo, si son extraídos de una biblioteca estática).

Estoy usando gcc 4.0.2, si eso hace la diferencia

La herramienta estándar para listar símbolos es nm , puedes usarla simplemente así:

 nm -g yourLib.so 

Si desea ver símbolos de una biblioteca C ++, agregue la opción “-C” que exige los símbolos (es mucho más legible exigir).

 nm -gC yourLib.so 

Si su archivo .so está en formato elf, tiene dos opciones:

O bien objdump ( -C también es útil para exigir C ++):

 $ objdump -TC libz.so libz.so: file format elf64-x86-64 DYNAMIC SYMBOL TABLE: 0000000000002010 ld .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 

O 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 

Si su archivo .so está en formato elf, puede usar el progtwig readelf para extraer información de símbolos del binario. Este comando te dará la tabla de símbolos:

 readelf -Ws /usr/lib/libexample.so 

Solo debe extraer los que están definidos en este archivo .so , no en las bibliotecas a las que hace referencia. La séptima columna debe contener un número en este caso. Puedes extraerlo usando una expresión regular simple:

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

o, como lo propuso Caspin ,

 readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}'; 
 objdump -TC /usr/lib/libexample.so 

Para las bibliotecas compartidas libNAME.so el parámetro -D era necesario para ver los símbolos en mi Linux

 nm -D libNAME.so 

y para la biblioteca estática según lo informado por otros

 nm -g libNAME.a 

Me preguntaba por qué -fvisibility = hidden y #pragma GCC visibility no parecía tener ninguna influencia, ya que todos los símbolos eran siempre visibles con nm – hasta que encontré esta publicación que me indicaba readelf y objdump , lo que me hizo darme cuenta de que había parecen ser en realidad dos tablas de símbolos:

  • El que puedes enumerar con nm
  • El que puede listar con readelf y objdump

Creo que el primero contiene símbolos de depuración que pueden ser eliminados con strip o el modificador -s que puede darle al enlazador o al comando de instalación . E incluso si nm ya no muestra nada, los símbolos exportados todavía se exportan porque están en la “tabla de símbolos dynamics” de ELF, que es la última.

Intente agregar -l a los indicadores nm para obtener la fuente de cada símbolo. Si la biblioteca está comstackda con información de depuración (gcc -g) este debe ser el archivo fuente y el número de línea. Como dijo Konrad, el archivo de objeto / biblioteca estática es probablemente desconocido en este momento.

Puede usar la herramienta nm -g de la cadena de herramientas binutils. Sin embargo, su fuente no siempre está disponible. y ni siquiera estoy seguro de que esta información pueda recuperarse. Quizás objcopy revela más información.

/ EDITAR: El nombre de la herramienta es, por supuesto, nm . El indicador -g se usa para mostrar solo símbolos exportados.

Para los archivos .so Android, la cadena de herramientas NDK viene con las herramientas requeridas mencionadas en las otras respuestas: readelf , objdump y nm .

nm -g lista la variable externa, que no es un símbolo exportado necesario. Cualquier variable de ámbito de archivo no estática (en C) son todas variables externas.

nm -D mostrará el símbolo en la tabla dinámica, que puede encontrar su dirección mediante dlsym.

nm –version

GNU nm 2.17.50.0.6-12.el5 20061020

Para archivos C ++ .so , el último comando nm es nm --demangle --dynamic --defined-only --extern-only

 # 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) 

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