LLVM API Documentation
00001 //===----- RuntimeDyldMachOARM.h ---- MachO/ARM specific code. ----*- C++ -*-=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H 00011 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H 00012 00013 #include "../RuntimeDyldMachO.h" 00014 00015 #define DEBUG_TYPE "dyld" 00016 00017 namespace llvm { 00018 00019 class RuntimeDyldMachOARM 00020 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> { 00021 private: 00022 typedef RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> ParentT; 00023 00024 public: 00025 00026 typedef uint32_t TargetPtrT; 00027 00028 RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} 00029 00030 unsigned getMaxStubSize() override { return 8; } 00031 00032 unsigned getStubAlignment() override { return 4; } 00033 00034 int64_t decodeAddend(const RelocationEntry &RE) const { 00035 const SectionEntry &Section = Sections[RE.SectionID]; 00036 uint8_t *LocalAddress = Section.Address + RE.Offset; 00037 00038 switch (RE.RelType) { 00039 default: 00040 return memcpyAddend(RE); 00041 case MachO::ARM_RELOC_BR24: { 00042 uint32_t Temp; 00043 memcpy(&Temp, LocalAddress, 4); 00044 Temp &= 0x00ffffff; // Mask out the opcode. 00045 // Now we've got the shifted immediate, shift by 2, sign extend and ret. 00046 return SignExtend32<26>(Temp << 2); 00047 } 00048 } 00049 } 00050 00051 relocation_iterator 00052 processRelocationRef(unsigned SectionID, relocation_iterator RelI, 00053 ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, 00054 const SymbolTableMap &Symbols, StubMap &Stubs) override { 00055 const MachOObjectFile &Obj = 00056 static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); 00057 MachO::any_relocation_info RelInfo = 00058 Obj.getRelocation(RelI->getRawDataRefImpl()); 00059 uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 00060 00061 if (Obj.isRelocationScattered(RelInfo)) { 00062 if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF) 00063 return processHALFSECTDIFFRelocation(SectionID, RelI, ObjImg, 00064 ObjSectionToID); 00065 else 00066 return ++++RelI; 00067 } 00068 00069 RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); 00070 RE.Addend = decodeAddend(RE); 00071 RelocationValueRef Value( 00072 getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); 00073 00074 if (RE.IsPCRel) 00075 makeValueAddendPCRel(Value, ObjImg, RelI, 8); 00076 00077 if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) 00078 processBranchRelocation(RE, Value, Stubs); 00079 else { 00080 RE.Addend = Value.Offset; 00081 if (Value.SymbolName) 00082 addRelocationForSymbol(RE, Value.SymbolName); 00083 else 00084 addRelocationForSection(RE, Value.SectionID); 00085 } 00086 00087 return ++RelI; 00088 } 00089 00090 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 00091 DEBUG(dumpRelocationToResolve(RE, Value)); 00092 const SectionEntry &Section = Sections[RE.SectionID]; 00093 uint8_t *LocalAddress = Section.Address + RE.Offset; 00094 00095 // If the relocation is PC-relative, the value to be encoded is the 00096 // pointer difference. 00097 if (RE.IsPCRel) { 00098 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 00099 Value -= FinalAddress; 00100 // ARM PCRel relocations have an effective-PC offset of two instructions 00101 // (four bytes in Thumb mode, 8 bytes in ARM mode). 00102 // FIXME: For now, assume ARM mode. 00103 Value -= 8; 00104 } 00105 00106 switch (RE.RelType) { 00107 default: 00108 llvm_unreachable("Invalid relocation type!"); 00109 case MachO::ARM_RELOC_VANILLA: 00110 writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 00111 break; 00112 case MachO::ARM_RELOC_BR24: { 00113 // Mask the value into the target address. We know instructions are 00114 // 32-bit aligned, so we can do it all at once. 00115 uint32_t *p = (uint32_t *)LocalAddress; 00116 Value += RE.Addend; 00117 // The low two bits of the value are not encoded. 00118 Value >>= 2; 00119 // Mask the value to 24 bits. 00120 uint64_t FinalValue = Value & 0xffffff; 00121 // FIXME: If the destination is a Thumb function (and the instruction 00122 // is a non-predicated BL instruction), we need to change it to a BLX 00123 // instruction instead. 00124 00125 // Insert the value into the instruction. 00126 *p = (*p & ~0xffffff) | FinalValue; 00127 break; 00128 } 00129 case MachO::ARM_RELOC_HALF_SECTDIFF: { 00130 uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress; 00131 uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress; 00132 assert((Value == SectionABase || Value == SectionBBase) && 00133 "Unexpected HALFSECTDIFF relocation value."); 00134 Value = SectionABase - SectionBBase + RE.Addend; 00135 if (RE.Size & 0x1) // :upper16: 00136 Value = (Value >> 16); 00137 Value &= 0xffff; 00138 00139 uint32_t Insn; 00140 memcpy(&Insn, LocalAddress, 4); 00141 Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff); 00142 memcpy(LocalAddress, &Insn, 4); 00143 break; 00144 } 00145 00146 case MachO::ARM_THUMB_RELOC_BR22: 00147 case MachO::ARM_THUMB_32BIT_BRANCH: 00148 case MachO::ARM_RELOC_HALF: 00149 case MachO::ARM_RELOC_PAIR: 00150 case MachO::ARM_RELOC_SECTDIFF: 00151 case MachO::ARM_RELOC_LOCAL_SECTDIFF: 00152 case MachO::ARM_RELOC_PB_LA_PTR: 00153 Error("Relocation type not implemented yet!"); 00154 return; 00155 } 00156 } 00157 00158 void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, 00159 const SectionRef &Section) { 00160 StringRef Name; 00161 Section.getName(Name); 00162 00163 if (Name == "__nl_symbol_ptr") 00164 populateIndirectSymbolPointersSection( 00165 cast<MachOObjectFile>(*ObjImg.getObjectFile()), 00166 Section, SectionID); 00167 } 00168 00169 private: 00170 00171 void processBranchRelocation(const RelocationEntry &RE, 00172 const RelocationValueRef &Value, 00173 StubMap &Stubs) { 00174 // This is an ARM branch relocation, need to use a stub function. 00175 // Look up for existing stub. 00176 SectionEntry &Section = Sections[RE.SectionID]; 00177 RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value); 00178 uint8_t *Addr; 00179 if (i != Stubs.end()) { 00180 Addr = Section.Address + i->second; 00181 } else { 00182 // Create a new stub function. 00183 Stubs[Value] = Section.StubOffset; 00184 uint8_t *StubTargetAddr = 00185 createStubFunction(Section.Address + Section.StubOffset); 00186 RelocationEntry StubRE(RE.SectionID, StubTargetAddr - Section.Address, 00187 MachO::GENERIC_RELOC_VANILLA, Value.Offset, false, 00188 2); 00189 if (Value.SymbolName) 00190 addRelocationForSymbol(StubRE, Value.SymbolName); 00191 else 00192 addRelocationForSection(StubRE, Value.SectionID); 00193 Addr = Section.Address + Section.StubOffset; 00194 Section.StubOffset += getMaxStubSize(); 00195 } 00196 RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0, 00197 RE.IsPCRel, RE.Size); 00198 resolveRelocation(TargetRE, (uint64_t)Addr); 00199 } 00200 00201 relocation_iterator 00202 processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 00203 ObjectImage &Obj, 00204 ObjSectionToIDMap &ObjSectionToID) { 00205 const MachOObjectFile *MachO = 00206 static_cast<const MachOObjectFile *>(Obj.getObjectFile()); 00207 MachO::any_relocation_info RE = 00208 MachO->getRelocation(RelI->getRawDataRefImpl()); 00209 00210 00211 // For a half-diff relocation the length bits actually record whether this 00212 // is a movw/movt, and whether this is arm or thumb. 00213 // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1). 00214 // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1). 00215 unsigned HalfDiffKindBits = MachO->getAnyRelocationLength(RE); 00216 if (HalfDiffKindBits & 0x2) 00217 llvm_unreachable("Thumb not yet supported."); 00218 00219 SectionEntry &Section = Sections[SectionID]; 00220 uint32_t RelocType = MachO->getAnyRelocationType(RE); 00221 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 00222 uint64_t Offset; 00223 RelI->getOffset(Offset); 00224 uint8_t *LocalAddress = Section.Address + Offset; 00225 int64_t Immediate = 0; 00226 memcpy(&Immediate, LocalAddress, 4); // Copy the whole instruction out. 00227 Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff); 00228 00229 ++RelI; 00230 MachO::any_relocation_info RE2 = 00231 MachO->getRelocation(RelI->getRawDataRefImpl()); 00232 uint32_t AddrA = MachO->getScatteredRelocationValue(RE); 00233 section_iterator SAI = getSectionByAddress(*MachO, AddrA); 00234 assert(SAI != MachO->section_end() && "Can't find section for address A"); 00235 uint64_t SectionABase; 00236 SAI->getAddress(SectionABase); 00237 uint64_t SectionAOffset = AddrA - SectionABase; 00238 SectionRef SectionA = *SAI; 00239 bool IsCode; 00240 SectionA.isText(IsCode); 00241 uint32_t SectionAID = 00242 findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); 00243 00244 uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); 00245 section_iterator SBI = getSectionByAddress(*MachO, AddrB); 00246 assert(SBI != MachO->section_end() && "Can't find section for address B"); 00247 uint64_t SectionBBase; 00248 SBI->getAddress(SectionBBase); 00249 uint64_t SectionBOffset = AddrB - SectionBBase; 00250 SectionRef SectionB = *SBI; 00251 uint32_t SectionBID = 00252 findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID); 00253 00254 uint32_t OtherHalf = MachO->getAnyRelocationAddress(RE2) & 0xffff; 00255 unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0; 00256 uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift)); 00257 int64_t Addend = FullImmVal - (AddrA - AddrB); 00258 00259 // addend = Encoded - Expected 00260 // = Encoded - (AddrA - AddrB) 00261 00262 DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB 00263 << ", Addend: " << Addend << ", SectionA ID: " << SectionAID 00264 << ", SectionAOffset: " << SectionAOffset 00265 << ", SectionB ID: " << SectionBID 00266 << ", SectionBOffset: " << SectionBOffset << "\n"); 00267 RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, 00268 SectionAOffset, SectionBID, SectionBOffset, IsPCRel, 00269 HalfDiffKindBits); 00270 00271 addRelocationForSection(R, SectionAID); 00272 addRelocationForSection(R, SectionBID); 00273 00274 return ++RelI; 00275 } 00276 00277 }; 00278 } 00279 00280 #undef DEBUG_TYPE 00281 00282 #endif