aboutsummaryrefslogtreecommitdiff
path: root/libexec/rtld-elf
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2008-04-04 20:59:26 +0000
committerWarner Losh <imp@FreeBSD.org>2008-04-04 20:59:26 +0000
commit652d402e7b7c71a9bbbc3bf97a30dcc1966dd33e (patch)
treebd5448ef61276b8447bde82b8d4e0a807873e873 /libexec/rtld-elf
parent8d3e1f8f7a17029e1047ece9a9d148edf2c8da79 (diff)
Notes
Diffstat (limited to 'libexec/rtld-elf')
-rw-r--r--libexec/rtld-elf/mips/reloc.c357
-rw-r--r--libexec/rtld-elf/mips/rtld_machdep.h74
-rw-r--r--libexec/rtld-elf/mips/rtld_start.S127
-rw-r--r--libexec/rtld-elf/rtld.c44
-rw-r--r--libexec/rtld-elf/rtld.h5
5 files changed, 602 insertions, 5 deletions
diff --git a/libexec/rtld-elf/mips/reloc.c b/libexec/rtld-elf/mips/reloc.c
new file mode 100644
index 000000000000..ab5dff3fc235
--- /dev/null
+++ b/libexec/rtld-elf/mips/reloc.c
@@ -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);
+}
diff --git a/libexec/rtld-elf/mips/rtld_machdep.h b/libexec/rtld-elf/mips/rtld_machdep.h
new file mode 100644
index 000000000000..dd046a9d5ae8
--- /dev/null
+++ b/libexec/rtld-elf/mips/rtld_machdep.h
@@ -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
diff --git a/libexec/rtld-elf/mips/rtld_start.S b/libexec/rtld-elf/mips/rtld_start.S
new file mode 100644
index 000000000000..138729dcaee3
--- /dev/null
+++ b/libexec/rtld-elf/mips/rtld_start.S
@@ -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
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 395079fc0def..ad276327209c 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -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
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index c7be5235578a..c76bc769fd9b 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -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 */