linker - ¿Cómo decir/forzar GNU ld para poner una sección/símbolo en una parte específica del archivo ELF de salida?
multiboot (1)
Para poner la sección antes de .text
, ¿ya has tratado de asignarlo ( A
) y ejecutable ( X
)?
Si el .interp
hack funciona, entonces está bien también, por supuesto.
Va a ser muy largo, así que tome un café / té / yerba.
Resumen
¿Cómo decir / forzar GNU ld para poner una sección / símbolo en una parte específica del archivo ELF de salida?
Específicamente, no estoy preguntando sobre la dirección física / de carga del símbolo sino sobre el desplazamiento dentro del archivo.
Fondo
Estoy tratando de tomar un kernel BSD del mundo real y hacerlo compatible con Multiboot y arrancable por GRUB. Para hacer que una imagen ELF sea compatible con Multiboot e identificable por GRUB, es necesario insertar un número mágico ( 0x1BADB002
) en los primeros 8KiB del archivo.
Me refiero a Multiboot 0.6.96 .
Como el kernel original es una pieza bastante grande de código, voy a usar ejemplos basados en el kernel Bare Bones de la wiki de OSDev . Como ese kernel ya es compatible con extra_symbol
voy a usar un extra_symbol
con el valor 0xCAFEBABE
como el ejemplo de mi pregunta.
boot.s
contiene:
.set CAFEBABE, 0xCAFEBABE
; ... snip ...
.section .extras
extra_symbol:
.long CAFEBABE
Símbolo adicional en .text
La opción más fácil sería poner un símbolo con ese valor en la sección .text
justo antes de cualquier otra cosa:
.text BLOCK(4K) : ALIGN(4K)
{
*(.extras)
*(.multiboot)
*(.text)
}
Eso está bien para el ejemplo, pero en el caso del kernel BSD real, el .text
comienza después de 0x2000 (8KiB) en el archivo. Este enfoque no es una opción.
Sección adicional antes de .text
?
Otra opción es poner toda la sección .text
antes de .text
. En mi ingenuidad, esperaba que poner esa sección antes de .text
en el script del enlazador también lo hiciera aparecer antes en el ELF de salida:
SECTIONS
{
// ... some stuff ...
.extras : { *(.extras) }
.text BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
*(.text)
}
// ... more stuff ...
}
Sin embargo, ese no es el caso:
$ i586-elf-readelf -S myos.bin
There are 10 section headers, starting at offset 0x6078:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .extras PROGBITS 00100000 006010 000004 00 0 0 1
[ 2] .comment PROGBITS 00000000 006014 000011 01 MS 0 0 1
[ 3] .text PROGBITS 00001000 001000 0001e4 00 AX 0 0 4096
[ 4] .rodata.str1.1 PROGBITS 000011e4 0011e4 000016 01 AMS 0 0 1
[ 5] .eh_frame PROGBITS 000011fc 0011fc 000104 00 A 0 0 4
[ 6] .bss PROGBITS 00002000 002000 004010 00 WA 0 0 4096
[ 7] .shstrtab STRTAB 00000000 006025 000050 00 0 0 1
[ 8] .symtab SYMTAB 00000000 006208 000210 10 9 19 4
[ 9] .strtab STRTAB 00000000 006418 000130 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
De hecho, la sección aparece primero en la tabla de encabezado de sección, pero su desplazamiento en el archivo ( 0x6010
) es muy posterior a .text
. De hecho, viene incluso después de .bss
.
La pregunta
La especificación ELF establece explícitamente que:
Aunque la figura muestra la tabla del encabezado del programa inmediatamente después del encabezado ELF, y la tabla del encabezado de sección que sigue a las secciones, los archivos reales pueden diferir. Además, las secciones y los segmentos no tienen un orden específico. Solo el encabezado ELF tiene una posición fija en el archivo.
¿Cómo hago uso de eso y le digo a GNU ld que coloque mi extra_symbol
(probablemente toda la sección .extras
) antes de cualquier otra sección en el archivo, preferiblemente justo después del encabezado ELF?