2008-08-29 25 views
344

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

estoy usando gcc 4.0.2, si eso hace la diferencia

+0

La plataforma hace la diferencia. Apple proporciona un GCC 4.0, pero su 'nm' no responde a algunas opciones, como' -D' y '-g' (IIRC). – jww

+0

Esto no imprime nada en Mac OS. –

+3

@jww porque eso es BSD 'nm', no GNU' nm'. – OrangeDog

Respuesta

419

La herramienta estándar para los símbolos en la lista es nm, se puede usar simplemente como esto:

nm -g yourLib.so 

Si usted quiere ver los símbolos de una biblioteca de C++, agregue la opción "-C", que demangle los símbolos (es mucho más legible exigido).

nm -gC yourLib.so 

Si el archivo .so está en formato ELF, tiene dos opciones:

De cualquier objdump (-C es también útil para el desenredo 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 

O utilice 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 [email protected]_2.2.5 (14) 
    3: 0000000000000000  0 FUNC GLOBAL DEFAULT UND [email protected]_2.2.5 (14) 
    4: 0000000000000000  0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable 
+23

Sin embargo, esto no siempre funciona con los archivos .so, por lo que es posible que deba utilizar la solución "readelf" mencionada en otra respuesta. –

+0

Excelente respuesta, pero no obtengo las firmas de función de nm, objdump o readelf. ¿Sabes cómo puedo obtener la firma de la función (parámetros) también? –

+7

Tenga en cuenta que las versiones de OS X de nm carecen de la opción '-C' para los símbolos demandados. C++ filt se puede usar en su lugar. Script de ejemplo aquí: http://v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | C++ filt -p -i – fredbaba

9

Puede utilizar 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. Tal vez objcopy revela más información.

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

11

Intente agregar -l a los indicadores nm para g et la fuente de cada símbolo. Si la biblioteca está compilada 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.

+0

'nm: argumento de línea de comando desconocido '-l'' –

64

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

readelf -Ws /usr/lib/libexample.so 

sólo se debe extraer los que se definen en este archivo .so, no en las bibliotecas de referencia por ella. La séptima columna debe contener un número en este caso.Usted puede extraer mediante el uso de una expresión regular simple:

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

o, como propone Caspin,:

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

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $ 8}'; Las expresiones regulares son increíbles, pero a veces un poco de disgusto recorre un largo camino. –

39
objdump -TC /usr/lib/libexample.so 
+3

Bueno. Da nombres exigidos que demuestran ser útiles – deepdive

28

Me preguntaba por qué -fvisibility = hidden y GCC#pragma visibilidad no parece tener ninguna influencia, ya que todos los símbolos siempre fueron visibles con nm - hasta que encontré esta publicación que me indicó readelf y objdump, lo que me hizo dar cuenta de que parece que hay realmente dos tablas de símbolos:

  • El uno puede hacer una lista con nm
  • el que usted puede también tener readelf y objdump

creo que el primero contiene debuggi ng símbolos que se pueden quitar con tira o el -s modificador que puede dar al vinculador o el instalar comando. 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 dinámicos" de ELF, que es la última.

+2

¡Gracias! Esto explica por qué a veces "nm" no muestra ningún símbolo para archivos .so. –

+5

nm -D - le permite listar la tabla de símbolos dinámicos – pt123

5

nm -g enumeran la variable externa, que no es un símbolo exportado. Cualquier variable de ámbito de archivos no estáticos (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

30

Para las bibliotecas compartidas lib .so el interruptor -D era necesario ver 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 
7

para Android .so, la herramienta NDK viene con las herramientas requeridas mencionadas en las otras respuestas: readelf, objdump y nm.

3

para C++ .so archivos, el último comando nm es 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) 

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

Cuestiones relacionadas