Skip to content

modify segments that start before flash#75

Merged
bradjc merged 2 commits intomasterfrom
segments-before-flash
Aug 22, 2023
Merged

modify segments that start before flash#75
bradjc merged 2 commits intomasterfrom
segments-before-flash

Conversation

@bradjc
Copy link
Copy Markdown
Contributor

@bradjc bradjc commented Jul 25, 2023

This is an alternative to #74.

The linker appears to be able to place segments before the start of flash. We detect this case and edit the segment to remove the portion that exists before the specified start of flash.

This if merged would be the end of an era: I've finally given in to use symbols to transfer information from the linker script to elf2tab.

@bradjc
Copy link
Copy Markdown
Contributor Author

bradjc commented Aug 1, 2023

I'm finding more elfs with segments before the start of flash. For example, when working with multiple address libtock-rs apps, I got this elf:

$ readelf.py -lS target/console/cortex-m4.0x00048000.0x20010000.elf
There are 22 section headers, starting at offset 0x2cf1c

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .start            PROGBITS        00048060 008060 000074 00  AX  0   0  1
  [ 2] .text             PROGBITS        000480d4 0080d4 0016c8 00  AX  0   0  2
  [ 3] .rodata           PROGBITS        0004979c 00979c 0001ec 00   A  0   0  4
  [ 4] .stack            NOBITS          20010000 010000 000100 00  WA  0   0  1
  [ 5] .data             PROGBITS        20010100 010100 000000 00  WA  0   0  1
  [ 6] .bss              NOBITS          20010100 010100 000000 00  WA  0   0  1
  [ 7] .debug_loc        PROGBITS        00000000 010100 0011c5 00      0   0  1
  [ 8] .debug_abbrev     PROGBITS        00000000 0112c5 0003f3 00      0   0  1
  [ 9] .debug_info       PROGBITS        00000000 0116b8 007c0d 00      0   0  1
  [10] .debug_aranges    PROGBITS        00000000 0192c5 000108 00      0   0  1
  [11] .debug_ranges     PROGBITS        00000000 0193cd 001278 00      0   0  1
  [12] .debug_str        PROGBITS        00000000 01a645 009310 01  MS  0   0  1
  [13] .debug_pubnames   PROGBITS        00000000 023955 004e3e 00      0   0  1
  [14] .debug_pubtypes   PROGBITS        00000000 028793 001021 00      0   0  1
  [15] .ARM.attributes   ARM_ATTRIBUTES  00000000 0297b4 000032 00      0   0  1
  [16] .debug_frame      PROGBITS        00000000 0297e8 000358 00      0   0  4
  [17] .debug_line       PROGBITS        00000000 029b40 0020c0 00      0   0  1
  [18] .comment          PROGBITS        00000000 02bc00 000013 01  MS  0   0  1
  [19] .symtab           SYMTAB          00000000 02bc14 0005c0 10     21  76  4
  [20] .shstrtab         STRTAB          00000000 02c1d4 0000e1 00      0   0  1
  [21] .strtab           STRTAB          00000000 02c2b5 000c65 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

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

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00040034 0x00040034 0x000c0 0x000c0 R   0x4
  LOAD           0x000000 0x00040000 0x00040000 0x000f4 0x000f4 R   0x10000
  LOAD           0x008060 0x00048060 0x00048060 0x0173c 0x0173c R E 0x10000
  LOAD           0x00979c 0x0004979c 0x0004979c 0x001ec 0x001ec R   0x10000
  LOAD           0x010000 0x20010000 0x00049988 0x00100 0x00100 RW  0x10000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x0

 Section to Segment mapping:
  Segment Sections...
   00
   01
   02     .start .text
   03     .rodata
   04     .stack
   05

Flash starts at 0x00048000, but the first load segment is at 0x00040000.

@lschuermann
Copy link
Copy Markdown
Member

What you're seeing here is the behavior I described in tock/libtock-rs#477. I'm pretty sure the above ELF is an example of a linker bug.

@bradjc
Copy link
Copy Markdown
Contributor Author

bradjc commented Aug 4, 2023

It seems like llvm ld really likes to have a segment aligned to 0x10000. So the "typical" app at 0x40000 looks ok:

