У меня есть плата STM32F4 Discovery, сервер отладки OpenOCD и armv7m-unknown-eabi-gdb, и я хочу, чтобы на моей плате был запущенный ELF с "голым железом", который я построил.Я запускаю gdb, даю ему команды target remote :3333
, load
, monitor reset halt
, а затем пытаюсь пройтись по коду, но ничего не получается.После некоторого расследования я обнаружил, что код был загружен по неправильному адресу.
readelf -S дает:
[ 1] vectors PROGBITS 00000000 000114 000040 00 A 0 0 1
[ 2] .interp PROGBITS 00000040 000154 000011 00 A 0 0 1
[ 3] .dynsym DYNSYM 00000054 000168 000030 10 A 4 3 4
[ 4] .dynstr STRTAB 00000084 000198 000001 00 A 0 0 1
[ 5] .hash HASH 00000088 00019c 000018 04 A 3 0 4
[ 6] .text PROGBITS 000000a0 0001b4 000134 00 WAX 0 0 4
И вы можете видеть, что компоновщик поставил два 3-байтовых дополнения: первый между .interp и .dynsym и второй между .dynstr и .hash разделами.
Но когда gdb загружает изображение на плату, он, кажется, игнорирует эти пробелы и помещает разделы сразу последругой (неважно адреса 0x2xxxxxxx, ЦП настроен для сопоставления их с областью 0x0xxxxxxx):
(gdb) load
Loading section vectors, size 0x40 lma 0x20000000
Loading section .interp, size 0x11 lma 0x20000040
Loading section .dynsym, size 0x30 lma 0x20000051
Loading section .dynstr, size 0x1 lma 0x20000081
Loading section .hash, size 0x18 lma 0x20000082
Loading section .text, size 0x134 lma 0x2000009a
В результате код находит себя за 6 байтов до того, как адрес GDB ожидает его нахождения, и, следовательно, всеинформация отладки применяется к памяти неправильно.Я буквально получаю сумасшедшие результаты, потому что следующая инструкция, которую я собираюсь выполнить (это та, на которую указывает GDB), на самом деле это какая-то другая (точнее, текущая инструкция + 3 полуслова).
* 1015Итак, что может быть не так?Я неправильно использую GDB?Или это ELF был построен неправильно?Может быть, виновен OpenOCD?Или что-то еще?
Редактировать
Похоже, GDB выполняет свою работу в соответствии с тем, что написано в ELF.LMA-адреса секций .dynsym и .hash действительно не выровнены.
objdump -h дает:
Sections:
Idx Name Size VMA LMA File off Algn
0 vectors 00000040 00000000 20000000 00000114 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .interp 00000011 00000040 20000040 00000154 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynsym 00000030 00000054 20000051 00000168 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynstr 00000001 00000084 20000081 00000198 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .hash 00000018 00000088 20000082 0000019c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .text 00000134 000000a0 2000009a 000001b4 2**2
CONTENTS, ALLOC, LOAD, CODE
Также оказывается, что .interp, .dynsym, .dynstr и.секции хеша были сгенерированы компоновщиком, потому что GCC дал ему флаг -pic.Я не упомянул эти разделы в своем скрипте компоновщика.Поэтому мне нужно понять, почему я выровнял адреса VMA, а не адреса LMA.