Формат файла ELF

Я пытаюсь вручную загрузить шестнадцатеричный дамп файла elf, который я скомпилировал с помощью g ++, в разработанную мной симуляцию процессора. В стандартном файле elf есть 30 разделов, и я загружаю все 30 сегментов с учетом их правильного смещения в памяти. Затем я запускаю свой счетчик программ в начале раздела .text (00400130), но мне кажется, что программа работает некорректно. Я довольно тщательно проверил дизайн своего процессора, используя SPIM как золотой стандарт. Странно то, что если я загружаю файл сборки в SPIM, а затем беру дизассемблированные разделы .text и .data, которые генерируются программой, загружаю их в память своего процессора, программы работают. Это отличается от того, что я хочу делать, потому что я хочу:

  • написать программу на c ++
  • скомпилируйте его с помощью mipseb-linux-g ++ (кросс-компилятор)
  • шестнадцатеричный дамп всех разделов в отдельный файл
  • читать файлы и загружать содержимое в "память" процессора
  • запустить программу

Где в файле ELF я должен изначально разместить счетчик программы? Он у меня в начале .text прямо сейчас. Кроме того, мне нужно включать только .text и .data, чтобы моя программа работала правильно? Что я здесь делаю не так?


person Dan Snyder    schedule 23.06.2010    source источник
comment
Кроме того, есть ли какие-либо команды, которые будут сбрасывать весь двоичный файл (адреса 0 - eof) в том же формате, что и у readelf?   -  person Dan Snyder    schedule 23.06.2010
comment
objcopy -S input output избавится от всего компоновщика / отладочного материала, который вам не важен, и сгенерирует файл (output) того же формата, что и его входной аргумент (input).   -  person Aidan Cully    schedule 23.06.2010
comment
Возможно, вы это сделали, но если вы этого не сделали, вам следует убедиться, что загружаемые вами разделы после их загрузки содержат данные, которые, по вашему мнению, должны. Если вы можете просматривать память в симуляции процессора, вам следует создать двоичное представление одного из ваших разделов (objcopy -O binary -j .text input output.bin) и сравнить содержимое памяти с данными в (в этом примере) output.bin.   -  person Aidan Cully    schedule 23.06.2010
comment
Я убедился, что отображение моей памяти работает правильно. Я могу просто вывести все выделенные элементы памяти с каждой ячейкой. Кажется, это нормально работает. Я получаю смещение для каждого раздела так же, как и начальную точку ПК.   -  person Dan Snyder    schedule 23.06.2010


Ответы (3)


Заголовок ELF должен включать адрес входа, который не обязательно совпадает с первым адресом в области .text. Используйте objdump -f, чтобы узнать, какова точка входа в файл - она ​​будет называться "начальным адресом".

Формат описан здесь - вы должны использовать program headers, а не section headers для загрузки изображения ELF в память (сомневаюсь, что там 30 заголовков программ), а точка входа будет описана полем e_entry в заголовке ELF.

