Hey all,

first of all, I'm not quite sure if those are bugs or a wished behavior, but if 
it's the latter, I'm curious what the use case might be.

Unexpected start address when using Interleaving
Context

I have a valid main.elf and need to write its .text and .rodata sections to two 
16-bit ROMs by exporting the binary to Intel hex and Verilog. The addresses 
should start at 0x0 though, and I also need to fill the rest of the ROMs with 
0x0.

objcopy

My arguments for riscv32-unknown-elf-objcopy are

  *   --adjust-vma -0xffffc000 To make the binary at address 0x0
  *   --only-section .text --only-section .rodata --pad-to=0x1000 To fill in 
the 0x0, --only-section is needed because the padding is appended after the 
last section and while .rodata is the last section to be exported, the --pad-to 
does not respect that
  *   --interleave-width 2 --interleave=4 --byte [0|2] Interleave to get either 
the lower or upper 16 bits.
  *   --output-format [ihex|verilog] [--verilog-data-width 2] Output as Intel 
Hex or Verilog with 16 bit data width

In my example the elf has the following structure (readelf -S):

There are 11 section headers, starting at offset 0x2bcc:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        ffffc000 001000 000a50 00  AX  0   0  4
  [ 2] .rodata           PROGBITS        ffffca50 001a50 0001ec 00   A  0   0  4
  [ 3] .data             PROGBITS        80000000 001c3c 000000 00  WA  0   0  4
  [ 4] .bss              NOBITS          80000000 002000 000008 00  WA  0   0  4
  [ 5] .heap             PROGBITS        80000008 001c3c 000000 00   W  0   0  4
  [ 6] .comment          PROGBITS        00000000 001c3c 00001b 01  MS  0   0  1
  [ 7] .riscv.attributes RISCV_ATTRIBUTE 00000000 001c57 000035 00      0   0  1
  [ 8] .symtab           SYMTAB          00000000 001c8c 000910 10      9 117  4
  [ 9] .strtab           STRTAB          00000000 00259c 0005db 00      0   0  1
  [10] .shstrtab         STRTAB          00000000 002b77 000055 00      0   0  1


Verilog output WITHOUT using interleaving

@00000000
20B7 0000 8093 8000 9073 3000 0097 0000
8093 0E40 9073 3050 1073 3040 4217 8000
[…]
2423 C000 2623 C000 F7B7 FFFF 8793 5007
A703 0007 4EE3 FE07 0793 0000 80E7 0007
@00000528
0A07 5245 5F52 0000 450A 5252 455F 4358
0020 0000 7741 6961 6974 676E 6E20 6F65
[…]
5845 0045 5300 5A49 0045 4843 534B 4600
534C 0048 5754 0049 0000 0000
@0000061E
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
[…]


So the part after @00000528 is the .rodata section and the address 0x528 is 
right after the .text section.

Verilog output WITH using interleaving (--byte 0)

Now for the unexpected behavior: the Verilog file sets the start address of the 
.rodata section too low when using interleaving.

@00000000
20B7 8093 9073 0097 8093 9073 1073 4217
0213 7113 4197 8193 0293 0313 0393 0413
[…]
0513 F0EF F0EF 0663 2423 2623 F7B7 8793
A703 4EE3 0793 80E7
@0000014A
0A07 5F52 450A 455F 0020 7741 6974 6E20
7672 655F 622E 2E2E 0000 6F4C 6E69 7266
[…]
3130 3534 3938 6463 5845 5300 0045 534B
534C 5754 0000
@000001C5
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
[…]


So the part after @00000528 is the .rodata section and the address 0x14A is in 
the middle of the previous .text section. So I miss the .text data after 
address 0x14A. This does not seem to be the case with the Intel hex files.

I expect this address to be the exact half of the non-interleaved one, so 0x294.

Versions

  *   GNU objcopy (GNU Binutils) 2.43.1
  *   riscv32-unknown-elf-gcc (g04696df0963) 14.2.0

Files

Elf, Intel Hex and Verilog files: 
riscv-toolchain-issue-address-shift.zip<https://github.com/user-attachments/files/17647294/riscv-toolchain-issue-address-shift.zip>

Workaround

I first build a Intel Hex file with --adjust-vma -0xffffc000 --only-section 
.text --only-section .rodata --pad-to=0x2000 --output-format ihex and then 
split.

To split to Intel Hex

--output-format ihex --interleave-width 2 --interleave=4 --byte [0|2] 
path/to_intel.hex

To split to Verilog

--reverse-bytes=2 --output-format verilog --verilog-data-width 2 
--interleave-width 2 --interleave=4 path/to_intel.hex The reverse-bytes is to 
interpret the byte order correctly. It surprises me a bit that this is 
necessary, but at least it works now.

Empty section and --pad-to=0x2000

Even with the workaround I got a new Problem: I might have a .data section as 
well. If I just add the .data to the --only-section commands, the 0x00 padding 
with --pad-to=0x2000 only works when the .data section is not empty. Otherwise 
no padding will happen. I also had the situation where objcopy wrote a gigabyte 
big file with 0x00 but I cannot reproduce it currently.

Workaround

Test if .data section is empty or not.



As I do have the workarounds I don't expect any bugfixes and unforutantelly I 
don't have the time to look at the source code myself, but I just want to let 
you know :)

Best regards,
Lukas Pajak

Reply via email to