diff options
| author | Warner Losh <imp@FreeBSD.org> | 2008-04-04 20:59:26 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2008-04-04 20:59:26 +0000 |
| commit | 652d402e7b7c71a9bbbc3bf97a30dcc1966dd33e (patch) | |
| tree | bd5448ef61276b8447bde82b8d4e0a807873e873 /libexec/rtld-elf | |
| parent | 8d3e1f8f7a17029e1047ece9a9d148edf2c8da79 (diff) | |
Notes
Diffstat (limited to 'libexec/rtld-elf')
| -rw-r--r-- | libexec/rtld-elf/mips/reloc.c | 357 | ||||
| -rw-r--r-- | libexec/rtld-elf/mips/rtld_machdep.h | 74 | ||||
| -rw-r--r-- | libexec/rtld-elf/mips/rtld_start.S | 127 | ||||
| -rw-r--r-- | libexec/rtld-elf/rtld.c | 44 | ||||
| -rw-r--r-- | libexec/rtld-elf/rtld.h | 5 |
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 */ |
