MFp4: Add mips support for dynamic linking.
This code came from the merged mips2 and Juniper mips repositories. Warner Losh, Randall Seager, Oleksandr Tymoshenko and Olivier Houchard worked to merge, debug and integrate this code. This code may also contain code derived from NetBSD.
This commit is contained in:
parent
8d3e1f8f7a
commit
652d402e7b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=177924
357
libexec/rtld-elf/mips/reloc.c
Normal file
357
libexec/rtld-elf/mips/reloc.c
Normal file
@ -0,0 +1,357 @@
|
||||
/* $NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "debug.h"
|
||||
#include "rtld.h"
|
||||
|
||||
void
|
||||
init_pltgot(Obj_Entry *obj)
|
||||
{
|
||||
if (obj->pltgot != NULL) {
|
||||
obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start;
|
||||
obj->pltgot[1] |= (Elf_Addr) obj;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
do_copy_relocations(Obj_Entry *dstobj)
|
||||
{
|
||||
/* Do nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _rtld_bind_start(void);
|
||||
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
|
||||
|
||||
int open();
|
||||
int _open();
|
||||
|
||||
static __inline Elf_Addr
|
||||
load_ptr(void *where)
|
||||
{
|
||||
Elf_Addr res;
|
||||
|
||||
memcpy(&res, where, sizeof(res));
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
void
|
||||
store_ptr(void *where, Elf_Addr val)
|
||||
{
|
||||
|
||||
memcpy(where, &val, sizeof(val));
|
||||
}
|
||||
|
||||
void
|
||||
_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
|
||||
{
|
||||
const Elf_Rel *rel = 0, *rellim;
|
||||
Elf_Addr relsz = 0;
|
||||
const Elf_Sym *symtab = NULL, *sym;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr *got = NULL;
|
||||
Elf_Word local_gotno = 0, symtabno = 0, gotsym = 0;
|
||||
int i;
|
||||
|
||||
for (; dynp->d_tag != DT_NULL; dynp++) {
|
||||
switch (dynp->d_tag) {
|
||||
case DT_REL:
|
||||
rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
|
||||
break;
|
||||
case DT_RELSZ:
|
||||
relsz = dynp->d_un.d_val;
|
||||
break;
|
||||
case DT_SYMTAB:
|
||||
symtab = (const Elf_Sym *)(relocbase + dynp->d_un.d_ptr);
|
||||
break;
|
||||
case DT_PLTGOT:
|
||||
got = (Elf_Addr *)(relocbase + dynp->d_un.d_ptr);
|
||||
break;
|
||||
case DT_MIPS_LOCAL_GOTNO:
|
||||
local_gotno = dynp->d_un.d_val;
|
||||
break;
|
||||
case DT_MIPS_SYMTABNO:
|
||||
symtabno = dynp->d_un.d_val;
|
||||
break;
|
||||
case DT_MIPS_GOTSYM:
|
||||
gotsym = dynp->d_un.d_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i = (got[1] & 0x80000000) ? 2 : 1;
|
||||
/* Relocate the local GOT entries */
|
||||
got += i;
|
||||
for (; i < local_gotno; i++) {
|
||||
*got++ += relocbase;
|
||||
}
|
||||
|
||||
sym = symtab + gotsym;
|
||||
/* Now do the global GOT entries */
|
||||
for (i = gotsym; i < symtabno; i++) {
|
||||
*got = sym->st_value + relocbase;
|
||||
++sym;
|
||||
++got;
|
||||
}
|
||||
|
||||
rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
|
||||
for (; rel < rellim; rel++) {
|
||||
where = (void *)(relocbase + rel->r_offset);
|
||||
|
||||
switch (ELF_R_TYPE(rel->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(REL32):
|
||||
assert(ELF_R_SYM(rel->r_info) < gotsym);
|
||||
sym = symtab + ELF_R_SYM(rel->r_info);
|
||||
assert(ELF_ST_BIND(sym->st_info) == STB_LOCAL);
|
||||
store_ptr(where, load_ptr(where) + relocbase);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Elf_Addr
|
||||
_mips_rtld_bind(Obj_Entry *obj, Elf_Size reloff)
|
||||
{
|
||||
Elf_Addr *got = obj->pltgot;
|
||||
const Elf_Sym *def;
|
||||
const Obj_Entry *defobj;
|
||||
Elf_Addr target;
|
||||
|
||||
def = find_symdef(reloff, obj, &defobj, SYMLOOK_IN_PLT, NULL);
|
||||
if (def == NULL)
|
||||
_rtld_error("bind failed no symbol");
|
||||
|
||||
target = (Elf_Addr)(defobj->relocbase + def->st_value);
|
||||
dbg("bind now/fixup at %s sym # %d in %s --> was=%p new=%p",
|
||||
obj->path,
|
||||
reloff, defobj->strtab + def->st_name,
|
||||
(void *)got[obj->local_gotno + reloff - obj->gotsym],
|
||||
(void *)target);
|
||||
got[obj->local_gotno + reloff - obj->gotsym] = target;
|
||||
return (Elf_Addr)target;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is possible for the compiler to emit relocations for unaligned data.
|
||||
* We handle this situation with these inlines.
|
||||
*/
|
||||
#define RELOC_ALIGNED_P(x) \
|
||||
(((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
|
||||
|
||||
/*
|
||||
* Process non-PLT relocations
|
||||
*/
|
||||
int
|
||||
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
|
||||
{
|
||||
const Elf_Rel *rel;
|
||||
const Elf_Rel *rellim;
|
||||
Elf_Addr *got = obj->pltgot;
|
||||
const Elf_Sym *sym, *def;
|
||||
const Obj_Entry *defobj;
|
||||
int i;
|
||||
|
||||
/* The relocation for the dynamic loader has already been done. */
|
||||
if (obj == obj_rtld)
|
||||
return (0);
|
||||
|
||||
i = (got[1] & 0x80000000) ? 2 : 1;
|
||||
|
||||
/* Relocate the local GOT entries */
|
||||
got += i;
|
||||
dbg("got:%p for %d entries adding %x",
|
||||
got, obj->local_gotno, (uint32_t)obj->relocbase);
|
||||
for (; i < obj->local_gotno; i++) {
|
||||
*got += (Elf_Addr)obj->relocbase;
|
||||
got++;
|
||||
}
|
||||
sym = obj->symtab + obj->gotsym;
|
||||
|
||||
|
||||
dbg("got:%p for %d entries",
|
||||
got, obj->symtabno);
|
||||
/* Now do the global GOT entries */
|
||||
for (i = obj->gotsym; i < obj->symtabno; i++) {
|
||||
if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
|
||||
sym->st_value != 0 && sym->st_shndx == SHN_UNDEF) {
|
||||
/*
|
||||
* If there are non-PLT references to the function,
|
||||
* st_value should be 0, forcing us to resolve the
|
||||
* address immediately.
|
||||
*
|
||||
* XXX DANGER WILL ROBINSON!
|
||||
* The linker is not outputting PLT slots for calls to
|
||||
* functions that are defined in the same shared
|
||||
* library. This is a bug, because it can screw up
|
||||
* link ordering rules if the symbol is defined in
|
||||
* more than one module. For now, if there is a
|
||||
* definition, we fail the test above and force a full
|
||||
* symbol lookup. This means that all intra-module
|
||||
* calls are bound immediately. - mycroft, 2003/09/24
|
||||
*/
|
||||
*got = sym->st_value + (Elf_Addr)obj->relocbase;
|
||||
if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) {
|
||||
dbg("Warning2, i:%d maps to relocbase address:%x",
|
||||
i, (uint32_t)obj->relocbase);
|
||||
}
|
||||
|
||||
} else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) {
|
||||
/* Symbols with index SHN_ABS are not relocated. */
|
||||
if (sym->st_shndx != SHN_ABS) {
|
||||
*got = sym->st_value +
|
||||
(Elf_Addr)obj->relocbase;
|
||||
if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) {
|
||||
dbg("Warning3, i:%d maps to relocbase address:%x",
|
||||
i, (uint32_t)obj->relocbase);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* TODO: add cache here */
|
||||
def = find_symdef(i, obj, &defobj, false, NULL);
|
||||
if (def == NULL) {
|
||||
dbg("Warning4, cant find symbole %d", i);
|
||||
return -1;
|
||||
}
|
||||
*got = def->st_value + (Elf_Addr)defobj->relocbase;
|
||||
if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) {
|
||||
dbg("Warning4, i:%d maps to relocbase address:%x",
|
||||
i, (uint32_t)obj->relocbase);
|
||||
dbg("via first obj symbol %s",
|
||||
obj->strtab + obj->symtab[i].st_name);
|
||||
dbg("found in obj %p:%s",
|
||||
defobj, defobj->path);
|
||||
}
|
||||
}
|
||||
++sym;
|
||||
++got;
|
||||
}
|
||||
got = obj->pltgot;
|
||||
rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize);
|
||||
for (rel = obj->rel; rel < rellim; rel++) {
|
||||
void *where;
|
||||
Elf_Addr tmp;
|
||||
unsigned long symnum;
|
||||
|
||||
where = obj->relocbase + rel->r_offset;
|
||||
symnum = ELF_R_SYM(rel->r_info);
|
||||
switch (ELF_R_TYPE(rel->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(REL32):
|
||||
/* 32-bit PC-relative reference */
|
||||
def = obj->symtab + symnum;
|
||||
tmp = load_ptr(where);
|
||||
if (tmp == 0) {
|
||||
def = find_symdef(symnum, obj, &defobj, false, NULL);
|
||||
if (def == NULL) {
|
||||
dbg("Warning5, cant find symbole %d:%s", (int)symnum,
|
||||
obj->strtab + obj->symtab[symnum].st_name);
|
||||
} else {
|
||||
tmp = def->st_value + (Elf_Addr)defobj->relocbase;
|
||||
dbg("Correctiong symnum:%d:%s to addr:%x", (int)symnum,
|
||||
obj->strtab + obj->symtab[symnum].st_name,
|
||||
(u_int32_t)tmp
|
||||
);
|
||||
}
|
||||
} else {
|
||||
tmp += (Elf_Addr)obj->relocbase;
|
||||
}
|
||||
store_ptr(where, tmp);
|
||||
if (tmp == (Elf_Addr)obj->relocbase) {
|
||||
dbg("rel sym %p falls on relocbase symidx:%x symbol:%s", rel,
|
||||
(uint32_t)ELF_R_SYM(rel->r_info),
|
||||
obj->strtab + obj->symtab[symnum].st_name
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dbg("sym = %lu, type = %lu, offset = %p, "
|
||||
"contents = %p, symbol = %s",
|
||||
symnum, (u_long)ELF_R_TYPE(rel->r_info),
|
||||
(void *)rel->r_offset, (void *)load_ptr(where),
|
||||
obj->strtab + obj->symtab[symnum].st_name);
|
||||
_rtld_error("%s: Unsupported relocation type %ld "
|
||||
"in non-PLT relocations\n",
|
||||
obj->path, (u_long) ELF_R_TYPE(rel->r_info));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the PLT relocations.
|
||||
*/
|
||||
int
|
||||
reloc_plt(Obj_Entry *obj)
|
||||
{
|
||||
const Elf_Rel *rellim;
|
||||
const Elf_Rel *rel;
|
||||
|
||||
dbg("reloc_plt obj:%p pltrel:%p sz:%d", obj, obj->pltrel, (int)obj->pltrelsize);
|
||||
dbg("gottable %p num syms:%d", obj->pltgot, obj->symtabno );
|
||||
dbg("*****************************************************");
|
||||
rellim = (const Elf_Rel *)((char *)obj->pltrel +
|
||||
obj->pltrelsize);
|
||||
for (rel = obj->pltrel; rel < rellim; rel++) {
|
||||
Elf_Addr *where;
|
||||
where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
|
||||
*where += (Elf_Addr )obj->relocbase;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* LD_BIND_NOW was set - force relocation for all jump slots
|
||||
*/
|
||||
int
|
||||
reloc_jmpslots(Obj_Entry *obj)
|
||||
{
|
||||
/* Do nothing */
|
||||
obj->jmpslots_done = true;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
{
|
||||
|
||||
/* Do nothing */
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
void
|
||||
allocate_initial_tls(Obj_Entry *objs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void *
|
||||
__tls_get_addr(tls_index* ti)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
74
libexec/rtld-elf/mips/rtld_machdep.h
Normal file
74
libexec/rtld-elf/mips/rtld_machdep.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 John D. Polstra.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef RTLD_MACHDEP_H
|
||||
#define RTLD_MACHDEP_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
|
||||
#define CACHE_LINE_SIZE 32
|
||||
|
||||
struct Struct_Obj_Entry;
|
||||
|
||||
/* Return the address of the .dynamic section in the dynamic linker. */
|
||||
#define rtld_dynamic(obj) (&_DYNAMIC)
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *defobj,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
||||
#define call_initfini_pointer(obj, target) \
|
||||
(((InitFunc)(target))())
|
||||
|
||||
typedef struct {
|
||||
unsigned long ti_module;
|
||||
unsigned long ti_offset;
|
||||
} tls_index;
|
||||
|
||||
#define round(size, align) \
|
||||
(((size) + (align) - 1) & ~((align) - 1))
|
||||
#define calculate_first_tls_offset(size, align) \
|
||||
round(size, align)
|
||||
#define calculate_tls_offset(prev_offset, prev_size, size, align) \
|
||||
round(prev_offset + prev_size, align)
|
||||
#define calculate_tls_end(off, size) ((off) + (size))
|
||||
|
||||
|
||||
/*
|
||||
* Lazy binding entry point, called via PLT.
|
||||
*/
|
||||
void _rtld_bind_start(void);
|
||||
|
||||
extern void *__tls_get_addr(tls_index *ti);
|
||||
|
||||
#endif
|
127
libexec/rtld-elf/mips/rtld_start.S
Normal file
127
libexec/rtld-elf/mips/rtld_start.S
Normal file
@ -0,0 +1,127 @@
|
||||
/* $NetBSD: rtld_start.S,v 1.9 2002/10/05 11:59:05 mycroft Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
|
||||
* Portions copyright 2002 Charles M. Hannum <root@ihack.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
.globl _C_LABEL(_rtld_relocate_nonplt_self)
|
||||
.globl _C_LABEL(_rtld)
|
||||
|
||||
LEAF(rtld_start)
|
||||
.abicalls
|
||||
.set noreorder
|
||||
|
||||
.cpload t9
|
||||
addu sp, sp, -16 /* adjust stack pointer */
|
||||
/* keep it aligned */
|
||||
.cprestore 0 /* -> 0(sp) for gp */
|
||||
/* -> 4(sp) for atexit */
|
||||
/* -> 8(sp) for obj_main */
|
||||
move s0,a0 /* save stack pointer from a0 */
|
||||
move s1,a3 /* save ps_strings pointer */
|
||||
|
||||
la a1, 1f
|
||||
bal 1f
|
||||
nop
|
||||
1: subu a1, ra, a1 /* relocbase */
|
||||
la t9,_C_LABEL(_rtld_relocate_nonplt_self)
|
||||
move s2,a1
|
||||
la a0,_DYNAMIC
|
||||
addu t9, a1, t9
|
||||
jalr t9
|
||||
addu a0, a1, a0 /* &_DYNAMIC */
|
||||
|
||||
|
||||
move a0, s0 /* stack pointer */
|
||||
addu a1, sp, 4 /* &exit_proc */
|
||||
addu a2, sp, 8 /* &objp */
|
||||
addu sp, sp, -16 /* arguments slot */
|
||||
jal _C_LABEL(_rtld) /* v0 = _rtld(sp, exit_proc, objp) */
|
||||
nop
|
||||
addu sp, sp, 16
|
||||
|
||||
move a0, s0 /* arguments pointer */
|
||||
move a3, s1 /* arguments pointer */
|
||||
lw a1, 4(sp) /* our atexit function */
|
||||
lw a2, 8(sp) /* obj_main entry */
|
||||
addu sp, sp, 16 /* readjust stack */
|
||||
move t9,v0
|
||||
move a2,s1 /* restore ps_strings */
|
||||
jr t9 /* _start(ap, cleanup, obj, ps_strings); */
|
||||
nop
|
||||
|
||||
END(rtld_start)
|
||||
|
||||
.globl _rtld_bind_start
|
||||
.ent _rtld_bind_start
|
||||
_rtld_bind_start:
|
||||
/* ABI conventions for stubs:
|
||||
* t8 contains symbol index
|
||||
* t7 contains return address
|
||||
*/
|
||||
.frame sp, 0, ra /* satisfy compiler */
|
||||
|
||||
move v1,gp /* save old GP */
|
||||
add t9,8 /* modify T9 to point at .cpload */
|
||||
.cpload t9
|
||||
subu sp,48 /* save arguments and sp value */
|
||||
.cprestore 36
|
||||
sw a0,16(sp)
|
||||
sw a1,20(sp)
|
||||
sw a2,24(sp)
|
||||
sw a3,28(sp)
|
||||
sw s0,32(sp)
|
||||
sw t7,40(sp)
|
||||
move s0,sp
|
||||
move a0,v1 /* old GP */
|
||||
subu a0,a0,0x7ff0 /* The offset of $gp from the */
|
||||
/* beginning of the .got section: */
|
||||
/* $gp = .got + 0x7ff0, so */
|
||||
/* .got = $gp - 0x7ff0 */
|
||||
/* Simple math as you can see. */
|
||||
|
||||
lw a0,4(a0) /* object = pltgot[1] & 0x7fffffff */
|
||||
and a0,a0,0x7fffffff
|
||||
move a1,t8 /* symbol index */
|
||||
|
||||
jal _C_LABEL(_mips_rtld_bind)
|
||||
nop
|
||||
move sp,s0
|
||||
lw ra,40(sp)
|
||||
lw a0,16(sp)
|
||||
lw a1,20(sp)
|
||||
lw a2,24(sp)
|
||||
lw a3,28(sp)
|
||||
lw s0,32(sp)
|
||||
addu sp,48
|
||||
move t9,v0
|
||||
jr t9
|
||||
nop
|
||||
.end _rtld_bind_start
|
@ -773,12 +773,19 @@ digest_dynamic(Obj_Entry *obj, int early)
|
||||
obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Don't process DT_DEBUG on MIPS as the dynamic section
|
||||
* is mapped read-only. DT_MIPS_RLD_MAP is used instead.
|
||||
*/
|
||||
|
||||
#ifndef __mips__
|
||||
case DT_DEBUG:
|
||||
/* XXX - not implemented yet */
|
||||
if (!early)
|
||||
dbg("Filling in DT_DEBUG entry");
|
||||
((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case DT_FLAGS:
|
||||
if (dynp->d_un.d_val & DF_ORIGIN) {
|
||||
@ -795,6 +802,27 @@ digest_dynamic(Obj_Entry *obj, int early)
|
||||
if (dynp->d_un.d_val & DF_STATIC_TLS)
|
||||
;
|
||||
break;
|
||||
#ifdef __mips__
|
||||
case DT_MIPS_LOCAL_GOTNO:
|
||||
obj->local_gotno = dynp->d_un.d_val;
|
||||
break;
|
||||
|
||||
case DT_MIPS_SYMTABNO:
|
||||
obj->symtabno = dynp->d_un.d_val;
|
||||
break;
|
||||
|
||||
case DT_MIPS_GOTSYM:
|
||||
obj->gotsym = dynp->d_un.d_val;
|
||||
break;
|
||||
|
||||
case DT_MIPS_RLD_MAP:
|
||||
#ifdef notyet
|
||||
if (!early)
|
||||
dbg("Filling in DT_DEBUG entry");
|
||||
((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
if (!early) {
|
||||
@ -1165,7 +1193,10 @@ init_rtld(caddr_t mapbase)
|
||||
objtmp.dynamic = rtld_dynamic(&objtmp);
|
||||
digest_dynamic(&objtmp, 1);
|
||||
assert(objtmp.needed == NULL);
|
||||
#if !defined(__mips__)
|
||||
/* MIPS and SH{3,5} have a bogus DT_TEXTREL. */
|
||||
assert(!objtmp.textrel);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Temporarily put the dynamic linker entry into the object list, so
|
||||
@ -2569,11 +2600,14 @@ symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj,
|
||||
continue;
|
||||
/* fallthrough */
|
||||
case STT_TLS:
|
||||
if (symp->st_shndx != SHN_UNDEF ||
|
||||
((flags & SYMLOOK_IN_PLT) == 0 &&
|
||||
ELF_ST_TYPE(symp->st_info) == STT_FUNC))
|
||||
if (symp->st_shndx != SHN_UNDEF)
|
||||
break;
|
||||
#ifndef __mips__
|
||||
else if (((flags & SYMLOOK_IN_PLT) == 0) &&
|
||||
(ELF_ST_TYPE(symp->st_info) == STT_FUNC))
|
||||
break;
|
||||
/* fallthrough */
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -2937,7 +2971,7 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign)
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \
|
||||
defined(__arm__)
|
||||
defined(__arm__) || defined(__mips__)
|
||||
|
||||
/*
|
||||
* Allocate Static TLS using the Variant II method.
|
||||
@ -3103,7 +3137,7 @@ void
|
||||
free_tls_offset(Obj_Entry *obj)
|
||||
{
|
||||
#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \
|
||||
defined(__arm__)
|
||||
defined(__arm__) || defined(__mips__)
|
||||
/*
|
||||
* If we were the last thing to allocate out of the static TLS
|
||||
* block, we give our space back to the 'allocator'. This is a
|
||||
|
@ -178,6 +178,11 @@ typedef struct Struct_Obj_Entry {
|
||||
const Elf_Sym *symtab; /* Symbol table */
|
||||
const char *strtab; /* String table */
|
||||
unsigned long strsize; /* Size in bytes of string table */
|
||||
#ifdef __mips__
|
||||
Elf_Word local_gotno; /* Number of local GOT entries */
|
||||
Elf_Word symtabno; /* Number of dynamic symbols */
|
||||
Elf_Word gotsym; /* First dynamic symbol in GOT */
|
||||
#endif
|
||||
|
||||
const Elf_Verneed *verneed; /* Required versions. */
|
||||
Elf_Word verneednum; /* Number of entries in verneed table */
|
||||
|
Loading…
Reference in New Issue
Block a user