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
Conversation
…, 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #230
The GNU module startup code in
gcc_setup.srebases 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 aschar *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.snow walks the.rel.dyntable after the data copy and adjusts everyR_ARM_RELATIVEentry 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 becausecrt0_memory_copyusesr3as 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.dynamicsection that-piewould otherwise place at address zero, which inflated the binary image from a few hundred bytes to nearly 200 KB.A module linked without
-piehas an empty relocation table, so the new loop is a no-op and the previous behaviour is preserved exactly.Changed:
gcc_setup.sfor Cortex-M3, M4, M7, M33 and M0+,sample_threadx_module.ldfor Cortex-M3, M4, M7 and M0+, andbuild_threadx_module_sample.batfor 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-armwith a module linked at one address and loaded at another: a globalcharpointer, 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-piestill starts and runs.