simavr
simavr copied to clipboard
simavr not loading .data correctly when avr_mmcu_vcd_trace_t is present.
Test one:
#include <avr/io.h>
unsigned char myvar = 0xab;
void main(void)
{
PORTB = myvar;
}
Compile and run it in simavr:
avr-gcc -g -mmcu=atmega168 -DF_CPU=16000000UL -c -o test.o test.c
avr-gcc -g -mmcu=atmega168 -DF_CPU=16000000UL -o test.elf test.o
Check the contents of the data section:
$ avr-objdump -s -j .data test.elf
test.elf: file format elf32-avr
Contents of section .data:
800100 ab00 ..
Run it in simavr:
$ run_avr -g -m atmega168 -f 16000000 test.elf
Loaded 182 .text at address 0x0
Loaded 2 .data
avr_gdb_init listening on port 1234
Debug with gdb:
(gdb) target remote :1234
Remote debugging using :1234
0x00000000 in __vectors ()
(gdb) break main
Note: breakpoints 1 and 2 also set at pc 0x9e.
Breakpoint 3 at 0x9e: file test.c, line 7.
(gdb) continue
Continuing.
Breakpoint 1, main () at test.c:7
7 PORTB = myvar;
(gdb) disassemble
Dump of assembler code for function main:
0x00000096 <+0>: push r28
0x00000098 <+2>: push r29
0x0000009a <+4>: in r28, 0x3d ; 61
0x0000009c <+6>: in r29, 0x3e ; 62
=> 0x0000009e <+8>: ldi r24, 0x25 ; 37
0x000000a0 <+10>: ldi r25, 0x00 ; 0
0x000000a2 <+12>: lds r18, 0x0100
0x000000a6 <+16>: movw r30, r24
0x000000a8 <+18>: st Z, r18
0x000000aa <+20>: nop
0x000000ac <+22>: pop r29
0x000000ae <+24>: pop r28
0x000000b0 <+26>: ret
End of assembler dump.
(gdb) x 0x100
0x800100 <myvar>: 0x000000ab
Test two:
Source code:
#include <avr/io.h>
#include "avr_mcu_section.h"
/* trace struct for simavr */
const struct avr_mmcu_vcd_trace_t _mytrace[] _MMCU_ = {
{ AVR_MCU_VCD_SYMBOL("B0"), .mask = (1 << 0), .what = (void*)&PORTB, },
{ AVR_MCU_VCD_SYMBOL("B1"), .mask = (1 << 1), .what = (void*)&PORTB, },
{ AVR_MCU_VCD_SYMBOL("B2"), .mask = (1 << 2), .what = (void*)&PORTB, },
{ AVR_MCU_VCD_SYMBOL("B3"), .mask = (1 << 3), .what = (void*)&PORTB, },
{ AVR_MCU_VCD_SYMBOL("B4"), .mask = (1 << 4), .what = (void*)&PORTB, },
{ AVR_MCU_VCD_SYMBOL("B5"), .mask = (1 << 5), .what = (void*)&PORTB, },
{ AVR_MCU_VCD_SYMBOL("B6"), .mask = (1 << 6), .what = (void*)&PORTB, },
{ AVR_MCU_VCD_SYMBOL("B7"), .mask = (1 << 7), .what = (void*)&PORTB, },
};
unsigned char myvar = 0xab;
void main(void)
{
PORTB = myvar;
}
Compile and run as before. Verify the data section again with objdump to confirm it is the same.
Run it in gdb:
(gdb) target remote :1234
Remote debugging using :1234
0x00000000 in __vectors ()
(gdb) break main
Breakpoint 1 at 0x9e: file test.c, line 24.
(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, main () at test.c:24
24 PORTB = myvar;
(gdb) disassemble
Dump of assembler code for function main:
0x00000096 <+0>: push r28
0x00000098 <+2>: push r29
0x0000009a <+4>: in r28, 0x3d ; 61
0x0000009c <+6>: in r29, 0x3e ; 62
=> 0x0000009e <+8>: ldi r24, 0x25 ; 37
0x000000a0 <+10>: ldi r25, 0x00 ; 0
0x000000a2 <+12>: lds r18, 0x0100
0x000000a6 <+16>: movw r30, r24
0x000000a8 <+18>: st Z, r18
0x000000aa <+20>: nop
0x000000ac <+22>: pop r29
0x000000ae <+24>: pop r28
0x000000b0 <+26>: ret
End of assembler dump.
(gdb) x 0x100
0x800100 <myvar>: 0x0000ffff
Result: myvar is now 0xff instead of 0xab, but the data section has not changed according to objdump.
Including the link flags "-Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000" makes this work, but I don't see why it should be necessary given that objdump can find the intact .data section just fine without it.
I realize this is quite old news, but this occurs because of section ordering. It's possible that the .mmcu section appears between .text and .data, but simavr loads .text and .data immediately adjacent to each other. This means the offsets in __do_copy_data (a stub inserted by libgcc) don't match the flash memory map simulated by simavr. Moving the section start address ensures it is not mapped between the two other sections.