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$ 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> 40253750Savg#include <machine/cpu.h> 41173745Sjb#include <machine/md_var.h> 42107572Sgrehan 43107572Sgrehan#include "debug.h" 44107572Sgrehan#include "rtld.h" 45107572Sgrehan 46209885Snwhitehornstruct funcdesc { 47209885Snwhitehorn Elf_Addr addr; 48209885Snwhitehorn Elf_Addr toc; 49209885Snwhitehorn Elf_Addr env; 50209885Snwhitehorn}; 51107572Sgrehan 52107572Sgrehan/* 53107572Sgrehan * Process the R_PPC_COPY relocations 54107572Sgrehan */ 55107572Sgrehanint 56107572Sgrehando_copy_relocations(Obj_Entry *dstobj) 57107572Sgrehan{ 58107572Sgrehan const Elf_Rela *relalim; 59107572Sgrehan const Elf_Rela *rela; 60107572Sgrehan 61115396Skan /* 62107572Sgrehan * COPY relocs are invalid outside of the main program 63107572Sgrehan */ 64115396Skan assert(dstobj->mainprog); 65107572Sgrehan 66115396Skan relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + 67107572Sgrehan dstobj->relasize); 68107572Sgrehan for (rela = dstobj->rela; rela < relalim; rela++) { 69107572Sgrehan void *dstaddr; 70107572Sgrehan const Elf_Sym *dstsym; 71107572Sgrehan const char *name; 72107572Sgrehan size_t size; 73107572Sgrehan const void *srcaddr; 74107572Sgrehan const Elf_Sym *srcsym = NULL; 75216695Skib const Obj_Entry *srcobj, *defobj; 76216695Skib SymLook req; 77216695Skib int res; 78107572Sgrehan 79107572Sgrehan if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) { 80107572Sgrehan continue; 81107572Sgrehan } 82107572Sgrehan 83107572Sgrehan dstaddr = (void *) (dstobj->relocbase + rela->r_offset); 84107572Sgrehan dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 85107572Sgrehan name = dstobj->strtab + dstsym->st_name; 86107572Sgrehan size = dstsym->st_size; 87216695Skib symlook_init(&req, name); 88216695Skib req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); 89233231Skib req.flags = SYMLOOK_EARLY; 90115396Skan 91115396Skan for (srcobj = dstobj->next; srcobj != NULL; 92107572Sgrehan srcobj = srcobj->next) { 93216695Skib res = symlook_obj(&req, srcobj); 94216695Skib if (res == 0) { 95216695Skib srcsym = req.sym_out; 96216695Skib defobj = req.defobj_out; 97107572Sgrehan break; 98107572Sgrehan } 99107572Sgrehan } 100107572Sgrehan 101107572Sgrehan if (srcobj == NULL) { 102107572Sgrehan _rtld_error("Undefined symbol \"%s\" " 103107572Sgrehan " referenced from COPY" 104107572Sgrehan " relocation in %s", name, dstobj->path); 105107572Sgrehan return (-1); 106107572Sgrehan } 107115396Skan 108216695Skib srcaddr = (const void *) (defobj->relocbase+srcsym->st_value); 109115396Skan memcpy(dstaddr, srcaddr, size); 110209885Snwhitehorn dbg("copy_reloc: src=%p,dst=%p,size=%zd\n",srcaddr,dstaddr,size); 111107572Sgrehan } 112115396Skan 113107572Sgrehan return (0); 114107572Sgrehan} 115107572Sgrehan 116107572Sgrehan 117107572Sgrehan/* 118107572Sgrehan * Perform early relocation of the run-time linker image 119107572Sgrehan */ 120107572Sgrehanvoid 121107572Sgrehanreloc_non_plt_self(Elf_Dyn *dynp, Elf_Addr relocbase) 122107572Sgrehan{ 123107572Sgrehan const Elf_Rela *rela = 0, *relalim; 124107572Sgrehan Elf_Addr relasz = 0; 125107572Sgrehan Elf_Addr *where; 126107572Sgrehan 127107572Sgrehan /* 128107572Sgrehan * Extract the rela/relasz values from the dynamic section 129107572Sgrehan */ 130107572Sgrehan for (; dynp->d_tag != DT_NULL; dynp++) { 131107572Sgrehan switch (dynp->d_tag) { 132107572Sgrehan case DT_RELA: 133107572Sgrehan rela = (const Elf_Rela *)(relocbase+dynp->d_un.d_ptr); 134107572Sgrehan break; 135107572Sgrehan case DT_RELASZ: 136107572Sgrehan relasz = dynp->d_un.d_val; 137107572Sgrehan break; 138107572Sgrehan } 139107572Sgrehan } 140107572Sgrehan 141107572Sgrehan /* 142115396Skan * Relocate these values 143107572Sgrehan */ 144107572Sgrehan relalim = (const Elf_Rela *)((caddr_t)rela + relasz); 145107572Sgrehan for (; rela < relalim; rela++) { 146107572Sgrehan where = (Elf_Addr *)(relocbase + rela->r_offset); 147107572Sgrehan *where = (Elf_Addr)(relocbase + rela->r_addend); 148107572Sgrehan } 149107572Sgrehan} 150107572Sgrehan 151107572Sgrehan 152107572Sgrehan/* 153115396Skan * Relocate a non-PLT object with addend. 154107572Sgrehan */ 155107572Sgrehanstatic int 156107572Sgrehanreloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela, 157233231Skib SymCache *cache, int flags, RtldLockState *lockstate) 158107572Sgrehan{ 159107572Sgrehan Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 160107572Sgrehan const Elf_Sym *def; 161107572Sgrehan const Obj_Entry *defobj; 162107572Sgrehan Elf_Addr tmp; 163107572Sgrehan 164107572Sgrehan switch (ELF_R_TYPE(rela->r_info)) { 165115396Skan 166107572Sgrehan case R_PPC_NONE: 167107572Sgrehan break; 168107572Sgrehan 169216939Snwhitehorn case R_PPC64_UADDR64: /* doubleword64 S + A */ 170216939Snwhitehorn case R_PPC64_ADDR64: 171209885Snwhitehorn case R_PPC_GLOB_DAT: 172107572Sgrehan def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 173233231Skib flags, cache, lockstate); 174107572Sgrehan if (def == NULL) { 175107572Sgrehan return (-1); 176107572Sgrehan } 177107572Sgrehan 178107572Sgrehan tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 179107572Sgrehan rela->r_addend); 180107572Sgrehan 181107572Sgrehan /* Don't issue write if unnecessary; avoid COW page fault */ 182107572Sgrehan if (*where != tmp) { 183107572Sgrehan *where = tmp; 184107572Sgrehan } 185107572Sgrehan break; 186107572Sgrehan 187209885Snwhitehorn case R_PPC_RELATIVE: /* doubleword64 B + A */ 188107572Sgrehan tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); 189115396Skan 190107572Sgrehan /* As above, don't issue write unnecessarily */ 191107572Sgrehan if (*where != tmp) { 192107572Sgrehan *where = tmp; 193107572Sgrehan } 194107572Sgrehan break; 195107572Sgrehan 196107572Sgrehan case R_PPC_COPY: 197107572Sgrehan /* 198107572Sgrehan * These are deferred until all other relocations 199107572Sgrehan * have been done. All we do here is make sure 200107572Sgrehan * that the COPY relocation is not in a shared 201107572Sgrehan * library. They are allowed only in executable 202107572Sgrehan * files. 203107572Sgrehan */ 204107572Sgrehan if (!obj->mainprog) { 205107572Sgrehan _rtld_error("%s: Unexpected R_COPY " 206107572Sgrehan " relocation in shared library", 207107572Sgrehan obj->path); 208107572Sgrehan return (-1); 209115396Skan } 210107572Sgrehan break; 211107572Sgrehan 212107572Sgrehan case R_PPC_JMP_SLOT: 213107572Sgrehan /* 214107572Sgrehan * These will be handled by the plt/jmpslot routines 215107572Sgrehan */ 216107572Sgrehan break; 217107572Sgrehan 218209885Snwhitehorn case R_PPC64_DTPMOD64: 219137122Sssouhlal def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 220233231Skib flags, cache, lockstate); 221137122Sssouhlal 222137122Sssouhlal if (def == NULL) 223137122Sssouhlal return (-1); 224137122Sssouhlal 225137122Sssouhlal *where = (Elf_Addr) defobj->tlsindex; 226137122Sssouhlal 227137122Sssouhlal break; 228137122Sssouhlal 229209885Snwhitehorn case R_PPC64_TPREL64: 230137122Sssouhlal def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 231233231Skib flags, cache, lockstate); 232137122Sssouhlal 233137122Sssouhlal if (def == NULL) 234137122Sssouhlal return (-1); 235137122Sssouhlal 236137122Sssouhlal /* 237137122Sssouhlal * We lazily allocate offsets for static TLS as we 238137122Sssouhlal * see the first relocation that references the 239137122Sssouhlal * TLS block. This allows us to support (small 240137122Sssouhlal * amounts of) static TLS in dynamically loaded 241137122Sssouhlal * modules. If we run out of space, we generate an 242137122Sssouhlal * error. 243137122Sssouhlal */ 244137122Sssouhlal if (!defobj->tls_done) { 245137122Sssouhlal if (!allocate_tls_offset((Obj_Entry*) defobj)) { 246137122Sssouhlal _rtld_error("%s: No space available for static " 247137122Sssouhlal "Thread Local Storage", obj->path); 248137122Sssouhlal return (-1); 249137122Sssouhlal } 250137122Sssouhlal } 251137122Sssouhlal 252137122Sssouhlal *(Elf_Addr **)where = *where * sizeof(Elf_Addr) 253137122Sssouhlal + (Elf_Addr *)(def->st_value + rela->r_addend 254161799Smarcel + defobj->tlsoffset - TLS_TP_OFFSET); 255137122Sssouhlal 256137122Sssouhlal break; 257137122Sssouhlal 258209885Snwhitehorn case R_PPC64_DTPREL64: 259137122Sssouhlal def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 260233231Skib flags, cache, lockstate); 261137122Sssouhlal 262137122Sssouhlal if (def == NULL) 263137122Sssouhlal return (-1); 264137122Sssouhlal 265137122Sssouhlal *where += (Elf_Addr)(def->st_value + rela->r_addend 266137122Sssouhlal - TLS_DTV_OFFSET); 267137122Sssouhlal 268137122Sssouhlal break; 269137122Sssouhlal 270107572Sgrehan default: 271209885Snwhitehorn _rtld_error("%s: Unsupported relocation type %ld" 272107572Sgrehan " in non-PLT relocations\n", obj->path, 273115396Skan ELF_R_TYPE(rela->r_info)); 274107572Sgrehan return (-1); 275107572Sgrehan } 276115396Skan return (0); 277107572Sgrehan} 278107572Sgrehan 279107572Sgrehan 280107572Sgrehan/* 281107572Sgrehan * Process non-PLT relocations 282107572Sgrehan */ 283107572Sgrehanint 284233231Skibreloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 285233231Skib RtldLockState *lockstate) 286107572Sgrehan{ 287107572Sgrehan const Elf_Rela *relalim; 288107572Sgrehan const Elf_Rela *rela; 289107572Sgrehan SymCache *cache; 290234841Skib int bytes = obj->dynsymcount * sizeof(SymCache); 291107572Sgrehan int r = -1; 292107572Sgrehan 293107572Sgrehan /* 294107572Sgrehan * The dynamic loader may be called from a thread, we have 295107572Sgrehan * limited amounts of stack available so we cannot use alloca(). 296107572Sgrehan */ 297171462Smarcel if (obj != obj_rtld) { 298209885Snwhitehorn cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, 299209885Snwhitehorn -1, 0); 300209885Snwhitehorn if (cache == MAP_FAILED) 301209885Snwhitehorn cache = NULL; 302171462Smarcel } else 303107572Sgrehan cache = NULL; 304107572Sgrehan 305107572Sgrehan /* 306107572Sgrehan * From the SVR4 PPC ABI: 307115396Skan * "The PowerPC family uses only the Elf32_Rela relocation 308107572Sgrehan * entries with explicit addends." 309107572Sgrehan */ 310107572Sgrehan relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize); 311107572Sgrehan for (rela = obj->rela; rela < relalim; rela++) { 312233231Skib if (reloc_nonplt_object(obj_rtld, obj, rela, cache, flags, 313233231Skib lockstate) < 0) 314107572Sgrehan goto done; 315107572Sgrehan } 316107572Sgrehan r = 0; 317107572Sgrehandone: 318228646Snwhitehorn if (cache) 319209885Snwhitehorn munmap(cache, bytes); 320228646Snwhitehorn 321228646Snwhitehorn /* Synchronize icache for text seg in case we made any changes */ 322228646Snwhitehorn __syncicache(obj->mapbase, obj->textsize); 323228646Snwhitehorn 324107572Sgrehan return (r); 325107572Sgrehan} 326107572Sgrehan 327209885Snwhitehorn 328107572Sgrehan/* 329107572Sgrehan * Initialise a PLT slot to the resolving trampoline 330107572Sgrehan */ 331107572Sgrehanstatic int 332107572Sgrehanreloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela) 333107572Sgrehan{ 334209885Snwhitehorn Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 335209885Snwhitehorn Elf_Addr *glink; 336209885Snwhitehorn long reloff; 337107572Sgrehan 338107572Sgrehan reloff = rela - obj->pltrela; 339107572Sgrehan 340209885Snwhitehorn if (obj->priv == NULL) 341233307Skib obj->priv = xmalloc(obj->pltrelasize); 342209885Snwhitehorn glink = obj->priv + reloff*sizeof(Elf_Addr)*2; 343209885Snwhitehorn 344209885Snwhitehorn dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%p", (void *)where, reloff, glink); 345107572Sgrehan 346209885Snwhitehorn memcpy(where, _rtld_bind_start, sizeof(struct funcdesc)); 347209885Snwhitehorn ((struct funcdesc *)(where))->env = (Elf_Addr)glink; 348209885Snwhitehorn *(glink++) = (Elf_Addr)obj; 349209885Snwhitehorn *(glink++) = reloff*sizeof(Elf_Rela); 350107572Sgrehan 351107572Sgrehan return (0); 352107572Sgrehan} 353107572Sgrehan 354107572Sgrehan 355107572Sgrehan/* 356107572Sgrehan * Process the PLT relocations. 357107572Sgrehan */ 358107572Sgrehanint 359107572Sgrehanreloc_plt(Obj_Entry *obj) 360107572Sgrehan{ 361107572Sgrehan const Elf_Rela *relalim; 362107572Sgrehan const Elf_Rela *rela; 363107572Sgrehan 364107572Sgrehan if (obj->pltrelasize != 0) { 365115396Skan relalim = (const Elf_Rela *)((char *)obj->pltrela + 366107572Sgrehan obj->pltrelasize); 367107572Sgrehan for (rela = obj->pltrela; rela < relalim; rela++) { 368107572Sgrehan assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 369107572Sgrehan 370107572Sgrehan if (reloc_plt_object(obj, rela) < 0) { 371107572Sgrehan return (-1); 372107572Sgrehan } 373107572Sgrehan } 374107572Sgrehan } 375107572Sgrehan 376107572Sgrehan return (0); 377107572Sgrehan} 378107572Sgrehan 379107572Sgrehan 380107572Sgrehan/* 381107572Sgrehan * LD_BIND_NOW was set - force relocation for all jump slots 382107572Sgrehan */ 383107572Sgrehanint 384233231Skibreloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 385107572Sgrehan{ 386107572Sgrehan const Obj_Entry *defobj; 387107572Sgrehan const Elf_Rela *relalim; 388107572Sgrehan const Elf_Rela *rela; 389107572Sgrehan const Elf_Sym *def; 390107572Sgrehan Elf_Addr *where; 391107572Sgrehan Elf_Addr target; 392107572Sgrehan 393107572Sgrehan relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 394107572Sgrehan for (rela = obj->pltrela; rela < relalim; rela++) { 395107572Sgrehan assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 396107572Sgrehan where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 397107572Sgrehan def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 398233231Skib SYMLOOK_IN_PLT | flags, NULL, lockstate); 399107572Sgrehan if (def == NULL) { 400107572Sgrehan dbg("reloc_jmpslots: sym not found"); 401107572Sgrehan return (-1); 402107572Sgrehan } 403107572Sgrehan 404107572Sgrehan target = (Elf_Addr)(defobj->relocbase + def->st_value); 405107572Sgrehan 406107572Sgrehan#if 0 407107572Sgrehan /* PG XXX */ 408107572Sgrehan dbg("\"%s\" in \"%s\" --> %p in \"%s\"", 409107572Sgrehan defobj->strtab + def->st_name, basename(obj->path), 410107572Sgrehan (void *)target, basename(defobj->path)); 411107572Sgrehan#endif 412107572Sgrehan 413212497Snwhitehorn if (def == &sym_zero) { 414212497Snwhitehorn /* Zero undefined weak symbols */ 415212497Snwhitehorn bzero(where, sizeof(struct funcdesc)); 416212497Snwhitehorn } else { 417212497Snwhitehorn reloc_jmpslot(where, target, defobj, obj, 418212497Snwhitehorn (const Elf_Rel *) rela); 419212497Snwhitehorn } 420107572Sgrehan } 421107572Sgrehan 422107572Sgrehan obj->jmpslots_done = true; 423107572Sgrehan 424107572Sgrehan return (0); 425107572Sgrehan} 426107572Sgrehan 427107572Sgrehan 428107572Sgrehan/* 429209885Snwhitehorn * Update the value of a PLT jump slot. 430107572Sgrehan */ 431107572SgrehanElf_Addr 432107572Sgrehanreloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj, 433107572Sgrehan const Obj_Entry *obj, const Elf_Rel *rel) 434107572Sgrehan{ 435209885Snwhitehorn dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)", 436209885Snwhitehorn (void *)wherep, (void *)target, *(Elf_Addr *)target, 437209885Snwhitehorn (Elf_Addr)defobj->relocbase); 438107572Sgrehan 439107572Sgrehan /* 440107572Sgrehan * At the PLT entry pointed at by `wherep', construct 441107572Sgrehan * a direct transfer to the now fully resolved function 442107572Sgrehan * address. 443107572Sgrehan */ 444107572Sgrehan 445209885Snwhitehorn memcpy(wherep, (void *)target, sizeof(struct funcdesc)); 446209885Snwhitehorn if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) { 447209885Snwhitehorn /* 448209885Snwhitehorn * XXX: It is possible (e.g. LD_BIND_NOW) that the function 449209885Snwhitehorn * descriptor we are copying has not yet been relocated. 450209885Snwhitehorn * If this happens, fix it. 451209885Snwhitehorn */ 452107572Sgrehan 453209885Snwhitehorn ((struct funcdesc *)(wherep))->addr += 454209885Snwhitehorn (Elf_Addr)defobj->relocbase; 455209885Snwhitehorn ((struct funcdesc *)(wherep))->toc += 456209885Snwhitehorn (Elf_Addr)defobj->relocbase; 457209885Snwhitehorn } 458107572Sgrehan 459209885Snwhitehorn __asm __volatile("dcbst 0,%0; sync" :: "r"(wherep) : "memory"); 460107572Sgrehan 461107572Sgrehan return (target); 462107572Sgrehan} 463107572Sgrehan 464228435Skibint 465228435Skibreloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) 466228435Skib{ 467228435Skib 468228435Skib /* XXX not implemented */ 469228435Skib return (0); 470228435Skib} 471228435Skib 472228435Skibint 473233231Skibreloc_gnu_ifunc(Obj_Entry *obj, int flags, 474233231Skib struct Struct_RtldLockState *lockstate) 475228435Skib{ 476228435Skib 477228435Skib /* XXX not implemented */ 478228435Skib return (0); 479228435Skib} 480228435Skib 481107572Sgrehanvoid 482107572Sgrehaninit_pltgot(Obj_Entry *obj) 483107572Sgrehan{ 484107572Sgrehan} 485133133Sdfr 486133133Sdfrvoid 487133133Sdfrallocate_initial_tls(Obj_Entry *list) 488133133Sdfr{ 489246556Snwhitehorn Elf_Addr **tp; 490133133Sdfr 491133133Sdfr /* 492133133Sdfr * Fix the size of the static TLS block by using the maximum 493133133Sdfr * offset allocated so far and adding a bit for dynamic modules to 494133133Sdfr * use. 495133133Sdfr */ 496133133Sdfr 497133133Sdfr tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; 498133133Sdfr 499246556Snwhitehorn tp = (Elf_Addr **) ((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16) 500137122Sssouhlal + TLS_TP_OFFSET + TLS_TCB_SIZE); 501137122Sssouhlal 502246556Snwhitehorn __asm __volatile("mr 13,%0" :: "r"(tp)); 503133133Sdfr} 504133133Sdfr 505133133Sdfrvoid* 506133133Sdfr__tls_get_addr(tls_index* ti) 507133133Sdfr{ 508246556Snwhitehorn Elf_Addr **tp; 509133133Sdfr char *p; 510133133Sdfr 511246556Snwhitehorn __asm __volatile("mr %0,13" : "=r"(tp)); 512137122Sssouhlal p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET 513137122Sssouhlal - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset); 514137122Sssouhlal 515137122Sssouhlal return (p + TLS_DTV_OFFSET); 516133133Sdfr} 517