Closed twilfredo closed 11 months ago
I want to make sure I'm understanding this correctly. When you build mbedtls
, GCC generates a .data.rel.ro
section, which is then relocated when mbedtls
is linked into the app binary, correct? I'm seeing a bit of a mismatch between that model (in which .data.rel.ro
is relocated when the app is statically linked) and the PR description/blog post, which indicate that .data.rel.ro
is dynamically relocated.
I want to make sure I'm understanding this correctly. When you build
mbedtls
, GCC generates a.data.rel.ro
section, which is then relocated whenmbedtls
is linked into the app binary, correct? I'm seeing a bit of a mismatch between that model (in which.data.rel.ro
is relocated when the app is statically linked) and the PR description/blog post, which indicate that.data.rel.ro
is dynamically relocated.
mbetls creates the following sections (and some more of the same type), this is from one of the mbedtls libraries:
Relocation section '.rel.data.rel.ro.local.ecp_x25519_bad_point_2' at offset 0x5200 contains 1 entry:
Offset Info Type Sym.Value Sym. Name
00000008 0000c502 R_ARM_ABS32 00000000 .rodata.x25519_ba[...]
Relocation section '.rel.data.rel.ro.local.ecp_x25519_bad_point_1' at offset 0x5208 contains 1 entry:
Offset Info Type Sym.Value Sym. Name
00000008 0000c702 R_ARM_ABS32 00000000 .rodata.x25519_ba[...]
When linking the static library to our libtock-rs app (without the changes in this PR), I see the following in the elf output :
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 00040080 001080 000074 00 AX 0 0 1
[ 2] .text PROGBITS 000400f4 0010f4 01defc 00 AX 0 0 8
[ 3] .rodata PROGBITS 0005dff0 01eff0 003432 00 AMS 0 0 8
[ 4] .stack NOBITS 20008000 023000 004000 00 WA 0 0 1
[ 5] .data PROGBITS 2000c000 027000 000268 00 WA 0 0 4
[ 6] .data..L_Mer[...] PROGBITS 2000c268 027268 00001d 00 WA 0 0 2
[ 7] .data.rel.ro[...] PROGBITS 2000c288 027288 0001d0 00 WA 0 0 4
[ 8] .data.rel.ro[...] PROGBITS 2000c458 027458 00000c 00 WA 0 0 4
...
[36] .data.rel.ro[...] PROGBITS 2000c95c 02795c 00001c 00 WA 0 0 4
[37] .data.rel.ro[...] PROGBITS 2000c978 027978 00001c 00 WA 0 0 4
...
...
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001080 0x00040080 0x00040080 0x1df70 0x1df70 R E 0x1000
LOAD 0x01eff0 0x0005dff0 0x0005dff0 0x03432 0x03432 R 0x1000
LOAD 0x023000 0x20008000 0x00061422 0x04268 0x04268 RW 0x1000
LOAD 0x027268 0x2000c268 0x2000c268 0x0072c 0x0072c RW 0x1000
LOAD 0x027994 0x2000c994 0x0006568c 0x00000 0x0266c RW 0x1000
LOAD 0x028000 0x2000f000 0x2000f000 0x0004c 0x0004c RW 0x1000 <--- [comment: this shouldn't be here]
GNU_RELRO 0x028000 0x2000f000 0x2000f000 0x0004c 0x01000 R 0x1
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
This is built for the nrf52840, so .data.rel.ro
has a RAM Addr here. When elf2tab is used to create the app.tab it runs into this issue https://github.com/tock/elf2tab/issues/83 (between addrs for this case 0x0006568c-0x2000f000), and outputs a TAB of 512MB!.
With the changes in the PR we see the following in the elf:
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 00040080 001080 000074 00 AX 0 0 1
[ 2] .text PROGBITS 000400f4 0010f4 01defc 00 AX 0 0 8
[ 3] .rodata PROGBITS 0005dff0 01eff0 003432 00 AMS 0 0 8
[ 4] ..data.rel.r[...] PROGBITS 00061424 022424 000708 00 WA 0 0 4
[ 5] .data..L_Mer[...] PROGBITS 00061b2c 022b2c 00001d 00 WA 0 0 2
[ 6] .data.one.0 PROGBITS 00061b4c 022b4c 000004 00 WA 0 0 4
[ 7] .got PROGBITS 00061b50 022b50 00004c 00 WA 0 0 4
[ 8] .stack NOBITS 20010000 023000 004000 00 WA 0 0 1
[ 9] .data PROGBITS 20014000 027000 000268 00 WA 0 0 4
[10] .bss NOBITS 20014268 027268 00266c 00 WA 0 0 4
...
...
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001080 0x00040080 0x00040080 0x1df70 0x1df70 R E 0x1000
LOAD 0x01eff0 0x0005dff0 0x0005dff0 0x03432 0x03432 R 0x1000
LOAD 0x022424 0x00061424 0x00061424 0x00778 0x00778 RW 0x1000
LOAD 0x023000 0x20010000 0x00061b9c 0x04268 0x068d4 RW 0x1000
GNU_RELRO 0x022b50 0x00061b50 0x00061b50 0x0004c 0x004b0 R 0x1
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
and we can compile and run the app without the issue from the prior case. So my thinking was that adding a .data.rel.ro.local
allows the respective data be put in the 'correct' place at link time. But it's kind of beyond my understanding. Perhaps you have a better idea of what is happening?
Okay, sounds reasonable to me.
Context: I encountered this issue when linking
mbedtls
to a libtock-rs app.This accommodates situations for example: where global variables are initialized to a value that requires relocation. Things like globally stored function pointers, or storing the address of another global variable. Such items require runtime initialization in the form of dynamic relocation, and cannot be placed in a RO segment. However, as it is declared to be a constant (not modified by the program), the dynamic linker can mark it as RO after the dynamic relocation as been applied [1].
When GCC sees a variable which is constant but requires dynamic relocation, it puts it into a section named
.data.rel.ro
, further, a variable that requires dynamic relocation against a local symbol is put into a.data.rel.ro.local
section, this helps group such variables together so that the dynamic linker may apply the relocations, which will always be RELATIVE locations [1].[1] https://www.airs.com/blog/archives/189