readelf.py -lS cortex-m4.0x00040000.0x20008000.elf
There are 22 section headers, starting at offset 0x32f1c

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .start            PROGBITS        00040060 010060 000074 00  AX  0   0  1
  [ 2] .text             PROGBITS        000400d4 0100d4 0016c8 00  AX  0   0  2
  [ 3] .rodata           PROGBITS        0004179c 01179c 0001ec 00   A  0   0  4
  [ 4] .stack            NOBITS          20006000 016000 000100 00  WA  0   0  1
  [ 5] .data             PROGBITS        20006100 016100 000000 00  WA  0   0  1
  [ 6] .bss              NOBITS          20006100 016100 000000 00  WA  0   0  1
  [ 7] .debug_loc        PROGBITS        00000000 016100 0011c5 00      0   0  1
  [ 8] .debug_abbrev     PROGBITS        00000000 0172c5 0003f3 00      0   0  1
  [ 9] .debug_info       PROGBITS        00000000 0176b8 007c0d 00      0   0  1
  [10] .debug_aranges    PROGBITS        00000000 01f2c5 000108 00      0   0  1
  [11] .debug_ranges     PROGBITS        00000000 01f3cd 001278 00      0   0  1
  [12] .debug_str        PROGBITS        00000000 020645 009310 01  MS  0   0  1
  [13] .debug_pubnames   PROGBITS        00000000 029955 004e3e 00      0   0  1
  [14] .debug_pubtypes   PROGBITS        00000000 02e793 001021 00      0   0  1
  [15] .ARM.attributes   ARM_ATTRIBUTES  00000000 02f7b4 000032 00      0   0  1
  [16] .debug_frame      PROGBITS        00000000 02f7e8 000358 00      0   0  4
  [17] .debug_line       PROGBITS        00000000 02fb40 0020c0 00      0   0  1
  [18] .comment          PROGBITS        00000000 031c00 000013 01  MS  0   0  1
  [19] .symtab           SYMTAB          00000000 031c14 0005c0 10     21  76  4
  [20] .shstrtab         STRTAB          00000000 0321d4 0000e1 00      0   0  1
  [21] .strtab           STRTAB          00000000 0322b5 000c65 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

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

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x010060 0x00040060 0x00040060 0x0173c 0x0173c R E 0x10000
  LOAD           0x01179c 0x0004179c 0x0004179c 0x001ec 0x001ec R   0x10000
  LOAD           0x016000 0x20006000 0x00041988 0x00100 0x00100 RW  0x10000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x0

 Section to Segment mapping:
  Segment Sections...
   00     .start .text
   01     .rodata
   02     .stack
   03

but then for apps at "intermediate" addresses:

readelf.py -lS target/cortex-m4.0x00048000.0x1000a000/console
There are 22 section headers, starting at offset 0x26f1c

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .start            PROGBITS        00048080 008080 000074 00  AX  0   0  1
  [ 2] .text             PROGBITS        000480f4 0080f4 0016c8 00  AX  0   0  2
  [ 3] .rodata           PROGBITS        000497bc 0097bc 0001ec 00   A  0   0  4
  [ 4] .stack            NOBITS          1000a000 00a000 000100 00  WA  0   0  1
  [ 5] .data             PROGBITS        1000a100 00a100 000000 00  WA  0   0  1
  [ 6] .bss              NOBITS          1000a100 00a100 000000 00  WA  0   0  1
  [ 7] .debug_loc        PROGBITS        00000000 00a100 0011c5 00      0   0  1
  [ 8] .debug_abbrev     PROGBITS        00000000 00b2c5 0003f3 00      0   0  1
  [ 9] .debug_info       PROGBITS        00000000 00b6b8 007c0d 00      0   0  1
  [10] .debug_aranges    PROGBITS        00000000 0132c5 000108 00      0   0  1
  [11] .debug_ranges     PROGBITS        00000000 0133cd 001278 00      0   0  1
  [12] .debug_str        PROGBITS        00000000 014645 009310 01  MS  0   0  1
  [13] .debug_pubnames   PROGBITS        00000000 01d955 004e3e 00      0   0  1
  [14] .debug_pubtypes   PROGBITS        00000000 022793 001021 00      0   0  1
  [15] .ARM.attributes   ARM_ATTRIBUTES  00000000 0237b4 000032 00      0   0  1
  [16] .debug_frame      PROGBITS        00000000 0237e8 000358 00      0   0  4
  [17] .debug_line       PROGBITS        00000000 023b40 0020c0 00      0   0  1
  [18] .comment          PROGBITS        00000000 025c00 000013 01  MS  0   0  1
  [19] .symtab           SYMTAB          00000000 025c14 0005c0 10     21  76  4
  [20] .shstrtab         STRTAB          00000000 0261d4 0000e1 00      0   0  1
  [21] .strtab           STRTAB          00000000 0262b5 000c65 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

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

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00040034 0x00040034 0x000c0 0x000c0 R   0x4
  LOAD           0x000000 0x00040000 0x00040000 0x000f4 0x000f4 R   0x10000
  LOAD           0x008080 0x00048080 0x00048080 0x0173c 0x0173c R E 0x10000
  LOAD           0x0097bc 0x000497bc 0x000497bc 0x001ec 0x001ec R   0x10000
  LOAD           0x00a000 0x1000a000 0x000499a8 0x00100 0x00100 RW  0x10000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x0

 Section to Segment mapping:
  Segment Sections...
   00
   01
   02     .start .text
   03     .rodata
   04     .stack
   05

