shared libraries - Recibe el error "símbolo indefinido" al cargar la biblioteca con dlopen
shared-libraries (3)
Estoy escribiendo un código que usa bibliotecas compartidas dinámicas como complementos.
Mi línea de comando para construir las bibliotecas compartidas se ve así:
cc -shared -fPIC -o module.so -g -Wall module.c
Dentro del módulo, puedo llamar a funciones que se encuentran en cualquier otra biblioteca compartida que se haya cargado dentro del ejecutable principal.
Sin embargo, no puedo acceder a las funciones (exportadas) que se encuentran en el archivo ejecutable (obtengo errores de undefined symbol
).
Mi llamada a dlopen
ve así:
void *handle = dlopen(plugin, RTLD_NOW);
¿Puede alguien avisar cómo mi módulo puede devolver la llamada a mi ejecutable, sin tener que poner todas las funciones de utilidad del ejecutable en otra biblioteca compartida?
Cuando encontré el mismo problema, acabo de utilizar la siguiente solución. Antes de cargar cualquier complemento, solo cargue el programa, llevando sus símbolos a las tablas dinámicas:
dlopen(NULL,RTLD_NOW|RTLD_GLOBAL);
Creo que la solución es mejor. La razón es que, también resuelve el mismo problema si
a) su programa (o un módulo tripartito) está vinculado (no en tiempo de ejecución) con la biblioteca compartida, cuyos símbolos deben estar en la tabla dinámica;
b) no puede recompilar ese módulo con el indicador -dinámico.
He encontrado la respuesta yo mismo.
Tuve que agregar las banderas --export-dynamic
a las opciones de enlace para el ejecutable principal.
Al crear un ejecutable vinculado dinámicamente, agregue todos los símbolos a la tabla de símbolos dinámicos. La tabla de símbolos dinámicos es el conjunto de símbolos que son visibles desde objetos dinámicos en tiempo de ejecución.
Si no utiliza esta opción, la tabla de símbolos dinámicos normalmente solo contendrá los símbolos a los que hace referencia un objeto dinámico mencionado en el enlace.
Si usa "dlopen" para cargar un objeto dinámico que necesita volver a referirse a los símbolos definidos por el programa, en lugar de a otro objeto dinámico, entonces probablemente necesite usar esta opción al vincular el programa mismo.
La solución correcta es agregar -rdynamic
al comando de enlace del ejecutable principal. Esto agregará la opción apropiada a ld
(que, al usar GNU ld
, pasa a ser --export-dynamic
).
Agregar --export-dynamic
directamente es técnicamente incorrecto: es una opción del enlazador, por lo que debe agregarse como -Wl,--export-dynamic
o -Wl,-E
. Esto también es menos portátil que -rdynamic
(otros vinculadores tienen un equivalente, pero la opción en sí es diferente).