1*c8754c30Sguenther /* $OpenBSD: rtld_machine.c,v 1.38 2019/11/28 16:54:29 guenther Exp $ */ 2672d3582Sdrahn 3672d3582Sdrahn /* 4672d3582Sdrahn * Copyright (c) 2002,2004 Dale Rahn 5672d3582Sdrahn * Copyright (c) 2001 Niklas Hallqvist 6672d3582Sdrahn * Copyright (c) 2001 Artur Grabowski 7672d3582Sdrahn * 8672d3582Sdrahn * Redistribution and use in source and binary forms, with or without 9672d3582Sdrahn * modification, are permitted provided that the following conditions 10672d3582Sdrahn * are met: 11672d3582Sdrahn * 1. Redistributions of source code must retain the above copyright 12672d3582Sdrahn * notice, this list of conditions and the following disclaimer. 13672d3582Sdrahn * 2. Redistributions in binary form must reproduce the above copyright 14672d3582Sdrahn * notice, this list of conditions and the following disclaimer in the 15672d3582Sdrahn * documentation and/or other materials provided with the distribution. 16672d3582Sdrahn * 17672d3582Sdrahn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18672d3582Sdrahn * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19672d3582Sdrahn * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20672d3582Sdrahn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 21672d3582Sdrahn * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22672d3582Sdrahn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23672d3582Sdrahn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24672d3582Sdrahn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25672d3582Sdrahn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26672d3582Sdrahn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27672d3582Sdrahn * SUCH DAMAGE. 28672d3582Sdrahn */ 29672d3582Sdrahn /*- 30672d3582Sdrahn * Copyright (c) 2000 Eduardo Horvath. 31672d3582Sdrahn * Copyright (c) 1999 The NetBSD Foundation, Inc. 32672d3582Sdrahn * All rights reserved. 33672d3582Sdrahn * 34672d3582Sdrahn * This code is derived from software contributed to The NetBSD Foundation 35672d3582Sdrahn * by Paul Kranenburg. 36672d3582Sdrahn * 37672d3582Sdrahn * Redistribution and use in source and binary forms, with or without 38672d3582Sdrahn * modification, are permitted provided that the following conditions 39672d3582Sdrahn * are met: 40672d3582Sdrahn * 1. Redistributions of source code must retain the above copyright 41672d3582Sdrahn * notice, this list of conditions and the following disclaimer. 42672d3582Sdrahn * 2. Redistributions in binary form must reproduce the above copyright 43672d3582Sdrahn * notice, this list of conditions and the following disclaimer in the 44672d3582Sdrahn * documentation and/or other materials provided with the distribution. 45672d3582Sdrahn * 3. All advertising materials mentioning features or use of this software 46672d3582Sdrahn * must display the following acknowledgement: 47672d3582Sdrahn * This product includes software developed by the NetBSD 48672d3582Sdrahn * Foundation, Inc. and its contributors. 49672d3582Sdrahn * 4. Neither the name of The NetBSD Foundation nor the names of its 50672d3582Sdrahn * contributors may be used to endorse or promote products derived 51672d3582Sdrahn * from this software without specific prior written permission. 52672d3582Sdrahn * 53672d3582Sdrahn * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 54672d3582Sdrahn * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55672d3582Sdrahn * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56672d3582Sdrahn * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 57672d3582Sdrahn * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 58672d3582Sdrahn * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 59672d3582Sdrahn * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 60672d3582Sdrahn * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 61672d3582Sdrahn * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 62672d3582Sdrahn * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 63672d3582Sdrahn * POSSIBILITY OF SUCH DAMAGE. 64672d3582Sdrahn */ 65672d3582Sdrahn 66672d3582Sdrahn #define _DYN_LOADER 67672d3582Sdrahn 68672d3582Sdrahn #include <sys/types.h> 69672d3582Sdrahn #include <sys/mman.h> 708465df4aSguenther #include <sys/syscall.h> 718465df4aSguenther #include <sys/unistd.h> 72672d3582Sdrahn 73672d3582Sdrahn #include <nlist.h> 74672d3582Sdrahn #include <link.h> 75672d3582Sdrahn 76672d3582Sdrahn #include "syscall.h" 77672d3582Sdrahn #include "archdep.h" 78672d3582Sdrahn #include "resolve.h" 79672d3582Sdrahn 808465df4aSguenther int64_t pcookie __attribute__((section(".openbsd.randomdata"))) __dso_hidden; 818465df4aSguenther 82*c8754c30Sguenther /* 83*c8754c30Sguenther * The following table holds for each relocation type: 84*c8754c30Sguenther * - the width in bits of the memory location the relocation 85*c8754c30Sguenther * applies to 86*c8754c30Sguenther * - the number of bits the relocation value must be shifted to the 87*c8754c30Sguenther * right (i.e. discard least significant bits) to fit into 88*c8754c30Sguenther * the appropriate field in the instruction word. 89*c8754c30Sguenther * - flags indicating whether 90*c8754c30Sguenther * * the relocation involves a symbol 91*c8754c30Sguenther * * the relocation is relative to the current position 92*c8754c30Sguenther * * the relocation is for a GOT entry 93*c8754c30Sguenther * * the relocation is relative to the load address 94*c8754c30Sguenther * 95*c8754c30Sguenther */ 96*c8754c30Sguenther #define _RF_S 0x80000000 /* Resolve symbol */ 97*c8754c30Sguenther #define _RF_A 0x40000000 /* Use addend */ 98*c8754c30Sguenther #define _RF_P 0x20000000 /* Location relative */ 99*c8754c30Sguenther #define _RF_G 0x10000000 /* GOT offset */ 100*c8754c30Sguenther #define _RF_B 0x08000000 /* Load address relative */ 101*c8754c30Sguenther #define _RF_E 0x02000000 /* ERROR */ 102*c8754c30Sguenther #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ 103*c8754c30Sguenther #define _RF_RS(s) ((s) & 0xff) /* right shift */ 104*c8754c30Sguenther static const int reloc_target_flags[] = { 105*c8754c30Sguenther 0, /* 0 NONE */ 106*c8754c30Sguenther _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* 1 _64*/ 107*c8754c30Sguenther _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* 2 PC32 */ 108*c8754c30Sguenther _RF_G|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 3 GOT32 */ 109*c8754c30Sguenther _RF_E|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 4 PLT32 */ 110*c8754c30Sguenther _RF_S| _RF_SZ(32) | _RF_RS(0), /* 5 COPY */ 111*c8754c30Sguenther _RF_S| _RF_SZ(64) | _RF_RS(0), /* 6 GLOB_DAT*/ 112*c8754c30Sguenther _RF_S| _RF_SZ(64) | _RF_RS(0), /* 7 JUMP_SLOT*/ 113*c8754c30Sguenther _RF_A| _RF_B| _RF_SZ(64) | _RF_RS(0), /* 8 RELATIVE*/ 114*c8754c30Sguenther _RF_E, /* 9 GOTPCREL*/ 115*c8754c30Sguenther _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 10 32 */ 116*c8754c30Sguenther _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 11 32S */ 117*c8754c30Sguenther _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* 12 16 */ 118*c8754c30Sguenther _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* 13 PC16 */ 119*c8754c30Sguenther _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* 14 8 */ 120*c8754c30Sguenther _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* 15 PC8 */ 121*c8754c30Sguenther _RF_E, /* 16 DTPMOD64*/ 122*c8754c30Sguenther _RF_E, /* 17 DTPOFF64*/ 123*c8754c30Sguenther _RF_E, /* 18 TPOFF64 */ 124*c8754c30Sguenther _RF_E, /* 19 TLSGD */ 125*c8754c30Sguenther _RF_E, /* 20 TLSLD */ 126*c8754c30Sguenther _RF_E, /* 21 DTPOFF32*/ 127*c8754c30Sguenther _RF_E, /* 22 GOTTPOFF*/ 128*c8754c30Sguenther _RF_E /* 23 TPOFF32*/ 129*c8754c30Sguenther }; 130*c8754c30Sguenther 131*c8754c30Sguenther #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) 132*c8754c30Sguenther #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) 133*c8754c30Sguenther #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) 134*c8754c30Sguenther #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) 135*c8754c30Sguenther #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) 136*c8754c30Sguenther #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) 137*c8754c30Sguenther #define RELOC_ERROR(t) (reloc_target_flags[t] & _RF_E) 138*c8754c30Sguenther 139*c8754c30Sguenther static const Elf_Addr reloc_target_bitmask[] = { 140*c8754c30Sguenther #define _BM(x) (~(Elf_Addr)0 >> ((8*sizeof(reloc_target_bitmask[0])) - (x))) 141*c8754c30Sguenther 0, /* 0 NONE */ 142*c8754c30Sguenther _BM(64), /* 1 _64*/ 143*c8754c30Sguenther _BM(32), /* 2 PC32 */ 144*c8754c30Sguenther _BM(32), /* 3 GOT32 */ 145*c8754c30Sguenther _BM(32), /* 4 PLT32 */ 146*c8754c30Sguenther 0, /* 5 COPY */ 147*c8754c30Sguenther _BM(64), /* 6 GLOB_DAT*/ 148*c8754c30Sguenther _BM(64), /* 7 JUMP_SLOT*/ 149*c8754c30Sguenther _BM(64), /* 8 RELATIVE*/ 150*c8754c30Sguenther _BM(32), /* 9 GOTPCREL*/ 151*c8754c30Sguenther _BM(32), /* 10 32 */ 152*c8754c30Sguenther _BM(32), /* 11 32S */ 153*c8754c30Sguenther _BM(16), /* 12 16 */ 154*c8754c30Sguenther _BM(16), /* 13 PC16 */ 155*c8754c30Sguenther _BM(8), /* 14 8 */ 156*c8754c30Sguenther _BM(8), /* 15 PC8 */ 157*c8754c30Sguenther 0, /* 16 DTPMOD64*/ 158*c8754c30Sguenther 0, /* 17 DTPOFF64*/ 159*c8754c30Sguenther 0, /* 18 TPOFF64 */ 160*c8754c30Sguenther 0, /* 19 TLSGD */ 161*c8754c30Sguenther 0, /* 20 TLSLD */ 162*c8754c30Sguenther 0, /* 21 DTPOFF32*/ 163*c8754c30Sguenther 0, /* 22 GOTTPOFF*/ 164*c8754c30Sguenther 0 /* 23 TPOFF32*/ 165*c8754c30Sguenther #undef _BM 166*c8754c30Sguenther }; 167*c8754c30Sguenther #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) 168*c8754c30Sguenther 169*c8754c30Sguenther void _dl_reloc_plt(Elf_Addr *where, Elf_Addr value); 170*c8754c30Sguenther 171672d3582Sdrahn int 172672d3582Sdrahn _dl_md_reloc(elf_object_t *object, int rel, int relsz) 173672d3582Sdrahn { 174672d3582Sdrahn long i; 175672d3582Sdrahn long numrel; 17688098a4dSguenther long relrel; 177*c8754c30Sguenther int fails = 0; 178672d3582Sdrahn Elf_Addr loff; 17988098a4dSguenther Elf_Addr prev_value = 0; 18088098a4dSguenther const Elf_Sym *prev_sym = NULL; 181672d3582Sdrahn Elf_RelA *rels; 182672d3582Sdrahn 183ce11e090Skurt loff = object->obj_base; 184672d3582Sdrahn numrel = object->Dyn.info[relsz] / sizeof(Elf_RelA); 185*c8754c30Sguenther relrel = rel == DT_RELA ? object->relacount : 0; 186672d3582Sdrahn rels = (Elf_RelA *)(object->Dyn.info[rel]); 187672d3582Sdrahn if (rels == NULL) 188e3b0f1d9Sguenther return 0; 189672d3582Sdrahn 1903b50b772Sguenther if (relrel > numrel) 1913b50b772Sguenther _dl_die("relacount > numrel: %ld > %ld", relrel, numrel); 19288098a4dSguenther 19388098a4dSguenther /* tight loop for leading RELATIVE relocs */ 19488098a4dSguenther for (i = 0; i < relrel; i++, rels++) { 19588098a4dSguenther Elf_Addr *where; 19688098a4dSguenther 19788098a4dSguenther where = (Elf_Addr *)(rels->r_offset + loff); 19888098a4dSguenther *where = rels->r_addend + loff; 19988098a4dSguenther } 20088098a4dSguenther for (; i < numrel; i++, rels++) { 201*c8754c30Sguenther Elf_Addr *where, value, mask; 202672d3582Sdrahn Elf_Word type; 203143e5accSguenther const Elf_Sym *sym; 204672d3582Sdrahn const char *symn; 205672d3582Sdrahn 206*c8754c30Sguenther type = ELF_R_TYPE(rels->r_info); 207*c8754c30Sguenther 208*c8754c30Sguenther if (RELOC_ERROR(type)) 209*c8754c30Sguenther _dl_die("relocation error %d idx %ld", type, i); 210*c8754c30Sguenther 211*c8754c30Sguenther if (type == R_TYPE(NONE)) 212*c8754c30Sguenther continue; 213*c8754c30Sguenther 214*c8754c30Sguenther if (type == R_TYPE(JUMP_SLOT) && rel != DT_JMPREL) 215*c8754c30Sguenther continue; 216*c8754c30Sguenther 217672d3582Sdrahn where = (Elf_Addr *)(rels->r_offset + loff); 218672d3582Sdrahn 219*c8754c30Sguenther if (RELOC_USE_ADDEND(type)) 220*c8754c30Sguenther value = rels->r_addend; 221*c8754c30Sguenther else 222*c8754c30Sguenther value = 0; 223*c8754c30Sguenther 224*c8754c30Sguenther sym = NULL; 225*c8754c30Sguenther symn = NULL; 226*c8754c30Sguenther if (RELOC_RESOLVE_SYMBOL(type)) { 227672d3582Sdrahn sym = object->dyn.symtab; 228672d3582Sdrahn sym += ELF_R_SYM(rels->r_info); 229672d3582Sdrahn symn = object->dyn.strtab + sym->st_name; 230672d3582Sdrahn 231672d3582Sdrahn if (sym->st_shndx != SHN_UNDEF && 232672d3582Sdrahn ELF_ST_BIND(sym->st_info) == STB_LOCAL) { 233672d3582Sdrahn value += loff; 23488098a4dSguenther } else if (sym == prev_sym) { 23588098a4dSguenther value += prev_value; 236672d3582Sdrahn } else { 237143e5accSguenther struct sym_res sr; 238143e5accSguenther 239143e5accSguenther sr = _dl_find_symbol(symn, 240*c8754c30Sguenther SYM_SEARCH_ALL|SYM_WARNNOTFOUND| 241*c8754c30Sguenther ((type == R_TYPE(JUMP_SLOT))? 242*c8754c30Sguenther SYM_PLT:SYM_NOTPLT), sym, object); 243143e5accSguenther if (sr.sym == NULL) { 244*c8754c30Sguenther resolve_failed: 245*c8754c30Sguenther if (ELF_ST_BIND(sym->st_info) != 246*c8754c30Sguenther STB_WEAK) 247*c8754c30Sguenther fails++; 248672d3582Sdrahn continue; 249672d3582Sdrahn } 25088098a4dSguenther prev_sym = sym; 251*c8754c30Sguenther prev_value = (Elf_Addr)(sr.obj->obj_base + 252*c8754c30Sguenther sr.sym->st_value); 25388098a4dSguenther value += prev_value; 254672d3582Sdrahn } 255672d3582Sdrahn } 256672d3582Sdrahn 257*c8754c30Sguenther if (type == R_TYPE(JUMP_SLOT)) { 258*c8754c30Sguenther _dl_reloc_plt(where, value); 259*c8754c30Sguenther continue; 260*c8754c30Sguenther } 261*c8754c30Sguenther 262*c8754c30Sguenther if (type == R_TYPE(COPY)) { 263*c8754c30Sguenther void *dstaddr = where; 264*c8754c30Sguenther const void *srcaddr; 265*c8754c30Sguenther const Elf_Sym *dstsym = sym; 266*c8754c30Sguenther struct sym_res sr; 267*c8754c30Sguenther 268*c8754c30Sguenther sr = _dl_find_symbol(symn, 269*c8754c30Sguenther SYM_SEARCH_OTHER|SYM_WARNNOTFOUND|SYM_NOTPLT, 270*c8754c30Sguenther dstsym, object); 271*c8754c30Sguenther if (sr.sym == NULL) 272*c8754c30Sguenther goto resolve_failed; 273*c8754c30Sguenther 274*c8754c30Sguenther srcaddr = (void *)(sr.obj->obj_base + sr.sym->st_value); 275*c8754c30Sguenther _dl_bcopy(srcaddr, dstaddr, dstsym->st_size); 276*c8754c30Sguenther continue; 277*c8754c30Sguenther } 278*c8754c30Sguenther 279*c8754c30Sguenther if (RELOC_PC_RELATIVE(type)) 280*c8754c30Sguenther value -= (Elf_Addr)where; 281*c8754c30Sguenther if (RELOC_BASE_RELATIVE(type)) 282*c8754c30Sguenther value += loff; 283*c8754c30Sguenther 284*c8754c30Sguenther mask = RELOC_VALUE_BITMASK(type); 285*c8754c30Sguenther value >>= RELOC_VALUE_RIGHTSHIFT(type); 286*c8754c30Sguenther value &= mask; 287*c8754c30Sguenther 288*c8754c30Sguenther if (RELOC_TARGET_SIZE(type) > 32) { 289*c8754c30Sguenther *where &= ~mask; 290*c8754c30Sguenther *where |= value; 291*c8754c30Sguenther } else { 292*c8754c30Sguenther Elf32_Addr *where32 = (Elf32_Addr *)where; 293*c8754c30Sguenther 294*c8754c30Sguenther *where32 &= ~mask; 295*c8754c30Sguenther *where32 |= value; 296*c8754c30Sguenther } 297*c8754c30Sguenther } 298*c8754c30Sguenther 299*c8754c30Sguenther return fails; 300*c8754c30Sguenther } 301*c8754c30Sguenther 302*c8754c30Sguenther void 303*c8754c30Sguenther _dl_reloc_plt(Elf_Addr *where, Elf_Addr value) 304*c8754c30Sguenther { 305*c8754c30Sguenther *where = value; 306672d3582Sdrahn } 307672d3582Sdrahn 308672d3582Sdrahn /* 309672d3582Sdrahn * Resolve a symbol at run-time. 310672d3582Sdrahn */ 311672d3582Sdrahn Elf_Addr 312672d3582Sdrahn _dl_bind(elf_object_t *object, int index) 313672d3582Sdrahn { 3140cab1769Sdrahn Elf_RelA *rel; 315143e5accSguenther const Elf_Sym *sym; 316672d3582Sdrahn const char *symn; 317143e5accSguenther struct sym_res sr; 3188465df4aSguenther int64_t cookie = pcookie; 3198465df4aSguenther struct { 3208465df4aSguenther struct __kbind param; 3218465df4aSguenther Elf_Addr newval; 3228465df4aSguenther } buf; 323672d3582Sdrahn 3248465df4aSguenther rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]) + index; 325672d3582Sdrahn 326672d3582Sdrahn sym = object->dyn.symtab; 327672d3582Sdrahn sym += ELF_R_SYM(rel->r_info); 328672d3582Sdrahn symn = object->dyn.strtab + sym->st_name; 329672d3582Sdrahn 330143e5accSguenther sr = _dl_find_symbol(symn, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 331143e5accSguenther sym, object); 332143e5accSguenther if (sr.sym == NULL) 3333b50b772Sguenther _dl_die("lazy binding failed!"); 334672d3582Sdrahn 335143e5accSguenther buf.newval = sr.obj->obj_base + sr.sym->st_value; 3360cab1769Sdrahn 337143e5accSguenther if (__predict_false(sr.obj->traced) && _dl_trace_plt(sr.obj, symn)) 338e3b0f1d9Sguenther return buf.newval; 339ae398163Smiod 3408465df4aSguenther buf.param.kb_addr = (Elf_Word *)(object->obj_base + rel->r_offset); 3418465df4aSguenther buf.param.kb_size = sizeof(Elf_Addr); 3428465df4aSguenther 3438465df4aSguenther /* directly code the syscall, so that it's actually inline here */ 3448465df4aSguenther { 3458465df4aSguenther register long syscall_num __asm("rax") = SYS_kbind; 3468465df4aSguenther register void *arg1 __asm("rdi") = &buf; 3478465df4aSguenther register long arg2 __asm("rsi") = sizeof(buf); 3488465df4aSguenther register long arg3 __asm("rdx") = cookie; 3498465df4aSguenther 3508465df4aSguenther __asm volatile("syscall" : "+r" (syscall_num), "+r" (arg3) : 3518465df4aSguenther "r" (arg1), "r" (arg2) : "cc", "rcx", "r11", "memory"); 352672d3582Sdrahn } 353e3b0f1d9Sguenther return buf.newval; 354672d3582Sdrahn } 355672d3582Sdrahn 356e9cfe40cSmiod int 357672d3582Sdrahn _dl_md_reloc_got(elf_object_t *object, int lazy) 358672d3582Sdrahn { 359672d3582Sdrahn extern void _dl_bind_start(void); /* XXX */ 360*c8754c30Sguenther int fails = 0; 361672d3582Sdrahn Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; 362*c8754c30Sguenther int i, num; 363*c8754c30Sguenther Elf_RelA *rel; 364672d3582Sdrahn 365672d3582Sdrahn if (pltgot == NULL) 366e3b0f1d9Sguenther return 0; /* it is possible to have no PLT/GOT relocations */ 367672d3582Sdrahn 368672d3582Sdrahn if (object->Dyn.info[DT_PLTREL] != DT_RELA) 369e3b0f1d9Sguenther return 0; 370672d3582Sdrahn 371ae398163Smiod if (object->traced) 372ae398163Smiod lazy = 1; 373ae398163Smiod 374*c8754c30Sguenther if (__predict_false(!lazy)) { 375*c8754c30Sguenther fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); 376*c8754c30Sguenther } else { 377e23a26ffSguenther pltgot[1] = (Elf_Addr)object; 378e23a26ffSguenther pltgot[2] = (Elf_Addr)&_dl_bind_start; 379e23a26ffSguenther 380*c8754c30Sguenther rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]); 381*c8754c30Sguenther num = (object->Dyn.info[DT_PLTRELSZ]); 382*c8754c30Sguenther for (i = 0; i < num/sizeof(Elf_RelA); i++, rel++) { 383672d3582Sdrahn Elf_Addr *where; 384*c8754c30Sguenther where = (Elf_Addr *)(rel->r_offset + object->obj_base); 385ce11e090Skurt *where += object->obj_base; 386672d3582Sdrahn } 387*c8754c30Sguenther } 3880cab1769Sdrahn 389*c8754c30Sguenther return fails; 390672d3582Sdrahn } 391