person Aidan Cully    schedule 23.06.2010
comment
Хорошо знать. Оказывается, начальный адрес для этого формата просто 400130. Что ж, я знаю, что в любом случае начинаю с правильного места. Нужно ли для запуска программы включать какие-либо другие разделы, кроме текста и данных? Может, родата? Я не уверен. - person Dan Snyder; 23.06.2010
comment
Если вы используете заголовки программы (что вам и следовало бы делать, поскольку вы заботитесь о представлении выполнения файла ELF, а не о представлении компоновщика), разделы не именуются. Но да, есть и другие разделы, которые вам небезразличны. Взгляните на вывод objdump -h - любые разделы, содержащие ALLOC или LOAD, вероятно, необходимо загрузить в память. Я не совсем уверен, что это так, потому что я использую заголовки программ, а не заголовки разделов, для загрузки изображений ELF. - person Aidan Cully; 23.06.2010
comment
objdump -p сообщит вам, какие заголовки программы для изображения. - person Aidan Cully; 23.06.2010
comment
Вам понадобится .rodata; это, скорее всего, там, где кончаются постоянные статические объекты. Вам необходимо выделить память для разделов .bss (неинициализированные данные); они не включены в файл. Есть несколько других разделов кода, а также .text, которые могут присутствовать: .ctors, .dtors, .init, .fini. - person Mike Seymour; 23.06.2010
comment
Для чего нужны заголовки? (Я не особо знаком с форматом ELF) - person Dan Snyder; 23.06.2010
comment
Я предлагаю прочитать документ, на который я ссылаюсь. Цитирование: таблица заголовков программы, если она есть, сообщает системе, как создать образ процесса. Файлы, используемые для построения образа процесса (выполнения программы), должны иметь таблицу заголовков программы; перемещаемые файлы в нем не нуждаются. Таблица заголовков раздела содержит информацию, описывающую разделы файла. Каждый раздел имеет запись в таблице; каждая запись дает такую ​​информацию, как имя раздела, размер раздела и т. д. Файлы, используемые во время связывания, должны иметь таблицу заголовков разделов; другие объектные файлы могут иметь или не иметь его. Он также описывает .bss, .data и т. Д. - person Aidan Cully; 23.06.2010

Используйте поле e_entry заголовка ELF, чтобы определить, где установить счетчик программы.

person AJ.    schedule 23.06.2010
comment
По-видимому, я настраивал свой компьютер в правильном месте. Раньше я просто сначала загружал свой раздел .text и автоматически определял начальную точку своего ПК, ссылаясь на первый адрес в файле дампа. Я могу использовать это, чтобы получить правильное значение более надежным способом. - person Dan Snyder; 23.06.2010

Посмотрите Elf32_Ehdr.e_entry (или Elf64_Ehdr.e_entry, если вы используете 64-битную платформу). Вы должны, по крайней мере, также включить раздел .bss, который пуст, но имеет размер «в памяти» в образе диска ELF.

Википедия предоставит вам всю необходимую документацию.

Редактировать:

Вот от objdump -h /usr/bin/vim на моем текущем ящике:

Sections:
Idx Name         Size      VMA               LMA               File off  Algn
...
22 .bss          00009628  00000000006df760  00000000006df760  001df760  2**5
                 ALLOC
23 .comment      00000bc8  0000000000000000  0000000000000000  001df760  2**0
                 CONTENTS, READONLY

Обратите внимание, что File off одинаково для .bss и .comment, что означает, что .bss пуст в файле на диске, но должен занимать 0x9628 байт в памяти.

person Nikolai Fetissov    schedule 23.06.2010
comment
Мой раздел .bss на самом деле не пуст. Что это могло значить? Кроме того, я использую карту C ++ для представления моей памяти, поэтому любое место, которому не присвоено значение, по умолчанию будет равно 0. - person Dan Snyder; 23.06.2010
comment
Откуда ты знаешь, что он не пустой? - person Nikolai Fetissov; 23.06.2010
comment
когда я запускаю readelf -x 15 helloworld, в разделе есть элементы во многих местах. Такой же плотный, как .text. - person Dan Snyder; 23.06.2010
comment
Да ладно, там совсем пусто. Я, должно быть, сослался не на тот раздел. - person Dan Snyder; 23.06.2010
comment
objdump нумерует разделы от 0, а readelf считает их от 1. Ищите заголовок Hex dump of section '.XXXX': - это .bss? - person Nikolai Fetissov; 23.06.2010
comment
Вам нужно выделить раздел в памяти, если он помечен ALLOC, и загрузить его из файла, если он помечен LOAD. - person Nikolai Fetissov; 23.06.2010
comment
О, я вижу. Технически любые произвольные элементы размещаются в памяти (при условии, что содержимое пустого элемента равно 0). - person Dan Snyder; 23.06.2010