Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

353
Views
¿Cómo puedo diferenciar funciones estáticas con salida nm o readelf en C?

Estoy tratando de procesar la salida de un nm o readelf -s en un ejecutable. Sin embargo, tengo problemas para diferenciar las funciones estáticas entre sí en la salida.

Esto es con lo que estoy trabajando:

prueba.c

 static int foo() { int x = 6; } main() {}

otro.c

 static int foo() { int x = 5; }

Los compilo así:

 gcc -o test test.c other.c

Y luego ejecute un comando nm para obtener todos los símbolos:

 nm test

Entre los cuales aparecen los siguientes dos símbolos (para mis funciones estáticas):

 00000000004004ed t foo 0000000000400500 t foo

¿Existe algún método para poder distinguir de qué archivo apareció la función foo específica? ¿O tendré que hacer algo de magia antes de compilar para que esto funcione?

Debo agregar que para mi caso de uso, tengo acceso al binario final y a los archivos de objeto que usa, pero en realidad no puedo construirlo yo mismo para asegurarme de que tenga una tabla de símbolos.

¡Gracias!

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Su pregunta asume que, dado un ejecutable, siempre puede descubrir los nombres de las funciones static (locales) que se compilaron en él, utilizando nm u otra herramienta. Por lo tanto, podrá ver cuándo dos o más de esos nombres son iguales y plantear la cuestión de cómo descubrir de qué archivos fuente se compilaron.

Sin embargo, esa suposición es falsa. En el caso de gcc, si los archivos se compilan con optimización -O0 , los símbolos locales se emitirán en la tabla de símbolos del archivo de objeto. -O0 es el valor predeterminado, por lo que se aplica en el caso de su:

 gcc -o test test.c other.c

Pero si los archivos se compilan en cualquier nivel de optimización más alto, como ciertamente lo serán para una compilación de lanzamiento, los símbolos locales se omiten de la tabla de símbolos de archivos de objetos. Así que el enlazador ni siquiera los ve. Entonces no puede recuperarlos del ejecutable con nm o cualquier otra cosa.

Compile sus archivos de muestra con:

 gcc -O1 -o test test.c other.c

luego nm test nuevo, y observará que:

 00000000004004ed t foo 0000000000400500 t foo

han desaparecido, junto con todos los demás nombres de funciones estáticas.

En ese caso, si como usted dice que no puede controlar cómo se construye el ejecutable, entonces no puede asegurarse de que sea posible que surja su pregunta .

Si pudiera controlar cómo se construye el ejecutable para asegurarse de que los archivos se compilan con -O0 , entonces hay varias formas en las que puede vincular los nombres de las funciones estáticas a los archivos de origen. Dos igualmente simples serían:

 readelf -s test

y

 objdump -t test

cada uno de los cuales enumerará un nombre de archivo de origen al principio de cada fragmento de símbolos que provienen de él.

(Y si es necesario decirlo, el enfoque gdb sugerido por @Amol no escapa a la restricción de que el ejecutable debe haber sido compilado con optimización -O0 )

over 4 years ago · Santiago Trujillo Report

0

Probé la siguiente secuencia.

Si ha eliminado el archivo de salida sin símbolos de depuración, al usar gdb puede crear un archivo de objeto. Siga los comandos de la siguiente manera:

 $ gdb a.out

dará lo siguiente como salida

 Reading symbols from /home/amol/amol/a.out...(no debugging symbols found)...done.

Entonces (gdb) vendrá en la terminal

Dé los siguientes comandos en secuencia (el indicador (gdb) viene por defecto a medida que escribe los comandos)

 (gdb) maint print symbols filename (gdb) maint print psymbols filename (gdb) maint print msymbols filename

Ahora en su carpeta puede ver un archivo con nombre como nombre de archivo . Abra este archivo en el editor de texto y podrá ver la información de la siguiente manera:

 [ 8] t 0x80483b4 foo section .text test.c [ 9] T 0x80483c3 main section .text other.c [10] t 0x80483c8 foo section .text other.c

Aquí puede ver claramente qué función foo() proviene de qué archivo .c . Espero que esto te ayude.

over 4 years ago · Santiago Trujillo Report

0

Es posible que deba leer la tabla de símbolos ELF y extraer el valor ELF32_ST_BIND.

Según la especificación ELF (consulte http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf ), los valores para ELF32_ST_BIND pueden ser:

 Name Value STB_LOCAL 0 STB_GLOBAL 1 STB_WEAK 2 STB_LOPROC 13 STB_HIPROC 15

Donde STB_LOCAL se define como "Los símbolos locales no son visibles fuera del archivo de objeto que contiene su definición. Los símbolos locales del mismo nombre pueden existir en varios archivos sin interferir entre sí". que parecen coincidir bastante bien con las funciones estáticas de C.

Por ejemplo, tomando su muestra y modificándola ligeramente:

 test.c: static int foo() { int x = 5; } int bar() { int y = 6; } main() {} other.c: static int foo() { int x = 7; }

y compilando con gcc -o test test.c other.c y mirando la tabla de símbolos (se eliminaron muchas entradas):

 readelf -s test Num: Value Size Type Bind Vis Ndx Name 37: 00000000004004f0 13 FUNC LOCAL DEFAULT 13 foo 39: 0000000000400510 13 FUNC LOCAL DEFAULT 13 foo 52: 00000000004004fd 13 FUNC GLOBAL DEFAULT 13 bar

Podemos ver que las dos funciones estáticas se muestran como LOCALES y la función 'normal' se muestra como GLOBAL

Nota: si bien este método funcionará con archivos que no sean de depuración, si se elimina el archivo final, no podemos usar este método.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!