simavr fails to run on ELF, but not on HEX
maxgerhardt opened this issue ยท 5 comments
After making adjustments to the build process as per #378 (comment), I now have a .elf
file with the needed ELF section .mmcu
, however simavr crashes on it.
Running it unde GDB reveals
>gdb --args simavr -v C:\Users\Max\temp\simavr_test\.pio\build\uno\firmware.elf
[...]
(gdb) r
Starting program: C:\Users\Max\Desktop\simavr_installed\bin\simavr.exe -v C:\Users\Max\temp\simavr_test\.pio\build\uno\firmware.elf
[New Thread 6544.0x20bc]
[New Thread 6544.0x25e8]
Loaded 1600 .text at address 0x0
Loaded 36 .data
avr_sadly_crashed
GDB: Can not bind socket: No errorwarning: Invalid parameter passed to C runtime function.
[Thread 6544.0x20bc exited with code 0]
[Thread 6544.0x25e8 exited with code 0]
[Inferior 1 (process 6544) exited normally]
(gdb) q
That it ends in avr_sadly_crashed
.
simavr
has no problem running the hex file created from that ELF file...
>C:\Users\Max\.platformio\packages\toolchain-atmelavr\bin\avr-objcopy.exe -O ihex -R .eeprom firmware.elf firmware.hex
>simavr --mcu atmega328p --freq 16000000 -v firmware.hex
Loaded 1 section of ihex
Load HEX flash 00000000, 1710
Hello, world!..
Hello, world!..
Hello, world!..
Firmware files are attached.
I think that the immediate problem is that a different modification to the build is needed. Try removing the previous changes and adding this line from Makefile.common:
-Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000
The first part stops ld from discarding .mmcu and the second places it at an address meaningless to simavr. Without that, .mmcu is placed between .text and .data, using Flash space. Worse, simavr discards it during loading and then loads .data at the wrong address. Then the startup code copies uninitialised Flash into RAM and things go rapidly downhill.
That might fix the problem, but there is a bigger underlying issue: simavr loads only the .text, .data, .eeprom, .fuse and .lock sections and assumes the first two are contiguous. I think code will fail if any statically allocated C++ objects are defined, introducing .ctor and .dtor sections.
I believe the way to fix this would be to use the Program Header Table for loading, as the ELF specification suggests. It seems the Section Table is intended for linkers. Add a helpful warning if .mmcu is included in Flash.
Note you appear to be using standard GDB. It is not directly compatible with AVR-GDB and cannot interpret ELFs correctly for AVR-style executables. I get all kinds of odd issues if I attempt to use it with SimAVR and atmel ELFs.
I haven't had issues loading ELFs from arduino directly with MK404 (just grabbed 'em from the tmp build dir) so I'm inclined to agree this is related to how the ELF is assembled in your case ๐
Note you appear to be using standard GDB. It is not directly compatible with AVR-GDB and cannot interpret ELFs correctly for AVR-style executables.
I'm using my host GDB to watch the execution of simavr.exe
, which is a x86 executable, not an AVR ELF.
-Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000
Thanks, I'll try these options.
D'oh... sorry. I'll crawl back under my rock now ๐
-Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000
This absolutely fixes the problem, and I don't even need to leave out the lto
flags and related anymore. Doing a platformio.ini
config of
[env:uno]
platform = atmelavr
board = uno
framework = arduino
build_flags = -Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000
produces a .elf
which now loads correctly!
> simavr -v C:\Users\Max\temp\simavr_test\.pio\build\uno\firmware.elf
Loaded 1600 .text at address 0x0
Loaded 36 .data
Hello, world!..
Hello, world!..
Hello, world!..
and it even runs nicely, although the Arduino code uses Serial
which is a statically allocated and constructed C++ object. Looking back in the elf there is however no separate section for ctors and dtors,
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 00000024 00800100 00000640 000006f4 2**0
CONTENTS, ALLOC, LOAD, DATA
1 .mmcu 0000004a 00910000 00910000 00000718 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .text 00000640 00000000 00000000 000000b4 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
3 .bss 000000a6 00800124 00800124 00000718 2**0
ALLOC
4 .comment 00000011 00000000 00000000 00000762 2**0
CONTENTS, READONLY
5 .note.gnu.avr.deviceinfo 00000040 00000000 00000000 00000774 2**2
CONTENTS, READONLY, OCTETS
6 .debug_aranges 000000a0 00000000 00000000 000007b8 2**3
CONTENTS, READONLY, DEBUGGING, OCTETS
7 .debug_info 0000099b 00000000 00000000 00000858 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
8 .debug_abbrev 00000606 00000000 00000000 000011f3 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
9 .debug_line 000002a6 00000000 00000000 000017f9 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
10 .debug_str 00000208 00000000 00000000 00001a9f 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
so it works just out.
Closing as solved, thanks @gatk555!