Skip to content

Relocated the R_ARM_RELATIVE entries when a GNU ThreadX module starts, so a global pointer initialized with the address of another global now holds the loaded address - #731

Open
fdesbiens wants to merge 1 commit into
eclipse-threadx:devfrom
fdesbiens:fix/issue-230

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Fixes #230

The GNU module startup code in gcc_setup.s rebases the GOT and copies the initialized data into the module data area, but it never applies the relocations the linker records for words inside that data. A global initialized with a link time constant, such as char *pBuffer = buffer;, a global function pointer, or a structure member holding the address of a string literal, therefore keeps the address it was linked at and points outside the loaded module.

gcc_setup.s now walks the .rel.dyn table after the data copy and adjusts every R_ARM_RELATIVE entry whose target lies in the module data area, using the same code and data base arithmetic as the existing GOT loop. Entries targeting the read only code area are skipped and a zero value is left alone, exactly as the GOT loop already does. The flash base is reloaded first because crt0_memory_copy uses r3 as a scratch register.

The relocation table is only emitted when the module is linked with -pie, so the example module build scripts now pass -pie --no-dynamic-linker, and the example module linker scripts discard the .dynamic section that -pie would otherwise place at address zero, which inflated the binary image from a few hundred bytes to nearly 200 KB.

A module linked without -pie has an empty relocation table, so the new loop is a no-op and the previous behaviour is preserved exactly.

Changed: gcc_setup.s for Cortex-M3, M4, M7, M33 and M0+, sample_threadx_module.ld for Cortex-M3, M4, M7 and M0+, and build_threadx_module_sample.bat for Cortex-M3, M4 and M7. Cortex-M23 and M33 ship no module linker script or build script, and the Cortex-A35 AArch64 startup code uses a different relocation format, so those are left for a follow up.

Verified on qemu-system-arm with a module linked at one address and loaded at another: a global char pointer, a global function pointer, a global string pointer, and pointer members of a global structure all resolve to the loaded addresses, and the same module linked without -pie still starts and runs.

…, so a global pointer initialized with the address of another global now holds the loaded address

The GNU module startup code in gcc_setup.s rebased the GOT and copied the
initialized data into the module data area, but it never applied the
relocations that the linker records for words inside that data. A global
variable initialized with a link time constant, such as "char *p = buffer;"
or a structure member holding the address of a function or a string literal,
therefore kept the address it was linked at and was left pointing outside the
module.

gcc_setup.s now walks the .rel.dyn table after the data copy and adjusts every
R_ARM_RELATIVE entry whose target is in the module data area, using the same
code and data base arithmetic as the existing GOT loop. Entries that target
the read only code area are skipped, and a zero value is left alone, exactly
as the GOT loop already does. The flash base is reloaded first because
crt0_memory_copy uses r3 as a scratch register.

The relocation table is only emitted when the module is linked with -pie, so
the example module build scripts now pass -pie and --no-dynamic-linker, and
the example module linker scripts discard the .dynamic section that -pie would
otherwise place at address zero and turn into a very large binary image. A
module linked without -pie has an empty relocation table, so the new loop does
nothing and the previous behaviour is preserved.

Verified on qemu-system-arm with a module linked at one address and loaded at
another: a global char pointer, a global function pointer, a global string
pointer, and pointer members of a global structure all resolve to the loaded
addresses, and the same module linked without -pie still starts and runs.

Assisted-by: Copilot (Opus 5) <noreply@github.com>
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.

1 participant