rust-embedded / msp430-rt

Minimal startup / runtime for MSP430 microcontrollers
Apache License 2.0
15 stars 4 forks source link

Generated ELF files appear to be subtly incorrect. #22

Open cr1901 opened 1 year ago

cr1901 commented 1 year ago

Per convo w/ @dragonmux:

[ELF] section headers are used specifically and only for linking and that kind of thing - they're there to allow compilers and manipulation tooling easier access to various contained data in the binary

... it's the program headers that control the runtime (loading) environment...

... a lot of tools misuse the headers

In other words, loaders (are) only (supposed to) look at program headers. mspdebug appears to use section headers to flash a binary (subject to other checks that e.g. filter out .bss). By contrast, avrdude uses program headers.

Looking at AT2XT as an example, the first program header appears incorrect:

$ msp430-elf-readelf -lS target/msp430-none-elf/release/at2xt
There are 10 section headers, starting at offset 0x10ac:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .vector_table     PROGBITS        0000ffe0 00085c 000020 00   A  0   0  2
  [ 2] .text             PROGBITS        0000f800 0000b4 00070e 00  AX  0   0  2
  [ 3] .rodata           PROGBITS        0000ff10 0007c4 000094 00   A  0   0  4
  [ 4] .bss              NOBITS          00000200 0000b4 000030 00  WA  0   0  2
  [ 5] .data             PROGBITS        00000230 000858 000002 00  WA  0   0  2
  [ 6] .MSP430.attribute MSP430_ATTRIBUT 00000000 00087c 000017 00      0   0  1
  [ 7] .symtab           SYMTAB          00000000 000894 000390 10      8  32  4
  [ 8] .strtab           STRTAB          00000000 000c24 000432 00      0   0  1
  [ 9] .shstrtab         STRTAB          00000000 001056 000055 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0xf800
There are 4 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x0000014c 0x0000014c 0x000b4 0x000e4 RW  0x4
  LOAD           0x0000b4 0x0000f800 0x0000f800 0x007a4 0x007a4 R E 0x4
  LOAD           0x000858 0x00000230 0x0000ffa4 0x00002 0x00002 RW  0x4
  LOAD           0x00085c 0x0000ffe0 0x0000ffe0 0x00020 0x00020 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     .bss
   01     .text .rodata
   02     .data
   03     .vector_table

A loader/tool that uses the program headers to flash this binary will attempt to "flash" peripheral and/or unmapped memory for 0xb4 bytes, up to address 0x200. At 0x200, flashing/loading stops, and the remaining 0xe4-0xb4 = 0x30 bytes is considered allocated (startup code will fill it in). This is not correct. Program header 00 should be something like:

Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
LOAD           0x000000 0x00000200 0x00000200 0x00000 0x00030 RW  0x4

Swapping .bss and .data order in link.x.in, as below, does not fix the problem:

diff --git a/link.x.in b/link.x.in
index a64ec06..0a1ad70 100644     
--- a/link.x.in
+++ b/link.x.in
@@ -45,14 +45,6 @@ SECTIONS       
     . = ALIGN(2);
   } > ROM

-  .bss : ALIGN(2)  
-  {
-    _sbss = .;     
-    *(.bss .bss.*);
-    . = ALIGN(2);
-    _ebss = .;
-  } > RAM
-
   .data : ALIGN(2)
   {
     _sidata = LOADADDR(.data);
@@ -62,6 +54,14 @@ SECTIONS
     _edata = .;
   } > RAM AT > ROM

+  .bss : ALIGN(2)
+  {
+    _sbss = .;
+    *(.bss .bss.*);
+    . = ALIGN(2);
+    _ebss = .;
+  } > RAM
+
   /* fake output .got section */
   /* Dynamic relocations are unsupported. This section is only used to detect
      relocatable code in the input files and raise an error if relocatable code
$ msp430-elf-readelf.exe -lS ~/Projects/legacy/AT2XT/target/msp430-none-elf/release/at2xt
There are 10 section headers, starting at offset 0x108c:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .vector_table     PROGBITS        0000ffe0 00083c 000020 00   A  0   0  2
  [ 2] .text             PROGBITS        0000f800 000094 00070e 00  AX  0   0  2
  [ 3] .rodata           PROGBITS        0000ff10 0007a4 000094 00   A  0   0  4
  [ 4] .data             PROGBITS        00000200 000838 000002 00  WA  0   0  2
  [ 5] .bss              NOBITS          00000202 00083a 000030 00  WA  0   0  2
  [ 6] .MSP430.attribute MSP430_ATTRIBUT 00000000 00085c 000017 00      0   0  1
  [ 7] .symtab           SYMTAB          00000000 000874 000390 10      8  32  4
  [ 8] .strtab           STRTAB          00000000 000c04 000432 00      0   0  1
  [ 9] .shstrtab         STRTAB          00000000 001036 000055 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0xf800
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x0000f76c 0x0000f76c 0x00838 0x00838 R E 0x4
  LOAD           0x000838 0x00000200 0x0000ffa4 0x00002 0x00032 RW  0x4
  LOAD           0x00083c 0x0000ffe0 0x0000ffe0 0x00020 0x00020 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata
   01     .data .bss
   02     .vector_table

Now the loader would be instructed to write .text and .rodata to unallocated memory for the MSP430G2211 part! It's like msp430-elf-ld hardcodes the first program header to load starting at Offset 0 in the ELF file." We need to figure out what causes the bad ELF program header and correct it; while flashing w/ mspdebug is unaffected, other tools may use the incorrect program headers to flash.