2012-05-02 7 views
15

Un archivo ELF para ejecutables tiene un programa (segmento) de cabecera y un encabezado de sección, que puede ser visto a través de readelf -a, aquí es un ejemplo:¿qué parte del archivo ELF debe cargarse en la memoria?

enter image description here

enter image description here

Las dos imágenes de arriba son encabezado de sección y encabezado de programa (segmento), respectivamente. Se puede ver que un encabezado de segmento se compone de varios encabezados de sección, que se utiliza para cargar el programa en la memoria.

¿Es sólo necesario para .text, .rodata, .data, secciones .bss para ser cargado en la memoria?

¿Son todas las otras secciones en el segmento (por ejemplo .ctors, .dtors .jcr en el tercero segmento) utilizados para alinear?

+1

Para _aligning_? –

+0

@ Adriano, sí se alinea con el tamaño de página, por lo que se puede usar protección diferente para diferentes partes del programa, por ejemplo, .text (rx),. Data (rw-) –

Respuesta

18

Secciones y segmentos son dos conceptos completamente diferentes. Las secciones pertenecen a la semántica de los datos almacenados allí (es decir, para qué se utilizarán) y son realmente irrelevantes una vez que un programa o una biblioteca compartida están vinculados excepto para fines de depuración. Incluso podría eliminar los encabezados de las secciones por completo (o sobrescribirlos con basura al azar) y un programa aún funcionaría.

segmentos (es decir, las directivas de carga cabecera del programa) son lo que el núcleo y/o enlazador dinámico realmente miran al cargar un programa. Por ejemplo, en su caso tiene dos directivas de carga. El primero hace que los primeros 4k (1 página) del archivo se mapeen en la dirección 0x08048000, e indica que solo los primeros bytes 0x4b8 de esta asignación se utilizarán en realidad (el resto es la alineación). El segundo causa que los primeros 8k (2 páginas) del archivo se mapeen en la dirección 0x08049000. La gran mayoría de eso es alineación. Los primeros bytes 0xf14 no son parte de la directiva de carga (solo alineación) y se desperdiciarán. A partir de 0x08049f14, en realidad se utilizan 0x108 bytes mapeados desde el archivo, y otros 0x10 bytes (para alcanzar el MemSize de 0x118) son llenados por cero por el cargador (núcleo o vinculador dinámico). Esto abarca hasta 0x0804a02c (en la segunda página asignada). El resto de la segunda página asignada no se usa/se desperdicia (pero malloc podría recuperarlo para usarlo como parte del montón).

Finalmente, aunque los encabezados de las secciones no se utilizarán en absoluto, el programa puede utilizar los contenidos de muchas secciones diferentes mientras se está ejecutando. Tenga en cuenta que los rangos de direcciones de .ctors y .dtors se encuentran en el inicio de la segunda asignación de carga, por lo que están mapeados y accesibles por el programa en tiempo de ejecución (el código de inicio de ejecución/salida se utilizan para ejecutar los constructores y destructores globales, si C++ o Se usó el código "GNU C" con atributo ctor/dtor). También tenga en cuenta que los .data comienza en la dirección 0x0804a00c, en la segunda página asignada. Esto permite que la primera página se proteja de solo lectura después de que se apliquen las reubicaciones (la directiva RELRO en el encabezado del programa).

+0

+1 para señalar GNU_RELRO – SquareRootOfTwentyThree

+0

Does C have constructors o destructores como C++? –

+0

No, pero GCC no es C, es "GNU C". Puedes hacer todo tipo de cosas no estándar como excepciones y constructores. –

Cuestiones relacionadas