1 1.78 christos /* $NetBSD: mips_reloc.c,v 1.78 2024/11/30 01:04:05 christos Exp $ */ 2 1.1 mhitch 3 1.1 mhitch /* 4 1.1 mhitch * Copyright 1997 Michael L. Hitch <mhitch (at) montana.edu> 5 1.37 mycroft * Portions copyright 2002 Charles M. Hannum <root (at) ihack.net> 6 1.1 mhitch * All rights reserved. 7 1.1 mhitch * 8 1.1 mhitch * Redistribution and use in source and binary forms, with or without 9 1.1 mhitch * modification, are permitted provided that the following conditions 10 1.1 mhitch * are met: 11 1.1 mhitch * 1. Redistributions of source code must retain the above copyright 12 1.1 mhitch * notice, this list of conditions and the following disclaimer. 13 1.1 mhitch * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 mhitch * notice, this list of conditions and the following disclaimer in the 15 1.1 mhitch * documentation and/or other materials provided with the distribution. 16 1.1 mhitch * 3. The name of the author may not be used to endorse or promote products 17 1.1 mhitch * derived from this software without specific prior written permission. 18 1.1 mhitch * 19 1.1 mhitch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 1.1 mhitch * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 1.1 mhitch * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 mhitch * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 mhitch * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 1.1 mhitch * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 1.1 mhitch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 1.1 mhitch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 1.1 mhitch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 1.1 mhitch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 1.1 mhitch */ 30 1.1 mhitch 31 1.77 riastrad /* 32 1.77 riastrad * MIPS ELF relocations, for all ABIs: o32, n32, n64. 33 1.77 riastrad * 34 1.77 riastrad * References: 35 1.77 riastrad * 36 1.77 riastrad * [SYSVMIPS32ABI] System V Application Binary Interface: MIPS 37 1.77 riastrad * RISC Processor Supplement, 3rd ed., 1996. 38 1.77 riastrad * https://www.sco.com/developers/devspecs/mipsabi.pdf 39 1.77 riastrad * https://web.archive.org/web/20221026055746/http://www.sco.com/developers/devspecs/mipsabi.pdf 40 1.77 riastrad * 41 1.77 riastrad * [SGIMIPS64ELF] 64-bit ELF Object File Specification, Draft 42 1.77 riastrad * Version 2.5, MIPS Technologies / Silicon Graphics Computer 43 1.77 riastrad * Systems. Archived 2015-08-18. 44 1.77 riastrad * https://web.archive.org/web/20150818210955/http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf 45 1.77 riastrad */ 46 1.77 riastrad 47 1.48 skrll #include <sys/cdefs.h> 48 1.48 skrll #ifndef lint 49 1.78 christos __RCSID("$NetBSD: mips_reloc.c,v 1.78 2024/11/30 01:04:05 christos Exp $"); 50 1.48 skrll #endif /* not lint */ 51 1.48 skrll 52 1.1 mhitch #include <sys/types.h> 53 1.56 matt #include <sys/endian.h> 54 1.61 matt #include <sys/tls.h> 55 1.40 mrg 56 1.40 mrg #include <stdlib.h> 57 1.33 thorpej #include <string.h> 58 1.1 mhitch 59 1.1 mhitch #include "debug.h" 60 1.1 mhitch #include "rtld.h" 61 1.1 mhitch 62 1.78 christos #include <machine/lwp_private.h> 63 1.78 christos 64 1.56 matt #ifdef __mips_o32 65 1.36 mycroft #define SUPPORT_OLD_BROKEN_LD 66 1.56 matt #endif 67 1.36 mycroft 68 1.22 mycroft void _rtld_bind_start(void); 69 1.17 mycroft void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); 70 1.36 mycroft caddr_t _rtld_bind(Elf_Word, Elf_Addr, Elf_Addr, Elf_Addr); 71 1.6 mycroft 72 1.45 simonb /* 73 1.45 simonb * It is possible for the compiler to emit relocations for unaligned data. 74 1.45 simonb * We handle this situation with these inlines. 75 1.45 simonb */ 76 1.45 simonb 77 1.56 matt #if ELFSIZE == 64 78 1.56 matt /* 79 1.56 matt * ELF64 MIPS encodes the relocs uniquely. The first 32-bits of info contain 80 1.56 matt * the symbol index. The top 32-bits contain three relocation types encoded 81 1.56 matt * in big-endian integer with first relocation in LSB. This means for little 82 1.71 maya * endian we have to byte swap that integer (r_type). 83 1.56 matt */ 84 1.56 matt #define Elf_Sxword Elf64_Sxword 85 1.56 matt #define ELF_R_NXTTYPE_64_P(r_type) ((((r_type) >> 8) & 0xff) == R_TYPE(64)) 86 1.56 matt #if BYTE_ORDER == LITTLE_ENDIAN 87 1.56 matt #undef ELF_R_SYM 88 1.56 matt #undef ELF_R_TYPE 89 1.56 matt #define ELF_R_SYM(r_info) ((r_info) & 0xffffffff) 90 1.56 matt #define ELF_R_TYPE(r_info) bswap32((r_info) >> 32) 91 1.56 matt #endif 92 1.56 matt #else 93 1.56 matt #define ELF_R_NXTTYPE_64_P(r_type) (0) 94 1.56 matt #define Elf_Sxword Elf32_Sword 95 1.56 matt #endif 96 1.60 matt #define GOT1_MASK (~(Elf_Addr)0 >> 1) 97 1.56 matt 98 1.56 matt static inline Elf_Sxword 99 1.56 matt load_ptr(void *where, size_t len) 100 1.45 simonb { 101 1.56 matt Elf_Sxword val; 102 1.45 simonb 103 1.56 matt if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) { 104 1.56 matt #if ELFSIZE == 64 105 1.56 matt if (len == sizeof(Elf_Sxword)) 106 1.56 matt return *(Elf_Sxword *)where; 107 1.56 matt #endif 108 1.56 matt return *(Elf_Sword *)where; 109 1.52 simonb } 110 1.56 matt 111 1.56 matt val = 0; 112 1.56 matt #if BYTE_ORDER == LITTLE_ENDIAN 113 1.56 matt (void)memcpy(&val, where, len); 114 1.56 matt #endif 115 1.56 matt #if BYTE_ORDER == BIG_ENDIAN 116 1.73 christos uint8_t *valp = (void *)&val; 117 1.73 christos (void)memcpy(valp + sizeof(val) - len, where, len); 118 1.56 matt #endif 119 1.56 matt return (len == sizeof(Elf_Sxword)) ? val : (Elf_Sword)val; 120 1.45 simonb } 121 1.45 simonb 122 1.49 perry static inline void 123 1.56 matt store_ptr(void *where, Elf_Sxword val, size_t len) 124 1.45 simonb { 125 1.56 matt if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) { 126 1.56 matt #if ELFSIZE == 64 127 1.56 matt if (len == sizeof(Elf_Sxword)) { 128 1.56 matt *(Elf_Sxword *)where = val; 129 1.56 matt return; 130 1.56 matt } 131 1.56 matt #endif 132 1.56 matt *(Elf_Sword *)where = val; 133 1.56 matt return; 134 1.56 matt } 135 1.56 matt #if BYTE_ORDER == LITTLE_ENDIAN 136 1.56 matt (void)memcpy(where, &val, len); 137 1.56 matt #endif 138 1.56 matt #if BYTE_ORDER == BIG_ENDIAN 139 1.73 christos const uint8_t *valp = (const void *)&val; 140 1.73 christos (void)memcpy(where, valp + sizeof(val) - len, len); 141 1.56 matt #endif 142 1.45 simonb } 143 1.45 simonb 144 1.45 simonb 145 1.1 mhitch void 146 1.39 skrll _rtld_setup_pltgot(const Obj_Entry *obj) 147 1.1 mhitch { 148 1.6 mycroft obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start; 149 1.6 mycroft /* XXX only if obj->pltgot[1] & 0x80000000 ?? */ 150 1.74 christos obj->pltgot[1] = (Elf_Addr) obj; 151 1.8 mycroft } 152 1.8 mycroft 153 1.17 mycroft void 154 1.39 skrll _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) 155 1.17 mycroft { 156 1.17 mycroft const Elf_Rel *rel = 0, *rellim; 157 1.17 mycroft Elf_Addr relsz = 0; 158 1.52 simonb void *where; 159 1.47 he const Elf_Sym *symtab = NULL, *sym; 160 1.47 he Elf_Addr *got = NULL; 161 1.56 matt Elf_Word local_gotno = 0, symtabno = 0, gotsym = 0; 162 1.56 matt size_t i; 163 1.17 mycroft 164 1.17 mycroft for (; dynp->d_tag != DT_NULL; dynp++) { 165 1.17 mycroft switch (dynp->d_tag) { 166 1.17 mycroft case DT_REL: 167 1.17 mycroft rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr); 168 1.17 mycroft break; 169 1.17 mycroft case DT_RELSZ: 170 1.17 mycroft relsz = dynp->d_un.d_val; 171 1.17 mycroft break; 172 1.17 mycroft case DT_SYMTAB: 173 1.17 mycroft symtab = (const Elf_Sym *)(relocbase + dynp->d_un.d_ptr); 174 1.17 mycroft break; 175 1.18 mycroft case DT_PLTGOT: 176 1.18 mycroft got = (Elf_Addr *)(relocbase + dynp->d_un.d_ptr); 177 1.18 mycroft break; 178 1.18 mycroft case DT_MIPS_LOCAL_GOTNO: 179 1.18 mycroft local_gotno = dynp->d_un.d_val; 180 1.18 mycroft break; 181 1.18 mycroft case DT_MIPS_SYMTABNO: 182 1.18 mycroft symtabno = dynp->d_un.d_val; 183 1.18 mycroft break; 184 1.18 mycroft case DT_MIPS_GOTSYM: 185 1.18 mycroft gotsym = dynp->d_un.d_val; 186 1.18 mycroft break; 187 1.17 mycroft } 188 1.17 mycroft } 189 1.34 mycroft 190 1.34 mycroft i = (got[1] & 0x80000000) ? 2 : 1; 191 1.34 mycroft /* Relocate the local GOT entries */ 192 1.34 mycroft got += i; 193 1.34 mycroft for (; i < local_gotno; i++) 194 1.34 mycroft *got++ += relocbase; 195 1.34 mycroft sym = symtab + gotsym; 196 1.34 mycroft /* Now do the global GOT entries */ 197 1.34 mycroft for (i = gotsym; i < symtabno; i++) { 198 1.34 mycroft *got = sym->st_value + relocbase; 199 1.34 mycroft ++sym; 200 1.34 mycroft ++got; 201 1.34 mycroft } 202 1.34 mycroft 203 1.56 matt rellim = (const Elf_Rel *)((uintptr_t)rel + relsz); 204 1.17 mycroft for (; rel < rellim; rel++) { 205 1.56 matt Elf_Word r_symndx, r_type; 206 1.56 matt 207 1.52 simonb where = (void *)(relocbase + rel->r_offset); 208 1.17 mycroft 209 1.56 matt r_symndx = ELF_R_SYM(rel->r_info); 210 1.56 matt r_type = ELF_R_TYPE(rel->r_info); 211 1.56 matt 212 1.56 matt switch (r_type & 0xff) { 213 1.56 matt case R_TYPE(REL32): { 214 1.56 matt const size_t rlen = 215 1.56 matt ELF_R_NXTTYPE_64_P(r_type) 216 1.56 matt ? sizeof(Elf_Sxword) 217 1.56 matt : sizeof(Elf_Sword); 218 1.56 matt Elf_Sxword old = load_ptr(where, rlen); 219 1.56 matt Elf_Sxword val = old; 220 1.56 matt #if ELFSIZE == 64 221 1.56 matt assert(r_type == R_TYPE(REL32) 222 1.56 matt || r_type == (R_TYPE(REL32)|(R_TYPE(64) << 8))); 223 1.56 matt #endif 224 1.56 matt assert(r_symndx < gotsym); 225 1.56 matt sym = symtab + r_symndx; 226 1.56 matt assert(ELF_ST_BIND(sym->st_info) == STB_LOCAL); 227 1.56 matt val += relocbase; 228 1.56 matt store_ptr(where, val, sizeof(Elf_Sword)); 229 1.56 matt rdbg(("REL32/L(%p) %p -> %p in <self>", 230 1.56 matt where, (void *)old, (void *)val)); 231 1.56 matt store_ptr(where, val, rlen); 232 1.56 matt break; 233 1.56 matt } 234 1.56 matt 235 1.56 matt case R_TYPE(GPREL32): 236 1.17 mycroft case R_TYPE(NONE): 237 1.17 mycroft break; 238 1.17 mycroft 239 1.17 mycroft 240 1.17 mycroft default: 241 1.17 mycroft abort(); 242 1.17 mycroft } 243 1.17 mycroft } 244 1.17 mycroft } 245 1.17 mycroft 246 1.8 mycroft int 247 1.59 joerg _rtld_relocate_nonplt_objects(Obj_Entry *obj) 248 1.8 mycroft { 249 1.9 mycroft const Elf_Rel *rel; 250 1.18 mycroft Elf_Addr *got = obj->pltgot; 251 1.67 joerg const Elf_Sym *sym, *def = NULL; 252 1.67 joerg const Obj_Entry *defobj = NULL; 253 1.66 joerg unsigned long last_symnum = ULONG_MAX; 254 1.54 christos Elf_Word i; 255 1.36 mycroft #ifdef SUPPORT_OLD_BROKEN_LD 256 1.36 mycroft int broken; 257 1.36 mycroft #endif 258 1.36 mycroft 259 1.36 mycroft #ifdef SUPPORT_OLD_BROKEN_LD 260 1.36 mycroft broken = 0; 261 1.36 mycroft sym = obj->symtab; 262 1.36 mycroft for (i = 1; i < 12; i++) 263 1.36 mycroft if (sym[i].st_info == ELF_ST_INFO(STB_LOCAL, STT_NOTYPE)) 264 1.36 mycroft broken = 1; 265 1.36 mycroft dbg(("%s: broken=%d", obj->path, broken)); 266 1.36 mycroft #endif 267 1.17 mycroft 268 1.34 mycroft i = (got[1] & 0x80000000) ? 2 : 1; 269 1.34 mycroft /* Relocate the local GOT entries */ 270 1.34 mycroft got += i; 271 1.34 mycroft for (; i < obj->local_gotno; i++) 272 1.34 mycroft *got++ += (Elf_Addr)obj->relocbase; 273 1.34 mycroft sym = obj->symtab + obj->gotsym; 274 1.34 mycroft /* Now do the global GOT entries */ 275 1.34 mycroft for (i = obj->gotsym; i < obj->symtabno; i++) { 276 1.56 matt rdbg((" doing got %d sym %p (%s, %lx)", i - obj->gotsym, sym, 277 1.56 matt sym->st_name + obj->strtab, (u_long) *got)); 278 1.34 mycroft 279 1.36 mycroft #ifdef SUPPORT_OLD_BROKEN_LD 280 1.34 mycroft if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && 281 1.36 mycroft broken && sym->st_shndx == SHN_UNDEF) { 282 1.34 mycroft /* 283 1.34 mycroft * XXX DANGER WILL ROBINSON! 284 1.34 mycroft * You might think this is stupid, as it intentionally 285 1.34 mycroft * defeats lazy binding -- and you'd be right. 286 1.34 mycroft * Unfortunately, for lazy binding to work right, we 287 1.34 mycroft * need to a way to force the GOT slots used for 288 1.34 mycroft * function pointers to be resolved immediately. This 289 1.34 mycroft * is supposed to be done automatically by the linker, 290 1.34 mycroft * by not outputting a PLT slot and setting st_value 291 1.36 mycroft * to 0 if there are non-PLT references, but older 292 1.36 mycroft * versions of GNU ld do not do this. 293 1.34 mycroft */ 294 1.38 skrll def = _rtld_find_symdef(i, obj, &defobj, false); 295 1.34 mycroft if (def == NULL) 296 1.34 mycroft return -1; 297 1.34 mycroft *got = def->st_value + (Elf_Addr)defobj->relocbase; 298 1.36 mycroft } else 299 1.36 mycroft #endif 300 1.36 mycroft if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && 301 1.41 mycroft sym->st_value != 0 && sym->st_shndx == SHN_UNDEF) { 302 1.34 mycroft /* 303 1.34 mycroft * If there are non-PLT references to the function, 304 1.34 mycroft * st_value should be 0, forcing us to resolve the 305 1.34 mycroft * address immediately. 306 1.41 mycroft * 307 1.41 mycroft * XXX DANGER WILL ROBINSON! 308 1.41 mycroft * The linker is not outputting PLT slots for calls to 309 1.41 mycroft * functions that are defined in the same shared 310 1.42 mycroft * library. This is a bug, because it can screw up 311 1.42 mycroft * link ordering rules if the symbol is defined in 312 1.42 mycroft * more than one module. For now, if there is a 313 1.42 mycroft * definition, we fail the test above and force a full 314 1.44 mycroft * symbol lookup. This means that all intra-module 315 1.44 mycroft * calls are bound immediately. - mycroft, 2003/09/24 316 1.34 mycroft */ 317 1.34 mycroft *got = sym->st_value + (Elf_Addr)obj->relocbase; 318 1.34 mycroft } else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) { 319 1.34 mycroft /* Symbols with index SHN_ABS are not relocated. */ 320 1.34 mycroft if (sym->st_shndx != SHN_ABS) 321 1.34 mycroft *got = sym->st_value + 322 1.34 mycroft (Elf_Addr)obj->relocbase; 323 1.34 mycroft } else { 324 1.38 skrll def = _rtld_find_symdef(i, obj, &defobj, false); 325 1.34 mycroft if (def == NULL) 326 1.34 mycroft return -1; 327 1.34 mycroft *got = def->st_value + (Elf_Addr)defobj->relocbase; 328 1.34 mycroft } 329 1.34 mycroft 330 1.56 matt rdbg((" --> now %lx", (u_long) *got)); 331 1.34 mycroft ++sym; 332 1.34 mycroft ++got; 333 1.34 mycroft } 334 1.34 mycroft 335 1.34 mycroft got = obj->pltgot; 336 1.9 mycroft for (rel = obj->rel; rel < obj->rellim; rel++) { 337 1.66 joerg unsigned long symnum; 338 1.52 simonb void *where; 339 1.9 mycroft 340 1.52 simonb where = obj->relocbase + rel->r_offset; 341 1.9 mycroft 342 1.72 christos switch (ELF_R_TYPE(rel->r_info) & 0xff) { 343 1.66 joerg #if ELFSIZE == 64 344 1.66 joerg case R_TYPE(TLS_DTPMOD64): 345 1.66 joerg case R_TYPE(TLS_DTPREL64): 346 1.66 joerg case R_TYPE(TLS_TPREL64): 347 1.66 joerg #else 348 1.76 riastrad case R_TYPE(TLS_DTPMOD32): 349 1.66 joerg case R_TYPE(TLS_DTPREL32): 350 1.66 joerg case R_TYPE(TLS_TPREL32): 351 1.66 joerg #endif 352 1.67 joerg symnum = ELF_R_SYM(rel->r_info); 353 1.66 joerg if (last_symnum != symnum) { 354 1.66 joerg last_symnum = symnum; 355 1.66 joerg def = _rtld_find_symdef(symnum, obj, &defobj, 356 1.66 joerg false); 357 1.66 joerg if (def == NULL) 358 1.66 joerg return -1; 359 1.66 joerg } 360 1.66 joerg break; 361 1.66 joerg default: 362 1.66 joerg break; 363 1.66 joerg } 364 1.66 joerg 365 1.72 christos switch (ELF_R_TYPE(rel->r_info) & 0xff) { 366 1.9 mycroft case R_TYPE(NONE): 367 1.9 mycroft break; 368 1.9 mycroft 369 1.56 matt case R_TYPE(REL32): { 370 1.9 mycroft /* 32-bit PC-relative reference */ 371 1.67 joerg const Elf_Sym *def2; 372 1.56 matt const size_t rlen = 373 1.68 joerg ELF_R_NXTTYPE_64_P(ELF_R_TYPE(rel->r_info)) 374 1.56 matt ? sizeof(Elf_Sxword) 375 1.56 matt : sizeof(Elf_Sword); 376 1.56 matt Elf_Sxword old = load_ptr(where, rlen); 377 1.56 matt Elf_Sxword val = old; 378 1.56 matt 379 1.67 joerg def2 = obj->symtab + ELF_R_SYM(rel->r_info); 380 1.56 matt 381 1.67 joerg if (ELF_R_SYM(rel->r_info) >= obj->gotsym) { 382 1.67 joerg val += got[obj->local_gotno + 383 1.67 joerg ELF_R_SYM(rel->r_info) - obj->gotsym]; 384 1.56 matt rdbg(("REL32/G(%p) %p --> %p (%s) in %s", 385 1.56 matt where, (void *)old, (void *)val, 386 1.67 joerg obj->strtab + def2->st_name, 387 1.56 matt obj->path)); 388 1.34 mycroft } else { 389 1.9 mycroft /* 390 1.9 mycroft * XXX: ABI DIFFERENCE! 391 1.9 mycroft * 392 1.9 mycroft * Old NetBSD binutils would generate shared 393 1.9 mycroft * libs with section-relative relocations being 394 1.9 mycroft * already adjusted for the start address of 395 1.9 mycroft * the section. 396 1.9 mycroft * 397 1.9 mycroft * New binutils, OTOH, generate shared libs 398 1.9 mycroft * with the same relocations being based at 399 1.9 mycroft * zero, so we need to add in the start address 400 1.9 mycroft * of the section. 401 1.9 mycroft * 402 1.9 mycroft * --rkb, Oct 6, 2001 403 1.9 mycroft */ 404 1.34 mycroft 405 1.67 joerg if (def2->st_info == 406 1.36 mycroft ELF_ST_INFO(STB_LOCAL, STT_SECTION) 407 1.36 mycroft #ifdef SUPPORT_OLD_BROKEN_LD 408 1.36 mycroft && !broken 409 1.36 mycroft #endif 410 1.36 mycroft ) 411 1.56 matt val += (Elf_Addr)def->st_value; 412 1.9 mycroft 413 1.56 matt val += (Elf_Addr)obj->relocbase; 414 1.9 mycroft 415 1.56 matt rdbg(("REL32/L(%p) %p -> %p (%s) in %s", 416 1.56 matt where, (void *)old, (void *)val, 417 1.67 joerg obj->strtab + def2->st_name, obj->path)); 418 1.9 mycroft } 419 1.56 matt store_ptr(where, val, rlen); 420 1.9 mycroft break; 421 1.56 matt } 422 1.9 mycroft 423 1.61 matt #if ELFSIZE == 64 424 1.61 matt case R_TYPE(TLS_DTPMOD64): 425 1.61 matt #else 426 1.76 riastrad case R_TYPE(TLS_DTPMOD32): 427 1.61 matt #endif 428 1.61 matt { 429 1.61 matt Elf_Addr old = load_ptr(where, ELFSIZE / 8); 430 1.61 matt Elf_Addr val = old; 431 1.61 matt 432 1.61 matt val += (Elf_Addr)defobj->tlsindex; 433 1.61 matt 434 1.61 matt store_ptr(where, val, ELFSIZE / 8); 435 1.61 matt rdbg(("DTPMOD %s in %s --> %p in %s", 436 1.70 maya obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name, 437 1.61 matt obj->path, (void *)old, defobj->path)); 438 1.61 matt break; 439 1.61 matt } 440 1.61 matt 441 1.61 matt #if ELFSIZE == 64 442 1.61 matt case R_TYPE(TLS_DTPREL64): 443 1.61 matt #else 444 1.61 matt case R_TYPE(TLS_DTPREL32): 445 1.61 matt #endif 446 1.61 matt { 447 1.61 matt Elf_Addr old = load_ptr(where, ELFSIZE / 8); 448 1.61 matt Elf_Addr val = old; 449 1.61 matt 450 1.61 matt val += (Elf_Addr)def->st_value - TLS_DTV_OFFSET; 451 1.61 matt store_ptr(where, val, ELFSIZE / 8); 452 1.61 matt 453 1.61 matt rdbg(("DTPREL %s in %s --> %p in %s", 454 1.70 maya obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name, 455 1.61 matt obj->path, (void *)old, defobj->path)); 456 1.61 matt break; 457 1.61 matt } 458 1.61 matt 459 1.61 matt #if ELFSIZE == 64 460 1.61 matt case R_TYPE(TLS_TPREL64): 461 1.61 matt #else 462 1.61 matt case R_TYPE(TLS_TPREL32): 463 1.61 matt #endif 464 1.61 matt { 465 1.61 matt Elf_Addr old = load_ptr(where, ELFSIZE / 8); 466 1.61 matt Elf_Addr val = old; 467 1.61 matt 468 1.75 joerg if (!defobj->tls_static && 469 1.75 joerg _rtld_tls_offset_allocate(__UNCONST(defobj))) 470 1.61 matt return -1; 471 1.61 matt 472 1.61 matt val += (Elf_Addr)(def->st_value + defobj->tlsoffset 473 1.61 matt - TLS_TP_OFFSET); 474 1.61 matt store_ptr(where, val, ELFSIZE / 8); 475 1.61 matt 476 1.61 matt rdbg(("TPREL %s in %s --> %p in %s", 477 1.70 maya obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name, 478 1.65 christos obj->path, where, defobj->path)); 479 1.61 matt break; 480 1.61 matt } 481 1.61 matt 482 1.9 mycroft default: 483 1.23 mycroft rdbg(("sym = %lu, type = %lu, offset = %p, " 484 1.9 mycroft "contents = %p, symbol = %s", 485 1.66 joerg (u_long)ELF_R_SYM(rel->r_info), 486 1.66 joerg (u_long)ELF_R_TYPE(rel->r_info), 487 1.56 matt (void *)rel->r_offset, 488 1.56 matt (void *)load_ptr(where, sizeof(Elf_Sword)), 489 1.70 maya obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name)); 490 1.9 mycroft _rtld_error("%s: Unsupported relocation type %ld " 491 1.55 jmmv "in non-PLT relocations", 492 1.9 mycroft obj->path, (u_long) ELF_R_TYPE(rel->r_info)); 493 1.9 mycroft return -1; 494 1.8 mycroft } 495 1.18 mycroft } 496 1.18 mycroft 497 1.8 mycroft return 0; 498 1.8 mycroft } 499 1.8 mycroft 500 1.8 mycroft int 501 1.69 joerg _rtld_relocate_plt_lazy(Obj_Entry *obj) 502 1.13 mycroft { 503 1.31 mycroft /* PLT fixups were done above in the GOT relocation. */ 504 1.28 mycroft return 0; 505 1.36 mycroft } 506 1.36 mycroft 507 1.50 skrll static inline int 508 1.50 skrll _rtld_relocate_plt_object(const Obj_Entry *obj, Elf_Word sym, Elf_Addr *tp) 509 1.36 mycroft { 510 1.50 skrll Elf_Addr *got = obj->pltgot; 511 1.36 mycroft const Elf_Sym *def; 512 1.36 mycroft const Obj_Entry *defobj; 513 1.36 mycroft Elf_Addr new_value; 514 1.36 mycroft 515 1.57 christos def = _rtld_find_plt_symdef(sym, obj, &defobj, tp != NULL); 516 1.57 christos if (__predict_false(def == NULL)) 517 1.50 skrll return -1; 518 1.57 christos if (__predict_false(def == &_rtld_sym_zero)) 519 1.57 christos return 0; 520 1.36 mycroft 521 1.63 joerg if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 522 1.63 joerg if (tp == NULL) 523 1.63 joerg return 0; 524 1.63 joerg new_value = _rtld_resolve_ifunc(defobj, def); 525 1.63 joerg } else { 526 1.63 joerg new_value = (Elf_Addr)(defobj->relocbase + def->st_value); 527 1.63 joerg } 528 1.36 mycroft rdbg(("bind now/fixup in %s --> new=%p", 529 1.36 mycroft defobj->strtab + def->st_name, (void *)new_value)); 530 1.50 skrll got[obj->local_gotno + sym - obj->gotsym] = new_value; 531 1.50 skrll 532 1.50 skrll if (tp) 533 1.50 skrll *tp = new_value; 534 1.50 skrll return 0; 535 1.50 skrll } 536 1.50 skrll 537 1.50 skrll caddr_t 538 1.50 skrll _rtld_bind(Elf_Word a0, Elf_Addr a1, Elf_Addr a2, Elf_Addr a3) 539 1.50 skrll { 540 1.50 skrll Elf_Addr *got = (Elf_Addr *)(a2 - 0x7ff0); 541 1.60 matt const Obj_Entry *obj = (Obj_Entry *)(got[1] & GOT1_MASK); 542 1.58 skrll Elf_Addr new_value = 0; /* XXX gcc */ 543 1.50 skrll int err; 544 1.50 skrll 545 1.62 joerg _rtld_shared_enter(); 546 1.50 skrll err = _rtld_relocate_plt_object(obj, a0, &new_value); 547 1.57 christos if (err) 548 1.50 skrll _rtld_die(); 549 1.62 joerg _rtld_shared_exit(); 550 1.50 skrll 551 1.50 skrll return (caddr_t)new_value; 552 1.50 skrll } 553 1.50 skrll 554 1.50 skrll int 555 1.50 skrll _rtld_relocate_plt_objects(const Obj_Entry *obj) 556 1.50 skrll { 557 1.50 skrll const Elf_Sym *sym = obj->symtab + obj->gotsym; 558 1.54 christos Elf_Word i; 559 1.50 skrll 560 1.50 skrll for (i = obj->gotsym; i < obj->symtabno; i++, sym++) { 561 1.50 skrll if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) 562 1.50 skrll if (_rtld_relocate_plt_object(obj, i, NULL) < 0) 563 1.50 skrll return -1; 564 1.50 skrll } 565 1.50 skrll 566 1.50 skrll return 0; 567 1.1 mhitch } 568