mirror of
https://github.com/apache/nuttx.git
synced 2026-09-09 18:36:37 +00:00
arch/arm, libs/libc/elf: Build FDPIC modules in the normal ELF build.
With CONFIG_FDPIC selected, a module built by apps/Application.mk is now an FDPIC shared object. Nothing about how a module is written or built changes: the same MODULE = m in the same Makefile, the same crt0 and the same linker script. Two things differ from the position independent build beside it. The compiler is told -mfdpic -fPIC, and the link is done by an arm-uclinuxfdpiceabi linker. The stock arm-none-eabi compiler emits correct FDPIC objects for both C and C++, so only the link needs it: the stock linker carries the armelf emulation alone and would turn every import into an R_ARM_JUMP_SLOT, one word, where the ABI wants an R_ARM_FUNCDESC_VALUE, which is two, a code address and the data base that goes with it. Such a module links cleanly and then calls out of itself with the caller's data base still in r9. That linker is in the CI image. gnu-elf.ld.in gains the two segments an FDPIC module needs, under CONFIG_FDPIC, because the loader places its read-only and writable segments independently, and names .dynamic, because a shared object is bound through it. The sections themselves are untouched and so are the symbols crt0.c walks, so one script serves both and both build systems get it. .bss moves to the end of the script, for every configuration and not only FDPIC. It held no file content but sat ahead of .got and .dynamic, which do, so the writable segment's p_filesz had to span it and the module file carried the whole of .bss. A module with 16 KiB of .bss went from 26724 to 10340 bytes, and its writable segment from p_filesz 0x40ac to 0xac against an unchanged p_memsz. The loader reads p_filesz off the media, so it read those bytes too. Built for mps3-an547:picostest with apps/examples/elf, CONFIG_FDPIC both ways. With it on, every module in apps/bin is ARM FDPIC with two PT_LOAD segments and enters at _start; hello++3, which has a static C++ object, carries DT_INIT_ARRAY and DT_FINI_ARRAY. With it off the generated script has no PHDRS and the modules are what they were. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
parent
a60ee84197
commit
4cdd3cdbda
2 changed files with 71 additions and 11 deletions
|
|
@ -642,11 +642,29 @@ ifeq ($(CONFIG_PIC),y)
|
|||
# after including this file, which would discard the flag.
|
||||
|
||||
ARCHCFLAGS += --fixed-r9
|
||||
|
||||
ifeq ($(CONFIG_FDPIC),y)
|
||||
# An FDPIC module is a shared object whose two segments the loader places
|
||||
# independently. The stock compiler emits correct FDPIC objects for both C
|
||||
# and C++, so only the link needs the arm-uclinuxfdpiceabi linker: the
|
||||
# stock one carries the armelf emulation alone and would turn every import
|
||||
# into a jump slot where the ABI wants a function descriptor.
|
||||
|
||||
FDPIC_CROSSDEV ?= arm-uclinuxfdpiceabi-
|
||||
MODULELD = $(FDPIC_CROSSDEV)ld
|
||||
|
||||
CELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack
|
||||
CXXELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack
|
||||
|
||||
LDELFFLAGS += -m armelf_linux_fdpiceabi -shared -z now
|
||||
else
|
||||
CELFFLAGS += $(PICFLAGS) -mpic-register=r9
|
||||
CXXELFFLAGS += $(PICFLAGS) -mpic-register=r9
|
||||
|
||||
# Generate an executable elf, need to ignore undefined symbols
|
||||
LDELFFLAGS += --unresolved-symbols=ignore-in-object-files --emit-relocs
|
||||
endif
|
||||
|
||||
else
|
||||
ifneq ($(CONFIG_BINFMT_ELF_EXECUTABLE),y)
|
||||
LDELFFLAGS += -r
|
||||
|
|
|
|||
|
|
@ -39,6 +39,34 @@
|
|||
# define SECTIONS_ALIGN 4
|
||||
#endif
|
||||
|
||||
/* An FDPIC module is a shared object whose read-only and writable segments
|
||||
* the loader places independently: the read-only one runs where the
|
||||
* filesystem already holds it and only the writable one is copied to RAM,
|
||||
* once per running instance. So the two go into segments of their own, and
|
||||
* .dynamic is named, because a shared object is bound through it.
|
||||
*
|
||||
* Everything else is common, the symbols crt0.c walks included, so a module
|
||||
* is built and entered the same way whichever this is.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FDPIC
|
||||
# define PHDR_TEXT :text
|
||||
# define PHDR_DATA :data
|
||||
# define DATA_ALIGN . = ALIGN(0x1000);
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(5); /* Read and execute */
|
||||
data PT_LOAD FLAGS(6); /* Read and write */
|
||||
dynamic PT_DYNAMIC FLAGS(6);
|
||||
}
|
||||
|
||||
#else
|
||||
# define PHDR_TEXT
|
||||
# define PHDR_DATA
|
||||
# define DATA_ALIGN
|
||||
#endif
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text TEXT :
|
||||
|
|
@ -53,7 +81,7 @@ SECTIONS
|
|||
*(.jcr)
|
||||
. = ALIGN(SECTIONS_ALIGN);
|
||||
_etext = . ;
|
||||
}
|
||||
} PHDR_TEXT
|
||||
|
||||
.rodata :
|
||||
{
|
||||
|
|
@ -64,7 +92,9 @@ SECTIONS
|
|||
*(.gnu.linkonce.r*)
|
||||
. = ALIGN(SECTIONS_ALIGN);
|
||||
_erodata = . ;
|
||||
}
|
||||
} PHDR_TEXT
|
||||
|
||||
DATA_ALIGN
|
||||
|
||||
.data DATA :
|
||||
{
|
||||
|
|
@ -75,7 +105,7 @@ SECTIONS
|
|||
*(.gnu.linkonce.d*)
|
||||
. = ALIGN(SECTIONS_ALIGN);
|
||||
_edata = . ;
|
||||
}
|
||||
} PHDR_DATA
|
||||
|
||||
.init_array :
|
||||
{
|
||||
|
|
@ -86,7 +116,7 @@ SECTIONS
|
|||
. = ALIGN(SECTIONS_ALIGN);
|
||||
_einit = .;
|
||||
_ectors = .;
|
||||
}
|
||||
} PHDR_DATA
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
|
|
@ -98,7 +128,24 @@ SECTIONS
|
|||
. = ALIGN(SECTIONS_ALIGN);
|
||||
_efini = .;
|
||||
_edtors = .;
|
||||
}
|
||||
} PHDR_DATA
|
||||
|
||||
#ifdef CONFIG_FDPIC
|
||||
.dynamic :
|
||||
{
|
||||
*(.dynamic)
|
||||
} :data :dynamic
|
||||
#endif
|
||||
|
||||
.got :
|
||||
{
|
||||
*(.got*)
|
||||
} PHDR_DATA
|
||||
|
||||
/* .bss holds no file content, so it comes last. Everything ahead of it
|
||||
* has content, thus the writable segment's p_filesz stops where .bss
|
||||
* starts and the file does not carry it.
|
||||
*/
|
||||
|
||||
.bss :
|
||||
{
|
||||
|
|
@ -111,12 +158,7 @@ SECTIONS
|
|||
*(COMMON)
|
||||
. = ALIGN(SECTIONS_ALIGN);
|
||||
_ebss = . ;
|
||||
}
|
||||
|
||||
.got :
|
||||
{
|
||||
*(.got*)
|
||||
}
|
||||
} PHDR_DATA
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue