1*e3b0f1d9Sguenther /* $OpenBSD: rtld_machine.c,v 1.35 2019/10/23 19:55:09 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 82672d3582Sdrahn /* 83672d3582Sdrahn * The following table holds for each relocation type: 84672d3582Sdrahn * - the width in bits of the memory location the relocation 858465df4aSguenther * applies to 86672d3582Sdrahn * - the number of bits the relocation value must be shifted to the 87672d3582Sdrahn * right (i.e. discard least significant bits) to fit into 88672d3582Sdrahn * the appropriate field in the instruction word. 89672d3582Sdrahn * - flags indicating whether 90672d3582Sdrahn * * the relocation involves a symbol 91672d3582Sdrahn * * the relocation is relative to the current position 92672d3582Sdrahn * * the relocation is for a GOT entry 93672d3582Sdrahn * * the relocation is relative to the load address 94672d3582Sdrahn * 95672d3582Sdrahn */ 96672d3582Sdrahn #define _RF_S 0x80000000 /* Resolve symbol */ 97672d3582Sdrahn #define _RF_A 0x40000000 /* Use addend */ 98672d3582Sdrahn #define _RF_P 0x20000000 /* Location relative */ 99672d3582Sdrahn #define _RF_G 0x10000000 /* GOT offset */ 100672d3582Sdrahn #define _RF_B 0x08000000 /* Load address relative */ 101672d3582Sdrahn #define _RF_E 0x02000000 /* ERROR */ 102672d3582Sdrahn #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ 103672d3582Sdrahn #define _RF_RS(s) ((s) & 0xff) /* right shift */ 1042668a398Sguenther static const int reloc_target_flags[] = { 105672d3582Sdrahn 0, /* 0 NONE */ 106672d3582Sdrahn _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* 1 _64*/ 107672d3582Sdrahn _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* 2 PC32 */ 108672d3582Sdrahn _RF_G|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 3 GOT32 */ 109672d3582Sdrahn _RF_E|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 4 PLT32 */ 110672d3582Sdrahn _RF_S| _RF_SZ(32) | _RF_RS(0), /* 5 COPY */ 111672d3582Sdrahn _RF_S| _RF_SZ(64) | _RF_RS(0), /* 6 GLOB_DAT*/ 112672d3582Sdrahn _RF_S| _RF_SZ(64) | _RF_RS(0), /* 7 JUMP_SLOT*/ 113672d3582Sdrahn _RF_A| _RF_B| _RF_SZ(64) | _RF_RS(0), /* 8 RELATIVE*/ 114672d3582Sdrahn _RF_E, /* 9 GOTPCREL*/ 115672d3582Sdrahn _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 10 32 */ 116672d3582Sdrahn _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 11 32S */ 117672d3582Sdrahn _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* 12 16 */ 118672d3582Sdrahn _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* 13 PC16 */ 119672d3582Sdrahn _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* 14 8 */ 120672d3582Sdrahn _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* 15 PC8 */ 1216ee5b79dSguenther _RF_E, /* 16 DTPMOD64*/ 122672d3582Sdrahn _RF_E, /* 17 DTPOFF64*/ 123672d3582Sdrahn _RF_E, /* 18 TPOFF64 */ 124672d3582Sdrahn _RF_E, /* 19 TLSGD */ 125672d3582Sdrahn _RF_E, /* 20 TLSLD */ 126672d3582Sdrahn _RF_E, /* 21 DTPOFF32*/ 127672d3582Sdrahn _RF_E, /* 22 GOTTPOFF*/ 128672d3582Sdrahn _RF_E /* 23 TPOFF32*/ 129672d3582Sdrahn }; 130672d3582Sdrahn 131672d3582Sdrahn #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) 132672d3582Sdrahn #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) 133672d3582Sdrahn #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) 134672d3582Sdrahn #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) 135672d3582Sdrahn #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) 136672d3582Sdrahn #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) 137672d3582Sdrahn #define RELOC_ERROR(t) (reloc_target_flags[t] & _RF_E) 138672d3582Sdrahn 1392668a398Sguenther static const Elf_Addr reloc_target_bitmask[] = { 14050ab7546Sbrad #define _BM(x) (~(Elf_Addr)0 >> ((8*sizeof(reloc_target_bitmask[0])) - (x))) 141672d3582Sdrahn 0, /* 0 NONE */ 142672d3582Sdrahn _BM(64), /* 1 _64*/ 143672d3582Sdrahn _BM(32), /* 2 PC32 */ 144672d3582Sdrahn _BM(32), /* 3 GOT32 */ 145672d3582Sdrahn _BM(32), /* 4 PLT32 */ 14650ab7546Sbrad 0, /* 5 COPY */ 147672d3582Sdrahn _BM(64), /* 6 GLOB_DAT*/ 148672d3582Sdrahn _BM(64), /* 7 JUMP_SLOT*/ 149672d3582Sdrahn _BM(64), /* 8 RELATIVE*/ 150672d3582Sdrahn _BM(32), /* 9 GOTPCREL*/ 151672d3582Sdrahn _BM(32), /* 10 32 */ 152672d3582Sdrahn _BM(32), /* 11 32S */ 153672d3582Sdrahn _BM(16), /* 12 16 */ 154672d3582Sdrahn _BM(16), /* 13 PC16 */ 155672d3582Sdrahn _BM(8), /* 14 8 */ 156672d3582Sdrahn _BM(8), /* 15 PC8 */ 1576ee5b79dSguenther 0, /* 16 DTPMOD64*/ 158672d3582Sdrahn 0, /* 17 DTPOFF64*/ 159672d3582Sdrahn 0, /* 18 TPOFF64 */ 160672d3582Sdrahn 0, /* 19 TLSGD */ 161672d3582Sdrahn 0, /* 20 TLSLD */ 162672d3582Sdrahn 0, /* 21 DTPOFF32*/ 163672d3582Sdrahn 0, /* 22 GOTTPOFF*/ 164672d3582Sdrahn 0 /* 23 TPOFF32*/ 165672d3582Sdrahn #undef _BM 166672d3582Sdrahn }; 167672d3582Sdrahn #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) 168672d3582Sdrahn 169672d3582Sdrahn void _dl_reloc_plt(Elf_Addr *where, Elf_Addr value); 170672d3582Sdrahn 171672d3582Sdrahn int 172672d3582Sdrahn _dl_md_reloc(elf_object_t *object, int rel, int relsz) 173672d3582Sdrahn { 174672d3582Sdrahn long i; 175672d3582Sdrahn long numrel; 17688098a4dSguenther long relrel; 177e9cfe40cSmiod 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); 18588098a4dSguenther relrel = rel == DT_RELA ? object->relacount : 0; 186672d3582Sdrahn rels = (Elf_RelA *)(object->Dyn.info[rel]); 187672d3582Sdrahn if (rels == NULL) 188*e3b0f1d9Sguenther 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++) { 201143e5accSguenther Elf_Addr *where, value, mask; 202672d3582Sdrahn Elf_Word type; 203143e5accSguenther const Elf_Sym *sym; 204672d3582Sdrahn const char *symn; 205672d3582Sdrahn 206672d3582Sdrahn type = ELF_R_TYPE(rels->r_info); 207672d3582Sdrahn 2083b50b772Sguenther if (RELOC_ERROR(type)) 2093b50b772Sguenther _dl_die("relocation error %d idx %ld", type, i); 210672d3582Sdrahn 211672d3582Sdrahn if (type == R_TYPE(NONE)) 212672d3582Sdrahn continue; 213672d3582Sdrahn 214672d3582Sdrahn if (type == R_TYPE(JUMP_SLOT) && rel != DT_JMPREL) 215672d3582Sdrahn continue; 216672d3582Sdrahn 217672d3582Sdrahn where = (Elf_Addr *)(rels->r_offset + loff); 218672d3582Sdrahn 219672d3582Sdrahn if (RELOC_USE_ADDEND(type)) 220672d3582Sdrahn value = rels->r_addend; 221672d3582Sdrahn else 222672d3582Sdrahn value = 0; 223672d3582Sdrahn 224672d3582Sdrahn sym = NULL; 225672d3582Sdrahn symn = NULL; 226672d3582Sdrahn 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, 2400acae5e5Sdrahn SYM_SEARCH_ALL|SYM_WARNNOTFOUND| 241672d3582Sdrahn ((type == R_TYPE(JUMP_SLOT))? 242143e5accSguenther SYM_PLT:SYM_NOTPLT), sym, object); 243143e5accSguenther if (sr.sym == NULL) { 244672d3582Sdrahn resolve_failed: 24506462af4Sdrahn if (ELF_ST_BIND(sym->st_info) != 24606462af4Sdrahn STB_WEAK) 247672d3582Sdrahn fails++; 248672d3582Sdrahn continue; 249672d3582Sdrahn } 25088098a4dSguenther prev_sym = sym; 251143e5accSguenther prev_value = (Elf_Addr)(sr.obj->obj_base + 252143e5accSguenther sr.sym->st_value); 25388098a4dSguenther value += prev_value; 254672d3582Sdrahn } 255672d3582Sdrahn } 256672d3582Sdrahn 257672d3582Sdrahn if (type == R_TYPE(JUMP_SLOT)) { 258672d3582Sdrahn _dl_reloc_plt(where, value); 259672d3582Sdrahn continue; 260672d3582Sdrahn } 261672d3582Sdrahn 262672d3582Sdrahn if (type == R_TYPE(COPY)) { 263672d3582Sdrahn void *dstaddr = where; 264672d3582Sdrahn const void *srcaddr; 265143e5accSguenther const Elf_Sym *dstsym = sym; 266143e5accSguenther struct sym_res sr; 267672d3582Sdrahn 268143e5accSguenther sr = _dl_find_symbol(symn, 269117639ecSguenther SYM_SEARCH_OTHER|SYM_WARNNOTFOUND|SYM_NOTPLT, 270143e5accSguenther dstsym, object); 271143e5accSguenther if (sr.sym == NULL) 272672d3582Sdrahn goto resolve_failed; 273672d3582Sdrahn 274143e5accSguenther srcaddr = (void *)(sr.obj->obj_base + sr.sym->st_value); 2756718d15cSdrahn _dl_bcopy(srcaddr, dstaddr, dstsym->st_size); 276672d3582Sdrahn continue; 277672d3582Sdrahn } 278672d3582Sdrahn 279672d3582Sdrahn if (RELOC_PC_RELATIVE(type)) 280672d3582Sdrahn value -= (Elf_Addr)where; 281672d3582Sdrahn if (RELOC_BASE_RELATIVE(type)) 282672d3582Sdrahn value += loff; 283672d3582Sdrahn 284672d3582Sdrahn mask = RELOC_VALUE_BITMASK(type); 285672d3582Sdrahn value >>= RELOC_VALUE_RIGHTSHIFT(type); 286672d3582Sdrahn value &= mask; 287672d3582Sdrahn 2888465df4aSguenther if (RELOC_TARGET_SIZE(type) > 32) { 289672d3582Sdrahn *where &= ~mask; 290672d3582Sdrahn *where |= value; 291672d3582Sdrahn } else { 292672d3582Sdrahn Elf32_Addr *where32 = (Elf32_Addr *)where; 293672d3582Sdrahn 294672d3582Sdrahn *where32 &= ~mask; 295672d3582Sdrahn *where32 |= value; 296672d3582Sdrahn } 297672d3582Sdrahn } 298672d3582Sdrahn 299*e3b0f1d9Sguenther return fails; 300672d3582Sdrahn } 301672d3582Sdrahn 302672d3582Sdrahn void 303672d3582Sdrahn _dl_reloc_plt(Elf_Addr *where, Elf_Addr value) 304672d3582Sdrahn { 305672d3582Sdrahn *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)) 338*e3b0f1d9Sguenther 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 } 353*e3b0f1d9Sguenther 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 */ 360e9cfe40cSmiod int fails = 0; 361672d3582Sdrahn Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; 362672d3582Sdrahn int i, num; 363672d3582Sdrahn Elf_RelA *rel; 364672d3582Sdrahn 365672d3582Sdrahn if (pltgot == NULL) 366*e3b0f1d9Sguenther return 0; /* it is possible to have no PLT/GOT relocations */ 367672d3582Sdrahn 368672d3582Sdrahn if (object->Dyn.info[DT_PLTREL] != DT_RELA) 369*e3b0f1d9Sguenther return 0; 370672d3582Sdrahn 371ae398163Smiod if (object->traced) 372ae398163Smiod lazy = 1; 373ae398163Smiod 3748465df4aSguenther if (__predict_false(!lazy)) { 375e9cfe40cSmiod fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); 376672d3582Sdrahn } else { 377e23a26ffSguenther pltgot[1] = (Elf_Addr)object; 378e23a26ffSguenther pltgot[2] = (Elf_Addr)&_dl_bind_start; 379e23a26ffSguenther 380672d3582Sdrahn rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]); 381672d3582Sdrahn num = (object->Dyn.info[DT_PLTRELSZ]); 382672d3582Sdrahn for (i = 0; i < num/sizeof(Elf_RelA); i++, rel++) { 383672d3582Sdrahn Elf_Addr *where; 384ce11e090Skurt where = (Elf_Addr *)(rel->r_offset + object->obj_base); 385ce11e090Skurt *where += object->obj_base; 386672d3582Sdrahn } 387672d3582Sdrahn } 3880cab1769Sdrahn 389*e3b0f1d9Sguenther return fails; 390672d3582Sdrahn } 391