1 /* $NetBSD: mips_reloc.c,v 1.5 2001/11/24 18:07:04 rafal Exp $ */ 2 3 /* 4 * Copyright 1997 Michael L. Hitch <mhitch@montana.edu> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 31 #include <stdarg.h> 32 #include <sys/types.h> 33 #include <sys/stat.h> 34 35 #include "debug.h" 36 #include "rtld.h" 37 38 /* 39 * Relocate a MIPS GOT 40 */ 41 42 void 43 _rtld_relocate_mips_got(obj) 44 Obj_Entry *obj; 45 { 46 Elf_Addr *got = obj->pltgot; 47 const Elf_Sym *sym = obj->symtab; 48 const Elf_Sym *def; 49 const Obj_Entry *defobj; 50 Elf_Word info; 51 int i; 52 53 i = (got[1] & 0x80000000) ? 2 : 1; 54 /* Relocate the local GOT entries */ 55 while (i < obj->local_gotno) 56 got[i++] += (Elf_Word)obj->relocbase; 57 got += obj->local_gotno; 58 i = obj->symtabno - obj->gotsym; 59 sym += obj->gotsym; 60 /* Now do the global GOT entries */ 61 while (i--) { 62 rdbg(1, (" doing got %d sym %p (%s, %x)", 63 obj->symtabno - obj->gotsym - i - 1, 64 sym, sym->st_name + obj->strtab, *got)); 65 66 info = ELF32_R_INFO(obj->symtabno - i - 1, sym->st_info); 67 def = _rtld_find_symdef(_rtld_objlist, info, NULL, obj, 68 &defobj, true); 69 70 if (def == NULL) 71 _rtld_error( 72 "%s: Undefined PLT symbol \"%s\" (reloc type = %ld, symnum = %ld)", 73 obj->path, sym->st_name + obj->strtab, 74 (u_long) ELF_R_TYPE(info), 75 (u_long) obj->symtabno - i - 1); 76 else { 77 78 if (sym->st_shndx == SHN_UNDEF) { 79 #if 0 /* These don't seem to work? */ 80 81 if (ELFDEFNNAME(ST_TYPE)(sym->st_info) == 82 STT_FUNC) { 83 if (sym->st_value) 84 *got = sym->st_value + 85 (Elf_Word)obj->relocbase; 86 else 87 *got = def->st_value + 88 (Elf_Word)defobj->relocbase; 89 } else 90 #endif 91 *got = def->st_value + 92 (Elf_Word)defobj->relocbase; 93 } else if (sym->st_shndx == SHN_COMMON) { 94 *got = def->st_value + 95 (Elf_Word)defobj->relocbase; 96 } else if (ELFDEFNNAME(ST_TYPE)(sym->st_info) == 97 STT_FUNC && 98 *got != sym->st_value) { 99 *got += (Elf_Word)obj->relocbase; 100 } else if (ELFDEFNNAME(ST_TYPE)(sym->st_info) == 101 STT_SECTION && ELFDEFNNAME(ST_BIND)(sym->st_info) == 102 STB_GLOBAL) { 103 if (sym->st_shndx == SHN_ABS) 104 *got = sym->st_value + 105 (Elf_Word)obj->relocbase; 106 /* else SGI stuff ignored */ 107 } else 108 *got = def->st_value + 109 (Elf_Word)defobj->relocbase; 110 } 111 112 ++sym; 113 ++got; 114 } 115 } 116 117 /* 118 * _rtld_bind_mips(symbol_index, return_address, old_gp, stub_return_addr) 119 */ 120 121 caddr_t 122 _rtld_bind_mips(a0, a1, a2, a3) 123 Elf_Word a0; 124 Elf_Addr a1, a2, a3; 125 { 126 Elf_Addr *u = (Elf_Addr *)(a2 - 0x7ff0); 127 Obj_Entry *obj = (Obj_Entry *)(u[1] & 0x7fffffff); 128 const Elf_Sym *def; 129 const Obj_Entry *defobj; 130 131 def = _rtld_find_symdef(_rtld_objlist, a0 << 8, NULL, obj, &defobj, 132 true); 133 if (def) { 134 u[obj->local_gotno + a0 - obj->gotsym] = (Elf_Addr) 135 (def->st_value + defobj->relocbase); 136 return((caddr_t)(def->st_value + defobj->relocbase)); 137 } 138 139 return(NULL); /* XXX */ 140 } 141