¿Qué hace exactamente `-rdynamic` y cuándo exactamente se necesita?
⏰ 8 minutos de lectura
PSkocik
que hace exactamente -rdynamic (o --export-dynamic en el nivel del enlazador) y cómo se relaciona con la visibilidad del símbolo según lo definido por el -fvisibility* banderas o visibilidad pragmaarena __attribute__¿s?
… Si usa “dlopen” para cargar un objeto dinámico que necesita hacer referencia a los símbolos definidos por el programa, en lugar de algún otro objeto dinámico, entonces probablemente necesitará usar esta opción cuando vincule el programa mismo. …
No estoy seguro de entender completamente esto. ¿Podría proporcionar un ejemplo que no funcione sin -rdynamic pero hace con eso?
Editar: De hecho, intenté compilar un par de bibliotecas ficticias (un solo archivo, varios archivos, varios niveles -O, algunas llamadas entre funciones, algunos símbolos ocultos, algunos visibles), con y sin -rdynamicy hasta ahora he estado recibiendo byte idéntico salidas (cuando se mantienen constantes todas las demás banderas, por supuesto), lo cual es bastante desconcertante.
mike reyhan
Aquí hay un proyecto de ejemplo simple para ilustrar el uso de -rdynamic.
Aquí, bar.c se convierte en una biblioteca compartida libbar.so y main.c se convierte en un programa que dlopens libbar y llamadas bar() de esa biblioteca. bar() llamadas foo()que es externo en bar.c y definido en main.c.
Su ejemplo deja perfectamente claro lo que significa la página de manual. ¡Muchas gracias!
– PSkocik
18/04/2016 a las 18:42
Me preguntaba por qué está rdynamic en el ejecutable y no en el objeto compartido. Según esta respuesta: stackoverflow.com/questions/50418941/…, un resumen conciso de esta respuesta es: Los símbolos solo se exportan de forma predeterminada desde bibliotecas compartidas. -rdynamic le dice al enlazador que haga lo mismo con los ejecutables.
– thejinx0r
12 de noviembre de 2018 a las 18:54
Además de usar -rdynamictambién verifique que su sistema de compilación no agregue -fvisibility=hidden ¡opción! (ya que descartará por completo el efecto de -rdynamic)
– Dima Litvinov
13 de mayo de 2020 a las 0:44
Buen ejemplo, pero el -L. -lbar no es necesario durante la compilación del programa, ¿verdad? solo son necesarios para la vinculación de bibliotecas estáticas. La biblioteca dinámica se encuentra mediante LD_LIBRARY_PATH.
-Chan Kim
8 de junio de 2021 a las 8:28
Estoy de acuerdo con @ChanKim. -L. -lbar no es necesario ya que estamos descargando la librería a mano. También debería funcionar bien sin tener que modificar LD_LIBRARY_PATH ya que estamos abriendo la lib con una ruta ("./libbar.so" en lugar de "libbar.so") así que está bien irse LD_LIBRARY_PATH solo o tal cual.
– mchiasson
26 de julio de 2021 a las 22:33
-rdynamic exporta los símbolos de un ejecutable, esto aborda principalmente escenarios como se describe en la respuesta de Mike Kinghan, pero también ayuda, por ejemplo, a Glibc backtrace_symbols() simbolizando el retroceso.
Aquí hay un pequeño experimento (programa de prueba copiado de aquí)
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
printf ("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);
free (strings);
}
/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
print_trace ();
}
int
main (void)
{
dummy_function ();
return 0;
}
compilar el programa: gcc main.c y ejecutarlo, la salida:
Como puede ver, ¡obtenemos un seguimiento de pila adecuado ahora!
Ahora, si investigamos la entrada de la tabla de símbolos de ELF (readelf --dyn-syms a.out):
sin -rdynamic
Symbol table '.dynsym' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace_symbols@GLIBC_2.2.5 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace@GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
con -rdynamictenemos más símbolos, incluidos los ejecutables:
Symbol table '.dynsym' contains 25 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace_symbols@GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace@GLIBC_2.2.5 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
11: 0000000000601060 0 NOTYPE GLOBAL DEFAULT 24 _edata
12: 0000000000601050 0 NOTYPE GLOBAL DEFAULT 24 __data_start
13: 0000000000601068 0 NOTYPE GLOBAL DEFAULT 25 _end
14: 00000000004009d8 12 FUNC GLOBAL DEFAULT 14 dummy_function
15: 0000000000601050 0 NOTYPE WEAK DEFAULT 24 data_start
16: 0000000000400a80 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
17: 0000000000400a00 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
18: 0000000000400850 42 FUNC GLOBAL DEFAULT 14 _start
19: 0000000000601060 0 NOTYPE GLOBAL DEFAULT 25 __bss_start
20: 00000000004009e4 16 FUNC GLOBAL DEFAULT 14 main
21: 00000000004007a0 0 FUNC GLOBAL DEFAULT 11 _init
22: 0000000000400a70 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
23: 0000000000400a74 0 FUNC GLOBAL DEFAULT 15 _fini
24: 0000000000400922 182 FUNC GLOBAL DEFAULT 14 print_trace
¡Espero que eso ayude!
alfombras_profundas
Yo uso rdynamic para imprimir backtraces usando el backtrace()/backtrace_symbols() de Glibc.
Sin -rdynamicno puede obtener nombres de funciones.
Una solución mucho mejor es usar un desbobinador normal que pueda acceder a la información de depuración.
– yugr
18 mayo 2018 a las 21:15
@yugr, ¿puede proporcionar alguna referencia a lo que se refiere?
– f3xy
26 de junio de 2019 a las 21:47
@f3xy Ver por ejemplo esta Flameeyes publica sobre las desventajas de agregar símbolos adicionales a la tabulación dinámica. Los desenrolladores dedicados, como libbacktrace o libunwind, pueden simbolizar la pila sin sobrecarga mediante el uso de la información de depuración del programa.
– yugr
27 de junio de 2019 a las 1:41
@yugr La información de depuración agrega mucho más volumen al ejecutable (piense en los sistemas integrados con pequeñas particiones flash) y puede no ser apropiado si está enviando software propietario. Ya -rdynamic agrega mucha información útil para alguien que realiza ingeniería inversa del binario. -rdynamic es un buen truco: el binario aún se puede eliminar, pero respetará esos símbolos porque son dinámicos.
– Kaz
3 de junio de 2020 a las 17:44
@Kaz “La información de depuración agrega mucho más volumen al ejecutable”: los desenrolladores basados en depuración solo necesitan -gline-tables-only que es significativamente más pequeño que lleno -g información de depuración. “sistemas integrados con pequeñas particiones flash”: estos sistemas generalmente solo imprimen direcciones de todos modos (que luego se simbolizan en el host). “puede no ser apropiado si está enviando software propietario”: no recomendaría ningún software propietario para imprimir trazas inversas simbolizadas en versiones de lanzamiento, ya sea con debuginfo o -rdynamic.
– yugr
3 de junio de 2020 a las 19:44
Desde La interfaz de programación de Linux:
42.1.6
Acceso a símbolos en el programa principal
Supongamos que usamos dlopen() para cargar dinámicamente una biblioteca compartidautilizar dlsym() para obtener la dirección de una función x() de esa biblioteca, y luego llamar x(). Si x() a su vez llama a una función y()luego y() normalmente se buscaría en una de las bibliotecas compartidas cargadas por el programa.
A veces, es deseable en lugar de tener x() invocar una implementación de y() en el programa principal. (Esto es similar a un mecanismo de devolución de llamada). Para hacer esto, debemos hacer que los símbolos (de alcance global) en el programa principal estén disponibles para el enlazador dinámico, vinculando el programa usando el --export-dynamic opción del enlazador:
$ gcc -Wl,--export-dynamic main.c (además de otras opciones y argumentos)
De manera equivalente, podemos escribir lo siguiente:
$ gcc -export-dynamic main.c
El uso de cualquiera de estas opciones permite que una biblioteca cargada dinámicamente acceda a símbolos globales en el programa principal.
los gcc -rdynamic opción y la gcc -Wl,-E la opción está más lejos
sinónimos de -Wl,--export-dynamic.
Supongo que esto solo funciona para la biblioteca compartida cargada dinámicamente, abierta con dlopen(). Corrígeme si estoy equivocado.
¿Ha sido útil esta solución?
Tu feedback nos ayuda a saber si la solución es correcta y está funcionando. De esta manera podemos revisar y corregir el contenido.
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información