Cortex-M3な環境を試してみる。
コードを以下のようなかんじで用意する。
import ldc.attributes; extern(C): @nogc: nothrow: pragma(LDC_no_moduleinfo); @(section("_reset")) void _reset() { int y = void; auto x = 42; y = x; while (true) {} }
ENTRY(_reset); MEMORY { FLASH : ORIGIN = 0x08000000, LENGTH = 128K RAM : ORIGIN = 0x20000000, LENGTH = 20K } SECTIONS { .text : { /* Vector table */ LONG(ORIGIN(RAM) + LENGTH(RAM)) LONG(_reset + 1); /* Reset handler */ _reset = .; *(.text._reset) *(.text*) } > FLASH /DISCARD/ : { *(.ARM.exidx*) *(.note.gnu.build-id*) } }
実行バイナリを作る。
$ ldc2 -march=thumb -mcpu=cortex-m3 -c -g main.d $ arm-none-eabi-ld main.o -T layout.ld -nostartfiles -o main.bin
OpenOCDを起動。
$ openocd -f interface/stlink-v2-1.cfg -f target/stm32f1x.cfg
gdbからプログラムを流しこもうとするとコネクションが閉じられる。
$ gdb -q main.bin Reading symbols from main.bin...done. (gdb) target remote :3333 Remote debugging using :3333 warning: Architecture rejected target-supplied description 0xffbefdde in ?? () (gdb) load Loading section .text, size 0x8 lma 0x8000000 Loading section _reset, size 0x1a lma 0x8000008 Start address 0x8000008, load size 34 Remote connection closed
OpenOCD側の出力はこのような感じ。
他のボードと同じように Error: gdb requested a non-existing register
が出力されている。
Info : accepting 'gdb' connection on tcp/3333 target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000008 msp: 0x20005000 target state: halted target halted due to breakpoint, current mode: Thread xPSR: 0x61000000 pc: 0x2000003a msp: 0x20005000 target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000008 msp: 0x20005000 Error: gdb requested a non-existing register Info : dropped 'gdb' connection
objdumpで実行バイナリをみる。があまりよくわからない。
$ arm-none-eabi-objdump -Cd main.bin main.bin: file format elf32-littlearm Disassembly of section .text: 08000000 <_reset-0x8>: 8000000: 20005000 .word 0x20005000 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
Rustで生成したものとreadelfを比較してみると、エントリポイントが0x1ずれているのが問題であることに気づいた。
以前書いた記事 で書いたfloat ABIの違いは関係ないようだ。さらに調べるとLLVMに渡すtripleのオプションでhardware floatを渡すことができた。ただしOSの関してはunknownを渡すことはできないようだ。
エントリポイントを外からいじってみる。
$ ldc2 -mtriple=thumbv7m-none-linux-eabi -c -g main.d $ arm-none-eabi-ld main.o -e 0x8000009 -T layout.ld -nostartfiles -o main.bin
$ arm-none-eabi-objdump -Cd main.bin main.bin: file format elf32-littlearm Disassembly of section .text: 08000000 <_reset-0x8>: 8000000: 20005000 .word 0x20005000 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
エントリポイントが0x8000009になっていることを確認。
$ 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: 0x5000200, Version5 EABI, soft-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
しかし結果は変わらず、うまくいかなかった。