diff --git a/Kconfig b/Kconfig index 090ae6c0e67..17aa39e3aa2 100644 --- a/Kconfig +++ b/Kconfig @@ -329,6 +329,13 @@ config BUILD_KERNEL endchoice # Build configuration +config BUILD_PIC + bool "NuttX PIC build" + default n + ---help--- + Builds NuttX with position-independent code (PIC). This will allow + load NuttX into memory at any address and run it. + config BUILD_2PASS bool "Two pass build" default n diff --git a/arch/arm/include/arch.h b/arch/arm/include/arch.h index d511574e7dc..f64a6298eed 100644 --- a/arch/arm/include/arch.h +++ b/arch/arm/include/arch.h @@ -62,7 +62,7 @@ do { \ "\tmov %0, " PIC_REG_STRING "\n\t" \ : "=r"(picbase) \ ); \ - *ppicbase = (void *)picbase; \ + *(uint32_t *)ppicbase = picbase; \ } while (0) #define up_setpicbase(picbase) \ diff --git a/arch/arm/src/armv6-m/arm_initialstate.c b/arch/arm/src/armv6-m/arm_initialstate.c index 15b3bb74c45..f501ba700eb 100644 --- a/arch/arm/src/armv6-m/arm_initialstate.c +++ b/arch/arm/src/armv6-m/arm_initialstate.c @@ -104,6 +104,12 @@ void up_initial_state(struct tcb_s *tcb) xcp->regs[REG_XPSR] = ARMV6M_XPSR_T; + /* All tasks need set to pic address to special register */ + +#ifdef CONFIG_BUILD_PIC + __asm__ ("mov %0, r9" : "=r"(xcp->regs[REG_R9])); +#endif + /* If this task is running PIC, then set the PIC base register to the * address of the allocated D-Space region. */ diff --git a/arch/arm/src/armv7-m/arm_initialstate.c b/arch/arm/src/armv7-m/arm_initialstate.c index 4baec4aee41..ef8bbc939e7 100644 --- a/arch/arm/src/armv7-m/arm_initialstate.c +++ b/arch/arm/src/armv7-m/arm_initialstate.c @@ -111,6 +111,12 @@ void up_initial_state(struct tcb_s *tcb) xcp->regs[REG_XPSR] = ARMV7M_XPSR_T; + /* All tasks need set to pic address to special register */ + +#ifdef CONFIG_BUILD_PIC + __asm__ ("mov %0, r9" : "=r"(xcp->regs[REG_R9])); +#endif + /* If this task is running PIC, then set the PIC base register to the * address of the allocated D-Space region. */ diff --git a/arch/arm/src/armv8-m/arm_initialstate.c b/arch/arm/src/armv8-m/arm_initialstate.c index 4916fc36ea3..53a8cab0308 100644 --- a/arch/arm/src/armv8-m/arm_initialstate.c +++ b/arch/arm/src/armv8-m/arm_initialstate.c @@ -117,6 +117,12 @@ void up_initial_state(struct tcb_s *tcb) xcp->regs[REG_XPSR] = ARMV8M_XPSR_T; + /* All tasks need to set pic address to special register */ + +#ifdef CONFIG_BUILD_PIC + __asm__ ("mov %0, r9" : "=r"(xcp->regs[REG_R9])); +#endif + /* If this task is running PIC, then set the PIC base register to the * address of the allocated D-Space region. */ diff --git a/arch/arm/src/common/Toolchain.defs b/arch/arm/src/common/Toolchain.defs index 540e4405d40..5548aec7e7c 100644 --- a/arch/arm/src/common/Toolchain.defs +++ b/arch/arm/src/common/Toolchain.defs @@ -495,6 +495,14 @@ ifeq ($(CONFIG_LIBCXXTOOLCHAIN),y) EXTRA_LIBS += $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) --print-file-name=libstdc++.a)) endif +PICFLAGS = -fpic -fPIE -mno-pic-data-is-text-relative -msingle-pic-base + +ifneq ($(CONFIG_BUILD_PIC),) + ARCHCFLAGS += $(PICFLAGS) -mpic-register=r9 + ARCHCXXFLAGS += $(PICFLAGS) -mpic-register=r9 + LDFLAGS += --emit-relocs +endif + # Loadable module definitions CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs @@ -502,10 +510,13 @@ LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) # ELF module definitions +CELFFLAGS = $(CFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs +CXXELFFLAGS = $(CXXFLAGS)-fvisibility=hidden + ifeq ($(CONFIG_PIC),y) CFLAGS += --fixed-r10 - PICFLAGS = -fpic -fPIE -mno-pic-data-is-text-relative \ - -msingle-pic-base -mpic-register=r10 + CELFFLAGS += $(PICFLAGS) -mpic-register=r10 + CXXELFFLAGS += $(PICFLAGS) -mpic-register=r10 # Generate an executable elf, need to ignore undefined symbols LDELFFLAGS += --unresolved-symbols=ignore-in-object-files --emit-relocs @@ -513,9 +524,6 @@ else LDELFFLAGS += -r endif -CELFFLAGS = $(CFLAGS) $(PICFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs -CXXELFFLAGS = $(CXXFLAGS) $(PICFLAGS) -fvisibility=hidden - LDELFFLAGS += -e main -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld) # Zig toolchain