1 //===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "RuntimeDyldELFMips.h" 11 #include "llvm/BinaryFormat/ELF.h" 12 13 #define DEBUG_TYPE "dyld" 14 15 void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE, 16 uint64_t Value) { 17 const SectionEntry &Section = Sections[RE.SectionID]; 18 if (IsMipsO32ABI) 19 resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend); 20 else if (IsMipsN32ABI) { 21 resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, 22 RE.SymOffset, RE.SectionID); 23 } else if (IsMipsN64ABI) 24 resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, 25 RE.SymOffset, RE.SectionID); 26 else 27 llvm_unreachable("Mips ABI not handled"); 28 } 29 30 uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE, 31 uint64_t Value, 32 uint64_t Addend) { 33 if (IsMipsN32ABI) { 34 const SectionEntry &Section = Sections[RE.SectionID]; 35 Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType, 36 Addend, RE.SymOffset, RE.SectionID); 37 return Value; 38 } 39 llvm_unreachable("Not reachable"); 40 } 41 42 void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE, 43 uint64_t Value) { 44 if (IsMipsN32ABI) { 45 const SectionEntry &Section = Sections[RE.SectionID]; 46 applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value, 47 RE.RelType); 48 return; 49 } 50 llvm_unreachable("Not reachable"); 51 } 52 53 int64_t 54 RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section, 55 uint64_t Offset, uint64_t Value, 56 uint32_t Type) { 57 58 LLVM_DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x" 59 << format("%llx", Section.getAddressWithOffset(Offset)) 60 << " FinalAddress: 0x" 61 << format("%llx", Section.getLoadAddressWithOffset(Offset)) 62 << " Value: 0x" << format("%llx", Value) << " Type: 0x" 63 << format("%x", Type) << "\n"); 64 65 switch (Type) { 66 default: 67 llvm_unreachable("Unknown relocation type!"); 68 return Value; 69 case ELF::R_MIPS_32: 70 return Value; 71 case ELF::R_MIPS_26: 72 return Value >> 2; 73 case ELF::R_MIPS_HI16: 74 // Get the higher 16-bits. Also add 1 if bit 15 is 1. 75 return (Value + 0x8000) >> 16; 76 case ELF::R_MIPS_LO16: 77 return Value; 78 case ELF::R_MIPS_PC32: { 79 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 80 return Value - FinalAddress; 81 } 82 case ELF::R_MIPS_PC16: { 83 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 84 return (Value - FinalAddress) >> 2; 85 } 86 case ELF::R_MIPS_PC19_S2: { 87 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 88 return (Value - (FinalAddress & ~0x3)) >> 2; 89 } 90 case ELF::R_MIPS_PC21_S2: { 91 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 92 return (Value - FinalAddress) >> 2; 93 } 94 case ELF::R_MIPS_PC26_S2: { 95 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 96 return (Value - FinalAddress) >> 2; 97 } 98 case ELF::R_MIPS_PCHI16: { 99 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 100 return (Value - FinalAddress + 0x8000) >> 16; 101 } 102 case ELF::R_MIPS_PCLO16: { 103 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 104 return Value - FinalAddress; 105 } 106 } 107 } 108 109 int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation( 110 const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, 111 int64_t Addend, uint64_t SymOffset, SID SectionID) { 112 113 LLVM_DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x" 114 << format("%llx", Section.getAddressWithOffset(Offset)) 115 << " FinalAddress: 0x" 116 << format("%llx", Section.getLoadAddressWithOffset(Offset)) 117 << " Value: 0x" << format("%llx", Value) << " Type: 0x" 118 << format("%x", Type) << " Addend: 0x" 119 << format("%llx", Addend) 120 << " Offset: " << format("%llx" PRIx64, Offset) 121 << " SID: " << format("%d", SectionID) 122 << " SymOffset: " << format("%x", SymOffset) << "\n"); 123 124 switch (Type) { 125 default: 126 llvm_unreachable("Not implemented relocation type!"); 127 break; 128 case ELF::R_MIPS_JALR: 129 case ELF::R_MIPS_NONE: 130 break; 131 case ELF::R_MIPS_32: 132 case ELF::R_MIPS_64: 133 return Value + Addend; 134 case ELF::R_MIPS_26: 135 return ((Value + Addend) >> 2) & 0x3ffffff; 136 case ELF::R_MIPS_GPREL16: { 137 uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]); 138 return Value + Addend - (GOTAddr + 0x7ff0); 139 } 140 case ELF::R_MIPS_SUB: 141 return Value - Addend; 142 case ELF::R_MIPS_HI16: 143 // Get the higher 16-bits. Also add 1 if bit 15 is 1. 144 return ((Value + Addend + 0x8000) >> 16) & 0xffff; 145 case ELF::R_MIPS_LO16: 146 return (Value + Addend) & 0xffff; 147 case ELF::R_MIPS_HIGHER: 148 return ((Value + Addend + 0x80008000) >> 32) & 0xffff; 149 case ELF::R_MIPS_HIGHEST: 150 return ((Value + Addend + 0x800080008000) >> 48) & 0xffff; 151 case ELF::R_MIPS_CALL16: 152 case ELF::R_MIPS_GOT_DISP: 153 case ELF::R_MIPS_GOT_PAGE: { 154 uint8_t *LocalGOTAddr = 155 getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset; 156 uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize()); 157 158 Value += Addend; 159 if (Type == ELF::R_MIPS_GOT_PAGE) 160 Value = (Value + 0x8000) & ~0xffff; 161 162 if (GOTEntry) 163 assert(GOTEntry == Value && 164 "GOT entry has two different addresses."); 165 else 166 writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize()); 167 168 return (SymOffset - 0x7ff0) & 0xffff; 169 } 170 case ELF::R_MIPS_GOT_OFST: { 171 int64_t page = (Value + Addend + 0x8000) & ~0xffff; 172 return (Value + Addend - page) & 0xffff; 173 } 174 case ELF::R_MIPS_GPREL32: { 175 uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]); 176 return Value + Addend - (GOTAddr + 0x7ff0); 177 } 178 case ELF::R_MIPS_PC16: { 179 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 180 return ((Value + Addend - FinalAddress) >> 2) & 0xffff; 181 } 182 case ELF::R_MIPS_PC32: { 183 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 184 return Value + Addend - FinalAddress; 185 } 186 case ELF::R_MIPS_PC18_S3: { 187 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 188 return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff; 189 } 190 case ELF::R_MIPS_PC19_S2: { 191 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 192 return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff; 193 } 194 case ELF::R_MIPS_PC21_S2: { 195 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 196 return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff; 197 } 198 case ELF::R_MIPS_PC26_S2: { 199 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 200 return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff; 201 } 202 case ELF::R_MIPS_PCHI16: { 203 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 204 return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff; 205 } 206 case ELF::R_MIPS_PCLO16: { 207 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 208 return (Value + Addend - FinalAddress) & 0xffff; 209 } 210 } 211 return 0; 212 } 213 214 void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value, 215 uint32_t Type) { 216 uint32_t Insn = readBytesUnaligned(TargetPtr, 4); 217 218 switch (Type) { 219 default: 220 llvm_unreachable("Unknown relocation type!"); 221 break; 222 case ELF::R_MIPS_GPREL16: 223 case ELF::R_MIPS_HI16: 224 case ELF::R_MIPS_LO16: 225 case ELF::R_MIPS_HIGHER: 226 case ELF::R_MIPS_HIGHEST: 227 case ELF::R_MIPS_PC16: 228 case ELF::R_MIPS_PCHI16: 229 case ELF::R_MIPS_PCLO16: 230 case ELF::R_MIPS_CALL16: 231 case ELF::R_MIPS_GOT_DISP: 232 case ELF::R_MIPS_GOT_PAGE: 233 case ELF::R_MIPS_GOT_OFST: 234 Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff); 235 writeBytesUnaligned(Insn, TargetPtr, 4); 236 break; 237 case ELF::R_MIPS_PC18_S3: 238 Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff); 239 writeBytesUnaligned(Insn, TargetPtr, 4); 240 break; 241 case ELF::R_MIPS_PC19_S2: 242 Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff); 243 writeBytesUnaligned(Insn, TargetPtr, 4); 244 break; 245 case ELF::R_MIPS_PC21_S2: 246 Insn = (Insn & 0xffe00000) | (Value & 0x001fffff); 247 writeBytesUnaligned(Insn, TargetPtr, 4); 248 break; 249 case ELF::R_MIPS_26: 250 case ELF::R_MIPS_PC26_S2: 251 Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff); 252 writeBytesUnaligned(Insn, TargetPtr, 4); 253 break; 254 case ELF::R_MIPS_32: 255 case ELF::R_MIPS_GPREL32: 256 case ELF::R_MIPS_PC32: 257 writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4); 258 break; 259 case ELF::R_MIPS_64: 260 case ELF::R_MIPS_SUB: 261 writeBytesUnaligned(Value, TargetPtr, 8); 262 break; 263 } 264 } 265 266 void RuntimeDyldELFMips::resolveMIPSN32Relocation( 267 const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, 268 int64_t Addend, uint64_t SymOffset, SID SectionID) { 269 int64_t CalculatedValue = evaluateMIPS64Relocation( 270 Section, Offset, Value, Type, Addend, SymOffset, SectionID); 271 applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue, 272 Type); 273 } 274 275 void RuntimeDyldELFMips::resolveMIPSN64Relocation( 276 const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, 277 int64_t Addend, uint64_t SymOffset, SID SectionID) { 278 uint32_t r_type = Type & 0xff; 279 uint32_t r_type2 = (Type >> 8) & 0xff; 280 uint32_t r_type3 = (Type >> 16) & 0xff; 281 282 // RelType is used to keep information for which relocation type we are 283 // applying relocation. 284 uint32_t RelType = r_type; 285 int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value, 286 RelType, Addend, 287 SymOffset, SectionID); 288 if (r_type2 != ELF::R_MIPS_NONE) { 289 RelType = r_type2; 290 CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType, 291 CalculatedValue, SymOffset, 292 SectionID); 293 } 294 if (r_type3 != ELF::R_MIPS_NONE) { 295 RelType = r_type3; 296 CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType, 297 CalculatedValue, SymOffset, 298 SectionID); 299 } 300 applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue, 301 RelType); 302 } 303 304 void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section, 305 uint64_t Offset, 306 uint32_t Value, uint32_t Type, 307 int32_t Addend) { 308 uint8_t *TargetPtr = Section.getAddressWithOffset(Offset); 309 Value += Addend; 310 311 LLVM_DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: " 312 << Section.getAddressWithOffset(Offset) << " FinalAddress: " 313 << format("%p", Section.getLoadAddressWithOffset(Offset)) 314 << " Value: " << format("%x", Value) << " Type: " 315 << format("%x", Type) << " Addend: " << format("%x", Addend) 316 << " SymOffset: " << format("%x", Offset) << "\n"); 317 318 Value = evaluateMIPS32Relocation(Section, Offset, Value, Type); 319 320 applyMIPSRelocation(TargetPtr, Value, Type); 321 } 322