There are two segments that start at 0x40000 still.

@lschuermann
Copy link
Copy Markdown
Member

This is not too surprising to me, as that's the exact reason I added this change: tock/libtock-rs#477. However, for me it was alignment to 0x1000 bytes:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x10004000 0x10004000 0x00094 0x00900 RW  0x1000

Which LLVM toolchain are you using? An align of 0x10000 is getting silly. Can we somehow control that parameter?

@bradjc
Copy link
Copy Markdown
Contributor Author

bradjc commented Aug 4, 2023

I added println!("cargo:rustc-link-arg=-zmax-page-size=4096"); to build.rs and now get:

readelf.py -lS target/cortex-m4.0x00048000.0x20010000/leds
There are 22 section headers, starting at offset 0x220e0

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .start            PROGBITS        00048080 001080 000074 00  AX  0   0  1
  [ 2] .text             PROGBITS        000480f4 0010f4 001826 00  AX  0   0  4
  [ 3] .rodata           PROGBITS        0004991c 00291c 000220 00  AM  0   0  4
  [ 4] .stack            NOBITS          20010000 003000 000200 00  WA  0   0  1
  [ 5] .data             PROGBITS        20010200 003200 000000 00  WA  0   0  1
  [ 6] .bss              NOBITS          20010200 003200 000000 00  WA  0   0  1
  [ 7] .debug_loc        PROGBITS        00000000 003200 0011ad 00      0   0  1
  [ 8] .debug_abbrev     PROGBITS        00000000 0043ad 00042d 00      0   0  1
  [ 9] .debug_info       PROGBITS        00000000 0047da 007f09 00      0   0  1
  [10] .debug_aranges    PROGBITS        00000000 00c6e3 000110 00      0   0  1
  [11] .debug_ranges     PROGBITS        00000000 00c7f3 0013a0 00      0   0  1
  [12] .debug_str        PROGBITS        00000000 00db93 009f0e 01  MS  0   0  1
  [13] .debug_pubnames   PROGBITS        00000000 017aa1 005475 00      0   0  1
  [14] .debug_pubtypes   PROGBITS        00000000 01cf16 001559 00      0   0  1
  [15] .ARM.attributes   ARM_ATTRIBUTES  00000000 01e46f 000032 00      0   0  1
  [16] .debug_frame      PROGBITS        00000000 01e4a4 000370 00      0   0  4
  [17] .debug_line       PROGBITS        00000000 01e814 0022b6 00      0   0  1
  [18] .comment          PROGBITS        00000000 020aca 000013 01  MS  0   0  1
  [19] .symtab           SYMTAB          00000000 020ae0 000690 10     21  89  4
  [20] .shstrtab         STRTAB          00000000 021170 0000e1 00      0   0  1
  [21] .strtab           STRTAB          00000000 021251 000e8e 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

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

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001080 0x00048080 0x00048080 0x0189a 0x0189a R E 0x1000
  LOAD           0x00291c 0x0004991c 0x0004991c 0x00220 0x00220 R   0x1000
  LOAD           0x003000 0x20010000 0x00049b3c 0x00200 0x00200 RW  0x1000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x0

 Section to Segment mapping:
  Segment Sections...
   00     .start .text
   01     .rodata
   02     .stack
   03

