c++ compilar - ¿Cómo enumero los símbolos en un archivo.so?




programa externo (9)

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

Estoy usando gcc 4.0.2, si eso hace una diferencia


Answers

Seguí preguntándome por qué -fvisibility = hidden y #pragma La visibilidad de GCC 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 que tenía que leer y hacer objdump , lo que me hizo darme cuenta de que Parece que en realidad son dos tablas de símbolos:

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

Creo que el primero contiene símbolos de depuración que pueden eliminarse con strip o con el modificador -s que puede proporcionar al vinculador 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 dinámicos" de ELF, que es la última.


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

nm -g yourLib.so

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

nm -gC yourLib.so

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

O bien objdump ( -C también es útil para desmantelar 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 [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

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 siempre pueda recuperarse. Tal vez objcopy revela más información.

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


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


Si su archivo .so 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 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 un simple regex:

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

o, según lo propuesto por Caspin

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

nm -g lista la variable externa, que no es necesario 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, donde puede encontrar su dirección por dlsym.

nm --version

GNU nm 2.17.50.0.6-12.el5 20061020


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


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

El orden de acceso a los elementos que se cuida aún quedan algunos frutos bajos. La acumulación se puede hacer de manera que cuando se itera a la derecha, solo se deben recuperar 3 valores nuevos de la memoria y acumular. El truco es saber cómo soltar la columna de la izquierda; cuando agregue una nueva columna, recuerde su valor hasta que salga de la ventana de muestreo.

El costo anterior: 9 lecturas, 9 adicionales, 1 división El costo posterior: 3 lecturas, 3 adicionales, 1 división

Piense en la ventana de muestreo como un cuadro de 3x3 en el que realiza un seguimiento de cada columna (1x3) por separado. Acumula una nueva columna y suelta la más antigua.

La división es una instrucción de alta latencia, por lo que podría ser ventajoso ocultar la latencia, pero antes de ir allí, la salida del compilador debe inspeccionarse si la división por constante se elimina y si el bucle que se desenrolla (por el compilador) ya hace alguna compensación de latencia.

Pero después de la optimización más dramática de usar el caché correctamente, estas son cosas realmente menores.





c++ c gcc symbols name-mangling