Index: ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h =================================================================== --- ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -149,26 +149,40 @@ /// The size of this relocation (MachO specific). unsigned Size; + // True if this is a thumb relocation to a function symbol (Windows specific). + bool IsThumbRel; + RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(false), Size(0) {} + SymOffset(0), IsPCRel(false), Size(0), IsThumbRel(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, uint64_t symoffset) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(symoffset), IsPCRel(false), Size(0) {} + SymOffset(symoffset), IsPCRel(false), Size(0), IsThumbRel(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, bool IsPCRel, unsigned Size) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(IsPCRel), Size(Size) {} + SymOffset(0), IsPCRel(IsPCRel), Size(Size), IsThumbRel(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, uint64_t SectionBOffset, bool IsPCRel, unsigned Size) : SectionID(id), Offset(offset), RelType(type), Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), - Size(Size) { + Size(Size), IsThumbRel(false) { + Sections.SectionA = SectionA; + Sections.SectionB = SectionB; + } + + RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, + unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, + uint64_t SectionBOffset, bool IsPCRel, unsigned Size, + bool IsThumbRel) + : SectionID(id), Offset(offset), RelType(type), + Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), + Size(Size), IsThumbRel(IsThumbRel) { Sections.SectionA = SectionA; Sections.SectionB = SectionB; } Index: ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h =================================================================== --- ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h +++ ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h @@ -22,6 +22,25 @@ namespace llvm { +static bool isThumbRelocation(symbol_iterator Symbol, const ObjectFile &Obj, + section_iterator Section) { + Expected SymTypeOrErr = Symbol->getType(); + if (!SymTypeOrErr) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, ""); + OS.flush(); + report_fatal_error(Buf); + } + + if (*SymTypeOrErr != SymbolRef::ST_Data && + *SymTypeOrErr != SymbolRef::ST_Function) { + return false; + } + return cast(Obj).getCOFFSection(*Section)->Characteristics & + COFF::IMAGE_SCN_MEM_16BIT; +} + class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF { public: RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, @@ -92,12 +111,29 @@ else return TargetSectionIDOrErr.takeError(); + Expected SymTypeOrErr = Symbol->getType(); + if (!SymTypeOrErr) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, ""); + OS.flush(); + report_fatal_error(Buf); + } + + bool IsThumbRel = isThumbRelocation(Symbol, Obj, Section); + switch (RelType) { default: llvm_unreachable("unsupported relocation type"); case COFF::IMAGE_REL_ARM_ABSOLUTE: // This relocation is ignored. break; - case COFF::IMAGE_REL_ARM_ADDR32: + case COFF::IMAGE_REL_ARM_ADDR32: { + RelocationEntry RE = RelocationEntry( + SectionID, Offset, RelType, Addend, TargetSectionID, + getSymbolOffset(*Symbol), 0, 0, false, 0, IsThumbRel); + addRelocationForSection(RE, TargetSectionID); + break; + } case COFF::IMAGE_REL_ARM_ADDR32NB: { RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, @@ -118,9 +154,9 @@ break; } case COFF::IMAGE_REL_ARM_MOV32T: { - RelocationEntry RE = - RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, - getSymbolOffset(*Symbol), 0, 0, false, 0); + RelocationEntry RE = RelocationEntry( + SectionID, Offset, RelType, Addend, TargetSectionID, + getSymbolOffset(*Symbol), 0, 0, false, 0, IsThumbRel); addRelocationForSection(RE, TargetSectionID); break; } @@ -154,6 +190,7 @@ RE.Sections.SectionA == static_cast(-1) ? Value : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend); + Result |= RE.IsThumbRel; assert(static_cast(Result) <= INT32_MAX && "relocation overflow"); assert(static_cast(Result) >= INT32_MIN && @@ -228,7 +265,8 @@ Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4); }; - EncodeImmediate(&Target[0], static_cast(Result) >> 00); + EncodeImmediate(&Target[0], + (static_cast(Result) >> 00) | RE.IsThumbRel); EncodeImmediate(&Target[4], static_cast(Result) >> 16); break;