Сценарий компоновщика не пропускает байты, как ожидалось

#assembly #x86 #ld #linker-scripts #objcopy

#сборка #x86 #ld #компоновщик-скрипты #objcopy

Вопрос:

Итак, у меня есть этот файл сборки, который я собираю с помощью GNU as и связываю с GNU ld с помощью скрипта компоновщика.

Скрипт компоновщика ( boot.ld ):

 INPUT(boot.o)
OUTPUT(boot.out)
ENTRY(boot_start)

SECTIONS {
        . = 0x7c00;
        .text : { *(.text) }
        .data : { *(.data) }
        . = 0x7dfe;
        .boot_end : { *(.boot_end) }
}
  

Как вы видите, я пытаюсь сделать файл ровно 512 байт, как это необходимо для загрузчика, выполнив . = 0x7cdfe . .boot_end содержит подпись загрузки и, таким образом, заполняет оставшиеся два байта.

Я создаю загрузчик следующим образом:

 m4 boot.S | as -o boot.o
ld -T boot.ld
objcopy -O binary boot.out boot.img
  

boot.out содержит разделы, уже имеющие абсолютные адреса, и все кажется нормальным. .boot_end находится в 0x7dfe , и я ожидаю, что отверстия будут заполнены нулями, но нет, boot.img всего 55 байт. Для меня странно то, что файл даже не содержит подписи загрузки. Это просто .text и .data без каких-либо .boot_end или пропущенных байтов.

Как мне переместить ld, чтобы пропустить эти байты? И куда пропала моя подпись загрузки?

Комментарии:

1. Какие имена разделов вы использовали для недостающих частей и какие флаги вы установили (что вы вводите as )? Также может иметь значение, используете ли вы ELF или COFF или любой другой формат объекта.

2. @tofro .boot_end — это раздел, который мне не хватает, и я собрал as его так же, как написано в моем вопросе. Я использую ELF.

3. И вы все еще не сказали, какие .section флаги вы указываете в as коде. Дело в том, что если as в ELF не заданы флаги раздела для нестандартного (не .text или .data или подобного) имени раздела, раздел не будет выделен. Попробуйте заменить вашу (предположительно) голую .section boot_end директиву во as входных данных на .section boot_end,"a" (или больше флагов, например, чтобы сделать ее исполняемой, в зависимости от того, что вам нужно) и повторите попытку.

4. @tofro О, хорошо, я попробую.

5. @tofro Большое спасибо, это сработало. Я попробовал .section .boot_end "", @progbits сначала, но результат был тот же. Я попробовал еще раз .section .boot_end "a", @progbits , просто ради этого, и это сработало. Дело в том, что a указывает на выделяемые разделы, а .boot_end это не так. Есть мысли о том, какой флаг я мог бы использовать? И почему GNU as не будет генерировать данные для пользовательских разделов без флагов?

Ответ №1:

Скорее всего, у вас отсутствует флаг раздела. Дело в том, что если as при последующей ссылке на ELF для нестандартного (не .text или .data или подобного) имени раздела не заданы флаги раздела, раздел не будет выделен в дампе (т.Е. Будет молча игнорироваться objcopy , обратите внимание, что это ведет себя по-разному при создании coff файлов)

Попробуйте заменить ваш (предположительно) голый

 .section boot_end 
  

директива во входном файле ассемблера с

 .section boot_end,"a" 
  

(или больше флагов, например, чтобы сделать его исполняемым, в зависимости от того, что вам нужно) и повторите попытку.

Флаг «a» делает раздел выделяемым, т. Е. Сообщает обоим ld , и objcopy вы хотите, чтобы он был в вашем двоичном файле.