2009-04-16 22 views
5

He creado una biblioteca compartida (* .so) usando los archivos de código de objeto * .o (código fuente C) utilizando el compilador RVDS en Windows Host.Cómo exportar símbolos de una biblioteca compartida

que enlazar este objeto compartido con una aplicación (usando gcc para la meta del brazo en el host Linux) y obtener un ejecutable, que en la ejecución genera fallo de segmentación. (Yo sé que tengo que depurarlo!)

En lugar de creando una biblioteca compartida, si creo una biblioteca estática con los mismos archivos fuente, y luego me enlace con la aplicación, y luego ejecuto la aplicación, funciona bien como se esperaba.

Así que mis preguntas son: -

  1. ¿Es necesario exportar símbolos (funciones exportadas de la aplicación) o cualquier otro símbolo, de manera explícita, en mi archivo de origen utilizando algunas construcciones para que funcione bien cuando se vinculan con una aplicación? ¿Qué se necesita y cómo lo hago?

  2. ¿Cómo funciona la biblioteca compartida ?, es decir, las direcciones donde se cargarán y ejecutarán las funciones, se darán en la biblioteca que se darán cuando se cree la biblioteca. ¿Cómo resuelve la aplicación (main()) las direcciones donde se ejecutarán las funciones de la biblioteca?

  3. ¿Cómo funciona la biblioteca estática, es decir, cómo ocurre esta especificación y resolución de direcciones en el caso de una biblioteca estática?

Gracias.

Respuesta

11

Ésta es la forma en que funciona en Linux:

1) No, no es necesario hacer nada. Sin embargo, puede restringir las variables de exportación con el argumento de línea de comando gcc -fvisibility y marcar explícitamente las entradas exportadas con el atributo de visibilidad.

2) El archivo ejecutable tendrá una tabla de todas las funciones que importa (estas son todas las funciones con visibilidad predeterminada). El cargador/vinculador seleccionará una dirección para cargar las bibliotecas y llenar esta tabla justo antes de ejecutar, las llamadas a esas funciones son llamadas indirectas. (Tenga en cuenta que esto también se aplica a los objetos compartidos)

3) El enlace estático se realiza en tiempo de enlace (que es después de la compilación). Las direcciones reales se sustituyen en el conjunto y son llamadas directas.

Nota: Existe lo que se llama PIC (código de posición independiente). AFAIK, esto trata con referencias a datos/funciones en el mismo objeto compartido, por lo que el enlazador no necesita sobrescribir la mitad del código de la biblioteca cuando carga la biblioteca, de la misma manera que el código no hace ninguna referencia absoluta a su propios datos. Puede tratar de experimentar con eso.

0

¿Sabe algo sobre la causa del accidente?

Una posibilidad si carga la biblioteca compartida dinámicamente (por ejemplo, a través de dlopen()) es que está asumiendo que la biblioteca cargó OK cuando no lo hizo, y luego intenta ejecutar funciones mediante punteros nulos.

+0

@Jonathan: no estoy cargando la biblioteca compartida mediante llamadas dlopen(). – goldenmean

+0

OK - No tengo ideas. Estoy más familiarizado con Unix/Linux; Podría ser más ayuda allí. –

3
  1. No es necesario exportar símbolos con gcc, ya que exporta todos los símbolos por defecto; RVDS puede o no hacer lo mismo, sin embargo. Verifique la documentación del compilador RVDS (intente configurarlo para la salida 'Relocatable ELF'?)

  2. Las bibliotecas compartidas en Linux deben ser reubicables, ya que la dirección base se determina en tiempo de ejecución. Generar código independiente de posición es ideal, ya que reduce la cantidad de trabajo necesario para reubicar la biblioteca. Si su biblioteca no es reubicable, bloqueará (en otras palabras, no quite la información de reubicación de los archivos de objeto antes de crear la biblioteca dinámica). Los símbolos se resuelven en direcciones en tiempo de ejecución después de seleccionar la dirección base y reubicar las referencias internas.

  3. Con bibliotecas estáticas, todas las direcciones de carga, resolución de traslado, ubicación y resolución de símbolos ocurren en tiempo de compilación.

Mi única suposición sería que, de alguna manera, el código que está ejecutando su compilador no es reubicable en tiempo de ejecución. Es un misterio para mí saber cómo ocurriría sin romper también las bibliotecas estáticas ...

Si está generando una biblioteca estática y una biblioteca compartida directamente desde RVDS, una opción sería intentar convertir esa biblioteca estática a una biblioteca compartida:

gcc -shared -o libfoo.so libfoo.a 

Si esto ayuda, luego de RVDS compartieron enlazador biblioteca (o en su configuración) es probable roto.

Cuestiones relacionadas