GNU/Linux >> Tutoriales Linux >  >> Linux

Conceptos básicos del formato de archivo de objeto ELF de Linux (y estructura de encabezado ELF)

ELF significa formato de archivo ejecutable y enlazable.

ELF se utiliza como formato de archivo estándar para archivos de objetos en Linux. Antes de esto, el formato de archivo a.out se usaba como estándar, pero últimamente ELF asumió el cargo como estándar.

ELF admite:

  • Distintos procesadores
  • Diferente codificación de datos
  • Diferentes clases de máquinas

Este artículo explica los diferentes tipos de archivos de objetos ELF y el encabezado ELF.

Archivos de objetos ELF

Un archivo que contiene código compilado se conoce como archivo de objeto. Un archivo de objeto puede ser cualquiera de los siguientes tipos:

1. Archivo reubicable

Este tipo de archivo de objeto contiene datos y código que se pueden vincular con otros archivos reubicables para producir un binario ejecutable o un archivo de objeto compartido. En términos sencillos, un archivo reubicable es lo mismo que el archivo .o producido cuando compilamos un código de la siguiente manera:

 gcc -Wall -c test.c -o test.o

Entonces, el test.o producido después de la operación anterior sería un archivo reubicable.

2. Archivo de objeto compartido

El vinculador dinámico utiliza este tipo de archivo de objeto para combinarlo con el ejecutable y/u otros archivos de objeto compartidos para crear una imagen de proceso completa. En términos sencillos, un archivo de objeto compartido es lo mismo que el archivo .so producido cuando el código se compila con el indicador -fPIC de la siguiente manera:

gcc -c -Wall -Werror -fPIC shared.c
gcc -shared -o libshared.so shared.o

Después de ejecutar los dos comandos anteriores, se produce como salida un archivo de objeto compartido libshared.o.

NOTA:Para obtener más información sobre las bibliotecas compartidas de Linux, consulte nuestro artículo Bibliotecas compartidas de Linux

3. Archivo ejecutable

Este tipo de archivo de objeto es un archivo que es capaz de ejecutar un programa cuando se ejecuta. En términos sencillos, es la salida de comandos como este:

 gcc -Wall test.c -o test

Entonces, la 'prueba' de salida sería un ejecutable que, cuando se ejecutara, ejecutaría la lógica escrita en el archivo test.c.

Entonces, como se puede concluir de los tipos anteriores de archivos de objetos, un archivo de objetos participa desde la construcción del programa hasta su ejecución o podemos decir desde el enlace hasta la etapa de ejecución (para saber más sobre las etapas de compilación de Linux/GCC, consulte nuestro artículo Journey of un programa en C).

Encabezado ELF

Todos los archivos de objetos que se describen arriba son de tipo ELF en Linux.

Esto se puede probar fácilmente examinando cada uno de estos archivos. Por ejemplo, investigué cada uno de los tres archivos en mi sistema:

Archivo reubicable:

 $ vim func.o

^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@^@^@^@^@^@^@^@^@^@
^@UHå¿^@^@^@^@è^@^@^@^@¸^@^@^@^@è^@^@^@^@ÉÃ^@^@
 Inside func()^@^@GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3^@^T^@^@^@^@
