2008-12-01 20 views
5

No entiendo cómo funciona GCC bajo Linux. En un archivo de origen, cuando hago una:Incluye con el Enlazador GCC de Linux

#include <math.h> 

¿El compilador de extraer el código binario correspondiente y vuelva a colocarlo (a-la DLL de Windows compilado ejecutable o no insertar el compilador una referencia a un archivo binario externo ?)

Supongo que una versión genérica de esta pregunta es: ¿Existe un concepto equivalente a las DLL de Windows en * nix?

Respuesta

25

Bien. Cuando se incluye math.h, el compilador leerá el archivo que contiene las declaraciones de las funciones y macros que se pueden usar. Si llama a una función declarada en ese archivo (encabezado), el compilador inserta una instrucción de llamada en ese lugar en su archivo de objeto que se creará desde el archivo que compila (llamémoslo test.c y el archivo de objeto creado test.o) . También agrega una entrada en la tabla de reubicación de ese objeto-archivo:

Relocation section '.rel.text' at offset 0x308 contains 1 entries: 
Offset  Info Type   Sym.Value Sym. Name 
0000001c 00000902 R_386_PC32  00000000 bar 

Esta sería una entrada de reubicación para una barra de funciones.Una entrada en la tabla de símbolos se hará teniendo en cuenta la función aún no está definido:

9: 00000000  0 NOTYPE GLOBAL DEFAULT UND bar 

Al vincular el archivo test.o objeto en un programa, es necesario enlazar con la biblioteca matemática llamada libm.so. La extensión so es similar a la extensión .dll para Windows. Significa que es un archivo de objeto compartido . El compilador, al vincular, reparará todos los lugares que aparecen en la tabla de reubicación test.o, reemplazando sus entradas con la dirección correcta de la función de la barra. Dependiendo de si usa la versión compartida de la biblioteca o la estática (se llama libm.a), el compilador hará esa reparación después de la compilación, o más tarde, en tiempo de ejecución cuando realmente inicie su programa. Cuando termine, inyectará una entrada en la tabla de bibliotecas compartidas necesarias para ese programa. (Se pueden mostrar con readelf -d ./test):

Dynamic section at offset 0x498 contains 22 entries: 
    Tag  Type       Name/Value 
0x00000001 (NEEDED)      Shared library: [libm.so.6] 
0x00000001 (NEEDED)      Shared library: [libc.so.6] 
... ... ... 

Ahora bien, si se inicia el programa, el enlazador dinámico de búsqueda que la biblioteca, y unirá esa biblioteca a su imagen ejecutable. En Linux, el programa que hace esto se llama ld.so. Las bibliotecas estáticas no tienen un lugar en la sección dinámica, ya que solo están vinculadas a los otros archivos de objetos y luego se olvidan de ellas; son parte del ejecutable a partir de ese momento.

En realidad, es mucho más complejo y tampoco lo entiendo en detalle. Ese es el plan aproximado, sin embargo.

+0

No mencionaste cómo vincularlo ... pero creo que el resto del detalle lo compensa. –

+0

Como siempre, una respuesta muy reflexiva, lúcida e integral. +1 solo porque no hay un +3. –

+0

La vinculación o generación de código realmente no tiene nada que ver con #includes embargo. La parte más complicada sobre #include es qué tan sencillo es, y cómo la generación de código y los enlaces están completamente separados de esto. – jalf

1

El compilador puede hacer lo que le plazca, siempre que, en efecto, actúe como si hubiera incluido el archivo. (Todos los compiladores que conozco, incluido GCC, simplemente incluyen un archivo llamado math.h.)

Y no, generalmente no contiene las definiciones de funciones. Eso es libm.so, un "objeto compartido", similar a windows .DLLs. Debería estar en cada sistema, ya que es un compañero de libc.so, el tiempo de ejecución de C.

Editar: Y es por eso que tienes que pasar -lm al enlazador si usas funciones matemáticas - lo instruye para enlazar contra libm.so.

1

Hay. El include incluye una inclusión textual del archivo de encabezado (que es el comportamiento estándar de C/C++). Lo que estás buscando es el linker. El argumento -l para gcc/g ++ le dice al enlazador qué biblioteca (es) debe agregar. Para matemáticas (libm.so), usaría -lm. El patrón común es: archivo

  • fuente: #include <foo.h>
  • gcc/g ++ línea de comandos: -lfoo
  • biblioteca compartida: libfoo.so

math.h es una ligera variación de este tema.

2

¿Existe un concepto equivalente a las DLL de Windows en * nix?

Sí, se llaman "Objetos compartidos" o archivos .so. Se vinculan dinámicamente a su binario en tiempo de ejecución. En Linux puedes usar el comando "ldd" en tu ejecutable para ver a qué objetos compartidos está vinculado tu binario. Puede usar ListDLLs desde sysinternals para lograr lo mismo en Windows.

8

Aquí hay varios aspectos involucrados.

Primero, archivos de encabezado. El compilador simplemente incluye el contenido del archivo en la ubicación donde se incluyó, nada más. Hasta donde yo sé, GCC ni siquiera trata los archivos de encabezado estándar de manera diferente (pero podría estar equivocado).

Sin embargo, los archivos de encabezado pueden no contener la implementación, solo su declaración. Si la implementación está ubicada en otro lugar, debe decirle al compilador/vinculador eso. De forma predeterminada, puede hacer esto simplemente pasando los archivos de biblioteca apropiados al compilador o al pasar un nombre de biblioteca. Por ejemplo, los dos siguientes son equivalentes (siempre que libcurl.a reside en un directorio en el que se puede encontrar por el enlazador):

gcc codefile.c -lcurl 
gcc codefile.c /path/to/libcurl.a 

Esto le dice al link editor (“enlazador”) para vincular el archivo de código contra de la implementación de la biblioteca estática libcurl.a (el compilador gcc realmente ignora estos argumentos porque no sabe qué hacer con ellos, y simplemente los pasa al enlazador). Sin embargo, esto se llama enlace estático. También hay dynamic linking, que tiene lugar al inicio de su programa, y ​​que ocurre con .dll en Windows (mientras que las bibliotecas estáticas corresponden a los archivos .lib en Windows). Los archivos de biblioteca dinámica en Linux generalmente tienen la extensión de archivo .so. La mejor manera de aprender más sobre estos archivos es familiarizarse con el enlazador GCC, ld, así como el excelente conjunto de herramientas binutils, con el que puede editar/ver archivos de biblioteca sin esfuerzo (cualquier código binario, realmente) .

+0

gcc trata los encabezados estándar de manera diferente, pero principalmente para ignorar algunas advertencias sobre ellos; ver http://gcc.gnu.org/onlinedocs/cpp/System-Headers.html para más detalles. – CesarB

Cuestiones relacionadas