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

486

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

Estoy usando gcc 4.0.2, si eso hace la diferencia.

Moe
fuente
La plataforma hace la diferencia. Apple proporciona un GCC 4.0, pero nmno responde a algunas opciones, como -Dy -g(IIRC).
jww
Esto no imprime nada en Mac OS.
IgorGanapolsky
3
@jww porque eso es BSD nm, no GNU nm.
OrangeDog

Respuestas:

577

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

nm -gD yourLib.so

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

nm -gDC yourLib.so

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

Cualquiera de los dos objdump( -Ctambién es útil para exigir 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 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
fuente
35
Sin embargo, esto no siempre funciona con archivos .so, por lo que es posible que deba usar la solución "readelf" mencionada en otra respuesta.
Brooks Moses el
99
Tenga en cuenta que a las versiones de OS X de nm les falta la opción '-C' para solicitar símbolos. c ++ filt se puede usar en su lugar. Ejemplo de script aquí: v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | c ++ filt -p -i
fredbaba
55
Tenga en cuenta que readelf -Wsle mostrará todos los símbolos y nm -gmuestra solo los símbolos visibles desde el exterior. Esto puede ser confuso si está examinando múltiples archivos de símbolos y comienza a intercambiar sus comandos.
Andrew B
3
También agregaría objectdump -TCa la lista. Por el contrario readelf -Ws, no muestra los nombres destrozados.
Yan Foto
2
@BrooksMoses Para los .soarchivos que deba agregar --dynamica la nmlínea de comandos.
user7610
84

Si su .soarchivo está en formato elf, puede usar el programa 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 definidos en este .soarchivo, no en las bibliotecas a las que hace referencia. La séptima columna debe contener un número en este caso. Puede extraerlo usando una expresión regular simple:

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

o, tal como se propone por Caspin ,:

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
P Shved
fuente
19
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $ 8}'; las expresiones regulares son impresionantes, pero a veces un poco de awk es muy útil.
deft_code
55
objdump -TC /usr/lib/libexample.so
Pavel Lapin
fuente
42

Para las bibliotecas compartidas libNAME.so fue necesario el interruptor -D para 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
cavila
fuente
35

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

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

Creo que el primero contiene símbolos de depuración que pueden eliminarse con strip o el modificador -s que puede asignar al vinculador o al comando de instalación . E incluso si nm ya no enumera nada, sus símbolos exportados todavía se exportan porque están en la "tabla de símbolos dinámicos" ELF, que es la última.

Peter Remmers
fuente
3
¡Gracias! Esto explica por qué a veces "nm" no muestra ningún símbolo para los archivos .so.
Brooks Moses el
10
nm -D: le permite enumerar la tabla de símbolos dinámicos
pt123
19

Para .soarchivos C ++ , el nmcomando final esnm --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

user7610
fuente
11

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

Adam Mitz
fuente
11

Para Android .soarchivos, la cadena de herramientas NDK viene con las herramientas necesarias mencionadas en las otras respuestas: readelf, objdumpy nm.

Adi Shavit
fuente
9

Puede usar la nm -gherramienta de la cadena de herramientas binutils. Sin embargo, su fuente no siempre está disponible. y ni siquiera estoy seguro de que esta información siempre se pueda recuperar. Quizás objcopyrevela más información.

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

Konrad Rudolph
fuente
6

nm -g enumera la variable externa, que no es necesariamente un símbolo exportado. Cualquier variable de alcance de archivo no estático (en C) son todas variables externas.

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

nm --version

GNU nm 2.17.50.0.6-12.el5 20061020

zhaorufei
fuente
1

Si solo quiere saber si hay símbolos presentes , puede usar

objdump -h /path/to/object

o para enumerar la información de depuración

objdump -g /path/to/object
Craig Ringer
fuente