^@^@^@^AzR^@^Ax^P^A^[^L^G^H^A^@^@^\^@^.symtab^@.strtab^@.shstrtab^
@.rela.text^@.data^@.bss^@.rodata^@.comment^@.note.GNU-stack^@.rela.eh_frame
^@^@^@^@^@^@^@^@^@^@^@^@^@

Archivo de objeto compartido:

$ vim libshared.so

^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^C^@>^@^A^@^@^@ ^@^@^@^@^@^A^@^@^@^F^@^
^@^@^@^@^@è^A^@^@^@^@^@^@è^A^@^@^@^@^@^@^A^@^@^@^@^@^@^@^D^@^@^@^T^@^@^
@^C^@^@^@GNU^@·YG®z^L^ZÊ7uÈí,?^N^@^@^@^@^C^@^@^@^L^@^@^@

Archivo ejecutable:

$ vim test

^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^B^@>^@^A^@^@^@P@^@^@^@^@^@@^@^@^@^@^@<
^@^@^@D^@^@^^B^@^@^@^@^@^@^A^@^@^@^@^@^@^@/lib64/ld-linux-x86-64.so.2^@^D^
@^@^@^D^@^@^@^T^@^@^@^C^@^@^@GNU^@òÁ}CKbE;ära`6"^O^N\^C^@^@^@

Entonces vemos que, como estos son archivos binarios, nada es comprensible, excepto la cadena ELF al comienzo de cada archivo. Esto muestra que estos archivos solo tienen formato ELF.

Cada archivo comienza con un encabezado ELF que prácticamente indica la organización completa del archivo. Por ejemplo, los archivos de objetos compartidos y reubicables contienen secciones, pero en el otro extremo, el archivo ejecutable se compone de segmentos. Entonces, según el tipo de archivo de objeto, el encabezado ELF brinda información detallada sobre el archivo.

Generalmente, en el caso de archivos ejecutables, un encabezado ELF es seguido por una tabla de encabezado de programa. Una tabla de encabezado de programa ayuda a crear la imagen del proceso. Dado que ayuda a crear la imagen del proceso (que se crea después de ejecutar el ejecutable), la tabla de encabezado del programa se vuelve obligatoria para los archivos ejecutables, pero es opcional para los archivos de objetos compartidos y reubicables.

La siguiente es la organización del encabezado ELF:

#define EI_NIDENT 16
typedef struct {
e_ident[EI_NIDENT];
unsigned char e_type;
Elf32_Half e_machine;
Elf32_Half e_version;
Elf32_Word e_entry;
Elf32_Addr e_phoff;
Elf32_Off e_shoff;
Elf32_Off e_flags;
Elf32_Word e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;

Entonces vemos que la organización que se muestra arriba tiene la forma de una estructura. Explicar cada miembro en detalle aquí complicaría las cosas, así que repasemos el significado básico y la información que tiene cada miembro de esta estructura para tener una idea de ese campo en particular.

1. e_ident

Como ya sabemos, el formato ELF admite varias clases de máquinas, procesadores, etc. Entonces, para admitir todo esto, la información inicial en el archivo ELF contiene información sobre cómo interpretar el archivo independientemente del procesador en el que se ejecuta el ejecutable. La matriz 'e_ident' proporciona exactamente la misma información:

Name     Value      Purpose
EI_MAG     0          File identification
EI_MAG1    1          File identification
EI_MAG2    2          File identification
EI_MAG3    3          File identification
EI_CLASS   4          File class
EI_DATA    5          Data encoding
EI_VERSION 6          File version
EI_PAD     7          Start of padding bytes
EI_NIDENT  16         Size of e_ident[]
  • EI_MAG Los primeros cuatro bytes anteriores contienen el número mágico '0x7fELF'.
  • EI_CLASS Un ELF puede tener dos clases, 32 bits o 64 bits. Esto hace que el formato de archivo sea portátil.
  • EI_DATA Este miembro brinda información sobre la codificación de datos. En pocas palabras, esta información indica si los datos están en formato big endian o little endian.
  • EI_VERSION Este miembro proporciona información sobre la versión del archivo del objeto.
  • EI_PAD Este miembro marca el comienzo de los bytes no utilizados en la matriz de información e_indent.
  • EI_NIDENT Este miembro proporciona el tamaño de la matriz e_indent. Esto ayuda a analizar el archivo ELF.

2. e_tipo

Este miembro identifica el tipo de archivo de objeto. Por ejemplo, un archivo de objeto puede ser de los siguientes tipos:

Name    Value    Meaning
ET_NONE  0       No file type
ET_REL   1       Relocatable file
ET_EXEC  2       Executable file
ET_DYN   3       Shared object file
ET_CORE  4       Core file

NOTA:La lista anterior no es exhaustiva, pero brinda información sobre los principales tipos de archivos de objetos a los que puede hacer referencia ELF.

3. e_máquina

Este miembro brinda información sobre la arquitectura que requiere un archivo ELF.

Name            Value      Meaning
ET_NONE           0          No machine
EM_M32            1          AT&T WE 32100
EM_SPARC          2          SPARC
EM_386            3          Intel Architecture
EM_68K            4          Motorola 68000
EM_88K            5          Motorola 88000
EM_860            7          Intel 80860
EM_MIPS           8          MIPS RS3000 Big-Endian
EM_MIPS_RS4_BE   10          MIPS RS4000 Big-Endian
RESERVED       11-16         Reserved for future use

4. Miembros adicionales

Además de los tres miembros anteriores, también tiene los siguientes miembros:

  • e_version:este miembro proporciona la información de la versión del archivo del objeto ELF.
  • e_entry:este miembro proporciona la información de la dirección virtual del punto de entrada al que el sistema debe transferir el control para que se pueda iniciar el proceso.
  • e_phoff:este miembro contiene el desplazamiento de la tabla de encabezado del programa. Esta información se almacena en términos de bytes. En ausencia de una tabla de encabezado de programa, la información contenida por este miembro es cero.
  • e_shoff:este miembro contiene el desplazamiento de la tabla de encabezado de sección. Al igual que con e_phoff, esta información también se almacena en forma de bytes y, en ausencia de una tabla de encabezado de sección, la información contenida en este campo es cero.
  • e_flags:este miembro contiene información relacionada con indicadores específicos del proceso.
  • e_ehsize:este miembro contiene información relacionada con el tamaño del encabezado ELF en byes.
  • e_phentsize:este miembro contiene información relacionada con el tamaño de una entrada en la tabla de encabezado del programa del archivo de objeto. Tenga en cuenta que todas las entradas tienen el mismo tamaño.
  • e_phnum:este miembro contiene la información relacionada con el número de entradas en la tabla de encabezado del programa.
  • e_shentsize:este miembro contiene la información relacionada con el tamaño de una entrada en la tabla de encabezado de sección. El tamaño se representa en forma de número de bytes.
  • e_shnum:este miembro brinda la información relacionada con el número de entradas en la tabla de encabezado de sección.

Tenga en cuenta que el producto de ephnum y ephentsize da el tamaño total de la tabla de encabezado del programa en bytes y, de la misma manera, el producto de eshnum y eshentsize da el tamaño total de la tabla de encabezado de sección en bytes.


Linux
  1. ¿Cómo descomprimir el formato de archivo .xz en Linux usando las utilidades tar y xz?

  2. Sistemas de archivos compatibles y recomendados en Linux

  3. Cómo agregar una línea de encabezado y final a un archivo en Linux

  4. glibc:archivo elf OS ABI inválido

  5. ¿Cuál es la diferencia de sección y segmento en formato de archivo ELF?

Cómo montar y desmontar sistemas de archivos en Linux

Comando Ls en Linux (Lista de archivos y directorios)

Conceptos básicos de Linux:cómo ocultar, bloquear, cifrar y proteger sus archivos en Linux

Archivo host de Linux:¿Cómo editarlo y usarlo?

Una introducción al hashing y las sumas de verificación en Linux

Conceptos básicos de la vinculación de Ethernet en Linux