trap tag songs preguntas las challenge canciones c gcc shared-libraries elf dynamic-loading

tag - ¿Qué hace exactamente `-rdynamic` y cuándo se necesita exactamente?



tag de las 20 preguntas (2)

¿Qué hace exactamente -rdynamic (o --export-dynamic en el nivel del vinculador) y cómo se relaciona con la visibilidad de los símbolos tal como se define mediante las banderas -fvisibility* o visibilidad pragma s y __attribute__ s?

Para --export-dynamic , ld(1) menciona:

... Si usa "dlopen" para cargar un objeto dinámico que necesita referirse 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. ...

No estoy seguro de entender completamente esto. ¿Podría por favor proporcionar un ejemplo que no funcione sin -rdynamic pero que sí lo haga?

Edición : en realidad traté de 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 -rdynamic , y hasta ahora he Se han obtenido salidas de bytes idénticos (cuando se mantienen constantes todas las demás banderas, por supuesto), lo cual es bastante desconcertante.


Aquí hay un proyecto de ejemplo simple para ilustrar el uso de -rdynamic .

bar.c

extern void foo(void); void bar(void) { foo(); }

C Principal

#include <dlfcn.h> #include <stdio.h> #include <stdlib.h> void foo(void) { puts("Hello world"); } int main(void) { void * dlh = dlopen("./libbar.so", RTLD_NOW); if (!dlh) { fprintf(stderr, "%s/n", dlerror()); exit(EXIT_FAILURE); } void (*bar)(void) = dlsym(dlh,"bar"); if (!bar) { fprintf(stderr, "%s/n", dlerror()); exit(EXIT_FAILURE); } bar(); return 0; }

Makefile

.PHONY: all clean test LDEXTRAFLAGS ?= all: prog bar.o: bar.c gcc -c -Wall -fpic -o $@ $< libbar.so: bar.o gcc -shared -o $@ $< main.o: main.c gcc -c -Wall -o $@ $< prog: main.o | libbar.so gcc $(LDEXTRAFLAGS) -o $@ $< -L. -lbar -ldl clean: rm -f *.o *.so prog test: prog ./$<

Aquí, bar.c convierte en una biblioteca compartida libbar.so y main.c convierte en un programa que dlopen s libbar y llama a la bar() desde esa biblioteca. bar() llama a foo() , que es externo en bar.c y se define en main.c

Entonces, sin -rdynamic :

$ make test gcc -c -Wall -o main.o main.c gcc -c -Wall -fpic -o bar.o bar.c gcc -shared -o libbar.so bar.o gcc -o prog main.o -L. -lbar -ldl ./prog ./libbar.so: undefined symbol: foo Makefile:23: recipe for target ''test'' failed

Y con -rdynamic

$ make clean rm -f *.o *.so prog $ make test LDEXTRAFLAGS=-rdynamic gcc -c -Wall -o main.o main.c gcc -c -Wall -fpic -o bar.o bar.c gcc -shared -o libbar.so bar.o gcc -rdynamic -o prog main.o -L. -lbar -ldl ./prog Hello world


Uso rdynamic para imprimir backtraces usando backtrace() / backtrace_symbols() de Glibc.

Sin -rdynamic , no puede obtener nombres de funciones.

Para saber más sobre el backtrace() lea here .