10b57cec5SDimitry Andric //===--- RuntimeDyldCOFFThumb.h --- COFF/Thumb specific code ---*- C++ --*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // COFF thumb support for MC-JIT runtime dynamic linker. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H 140b57cec5SDimitry Andric #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "../RuntimeDyldCOFF.h" 1706c3fb27SDimitry Andric #include "llvm/ADT/SmallString.h" 180b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 190b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #define DEBUG_TYPE "dyld" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace llvm { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric static bool isThumbFunc(object::symbol_iterator Symbol, 260b57cec5SDimitry Andric const object::ObjectFile &Obj, 270b57cec5SDimitry Andric object::section_iterator Section) { 280b57cec5SDimitry Andric Expected<object::SymbolRef::Type> SymTypeOrErr = Symbol->getType(); 290b57cec5SDimitry Andric if (!SymTypeOrErr) { 300b57cec5SDimitry Andric std::string Buf; 310b57cec5SDimitry Andric raw_string_ostream OS(Buf); 320b57cec5SDimitry Andric logAllUnhandledErrors(SymTypeOrErr.takeError(), OS); 33349cc55cSDimitry Andric report_fatal_error(Twine(OS.str())); 340b57cec5SDimitry Andric } 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric if (*SymTypeOrErr != object::SymbolRef::ST_Function) 370b57cec5SDimitry Andric return false; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric // We check the IMAGE_SCN_MEM_16BIT flag in the section of the symbol to tell 400b57cec5SDimitry Andric // if it's thumb or not 410b57cec5SDimitry Andric return cast<object::COFFObjectFile>(Obj) 420b57cec5SDimitry Andric .getCOFFSection(*Section) 430b57cec5SDimitry Andric ->Characteristics & 440b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_16BIT; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF { 480b57cec5SDimitry Andric public: 490b57cec5SDimitry Andric RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, 500b57cec5SDimitry Andric JITSymbolResolver &Resolver) 515ffd83dbSDimitry Andric : RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_ARM_ADDR32) {} 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric unsigned getMaxStubSize() const override { 540b57cec5SDimitry Andric return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 57*5f757f3fSDimitry Andric Expected<JITSymbolFlags> getJITSymbolFlags(const SymbolRef &SR) override { 58*5f757f3fSDimitry Andric 59*5f757f3fSDimitry Andric auto Flags = RuntimeDyldImpl::getJITSymbolFlags(SR); 60*5f757f3fSDimitry Andric 61*5f757f3fSDimitry Andric if (!Flags) { 62*5f757f3fSDimitry Andric return Flags.takeError(); 63*5f757f3fSDimitry Andric } 64*5f757f3fSDimitry Andric auto SectionIterOrErr = SR.getSection(); 65*5f757f3fSDimitry Andric if (!SectionIterOrErr) { 66*5f757f3fSDimitry Andric return SectionIterOrErr.takeError(); 67*5f757f3fSDimitry Andric } 68*5f757f3fSDimitry Andric SectionRef Sec = *SectionIterOrErr.get(); 69*5f757f3fSDimitry Andric const object::COFFObjectFile *COFFObjPtr = 70*5f757f3fSDimitry Andric cast<object::COFFObjectFile>(Sec.getObject()); 71*5f757f3fSDimitry Andric const coff_section *CoffSec = COFFObjPtr->getCOFFSection(Sec); 72*5f757f3fSDimitry Andric bool isThumb = CoffSec->Characteristics & COFF::IMAGE_SCN_MEM_16BIT; 73*5f757f3fSDimitry Andric 74*5f757f3fSDimitry Andric Flags->getTargetFlags() = isThumb; 75*5f757f3fSDimitry Andric 76*5f757f3fSDimitry Andric return Flags; 77*5f757f3fSDimitry Andric } 78*5f757f3fSDimitry Andric 79bdd1243dSDimitry Andric Align getStubAlignment() override { return Align(1); } 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric Expected<object::relocation_iterator> 820b57cec5SDimitry Andric processRelocationRef(unsigned SectionID, 830b57cec5SDimitry Andric object::relocation_iterator RelI, 840b57cec5SDimitry Andric const object::ObjectFile &Obj, 850b57cec5SDimitry Andric ObjSectionToIDMap &ObjSectionToID, 860b57cec5SDimitry Andric StubMap &Stubs) override { 870b57cec5SDimitry Andric auto Symbol = RelI->getSymbol(); 880b57cec5SDimitry Andric if (Symbol == Obj.symbol_end()) 890b57cec5SDimitry Andric report_fatal_error("Unknown symbol in relocation"); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric Expected<StringRef> TargetNameOrErr = Symbol->getName(); 920b57cec5SDimitry Andric if (!TargetNameOrErr) 930b57cec5SDimitry Andric return TargetNameOrErr.takeError(); 940b57cec5SDimitry Andric StringRef TargetName = *TargetNameOrErr; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric auto SectionOrErr = Symbol->getSection(); 970b57cec5SDimitry Andric if (!SectionOrErr) 980b57cec5SDimitry Andric return SectionOrErr.takeError(); 990b57cec5SDimitry Andric auto Section = *SectionOrErr; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric uint64_t RelType = RelI->getType(); 1020b57cec5SDimitry Andric uint64_t Offset = RelI->getOffset(); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric // Determine the Addend used to adjust the relocation value. 1050b57cec5SDimitry Andric uint64_t Addend = 0; 1060b57cec5SDimitry Andric SectionEntry &AddendSection = Sections[SectionID]; 1070b57cec5SDimitry Andric uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset; 1080b57cec5SDimitry Andric uint8_t *Displacement = (uint8_t *)ObjTarget; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric switch (RelType) { 1110b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32: 1120b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32NB: 1130b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL: 1140b57cec5SDimitry Andric Addend = readBytesUnaligned(Displacement, 4); 1150b57cec5SDimitry Andric break; 1160b57cec5SDimitry Andric default: 1170b57cec5SDimitry Andric break; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric #if !defined(NDEBUG) 1210b57cec5SDimitry Andric SmallString<32> RelTypeName; 1220b57cec5SDimitry Andric RelI->getTypeName(RelTypeName); 1230b57cec5SDimitry Andric #endif 1240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 1250b57cec5SDimitry Andric << " RelType: " << RelTypeName << " TargetName: " 1260b57cec5SDimitry Andric << TargetName << " Addend " << Addend << "\n"); 1270b57cec5SDimitry Andric 1285ffd83dbSDimitry Andric bool IsExtern = Section == Obj.section_end(); 1290b57cec5SDimitry Andric unsigned TargetSectionID = -1; 1305ffd83dbSDimitry Andric uint64_t TargetOffset = -1; 1315ffd83dbSDimitry Andric 132*5f757f3fSDimitry Andric if (TargetName.starts_with(getImportSymbolPrefix())) { 1335ffd83dbSDimitry Andric TargetSectionID = SectionID; 1345ffd83dbSDimitry Andric TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true); 1355ffd83dbSDimitry Andric TargetName = StringRef(); 1365ffd83dbSDimitry Andric IsExtern = false; 1375ffd83dbSDimitry Andric } else if (!IsExtern) { 1380b57cec5SDimitry Andric if (auto TargetSectionIDOrErr = 1390b57cec5SDimitry Andric findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID)) 1400b57cec5SDimitry Andric TargetSectionID = *TargetSectionIDOrErr; 1410b57cec5SDimitry Andric else 1420b57cec5SDimitry Andric return TargetSectionIDOrErr.takeError(); 1435ffd83dbSDimitry Andric if (RelType != COFF::IMAGE_REL_ARM_SECTION) 1445ffd83dbSDimitry Andric TargetOffset = getSymbolOffset(*Symbol); 1455ffd83dbSDimitry Andric } 1465ffd83dbSDimitry Andric 1475ffd83dbSDimitry Andric if (IsExtern) { 1485ffd83dbSDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); 1495ffd83dbSDimitry Andric addRelocationForSymbol(RE, TargetName); 1505ffd83dbSDimitry Andric } else { 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // We need to find out if the relocation is relative to a thumb function 1530b57cec5SDimitry Andric // so that we include the ISA selection bit when resolve the relocation 1540b57cec5SDimitry Andric bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric switch (RelType) { 1570b57cec5SDimitry Andric default: llvm_unreachable("unsupported relocation type"); 1580b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ABSOLUTE: 1590b57cec5SDimitry Andric // This relocation is ignored. 1600b57cec5SDimitry Andric break; 1610b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32: { 1625ffd83dbSDimitry Andric RelocationEntry RE = 1635ffd83dbSDimitry Andric RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, 1645ffd83dbSDimitry Andric TargetOffset, 0, 0, false, 0, IsTargetThumbFunc); 1650b57cec5SDimitry Andric addRelocationForSection(RE, TargetSectionID); 1660b57cec5SDimitry Andric break; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32NB: { 1690b57cec5SDimitry Andric RelocationEntry RE = 1700b57cec5SDimitry Andric RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, 1715ffd83dbSDimitry Andric TargetOffset, 0, 0, false, 0); 1720b57cec5SDimitry Andric addRelocationForSection(RE, TargetSectionID); 1730b57cec5SDimitry Andric break; 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_SECTION: { 1760b57cec5SDimitry Andric RelocationEntry RE = 1770b57cec5SDimitry Andric RelocationEntry(TargetSectionID, Offset, RelType, 0); 1780b57cec5SDimitry Andric addRelocationForSection(RE, TargetSectionID); 1790b57cec5SDimitry Andric break; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL: { 1825ffd83dbSDimitry Andric RelocationEntry RE = 1835ffd83dbSDimitry Andric RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend); 1840b57cec5SDimitry Andric addRelocationForSection(RE, TargetSectionID); 1850b57cec5SDimitry Andric break; 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_MOV32T: { 1885ffd83dbSDimitry Andric RelocationEntry RE = 1895ffd83dbSDimitry Andric RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, 1905ffd83dbSDimitry Andric TargetOffset, 0, 0, false, 0, IsTargetThumbFunc); 1910b57cec5SDimitry Andric addRelocationForSection(RE, TargetSectionID); 1920b57cec5SDimitry Andric break; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH20T: 1950b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH24T: 1960b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_BLX23T: { 1975ffd83dbSDimitry Andric RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, 1985ffd83dbSDimitry Andric TargetOffset + Addend, true, 0); 1990b57cec5SDimitry Andric addRelocationForSection(RE, TargetSectionID); 2000b57cec5SDimitry Andric break; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric return ++RelI; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 2090b57cec5SDimitry Andric const auto Section = Sections[RE.SectionID]; 2100b57cec5SDimitry Andric uint8_t *Target = Section.getAddressWithOffset(RE.Offset); 2110b57cec5SDimitry Andric int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric switch (RE.RelType) { 2140b57cec5SDimitry Andric default: llvm_unreachable("unsupported relocation type"); 2150b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ABSOLUTE: 2160b57cec5SDimitry Andric // This relocation is ignored. 2170b57cec5SDimitry Andric break; 2180b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32: { 2190b57cec5SDimitry Andric // The target's 32-bit VA. 2200b57cec5SDimitry Andric uint64_t Result = 2210b57cec5SDimitry Andric RE.Sections.SectionA == static_cast<uint32_t>(-1) 2220b57cec5SDimitry Andric ? Value 2230b57cec5SDimitry Andric : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend); 2240b57cec5SDimitry Andric Result |= ISASelectionBit; 2250b57cec5SDimitry Andric assert(Result <= UINT32_MAX && "relocation overflow"); 2260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 2270b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_ADDR32" 2280b57cec5SDimitry Andric << " TargetSection: " << RE.Sections.SectionA 2290b57cec5SDimitry Andric << " Value: " << format("0x%08" PRIx32, Result) 2300b57cec5SDimitry Andric << '\n'); 2310b57cec5SDimitry Andric writeBytesUnaligned(Result, Target, 4); 2320b57cec5SDimitry Andric break; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32NB: { 2350b57cec5SDimitry Andric // The target's 32-bit RVA. 2360b57cec5SDimitry Andric // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase 2370b57cec5SDimitry Andric uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() - 2380b57cec5SDimitry Andric Sections[0].getLoadAddress() + RE.Addend; 2390b57cec5SDimitry Andric assert(Result <= UINT32_MAX && "relocation overflow"); 2400b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 2410b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_ADDR32NB" 2420b57cec5SDimitry Andric << " TargetSection: " << RE.Sections.SectionA 2430b57cec5SDimitry Andric << " Value: " << format("0x%08" PRIx32, Result) 2440b57cec5SDimitry Andric << '\n'); 2450b57cec5SDimitry Andric Result |= ISASelectionBit; 2460b57cec5SDimitry Andric writeBytesUnaligned(Result, Target, 4); 2470b57cec5SDimitry Andric break; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_SECTION: 2500b57cec5SDimitry Andric // 16-bit section index of the section that contains the target. 2510b57cec5SDimitry Andric assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX && 2520b57cec5SDimitry Andric "relocation overflow"); 2530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 2540b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_SECTION Value: " 2550b57cec5SDimitry Andric << RE.SectionID << '\n'); 2560b57cec5SDimitry Andric writeBytesUnaligned(RE.SectionID, Target, 2); 2570b57cec5SDimitry Andric break; 2580b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL: 2590b57cec5SDimitry Andric // 32-bit offset of the target from the beginning of its section. 2600b57cec5SDimitry Andric assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX && 2610b57cec5SDimitry Andric "relocation overflow"); 2620b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 2630b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend 2640b57cec5SDimitry Andric << '\n'); 2650b57cec5SDimitry Andric writeBytesUnaligned(RE.Addend, Target, 2); 2660b57cec5SDimitry Andric break; 2670b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_MOV32T: { 2680b57cec5SDimitry Andric // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair. 2690b57cec5SDimitry Andric uint64_t Result = 2700b57cec5SDimitry Andric Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend); 2710b57cec5SDimitry Andric assert(Result <= UINT32_MAX && "relocation overflow"); 2720b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 2730b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_MOV32T" 2740b57cec5SDimitry Andric << " TargetSection: " << RE.Sections.SectionA 2750b57cec5SDimitry Andric << " Value: " << format("0x%08" PRIx32, Result) 2760b57cec5SDimitry Andric << '\n'); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8| 2790b57cec5SDimitry Andric // imm32 = zext imm4:i:imm3:imm8 2800b57cec5SDimitry Andric // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8| 2810b57cec5SDimitry Andric // imm16 = imm4:i:imm3:imm8 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate) { 2840b57cec5SDimitry Andric Bytes[0] |= ((Immediate & 0xf000) >> 12); 2850b57cec5SDimitry Andric Bytes[1] |= ((Immediate & 0x0800) >> 11); 2860b57cec5SDimitry Andric Bytes[2] |= ((Immediate & 0x00ff) >> 0); 2870b57cec5SDimitry Andric Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4); 2880b57cec5SDimitry Andric }; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric EncodeImmediate(&Target[0], 2910b57cec5SDimitry Andric (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit); 2920b57cec5SDimitry Andric EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16); 2930b57cec5SDimitry Andric break; 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH20T: { 2960b57cec5SDimitry Andric // The most significant 20-bits of the signed 21-bit relative displacement 2970b57cec5SDimitry Andric uint64_t Value = 2980b57cec5SDimitry Andric RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; 2990b57cec5SDimitry Andric assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX && 3000b57cec5SDimitry Andric "relocation overflow"); 3010b57cec5SDimitry Andric assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN && 3020b57cec5SDimitry Andric "relocation underflow"); 3030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 3040b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_BRANCH20T" 3050b57cec5SDimitry Andric << " Value: " << static_cast<int32_t>(Value) << '\n'); 3060b57cec5SDimitry Andric static_cast<void>(Value); 3070b57cec5SDimitry Andric llvm_unreachable("unimplemented relocation"); 3080b57cec5SDimitry Andric break; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH24T: { 3110b57cec5SDimitry Andric // The most significant 24-bits of the signed 25-bit relative displacement 3120b57cec5SDimitry Andric uint64_t Value = 3130b57cec5SDimitry Andric RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; 3140b57cec5SDimitry Andric assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX && 3150b57cec5SDimitry Andric "relocation overflow"); 3160b57cec5SDimitry Andric assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN && 3170b57cec5SDimitry Andric "relocation underflow"); 3180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 3190b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_BRANCH24T" 3200b57cec5SDimitry Andric << " Value: " << static_cast<int32_t>(Value) << '\n'); 3210b57cec5SDimitry Andric static_cast<void>(Value); 3220b57cec5SDimitry Andric llvm_unreachable("unimplemented relocation"); 3230b57cec5SDimitry Andric break; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric case COFF::IMAGE_REL_ARM_BLX23T: { 3260b57cec5SDimitry Andric // The most significant 24-bits of the signed 25-bit relative displacement 3270b57cec5SDimitry Andric uint64_t Value = 3280b57cec5SDimitry Andric RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; 3290b57cec5SDimitry Andric assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX && 3300b57cec5SDimitry Andric "relocation overflow"); 3310b57cec5SDimitry Andric assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN && 3320b57cec5SDimitry Andric "relocation underflow"); 3330b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 3340b57cec5SDimitry Andric << " RelType: IMAGE_REL_ARM_BLX23T" 3350b57cec5SDimitry Andric << " Value: " << static_cast<int32_t>(Value) << '\n'); 3360b57cec5SDimitry Andric static_cast<void>(Value); 3370b57cec5SDimitry Andric llvm_unreachable("unimplemented relocation"); 3380b57cec5SDimitry Andric break; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric void registerEHFrames() override {} 3440b57cec5SDimitry Andric }; 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric #endif 349