Révision | 365da5ab379a3e38e196cad370695c4b300cfe51 (tree) |
---|---|
l'heure | 2022-09-07 15:32:47 |
Auteur | linted <linted@user...> |
Commiter | Waldemar Brodkorb |
Added support for creation of Static Position-Independent Executables (PIE) on mips
Updated config to allow compilation of rcrt1.o for mips and modified it's crt1.S to perform relocates in start.
The mips architecture performs relocations differently then most other architectures. reloc_static_pie was rewritten, taking code from dl-startup.c, in order to perfrom the additional relocations. Modifications were made to mips' dl-startup.h to allow for the use of contained macros without including _start definition.
Signed-off-by: linted <linted@users.noreply.github.com>
@@ -324,7 +324,7 @@ config DOPIC | ||
324 | 324 | config STATIC_PIE |
325 | 325 | bool "Add support for Static Position Independent Executables (PIE)" |
326 | 326 | default n |
327 | - depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64) | |
327 | + depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || TARGET_mips) | |
328 | 328 | |
329 | 329 | config ARCH_HAS_NO_SHARED |
330 | 330 | bool |
@@ -7,6 +7,7 @@ | ||
7 | 7 | |
8 | 8 | |
9 | 9 | #include <sgidefs.h> |
10 | +#ifndef L_rcrt1 | |
10 | 11 | __asm__("" |
11 | 12 | " .text\n" |
12 | 13 | " .globl _start\n" |
@@ -114,6 +115,7 @@ __asm__("" | ||
114 | 115 | "\n\n" |
115 | 116 | ".previous\n" |
116 | 117 | ); |
118 | +#endif | |
117 | 119 | |
118 | 120 | /* |
119 | 121 | * Get a pointer to the argv array. On many platforms this can be just |
@@ -191,6 +193,5 @@ do { \ | ||
191 | 193 | case R_MIPS_NONE: \ |
192 | 194 | break; \ |
193 | 195 | default: \ |
194 | - SEND_STDERR("Aiieeee!"); \ | |
195 | 196 | _dl_exit(1); \ |
196 | 197 | } |
@@ -17,7 +17,7 @@ MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC-y)) | ||
17 | 17 | MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC-y)) |
18 | 18 | |
19 | 19 | CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS) |
20 | -CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) | |
20 | +CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) -DL_rcrt1 | |
21 | 21 | |
22 | 22 | libc-y += $(MISC_INTERNALS_OBJ) |
23 | 23 | ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y) |
@@ -15,33 +15,96 @@ | ||
15 | 15 | You should have received a copy of the GNU Lesser General Public |
16 | 16 | License along with the GNU C Library; if not, see |
17 | 17 | <https://www.gnu.org/licenses/>. */ |
18 | - | |
18 | +#define IS_IN_rtld // force inline function calls | |
19 | 19 | #include <link.h> |
20 | 20 | #include <elf.h> |
21 | 21 | #include <dl-elf.h> |
22 | 22 | |
23 | +#include <ldso.h> | |
24 | +#ifdef __mips__ | |
25 | +#include <dl-startup.h> | |
26 | +#endif | |
27 | + | |
23 | 28 | ElfW(Addr) _dl_load_base = NULL; |
24 | 29 | |
25 | 30 | void |
26 | 31 | reloc_static_pie (ElfW(Addr) load_addr); |
27 | 32 | |
28 | 33 | void |
29 | -reloc_static_pie (ElfW(Addr) load_addr) | |
34 | +reloc_static_pie(ElfW(Addr) load_addr) | |
30 | 35 | { |
31 | - ElfW(Word) relative_count = 0; | |
32 | - ElfW(Addr) rel_addr = 0; | |
33 | - ElfW(Dyn) * dyn_addr = NULL; | |
34 | - unsigned long dynamic_info[DYNAMIC_SIZE] = {0}; | |
36 | + int indx; | |
37 | + ElfW(Addr) got; | |
38 | + ElfW(Dyn) *dpnt; | |
39 | + struct elf_resolve tpnt_tmp; | |
40 | + struct elf_resolve *tpnt = &tpnt_tmp; | |
41 | + | |
42 | + DL_BOOT_COMPUTE_GOT(got); | |
43 | + DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr); | |
44 | + | |
45 | + _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); | |
46 | + tpnt->loadaddr = load_addr; | |
47 | + tpnt->dynamic_addr = dpnt; | |
48 | + | |
49 | + __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); | |
50 | + | |
51 | +#if defined(PERFORM_BOOTSTRAP_GOT) | |
52 | + /* some arches (like MIPS) we have to tweak the GOT before relocations */ | |
53 | + PERFORM_BOOTSTRAP_GOT(tpnt); | |
54 | +#endif | |
55 | + | |
56 | + | |
57 | +#if defined(ELF_MACHINE_PLTREL_OVERLAP) | |
58 | +# define INDX_MAX 1 | |
59 | +#else | |
60 | +# define INDX_MAX 2 | |
61 | +#endif | |
62 | + | |
63 | + for (indx = 0; indx < INDX_MAX; indx++) { | |
64 | + unsigned long rel_addr, rel_size; | |
65 | + ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; | |
66 | + | |
67 | + rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : | |
68 | + tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]); | |
69 | + rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : | |
70 | + tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]); | |
71 | + | |
72 | + if (!rel_addr) | |
73 | + continue; | |
35 | 74 | |
36 | - /* Read our own dynamic section and fill in the info array. */ | |
37 | - dyn_addr = ((void *) load_addr + elf_machine_dynamic ()); | |
75 | + if((0 == indx) && relative_count) { | |
76 | + rel_size -= relative_count * sizeof(ELF_RELOC); | |
77 | + elf_machine_relative(load_addr, rel_addr, relative_count); | |
78 | + rel_addr += relative_count * sizeof(ELF_RELOC); | |
79 | + } | |
38 | 80 | |
39 | - /* Use the underlying function to avoid TLS access before initialization */ | |
40 | - __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr); | |
81 | +#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS | |
82 | + { | |
83 | + ELF_RELOC *rpnt; | |
84 | + unsigned int i; | |
85 | + ElfW(Sym) *sym; | |
86 | + unsigned long symbol_addr; | |
87 | + int symtab_index; | |
88 | + unsigned long *reloc_addr; | |
41 | 89 | |
42 | - /* Perform relocations */ | |
43 | - relative_count = dynamic_info[DT_RELCONT_IDX]; | |
44 | - rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR]; | |
45 | - elf_machine_relative(load_addr, rel_addr, relative_count); | |
90 | + /* Now parse the relocation information */ | |
91 | + rpnt = (ELF_RELOC *) rel_addr; | |
92 | + for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { | |
93 | + reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset); | |
94 | + symtab_index = ELF_R_SYM(rpnt->r_info); | |
95 | + symbol_addr = 0; | |
96 | + sym = NULL; | |
97 | + if (symtab_index) { | |
98 | + ElfW(Sym) *symtab; | |
99 | + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; | |
100 | + sym = &symtab[symtab_index]; | |
101 | + symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value); | |
102 | + } | |
103 | + /* Use this machine-specific macro to perform the actual relocation. */ | |
104 | + PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym); | |
105 | + } | |
106 | + } | |
107 | +#endif | |
108 | + } | |
46 | 109 | _dl_load_base = load_addr; |
47 | -} | |
110 | +} | |
\ No newline at end of file |
@@ -78,6 +78,10 @@ | ||
78 | 78 | .weak _init |
79 | 79 | .weak _fini |
80 | 80 | #endif |
81 | +#ifdef L_rcrt1 | |
82 | + .type reloc_static_pie,@function | |
83 | + .hidden .L0 | |
84 | +#endif | |
81 | 85 | .type main,@function |
82 | 86 | .type __uClibc_main,@function |
83 | 87 | .ent __start |
@@ -90,6 +94,25 @@ __start: | ||
90 | 94 | PTR_LA $28, _gp /* Setup GP correctly if we're non-PIC. */ |
91 | 95 | move $31, $0 |
92 | 96 | #endif |
97 | +#ifdef L_rcrt1 | |
98 | + PTR_LA $4, _DYNAMIC /* Place _DYNAMIC into the GOT */ | |
99 | + REG_S $4, -0x7ff0($28) /* offset to GOT stolen from dl-startup */ | |
100 | + jal .L0 /* Get the current $pc address */ | |
101 | +.L0: | |
102 | + PTR_SUBU $4, $31, $25 /* Calculate load addr */ | |
103 | + move $31, $0 /* Clear ra */ | |
104 | + and $29, -2 * SZREG /* Ensure stack is aligned */ | |
105 | + PTR_ADDIU $29, (-2 * SZREG) /* Allocate 2 register spaces on stack */ | |
106 | + REG_S $2, SZREG($29) /* Store atexit in case it exists */ | |
107 | + PTR_LA $5, reloc_static_pie /* function calls before relocation | |
108 | + don't work unless we set $t9 manually */ | |
109 | + PTR_ADDU $25, $4, $5 /* store reloc_static_pie in $t9 */ | |
110 | + jalr $25 /* call reloc_static_pie */ | |
111 | + nop /* delay slot, just in case */ | |
112 | + REG_L $2, SZREG($29) /* cleanup stack */ | |
113 | + PTR_ADDIU $29, $29, (2 * SZREG) | |
114 | + | |
115 | +#endif | |
93 | 116 | |
94 | 117 | PTR_LA $4, main /* main */ |
95 | 118 | PTR_L $5, 0($29) /* argc */ |