Как указать/заставить GNU ld поместить раздел/символ в определенную часть выходного файла ELF?

Это будет длинный, поэтому возьмите кофе/чай/йербу.

Резюме

Как сказать/заставить GNU ld поставить раздел/символ в определенной части выходного файла ELF?

В частности, я не спрашиваю о физическом/нагрузочном адресе символа но о смещении внутри файла.

Фон

Я пытаюсь взять реальное ядро ​​BSD и сделать его совместимым с Мультизагрузка и загрузка GRUB. Чтобы сделать изображение ELF совместимым с Multiboot и идентифицируемым GRUB нужно вставить магическое число (0x1BADB002) в первый 8KiB файла.

Я имею в виду Multiboot 0.6.96.

Поскольку исходное ядро ​​- довольно большая часть кода, Я буду использовать примеры, основанные на ядре Bare Bones из вики OSDev. Поскольку это ядро ​​уже совместимо с Multiboot, я собираюсь использовать extra_symbol со значением 0xCAFEBABE в качестве примера для моего вопроса.

boot.s содержит:

.set CAFEBABE, 0xCAFEBABE
; ... snip ...
.section .extras
extra_symbol:
    .long CAFEBABE

Дополнительный символ в .text

Самый простой вариант - поместить символ с этим значением в .text раздел перед чем-либо еще:

.text BLOCK(4K) : ALIGN(4K)
{
    *(.extras)
    *(.multiboot)
    *(.text)
}

Это хорошо для примера, но в случае реального ядра BSD .text запускает путь после 0x2000 (8KiB) в файле. Этот подход не является вариантом.

Дополнительный раздел до .text?

Другой вариант - поставить весь раздел .extras до .text. В своей наивности я надеялся, что поставить такой раздел до .text в компоновщик script также запустит его в предыдущем элементе ELF:

SECTIONS
{
    // ... some stuff ...

    .extras : { *(.extras) }

    .text BLOCK(4K) : ALIGN(4K)
    {
        *(.multiboot)
        *(.text)
    }

    // ... more stuff ...

}

Это не тот случай:

$ 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)

Фактически, раздел входит в первую очередь в таблицу заголовков разделов, но его смещение в файле (0x6010) происходит после .text. На самом деле, он приходит даже после .bss.

Вопрос

В спецификации ELF явно указано, что:

Хотя на рисунке показана таблица заголовков программ сразу после Заголовок ELF и таблица заголовка раздела, следующие за разделами, фактические файлы могут отличаться. Кроме того, разделы и сегменты не имеют определенного порядка. Только заголовок ELF имеет фиксированное положение в файле.

Как я могу это использовать и сообщить GNU ld о размещении моего extra_symbol (возможно, весь раздел .extras) перед любым другим разделом файла, предпочтительно сразу после заголовка ELF?

Ответ 1

Чтобы поставить раздел до .text, вы уже пытались сделать его выделенным (A) и исполняемым (X)?

Если работает .interp хак, то это тоже нормально.