static pie: fix building static PDE
[uclibc-ng.git] / libc / misc / internals / reloc_static_pie.c
blobce42cb9b30dff5a013d815e64767b696a0048375
1 /* Support for relocating static PIE.
2 Copyright (C) 2017-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18 #define IS_IN_rtld // force inline function calls
19 #include <link.h>
20 #include <elf.h>
21 #include <dl-elf.h>
23 #include <ldso.h>
24 #ifdef __mips__
25 #include <dl-startup.h>
26 #endif
28 extern ElfW(Addr) _dl_load_base;
30 void
31 reloc_static_pie (ElfW(Addr) load_addr);
33 void
34 reloc_static_pie(ElfW(Addr) load_addr)
36 int indx;
37 ElfW(Addr) got;
38 ElfW(Dyn) *dpnt;
39 struct elf_resolve tpnt_tmp;
40 struct elf_resolve *tpnt = &tpnt_tmp;
42 DL_BOOT_COMPUTE_GOT(got);
43 DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr);
45 _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
46 tpnt->loadaddr = load_addr;
47 tpnt->dynamic_addr = dpnt;
49 __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
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
57 #if defined(ELF_MACHINE_PLTREL_OVERLAP)
58 # define INDX_MAX 1
59 #else
60 # define INDX_MAX 2
61 #endif
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];
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]);
72 if (!rel_addr)
73 continue;
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);
81 #ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS
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;
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);
103 /* Use this machine-specific macro to perform the actual relocation. */
104 PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
107 #endif
109 _dl_load_base = load_addr;