| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 1 | //===----- RuntimeDyldMachOARM.h ---- MachO/ARM 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 |  | 
| Benjamin Kramer | a7c40ef | 2014-08-13 16:26:38 +0000 | [diff] [blame] | 10 | #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H | 
|  | 11 | #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 12 |  | 
|  | 13 | #include "../RuntimeDyldMachO.h" | 
|  | 14 |  | 
|  | 15 | #define DEBUG_TYPE "dyld" | 
|  | 16 |  | 
|  | 17 | namespace llvm { | 
|  | 18 |  | 
|  | 19 | class RuntimeDyldMachOARM | 
|  | 20 | : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> { | 
| Lang Hames | 1316365 | 2014-07-30 03:35:05 +0000 | [diff] [blame] | 21 | private: | 
|  | 22 | typedef RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> ParentT; | 
|  | 23 |  | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 24 | public: | 
|  | 25 | RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} | 
|  | 26 |  | 
|  | 27 | unsigned getMaxStubSize() override { return 8; } | 
|  | 28 |  | 
| Lang Hames | e5fc826 | 2014-07-17 23:11:30 +0000 | [diff] [blame] | 29 | unsigned getStubAlignment() override { return 4; } | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 30 |  | 
| Lang Hames | 25d9309 | 2014-08-08 23:12:22 +0000 | [diff] [blame] | 31 | int64_t decodeAddend(const RelocationEntry &RE) const { | 
|  | 32 | const SectionEntry &Section = Sections[RE.SectionID]; | 
|  | 33 | uint8_t *LocalAddress = Section.Address + RE.Offset; | 
|  | 34 |  | 
|  | 35 | switch (RE.RelType) { | 
| Lang Hames | 1316365 | 2014-07-30 03:35:05 +0000 | [diff] [blame] | 36 | default: | 
| Lang Hames | 25d9309 | 2014-08-08 23:12:22 +0000 | [diff] [blame] | 37 | return memcpyAddend(RE); | 
| Lang Hames | 1316365 | 2014-07-30 03:35:05 +0000 | [diff] [blame] | 38 | case MachO::ARM_RELOC_BR24: { | 
|  | 39 | uint32_t Temp; | 
|  | 40 | memcpy(&Temp, LocalAddress, 4); | 
|  | 41 | Temp &= 0x00ffffff; // Mask out the opcode. | 
|  | 42 | // Now we've got the shifted immediate, shift by 2, sign extend and ret. | 
|  | 43 | return SignExtend32<26>(Temp << 2); | 
|  | 44 | } | 
|  | 45 | } | 
|  | 46 | } | 
|  | 47 |  | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 48 | relocation_iterator | 
|  | 49 | processRelocationRef(unsigned SectionID, relocation_iterator RelI, | 
|  | 50 | ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, | 
|  | 51 | const SymbolTableMap &Symbols, StubMap &Stubs) override { | 
|  | 52 | const MachOObjectFile &Obj = | 
|  | 53 | static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); | 
|  | 54 | MachO::any_relocation_info RelInfo = | 
|  | 55 | Obj.getRelocation(RelI->getRawDataRefImpl()); | 
|  | 56 |  | 
|  | 57 | if (Obj.isRelocationScattered(RelInfo)) | 
|  | 58 | return ++++RelI; | 
|  | 59 |  | 
| Lang Hames | 25d9309 | 2014-08-08 23:12:22 +0000 | [diff] [blame] | 60 | RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); | 
|  | 61 | RE.Addend = decodeAddend(RE); | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 62 | RelocationValueRef Value( | 
|  | 63 | getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); | 
|  | 64 |  | 
| Lang Hames | 1316365 | 2014-07-30 03:35:05 +0000 | [diff] [blame] | 65 | if (RE.IsPCRel) | 
|  | 66 | makeValueAddendPCRel(Value, ObjImg, RelI, 8); | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 67 |  | 
|  | 68 | if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) | 
|  | 69 | processBranchRelocation(RE, Value, Stubs); | 
|  | 70 | else { | 
|  | 71 | RE.Addend = Value.Addend; | 
|  | 72 | if (Value.SymbolName) | 
|  | 73 | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | 74 | else | 
|  | 75 | addRelocationForSection(RE, Value.SectionID); | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | return ++RelI; | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { | 
|  | 82 | DEBUG(dumpRelocationToResolve(RE, Value)); | 
|  | 83 | const SectionEntry &Section = Sections[RE.SectionID]; | 
|  | 84 | uint8_t *LocalAddress = Section.Address + RE.Offset; | 
|  | 85 |  | 
|  | 86 | // If the relocation is PC-relative, the value to be encoded is the | 
|  | 87 | // pointer difference. | 
|  | 88 | if (RE.IsPCRel) { | 
|  | 89 | uint64_t FinalAddress = Section.LoadAddress + RE.Offset; | 
|  | 90 | Value -= FinalAddress; | 
|  | 91 | // ARM PCRel relocations have an effective-PC offset of two instructions | 
|  | 92 | // (four bytes in Thumb mode, 8 bytes in ARM mode). | 
|  | 93 | // FIXME: For now, assume ARM mode. | 
|  | 94 | Value -= 8; | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | switch (RE.RelType) { | 
|  | 98 | default: | 
|  | 99 | llvm_unreachable("Invalid relocation type!"); | 
|  | 100 | case MachO::ARM_RELOC_VANILLA: | 
|  | 101 | writeBytesUnaligned(LocalAddress, Value, 1 << RE.Size); | 
|  | 102 | break; | 
|  | 103 | case MachO::ARM_RELOC_BR24: { | 
|  | 104 | // Mask the value into the target address. We know instructions are | 
|  | 105 | // 32-bit aligned, so we can do it all at once. | 
|  | 106 | uint32_t *p = (uint32_t *)LocalAddress; | 
|  | 107 | // The low two bits of the value are not encoded. | 
|  | 108 | Value >>= 2; | 
|  | 109 | // Mask the value to 24 bits. | 
|  | 110 | uint64_t FinalValue = Value & 0xffffff; | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 111 | // FIXME: If the destination is a Thumb function (and the instruction | 
|  | 112 | // is a non-predicated BL instruction), we need to change it to a BLX | 
|  | 113 | // instruction instead. | 
|  | 114 |  | 
|  | 115 | // Insert the value into the instruction. | 
|  | 116 | *p = (*p & ~0xffffff) | FinalValue; | 
|  | 117 | break; | 
|  | 118 | } | 
|  | 119 | case MachO::ARM_THUMB_RELOC_BR22: | 
|  | 120 | case MachO::ARM_THUMB_32BIT_BRANCH: | 
|  | 121 | case MachO::ARM_RELOC_HALF: | 
|  | 122 | case MachO::ARM_RELOC_HALF_SECTDIFF: | 
|  | 123 | case MachO::ARM_RELOC_PAIR: | 
|  | 124 | case MachO::ARM_RELOC_SECTDIFF: | 
|  | 125 | case MachO::ARM_RELOC_LOCAL_SECTDIFF: | 
|  | 126 | case MachO::ARM_RELOC_PB_LA_PTR: | 
|  | 127 | Error("Relocation type not implemented yet!"); | 
|  | 128 | return; | 
|  | 129 | } | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 | void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, | 
|  | 133 | const SectionRef &Section) {} | 
|  | 134 |  | 
|  | 135 | private: | 
|  | 136 | void processBranchRelocation(const RelocationEntry &RE, | 
|  | 137 | const RelocationValueRef &Value, | 
|  | 138 | StubMap &Stubs) { | 
|  | 139 | // This is an ARM branch relocation, need to use a stub function. | 
|  | 140 | // Look up for existing stub. | 
|  | 141 | SectionEntry &Section = Sections[RE.SectionID]; | 
|  | 142 | RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value); | 
|  | 143 | uint8_t *Addr; | 
|  | 144 | if (i != Stubs.end()) { | 
|  | 145 | Addr = Section.Address + i->second; | 
|  | 146 | } else { | 
|  | 147 | // Create a new stub function. | 
|  | 148 | Stubs[Value] = Section.StubOffset; | 
|  | 149 | uint8_t *StubTargetAddr = | 
|  | 150 | createStubFunction(Section.Address + Section.StubOffset); | 
|  | 151 | RelocationEntry StubRE(RE.SectionID, StubTargetAddr - Section.Address, | 
| Lang Hames | 1316365 | 2014-07-30 03:35:05 +0000 | [diff] [blame] | 152 | MachO::GENERIC_RELOC_VANILLA, Value.Addend, false, | 
|  | 153 | 2); | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 154 | if (Value.SymbolName) | 
|  | 155 | addRelocationForSymbol(StubRE, Value.SymbolName); | 
|  | 156 | else | 
|  | 157 | addRelocationForSection(StubRE, Value.SectionID); | 
|  | 158 | Addr = Section.Address + Section.StubOffset; | 
|  | 159 | Section.StubOffset += getMaxStubSize(); | 
|  | 160 | } | 
| Lang Hames | 1316365 | 2014-07-30 03:35:05 +0000 | [diff] [blame] | 161 | RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0, | 
| Lang Hames | a521688 | 2014-07-17 18:54:50 +0000 | [diff] [blame] | 162 | RE.IsPCRel, RE.Size); | 
|  | 163 | resolveRelocation(TargetRE, (uint64_t)Addr); | 
|  | 164 | } | 
|  | 165 | }; | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | #undef DEBUG_TYPE | 
|  | 169 |  | 
| Benjamin Kramer | a7c40ef | 2014-08-13 16:26:38 +0000 | [diff] [blame] | 170 | #endif |