X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FExecutionEngine%2FRuntimeDyld%2FTargets%2FRuntimeDyldMachOARM.h;h=09e430e2261986018362df4acd543b791f97ff6c;hp=1de9942198249a695bcb623bff21bbab03b8b183;hb=973e54ac96b4bfd71bf9999c46f3e267c819bcc0;hpb=353cec5eba93633652a7acff2ee2c5691e80e3a5 diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 1de99421982..09e430e2261 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIMEDYLDMACHOARM_H -#define LLVM_RUNTIMEDYLDMACHOARM_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H #include "../RuntimeDyldMachO.h" @@ -18,37 +18,66 @@ namespace llvm { class RuntimeDyldMachOARM : public RuntimeDyldMachOCRTPBase { +private: + typedef RuntimeDyldMachOCRTPBase ParentT; + public: + + typedef uint32_t TargetPtrT; + RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} unsigned getMaxStubSize() override { return 8; } unsigned getStubAlignment() override { return 4; } + int64_t decodeAddend(const RelocationEntry &RE) const { + const SectionEntry &Section = Sections[RE.SectionID]; + uint8_t *LocalAddress = Section.Address + RE.Offset; + + switch (RE.RelType) { + default: + return memcpyAddend(RE); + case MachO::ARM_RELOC_BR24: { + uint32_t Temp = readBytesUnaligned(LocalAddress, 4); + Temp &= 0x00ffffff; // Mask out the opcode. + // Now we've got the shifted immediate, shift by 2, sign extend and ret. + return SignExtend32<26>(Temp << 2); + } + } + } + relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); + uint32_t RelType = Obj.getAnyRelocationType(RelInfo); - if (Obj.isRelocationScattered(RelInfo)) - return ++++RelI; + if (Obj.isRelocationScattered(RelInfo)) { + if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF) + return processHALFSECTDIFFRelocation(SectionID, RelI, Obj, + ObjSectionToID); + else + return ++++RelI; + } - RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); + RE.Addend = decodeAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); - bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); - if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + if (RE.IsPCRel) + makeValueAddendPCRel(Value, Obj, RelI, 8); if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) processBranchRelocation(RE, Value, Stubs); else { - RE.Addend = Value.Addend; + RE.Addend = Value.Offset; if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -58,7 +87,7 @@ public: return ++RelI; } - void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { DEBUG(dumpRelocationToResolve(RE, Value)); const SectionEntry &Section = Sections[RE.SectionID]; uint8_t *LocalAddress = Section.Address + RE.Offset; @@ -78,33 +107,45 @@ public: default: llvm_unreachable("Invalid relocation type!"); case MachO::ARM_RELOC_VANILLA: - writeBytesUnaligned(LocalAddress, Value, 1 << RE.Size); + writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); break; case MachO::ARM_RELOC_BR24: { // Mask the value into the target address. We know instructions are // 32-bit aligned, so we can do it all at once. - uint32_t *p = (uint32_t *)LocalAddress; + Value += RE.Addend; // The low two bits of the value are not encoded. Value >>= 2; // Mask the value to 24 bits. uint64_t FinalValue = Value & 0xffffff; - // Check for overflow. - if (Value != FinalValue) { - Error("ARM BR24 relocation out of range."); - return; - } // FIXME: If the destination is a Thumb function (and the instruction // is a non-predicated BL instruction), we need to change it to a BLX // instruction instead. // Insert the value into the instruction. - *p = (*p & ~0xffffff) | FinalValue; + uint32_t Temp = readBytesUnaligned(LocalAddress, 4); + writeBytesUnaligned((Temp & ~0xffffff) | FinalValue, LocalAddress, 4); + + break; + } + case MachO::ARM_RELOC_HALF_SECTDIFF: { + uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress; + uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress; + assert((Value == SectionABase || Value == SectionBBase) && + "Unexpected HALFSECTDIFF relocation value."); + Value = SectionABase - SectionBBase + RE.Addend; + if (RE.Size & 0x1) // :upper16: + Value = (Value >> 16); + Value &= 0xffff; + + uint32_t Insn = readBytesUnaligned(LocalAddress, 4); + Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff); + writeBytesUnaligned(Insn, LocalAddress, 4); break; } + case MachO::ARM_THUMB_RELOC_BR22: case MachO::ARM_THUMB_32BIT_BRANCH: case MachO::ARM_RELOC_HALF: - case MachO::ARM_RELOC_HALF_SECTDIFF: case MachO::ARM_RELOC_PAIR: case MachO::ARM_RELOC_SECTDIFF: case MachO::ARM_RELOC_LOCAL_SECTDIFF: @@ -114,10 +155,18 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, - const SectionRef &Section) {} + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, + const SectionRef &Section) { + StringRef Name; + Section.getName(Name); + + if (Name == "__nl_symbol_ptr") + populateIndirectSymbolPointersSection(cast(Obj), + Section, SectionID); + } private: + void processBranchRelocation(const RelocationEntry &RE, const RelocationValueRef &Value, StubMap &Stubs) { @@ -134,7 +183,8 @@ private: uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry StubRE(RE.SectionID, StubTargetAddr - Section.Address, - MachO::GENERIC_RELOC_VANILLA, Value.Addend); + MachO::GENERIC_RELOC_VANILLA, Value.Offset, false, + 2); if (Value.SymbolName) addRelocationForSymbol(StubRE, Value.SymbolName); else @@ -142,13 +192,86 @@ private: Addr = Section.Address + Section.StubOffset; Section.StubOffset += getMaxStubSize(); } - RelocationEntry TargetRE(Value.SectionID, RE.Offset, RE.RelType, 0, + RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0, RE.IsPCRel, RE.Size); resolveRelocation(TargetRE, (uint64_t)Addr); } + + relocation_iterator + processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, + const ObjectFile &BaseTObj, + ObjSectionToIDMap &ObjSectionToID) { + const MachOObjectFile &MachO = + static_cast(BaseTObj); + MachO::any_relocation_info RE = + MachO.getRelocation(RelI->getRawDataRefImpl()); + + + // For a half-diff relocation the length bits actually record whether this + // is a movw/movt, and whether this is arm or thumb. + // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1). + // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1). + unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE); + if (HalfDiffKindBits & 0x2) + llvm_unreachable("Thumb not yet supported."); + + SectionEntry &Section = Sections[SectionID]; + uint32_t RelocType = MachO.getAnyRelocationType(RE); + bool IsPCRel = MachO.getAnyRelocationPCRel(RE); + uint64_t Offset; + RelI->getOffset(Offset); + uint8_t *LocalAddress = Section.Address + Offset; + int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out. + Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff); + + ++RelI; + MachO::any_relocation_info RE2 = + MachO.getRelocation(RelI->getRawDataRefImpl()); + uint32_t AddrA = MachO.getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(MachO, AddrA); + assert(SAI != MachO.section_end() && "Can't find section for address A"); + uint64_t SectionABase = SAI->getAddress(); + uint64_t SectionAOffset = AddrA - SectionABase; + SectionRef SectionA = *SAI; + bool IsCode = SectionA.isText(); + uint32_t SectionAID = + findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID); + + uint32_t AddrB = MachO.getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(MachO, AddrB); + assert(SBI != MachO.section_end() && "Can't find section for address B"); + uint64_t SectionBBase = SBI->getAddress(); + uint64_t SectionBOffset = AddrB - SectionBBase; + SectionRef SectionB = *SBI; + uint32_t SectionBID = + findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID); + + uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff; + unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0; + uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift)); + int64_t Addend = FullImmVal - (AddrA - AddrB); + + // addend = Encoded - Expected + // = Encoded - (AddrA - AddrB) + + DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB + << ", Addend: " << Addend << ", SectionA ID: " << SectionAID + << ", SectionAOffset: " << SectionAOffset + << ", SectionB ID: " << SectionBID + << ", SectionBOffset: " << SectionBOffset << "\n"); + RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, + SectionAOffset, SectionBID, SectionBOffset, IsPCRel, + HalfDiffKindBits); + + addRelocationForSection(R, SectionAID); + addRelocationForSection(R, SectionBID); + + return ++RelI; + } + }; } #undef DEBUG_TYPE -#endif // LLVM_RUNTIMEDYLDMACHOARM_H +#endif