Which looks more reasonable.

@bradjc
Copy link
Copy Markdown
Contributor Author

bradjc commented Aug 7, 2023

Latest update: tock/libtock-rs#495

@bradjc
Copy link
Copy Markdown
Contributor Author

bradjc commented Aug 7, 2023

For fun, I tried to build the original problem app (bare bones with STACK=0) with an alignment of 1:

diff --git a/Configuration.mk b/Configuration.mk
index 166cbd1..2c1bddc 100644
--- a/Configuration.mk
+++ b/Configuration.mk
@@ -180,7 +180,8 @@ override CPPFLAGS += \
 override WLFLAGS += \
       -Wl,--warn-common\
       -Wl,--gc-sections\
-      -Wl,--build-id=none
+      -Wl,--build-id=none\
+      -Wl,-zmax-page-size=1

The elf is different yet, but still not workable without this change:

readelf.py -lS build/rv32imac/rv32imac.0x20040080.0x80002800.elf
There are 22 section headers, starting at offset 0x7f4

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .got              PROGBITS        80002800 0000a4 000000 00  WA  0   0  1
  [ 2] .crt0_header      PROGBITS        20040080 000074 000028 00   A  0   0  1
  [ 3] .data             PROGBITS        80002800 0000a4 000000 00  WA  0   0  1
  [ 4] .bss              NOBITS          80002800 0000a4 000000 00  WA  0   0  1
  [ 5] .GCC.command.line PROGBITS        00000000 0000a4 0000a4 01  MS  0   0  1
  [ 6] .comment          PROGBITS        00000000 000148 000012 01  MS  0   0  1
  [ 7] .riscv.attributes ARM_ATTRIBUTES  00000000 00015a 00002b 00      0   0  1
  [ 8] .wfr.app_state    PROGBITS        200400a8 000185 000000 00   W  0   0  1
  [ 9] .text             PROGBITS        200400a8 00009c 000008 00  AX  0   0  2
  [10] .stack            PROGBITS        80002800 000185 000000 00   W  0   0  1
  [11] .debug_info       PROGBITS        00000000 000185 000087 00      0   0  1
  [12] .debug_abbrev     PROGBITS        00000000 00020c 00004a 00      0   0  1
  [13] .debug_loc        PROGBITS        00000000 000256 000084 00      0   0  1
  [14] .debug_aranges    PROGBITS        00000000 0002da 000020 00      0   0  1
  [15] .debug_ranges     PROGBITS        00000000 0002fa 000010 00      0   0  1
  [16] .debug_line       PROGBITS        00000000 00030a 000041 00      0   0  1
  [17] .debug_str        PROGBITS        00000000 00034b 00010f 01  MS  0   0  1
  [18] .debug_frame      PROGBITS        00000000 00045c 000020 00      0   0  4
  [19] .symtab           SYMTAB          00000000 00047c 000210 10     20  20  4
  [20] .strtab           STRTAB          00000000 00068c 000081 00      0   0  1
  [21] .shstrtab         STRTAB          00000000 00070d 0000e7 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

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

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x2004000c 0x2004000c 0x000a4 0x000a4 R E 0x1
  LOAD           0x0000a4 0x80002800 0x200400b0 0x00000 0x00000 RW  0x1

 Section to Segment mapping:
  Segment Sections...
   00     .crt0_header .text
   01

bradjc added 2 commits August 8, 2023 18:16
The linker appears to be able to place segements before the start of
flash. We detect this case and edit the segment to remove the portion
that exists before the specified start of flash.
@bradjc
Copy link
Copy Markdown
Contributor Author

bradjc commented Aug 22, 2023

I think it's time to decide on this. I say we go ahead with it. I don't know how else to fix STACK=0 libtock-c riscv apps.

@lschuermann
Copy link
Copy Markdown
Member

Sure. I didn't get to test this only my WIP code just yet, but it seems like a strict improvement over the current state.

@bradjc bradjc merged commit fc14c93 into master Aug 22, 2023
@bradjc bradjc deleted the segments-before-flash branch August 29, 2023 02:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants