LDCコンパイラでSTM32F3DISCOVERYで動く実行バイナリをいろいろ苦労して作成した。
いろいろ罠
LDCのオプションは罠だらけ
march,mcpuの指定が罠
- float ABIの指定でhardが効かない、soft ABIとなる
tripleの指定が罠
- eabihfだとsoft-float ABIになってしまう、gnueabihfにしないとhard-float ABIにならない
- OSにunknownが指定できない、とりあえずLinuxを指定して対処
リンカまわり
- エントリポイントが0x1バイトずれる
- 外から-eオプションで渡して回避
最終的な実行バイナリ生成コマンド
$ ldc2 -mtriple=thumbv7em-none-linux-gnueabihf -c -g main.d $ arm-none-eabi-ld main.o -e 0x8000009 -T layout.ld -nostartfiles -o main.bin
readelfの出力
- エントリポイントアドレスが
0x8000009
になっていればよい - Float ABIが
hard-float ABI
になっていればよい
$ arm-none-eabi-readelf -h main.bin ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: ARM Version: 0x1 Entry point address: 0x8000009 Start of program headers: 52 (bytes into file) Start of section headers: 1548 (bytes into file) Flags: 0x5000400, Version5 EABI, hard-float ABI Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 2 Size of section headers: 40 (bytes) Number of section headers: 16 Section header string table index: 13
objdumpの出力
このような内容になった
$ arm-none-eabi-objdump -Cd main.bin main.bin: file format elf32-littlearm Disassembly of section .text: 08000000 <_reset-0x8>: 8000000: 2000a000 .word 0x2000a000 8000004: 08000009 .word 0x08000009 Disassembly of section _reset: 08000008 <_reset>: 8000008: b082 sub sp, #8 800000a: 202a movs r0, #42 ; 0x2a 800000c: 9000 str r0, [sp, #0] 800000e: 9001 str r0, [sp, #4] 8000010: e7ff b.n 8000012 <_reset+0xa> 8000012: 2000 movs r0, #0 8000014: 2800 cmp r0, #0 8000016: d102 bne.n 800001e <_reset+0x16> 8000018: e7ff b.n 800001a <_reset+0x12> 800001a: e7ff b.n 800001c <_reset+0x14> 800001c: e7f9 b.n 8000012 <_reset+0xa> 800001e: b002 add sp, #8 8000020: 4770 bx lr
OpenOCD
APTで入れたものであればこのような表示になる。
$ openocd -f board/stm32f3discovery.cfg Open On-Chip Debugger 0.9.0 (2015-09-02-10:42) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html adapter speed: 1000 kHz adapter_nsrst_delay: 100 Info : The selected transport took over low-level target control. The results mi ght differ compared to plain JTAG/SWD none separate srst_only separate srst_nogate srst_open_drain connect_deassert_srst Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : clock speed 950 kHz Info : STLINK v2 JTAG v16 API v2 SWIM v0 VID 0x0483 PID 0x3748 Info : using stlink api v2 Info : Target voltage: 2.917647 Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
GDB
GDBでリモート接続する。
$ arm-none-eabi-gdb -q main.bin Reading symbols from main.bin...done. (gdb) target remote :3333 Remote debugging using :3333
loadしてSTM32F3DISCOVERYボード上で実行できるようにする。
(gdb) load Loading section .text, size 0x8 lma 0x8000000 Loading section _reset, size 0x1a lma 0x8000008 Start address 0x8000008, load size 34 Transfer rate: 244 bytes/sec, 17 bytes/write.
エントリポイントは 0x08000009
となっているが、プログラムの先頭は 0x08000008
となっている。
(gdb) disas Dump of assembler code for function main: => 0x08000008 <+0>: sub sp, #8 0x0800000a <+2>: movs r0, #42 ; 0x2a 0x0800000c <+4>: str r0, [sp, #0] 0x0800000e <+6>: str r0, [sp, #4] 0x08000010 <+8>: b.n 0x8000012 <main+10> 0x08000012 <+10>: movs r0, #0 0x08000014 <+12>: cmp r0, #0 0x08000016 <+14>: bne.n 0x800001e <main+22> 0x08000018 <+16>: b.n 0x800001a <main+18> 0x0800001a <+18>: b.n 0x800001c <main+20> 0x0800001c <+20>: b.n 0x8000012 <main+10> 0x0800001e <+22>: add sp, #8 0x08000020 <+24>: bx lr End of assembler dump.
ステップ実行で確認。たしかに動いているようだ。
(gdb) step main () at main.d:13 13 auto x = 42; (gdb) print x $1 = 42 (gdb) step 14 y = x; (gdb) print y $2 = 42 (gdb) print &x $3 = (int *) 0x20009ff8 (gdb) print &y $4 = (int *) 0x20009ffc