reloc.c revision 115396
1107572Sgrehan/* $NetBSD: ppc_reloc.c,v 1.10 2001/09/10 06:09:41 mycroft Exp $ */ 2107572Sgrehan 3107572Sgrehan/*- 4107572Sgrehan * Copyright (C) 1998 Tsubai Masanari 5107572Sgrehan * All rights reserved. 6107572Sgrehan * 7107572Sgrehan * Redistribution and use in source and binary forms, with or without 8107572Sgrehan * modification, are permitted provided that the following conditions 9107572Sgrehan * are met: 10107572Sgrehan * 1. Redistributions of source code must retain the above copyright 11107572Sgrehan * notice, this list of conditions and the following disclaimer. 12107572Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 13107572Sgrehan * notice, this list of conditions and the following disclaimer in the 14107572Sgrehan * documentation and/or other materials provided with the distribution. 15107572Sgrehan * 3. The name of the author may not be used to endorse or promote products 16107572Sgrehan * derived from this software without specific prior written permission. 17107572Sgrehan * 18107572Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19107572Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20107572Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21107572Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22107572Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23107572Sgrehan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24107572Sgrehan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25107572Sgrehan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26107572Sgrehan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27107572Sgrehan * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28107572Sgrehan * 29107572Sgrehan * $FreeBSD: head/libexec/rtld-elf/powerpc/reloc.c 115396 2003-05-29 22:58:26Z kan $ 30107572Sgrehan */ 31107572Sgrehan 32107572Sgrehan#include <sys/param.h> 33107572Sgrehan#include <sys/mman.h> 34107572Sgrehan 35107572Sgrehan#include <errno.h> 36107572Sgrehan#include <stdio.h> 37107572Sgrehan#include <stdlib.h> 38107572Sgrehan#include <string.h> 39107572Sgrehan#include <unistd.h> 40107572Sgrehan#include <machine/cpu.h> 41107572Sgrehan 42107572Sgrehan#include "debug.h" 43107572Sgrehan#include "rtld.h" 44107572Sgrehan 45107572Sgrehan#define _ppc_ha(x) ((((u_int32_t)(x) & 0x8000) ? \ 46107572Sgrehan ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16) 47107572Sgrehan#define _ppc_la(x) ((u_int32_t)(x) & 0xffff) 48107572Sgrehan 49107572Sgrehan/* 50107572Sgrehan * Process the R_PPC_COPY relocations 51107572Sgrehan */ 52107572Sgrehanint 53107572Sgrehando_copy_relocations(Obj_Entry *dstobj) 54107572Sgrehan{ 55107572Sgrehan const Elf_Rela *relalim; 56107572Sgrehan const Elf_Rela *rela; 57107572Sgrehan 58115396Skan /* 59107572Sgrehan * COPY relocs are invalid outside of the main program 60107572Sgrehan */ 61115396Skan assert(dstobj->mainprog); 62107572Sgrehan 63115396Skan relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + 64107572Sgrehan dstobj->relasize); 65107572Sgrehan for (rela = dstobj->rela; rela < relalim; rela++) { 66107572Sgrehan void *dstaddr; 67107572Sgrehan const Elf_Sym *dstsym; 68107572Sgrehan const char *name; 69107572Sgrehan unsigned long hash; 70107572Sgrehan size_t size; 71107572Sgrehan const void *srcaddr; 72107572Sgrehan const Elf_Sym *srcsym = NULL; 73107572Sgrehan Obj_Entry *srcobj; 74107572Sgrehan 75107572Sgrehan if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) { 76107572Sgrehan continue; 77107572Sgrehan } 78107572Sgrehan 79107572Sgrehan dstaddr = (void *) (dstobj->relocbase + rela->r_offset); 80107572Sgrehan dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 81107572Sgrehan name = dstobj->strtab + dstsym->st_name; 82107572Sgrehan hash = elf_hash(name); 83107572Sgrehan size = dstsym->st_size; 84115396Skan 85115396Skan for (srcobj = dstobj->next; srcobj != NULL; 86107572Sgrehan srcobj = srcobj->next) { 87107572Sgrehan if ((srcsym = symlook_obj(name, hash, srcobj, false)) 88107572Sgrehan != NULL) { 89107572Sgrehan break; 90107572Sgrehan } 91107572Sgrehan } 92107572Sgrehan 93107572Sgrehan if (srcobj == NULL) { 94107572Sgrehan _rtld_error("Undefined symbol \"%s\" " 95107572Sgrehan " referenced from COPY" 96107572Sgrehan " relocation in %s", name, dstobj->path); 97107572Sgrehan return (-1); 98107572Sgrehan } 99115396Skan 100107572Sgrehan srcaddr = (const void *) (srcobj->relocbase+srcsym->st_value); 101115396Skan memcpy(dstaddr, srcaddr, size); 102107572Sgrehan dbg("copy_reloc: src=%p,dst=%p,size=%d\n",srcaddr,dstaddr,size); 103107572Sgrehan } 104115396Skan 105107572Sgrehan return (0); 106107572Sgrehan} 107107572Sgrehan 108107572Sgrehan 109107572Sgrehan/* 110107572Sgrehan * Perform early relocation of the run-time linker image 111107572Sgrehan */ 112107572Sgrehanvoid 113107572Sgrehanreloc_non_plt_self(Elf_Dyn *dynp, Elf_Addr relocbase) 114107572Sgrehan{ 115107572Sgrehan const Elf_Rela *rela = 0, *relalim; 116107572Sgrehan Elf_Addr relasz = 0; 117107572Sgrehan Elf_Addr *where; 118107572Sgrehan 119107572Sgrehan /* 120107572Sgrehan * Extract the rela/relasz values from the dynamic section 121107572Sgrehan */ 122107572Sgrehan for (; dynp->d_tag != DT_NULL; dynp++) { 123107572Sgrehan switch (dynp->d_tag) { 124107572Sgrehan case DT_RELA: 125107572Sgrehan rela = (const Elf_Rela *)(relocbase+dynp->d_un.d_ptr); 126107572Sgrehan break; 127107572Sgrehan case DT_RELASZ: 128107572Sgrehan relasz = dynp->d_un.d_val; 129107572Sgrehan break; 130107572Sgrehan } 131107572Sgrehan } 132107572Sgrehan 133107572Sgrehan /* 134115396Skan * Relocate these values 135107572Sgrehan */ 136107572Sgrehan relalim = (const Elf_Rela *)((caddr_t)rela + relasz); 137107572Sgrehan for (; rela < relalim; rela++) { 138107572Sgrehan where = (Elf_Addr *)(relocbase + rela->r_offset); 139107572Sgrehan *where = (Elf_Addr)(relocbase + rela->r_addend); 140107572Sgrehan } 141107572Sgrehan} 142107572Sgrehan 143107572Sgrehan 144107572Sgrehan/* 145115396Skan * Relocate a non-PLT object with addend. 146107572Sgrehan */ 147107572Sgrehanstatic int 148107572Sgrehanreloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela, 149107572Sgrehan SymCache *cache) 150107572Sgrehan{ 151107572Sgrehan Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 152107572Sgrehan const Elf_Sym *def; 153107572Sgrehan const Obj_Entry *defobj; 154107572Sgrehan Elf_Addr tmp; 155107572Sgrehan 156107572Sgrehan switch (ELF_R_TYPE(rela->r_info)) { 157115396Skan 158107572Sgrehan case R_PPC_NONE: 159107572Sgrehan break; 160107572Sgrehan 161107572Sgrehan case R_PPC_ADDR32: /* word32 S + A */ 162107572Sgrehan case R_PPC_GLOB_DAT: /* word32 S + A */ 163107572Sgrehan def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 164107572Sgrehan false, cache); 165107572Sgrehan if (def == NULL) { 166107572Sgrehan return (-1); 167107572Sgrehan } 168107572Sgrehan 169107572Sgrehan tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 170107572Sgrehan rela->r_addend); 171107572Sgrehan 172107572Sgrehan /* Don't issue write if unnecessary; avoid COW page fault */ 173107572Sgrehan if (*where != tmp) { 174107572Sgrehan *where = tmp; 175107572Sgrehan } 176107572Sgrehan break; 177107572Sgrehan 178107572Sgrehan case R_PPC_RELATIVE: /* word32 B + A */ 179107572Sgrehan tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); 180115396Skan 181107572Sgrehan /* As above, don't issue write unnecessarily */ 182107572Sgrehan if (*where != tmp) { 183107572Sgrehan *where = tmp; 184107572Sgrehan } 185107572Sgrehan break; 186107572Sgrehan 187107572Sgrehan case R_PPC_COPY: 188107572Sgrehan /* 189107572Sgrehan * These are deferred until all other relocations 190107572Sgrehan * have been done. All we do here is make sure 191107572Sgrehan * that the COPY relocation is not in a shared 192107572Sgrehan * library. They are allowed only in executable 193107572Sgrehan * files. 194107572Sgrehan */ 195107572Sgrehan if (!obj->mainprog) { 196107572Sgrehan _rtld_error("%s: Unexpected R_COPY " 197107572Sgrehan " relocation in shared library", 198107572Sgrehan obj->path); 199107572Sgrehan return (-1); 200115396Skan } 201107572Sgrehan break; 202107572Sgrehan 203107572Sgrehan case R_PPC_JMP_SLOT: 204107572Sgrehan /* 205107572Sgrehan * These will be handled by the plt/jmpslot routines 206107572Sgrehan */ 207107572Sgrehan break; 208107572Sgrehan 209107572Sgrehan default: 210107572Sgrehan _rtld_error("%s: Unsupported relocation type %d" 211107572Sgrehan " in non-PLT relocations\n", obj->path, 212115396Skan ELF_R_TYPE(rela->r_info)); 213107572Sgrehan return (-1); 214107572Sgrehan } 215115396Skan return (0); 216107572Sgrehan} 217107572Sgrehan 218107572Sgrehan 219107572Sgrehan/* 220107572Sgrehan * Process non-PLT relocations 221107572Sgrehan */ 222107572Sgrehanint 223107572Sgrehanreloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) 224107572Sgrehan{ 225107572Sgrehan const Elf_Rela *relalim; 226107572Sgrehan const Elf_Rela *rela; 227107572Sgrehan SymCache *cache; 228107572Sgrehan int bytes = obj->nchains * sizeof(SymCache); 229107572Sgrehan int r = -1; 230107572Sgrehan 231107572Sgrehan /* 232107572Sgrehan * The dynamic loader may be called from a thread, we have 233107572Sgrehan * limited amounts of stack available so we cannot use alloca(). 234107572Sgrehan */ 235107572Sgrehan cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); 236112242Skan if (cache == MAP_FAILED) 237107572Sgrehan cache = NULL; 238107572Sgrehan 239107572Sgrehan /* 240107572Sgrehan * From the SVR4 PPC ABI: 241115396Skan * "The PowerPC family uses only the Elf32_Rela relocation 242107572Sgrehan * entries with explicit addends." 243107572Sgrehan */ 244107572Sgrehan relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize); 245107572Sgrehan for (rela = obj->rela; rela < relalim; rela++) { 246107572Sgrehan if (reloc_nonplt_object(obj_rtld, obj, rela, cache) < 0) 247107572Sgrehan goto done; 248107572Sgrehan } 249107572Sgrehan r = 0; 250107572Sgrehandone: 251107572Sgrehan if (cache) { 252107572Sgrehan munmap(cache, bytes); 253107572Sgrehan } 254107572Sgrehan return (r); 255107572Sgrehan} 256107572Sgrehan 257107572Sgrehan 258107572Sgrehan/* 259107572Sgrehan * Initialise a PLT slot to the resolving trampoline 260107572Sgrehan */ 261107572Sgrehanstatic int 262107572Sgrehanreloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela) 263107572Sgrehan{ 264107572Sgrehan Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); 265107572Sgrehan Elf_Addr *pltresolve; 266107572Sgrehan Elf_Addr distance; 267107572Sgrehan int reloff; 268107572Sgrehan 269107572Sgrehan reloff = rela - obj->pltrela; 270107572Sgrehan 271107572Sgrehan if ((reloff < 0) || (reloff >= 0x8000)) { 272107572Sgrehan return (-1); 273107572Sgrehan } 274107572Sgrehan 275107572Sgrehan pltresolve = obj->pltgot + 8; 276107572Sgrehan 277107572Sgrehan distance = (Elf_Addr)pltresolve - (Elf_Addr)(where + 1); 278107572Sgrehan 279115396Skan dbg(" reloc_plt_object: where=%p,pltres=%p,reloff=%x,distance=%x", 280107572Sgrehan (void *)where, (void *)pltresolve, reloff, distance); 281107572Sgrehan 282107572Sgrehan /* li r11,reloff */ 283107572Sgrehan /* b pltresolve */ 284107572Sgrehan where[0] = 0x39600000 | reloff; 285107572Sgrehan where[1] = 0x48000000 | (distance & 0x03fffffc); 286107572Sgrehan 287107572Sgrehan /* 288107572Sgrehan * The icache will be sync'd in init_pltgot, which is called 289107572Sgrehan * after all the slots have been updated 290107572Sgrehan */ 291107572Sgrehan 292107572Sgrehan return (0); 293107572Sgrehan} 294107572Sgrehan 295107572Sgrehan 296107572Sgrehan/* 297107572Sgrehan * Process the PLT relocations. 298107572Sgrehan */ 299107572Sgrehanint 300107572Sgrehanreloc_plt(Obj_Entry *obj) 301107572Sgrehan{ 302107572Sgrehan const Elf_Rela *relalim; 303107572Sgrehan const Elf_Rela *rela; 304107572Sgrehan 305107572Sgrehan if (obj->pltrelasize != 0) { 306107572Sgrehan 307115396Skan relalim = (const Elf_Rela *)((char *)obj->pltrela + 308107572Sgrehan obj->pltrelasize); 309107572Sgrehan for (rela = obj->pltrela; rela < relalim; rela++) { 310107572Sgrehan assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 311107572Sgrehan 312107572Sgrehan if (reloc_plt_object(obj, rela) < 0) { 313107572Sgrehan return (-1); 314107572Sgrehan } 315107572Sgrehan } 316107572Sgrehan } 317107572Sgrehan 318107572Sgrehan return (0); 319107572Sgrehan} 320107572Sgrehan 321107572Sgrehan 322107572Sgrehan/* 323107572Sgrehan * LD_BIND_NOW was set - force relocation for all jump slots 324107572Sgrehan */ 325107572Sgrehanint 326107572Sgrehanreloc_jmpslots(Obj_Entry *obj) 327107572Sgrehan{ 328107572Sgrehan const Obj_Entry *defobj; 329107572Sgrehan const Elf_Rela *relalim; 330107572Sgrehan const Elf_Rela *rela; 331107572Sgrehan const Elf_Sym *def; 332107572Sgrehan Elf_Addr *where; 333107572Sgrehan Elf_Addr target; 334107572Sgrehan 335107572Sgrehan relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 336107572Sgrehan for (rela = obj->pltrela; rela < relalim; rela++) { 337107572Sgrehan assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 338107572Sgrehan where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 339107572Sgrehan def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 340107572Sgrehan true, NULL); 341107572Sgrehan if (def == NULL) { 342107572Sgrehan dbg("reloc_jmpslots: sym not found"); 343107572Sgrehan return (-1); 344107572Sgrehan } 345107572Sgrehan 346107572Sgrehan target = (Elf_Addr)(defobj->relocbase + def->st_value); 347107572Sgrehan 348107572Sgrehan#if 0 349107572Sgrehan /* PG XXX */ 350107572Sgrehan dbg("\"%s\" in \"%s\" --> %p in \"%s\"", 351107572Sgrehan defobj->strtab + def->st_name, basename(obj->path), 352107572Sgrehan (void *)target, basename(defobj->path)); 353107572Sgrehan#endif 354107572Sgrehan 355115396Skan reloc_jmpslot(where, target, defobj, obj, 356107572Sgrehan (const Elf_Rel *) rela); 357107572Sgrehan } 358107572Sgrehan 359107572Sgrehan obj->jmpslots_done = true; 360107572Sgrehan 361107572Sgrehan return (0); 362107572Sgrehan} 363107572Sgrehan 364107572Sgrehan 365107572Sgrehan/* 366107572Sgrehan * Update the value of a PLT jump slot. Branch directly to the target if 367107572Sgrehan * it is within +/- 32Mb, otherwise go indirectly via the pltcall 368107572Sgrehan * trampoline call and jump table. 369107572Sgrehan */ 370107572SgrehanElf_Addr 371107572Sgrehanreloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj, 372107572Sgrehan const Obj_Entry *obj, const Elf_Rel *rel) 373107572Sgrehan{ 374107572Sgrehan Elf_Addr offset; 375107572Sgrehan const Elf_Rela *rela = (const Elf_Rela *) rel; 376107572Sgrehan 377115396Skan dbg(" reloc_jmpslot: where=%p, target=%p", 378107572Sgrehan (void *)wherep, (void *)target); 379107572Sgrehan 380107572Sgrehan /* 381107572Sgrehan * At the PLT entry pointed at by `wherep', construct 382107572Sgrehan * a direct transfer to the now fully resolved function 383107572Sgrehan * address. 384107572Sgrehan */ 385107572Sgrehan offset = target - (Elf_Addr)wherep; 386107572Sgrehan 387107572Sgrehan if (abs(offset) < 32*1024*1024) { /* inside 32MB? */ 388107572Sgrehan /* b value # branch directly */ 389107572Sgrehan *wherep = 0x48000000 | (offset & 0x03fffffc); 390107572Sgrehan __syncicache(wherep, 4); 391107572Sgrehan } else { 392107572Sgrehan Elf_Addr *pltcall, *jmptab; 393107572Sgrehan int distance; 394107572Sgrehan int N = obj->pltrelasize / sizeof(Elf_Rela); 395107572Sgrehan int reloff = rela - obj->pltrela; 396107572Sgrehan 397107572Sgrehan if ((reloff < 0) || (reloff >= 0x8000)) { 398107572Sgrehan return (-1); 399107572Sgrehan } 400107572Sgrehan 401107572Sgrehan pltcall = obj->pltgot; 402107572Sgrehan 403107572Sgrehan dbg(" reloc_jmpslot: indir, reloff=%d, N=%d\n", 404107572Sgrehan reloff, N); 405107572Sgrehan 406107572Sgrehan jmptab = obj->pltgot + 18 + N * 2; 407107572Sgrehan jmptab[reloff] = target; 408107572Sgrehan 409107572Sgrehan distance = (Elf_Addr)pltcall - (Elf_Addr)(wherep + 1); 410107572Sgrehan 411107572Sgrehan /* li r11,reloff */ 412107572Sgrehan /* b pltcall # use indirect pltcall routine */ 413107572Sgrehan wherep[0] = 0x39600000 | reloff; 414107572Sgrehan wherep[1] = 0x48000000 | (distance & 0x03fffffc); 415107572Sgrehan __syncicache(wherep, 8); 416107572Sgrehan } 417107572Sgrehan 418107572Sgrehan return (target); 419107572Sgrehan} 420107572Sgrehan 421107572Sgrehan 422107572Sgrehan/* 423107572Sgrehan * Setup the plt glue routines. 424107572Sgrehan */ 425107572Sgrehan#define PLTCALL_SIZE 20 426107572Sgrehan#define PLTRESOLVE_SIZE 24 427107572Sgrehan 428107572Sgrehanvoid 429107572Sgrehaninit_pltgot(Obj_Entry *obj) 430107572Sgrehan{ 431107572Sgrehan Elf_Word *pltcall, *pltresolve; 432107572Sgrehan Elf_Word *jmptab; 433107572Sgrehan int N = obj->pltrelasize / sizeof(Elf_Rela); 434107572Sgrehan 435107572Sgrehan pltcall = obj->pltgot; 436107572Sgrehan 437107572Sgrehan if (pltcall == NULL) { 438107572Sgrehan return; 439107572Sgrehan } 440107572Sgrehan 441107572Sgrehan /* 442107572Sgrehan * From the SVR4 PPC ABI: 443107572Sgrehan * 444107572Sgrehan * 'The first 18 words (72 bytes) of the PLT are reserved for 445107572Sgrehan * use by the dynamic linker. 446107572Sgrehan * ... 447115396Skan * 'If the executable or shared object requires N procedure 448115396Skan * linkage table entries, the link editor shall reserve 3*N 449115396Skan * words (12*N bytes) following the 18 reserved words. The 450115396Skan * first 2*N of these words are the procedure linkage table 451115396Skan * entries themselves. The static linker directs calls to bytes 452115396Skan * (72 + (i-1)*8), for i between 1 and N inclusive. The remaining 453107572Sgrehan * N words (4*N bytes) are reserved for use by the dynamic linker.' 454107572Sgrehan */ 455107572Sgrehan 456107572Sgrehan /* 457107572Sgrehan * Copy the absolute-call assembler stub into the first part of 458107572Sgrehan * the reserved PLT area. 459107572Sgrehan */ 460107572Sgrehan memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE); 461107572Sgrehan 462107572Sgrehan /* 463107572Sgrehan * Determine the address of the jumptable, which is the dyn-linker 464107572Sgrehan * reserved area after the call cells. Write the absolute address 465107572Sgrehan * of the jumptable into the absolute-call assembler code so it 466107572Sgrehan * can determine this address. 467107572Sgrehan */ 468107572Sgrehan jmptab = pltcall + 18 + N * 2; 469107572Sgrehan pltcall[1] |= _ppc_ha(jmptab); /* addis 11,11,jmptab@ha */ 470107572Sgrehan pltcall[2] |= _ppc_la(jmptab); /* lwz 11,jmptab@l(11) */ 471107572Sgrehan 472107572Sgrehan /* 473107572Sgrehan * Skip down 32 bytes into the initial reserved area and copy 474107572Sgrehan * in the standard resolving assembler call. Into this assembler, 475107572Sgrehan * insert the absolute address of the _rtld_bind_start routine 476107572Sgrehan * and the address of the relocation object. 477107572Sgrehan */ 478107572Sgrehan pltresolve = obj->pltgot + 8; 479107572Sgrehan 480107572Sgrehan memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE); 481107572Sgrehan pltresolve[0] |= _ppc_ha(_rtld_bind_start); 482107572Sgrehan pltresolve[1] |= _ppc_la(_rtld_bind_start); 483107572Sgrehan pltresolve[3] |= _ppc_ha(obj); 484107572Sgrehan pltresolve[4] |= _ppc_la(obj); 485107572Sgrehan 486107572Sgrehan /* 487107572Sgrehan * Sync the icache for the byte range represented by the 488107572Sgrehan * trampoline routines and call slots. 489107572Sgrehan */ 490107572Sgrehan __syncicache(pltcall, 72 + N * 8); 491107572Sgrehan} 492