Index: include/llvm/DebugInfo/DWARF/DWARFRelocMap.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFRelocMap.h +++ include/llvm/DebugInfo/DWARF/DWARFRelocMap.h @@ -10,6 +10,7 @@ #define LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/Object/RelocationResolver.h" #include namespace llvm { @@ -18,7 +19,9 @@ /// Section index is -1LL if relocation points to absolute symbol. struct RelocAddrEntry { uint64_t SectionIndex; - uint64_t Value; + object::RelocationRef Reloc; + object::RelocationResolver Resolver; + uint64_t S; }; /// In place of applying the relocations to the data we've read from disk we use Index: include/llvm/Object/RelocVisitor.h =================================================================== --- include/llvm/Object/RelocVisitor.h +++ /dev/null @@ -1,362 +0,0 @@ -//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides a wrapper around all the different types of relocations -// in different file formats, such that a client can handle them in a unified -// manner by only implementing a minimal number of functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_RELOCVISITOR_H -#define LLVM_OBJECT_RELOCVISITOR_H - -#include "llvm/ADT/Triple.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/Object/COFF.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/Wasm.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include - -namespace llvm { -namespace object { - -/// Base class for object file relocation visitors. -class RelocVisitor { -public: - explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {} - - // TODO: Should handle multiple applied relocations via either passing in the - // previously computed value or just count paired relocations as a single - // visit. - uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) { - if (isa(ObjToVisit)) - return visitELF(Rel, R, Value); - if (isa(ObjToVisit)) - return visitCOFF(Rel, R, Value); - if (isa(ObjToVisit)) - return visitMachO(Rel, R, Value); - if (isa(ObjToVisit)) - return visitWasm(Rel, R, Value); - - HasError = true; - return 0; - } - - bool error() { return HasError; } - -private: - const ObjectFile &ObjToVisit; - bool HasError = false; - - uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file - switch (ObjToVisit.getArch()) { - case Triple::x86_64: - return visitX86_64(Rel, R, Value); - case Triple::aarch64: - case Triple::aarch64_be: - return visitAarch64(Rel, R, Value); - case Triple::bpfel: - case Triple::bpfeb: - return visitBpf(Rel, R, Value); - case Triple::mips64el: - case Triple::mips64: - return visitMips64(Rel, R, Value); - case Triple::ppc64le: - case Triple::ppc64: - return visitPPC64(Rel, R, Value); - case Triple::systemz: - return visitSystemz(Rel, R, Value); - case Triple::sparcv9: - return visitSparc64(Rel, R, Value); - case Triple::amdgcn: - return visitAmdgpu(Rel, R, Value); - default: - HasError = true; - return 0; - } - } - - // 32-bit object file - assert(ObjToVisit.getBytesInAddress() == 4 && - "Invalid word size in object file"); - - switch (ObjToVisit.getArch()) { - case Triple::x86: - return visitX86(Rel, R, Value); - case Triple::ppc: - return visitPPC32(Rel, R, Value); - case Triple::arm: - case Triple::armeb: - return visitARM(Rel, R, Value); - case Triple::avr: - return visitAVR(Rel, R, Value); - case Triple::lanai: - return visitLanai(Rel, R, Value); - case Triple::mipsel: - case Triple::mips: - return visitMips32(Rel, R, Value); - case Triple::sparc: - return visitSparc32(Rel, R, Value); - case Triple::hexagon: - return visitHexagon(Rel, R, Value); - default: - HasError = true; - return 0; - } - } - - int64_t getELFAddend(RelocationRef R) { - Expected AddendOrErr = ELFRelocationRef(R).getAddend(); - handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { - report_fatal_error(EI.message()); - }); - return *AddendOrErr; - } - - uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_X86_64_NONE: - return 0; - case ELF::R_X86_64_64: - case ELF::R_X86_64_DTPOFF32: - case ELF::R_X86_64_DTPOFF64: - return Value + getELFAddend(R); - case ELF::R_X86_64_PC32: - return Value + getELFAddend(R) - R.getOffset(); - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - } - HasError = true; - return 0; - } - - uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_AARCH64_ABS32: { - int64_t Res = Value + getELFAddend(R); - if (Res < INT32_MIN || Res > UINT32_MAX) - HasError = true; - return static_cast(Res); - } - case ELF::R_AARCH64_ABS64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_BPF_64_32: - return Value & 0xFFFFFFFF; - case ELF::R_BPF_64_64: - return Value; - } - HasError = true; - return 0; - } - - uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_MIPS_32: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - case ELF::R_MIPS_64: - return Value + getELFAddend(R); - case ELF::R_MIPS_TLS_DTPREL64: - return Value + getELFAddend(R) - 0x8000; - } - HasError = true; - return 0; - } - - uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_PPC64_ADDR32: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - case ELF::R_PPC64_ADDR64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_390_32: { - int64_t Res = Value + getELFAddend(R); - if (Res < INT32_MIN || Res > UINT32_MAX) - HasError = true; - return static_cast(Res); - } - case ELF::R_390_64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_SPARC_32: - case ELF::R_SPARC_64: - case ELF::R_SPARC_UA32: - case ELF::R_SPARC_UA64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_AMDGPU_ABS32: - case ELF::R_AMDGPU_ABS64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_386_NONE: - return 0; - case ELF::R_386_32: - return Value; - case ELF::R_386_PC32: - return Value - R.getOffset(); - } - HasError = true; - return 0; - } - - uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_PPC_ADDR32) - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - HasError = true; - return 0; - } - - uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_ARM_ABS32) { - if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX) - HasError = true; - return static_cast(Value); - } - HasError = true; - return 0; - } - - uint64_t visitAVR(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_AVR_16) { - return (Value + getELFAddend(R)) & 0xFFFF; - } else if (Rel == ELF::R_AVR_32) { - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - } - HasError = true; - return 0; - } - - uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_LANAI_32) - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - HasError = true; - return 0; - } - - uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) { - // FIXME: Take in account implicit addends to get correct results. - if (Rel == ELF::R_MIPS_32) - return Value & 0xFFFFFFFF; - if (Rel == ELF::R_MIPS_TLS_DTPREL32) - return Value & 0xFFFFFFFF; - HasError = true; - return 0; - } - - uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) - return Value + getELFAddend(R); - HasError = true; - return 0; - } - - uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_HEX_32) - return Value + getELFAddend(R); - HasError = true; - return 0; - } - - uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (ObjToVisit.getArch()) { - case Triple::x86: - switch (Rel) { - case COFF::IMAGE_REL_I386_SECREL: - case COFF::IMAGE_REL_I386_DIR32: - return static_cast(Value); - } - break; - case Triple::x86_64: - switch (Rel) { - case COFF::IMAGE_REL_AMD64_SECREL: - return static_cast(Value); - case COFF::IMAGE_REL_AMD64_ADDR64: - return Value; - } - break; - default: - break; - } - HasError = true; - return 0; - } - - uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getArch() == Triple::x86_64 && - Rel == MachO::X86_64_RELOC_UNSIGNED) - return Value; - HasError = true; - return 0; - } - - uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getArch() == Triple::wasm32) { - switch (Rel) { - case wasm::R_WASM_FUNCTION_INDEX_LEB: - case wasm::R_WASM_TABLE_INDEX_SLEB: - case wasm::R_WASM_TABLE_INDEX_I32: - case wasm::R_WASM_MEMORY_ADDR_LEB: - case wasm::R_WASM_MEMORY_ADDR_SLEB: - case wasm::R_WASM_MEMORY_ADDR_I32: - case wasm::R_WASM_TYPE_INDEX_LEB: - case wasm::R_WASM_GLOBAL_INDEX_LEB: - case wasm::R_WASM_FUNCTION_OFFSET_I32: - case wasm::R_WASM_SECTION_OFFSET_I32: - case wasm::R_WASM_EVENT_INDEX_LEB: - // For wasm section, its offset at 0 -- ignoring Value - return 0; - } - } - HasError = true; - return 0; - } -}; - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_RELOCVISITOR_H Index: include/llvm/Object/RelocationResolver.h =================================================================== --- /dev/null +++ include/llvm/Object/RelocationResolver.h @@ -0,0 +1,42 @@ +//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around all the different types of relocations +// in different file formats, such that a client can handle them in a unified +// manner by only implementing a minimal number of functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_RELOCVISITOR_H +#define LLVM_OBJECT_RELOCVISITOR_H + +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include + +namespace llvm { +namespace object { + +using RelocationResolver = Optional (*)(RelocationRef R, uint64_t S, + int64_t A); + +RelocationResolver getRelocationResolver(const ObjectFile &Obj); + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_RELOCVISITOR_H Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -36,7 +36,7 @@ #include "llvm/Object/Decompressor.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Object/RelocVisitor.h" +#include "llvm/Object/RelocationResolver.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" @@ -1494,6 +1494,7 @@ // Symbol to [address, section index] cache mapping. std::map AddrCache; + RelocationResolver Resolver = getRelocationResolver(Obj); for (const RelocationRef &Reloc : Section.relocations()) { // FIXME: it's not clear how to correctly handle scattered // relocations. @@ -1508,9 +1509,12 @@ continue; } - object::RelocVisitor V(Obj); - uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); - if (V.error()) { + if (Optional Val = + Resolver ? Resolver(Reloc, SymInfoOrErr->Address, 0) : None) { + Map->try_emplace(Reloc.getOffset(), + RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc, + Resolver, SymInfoOrErr->Address}); + } else { SmallString<32> Type; Reloc.getTypeName(Type); ErrorPolicy EP = HandleError( @@ -1518,10 +1522,7 @@ errorCodeToError(object_error::parse_failed))); if (EP == ErrorPolicy::Halt) return; - continue; } - RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; - Map->insert({Reloc.getOffset(), Rel}); } } Index: lib/DebugInfo/DWARF/DWARFDataExtractor.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -18,12 +18,13 @@ *SecNdx = -1ULL; if (!Section) return getUnsigned(Off, Size); - Optional Rel = Obj->find(*Section, *Off); - if (!Rel) - return getUnsigned(Off, Size); + Optional E = Obj->find(*Section, *Off); + uint64_t A = getUnsigned(Off, Size); + if (!E) + return A; if (SecNdx) - *SecNdx = Rel->SectionIndex; - return getUnsigned(Off, Size) + Rel->Value; + *SecNdx = E->SectionIndex; + return E->Resolver(E->Reloc, E->S, A).getValueOr(A); } Optional Index: lib/Object/CMakeLists.txt =================================================================== --- lib/Object/CMakeLists.txt +++ lib/Object/CMakeLists.txt @@ -17,6 +17,7 @@ Object.cpp ObjectFile.cpp RecordStreamer.cpp + RelocationResolver.cpp SymbolicFile.cpp SymbolSize.cpp WasmObjectFile.cpp Index: lib/Object/RelocationResolver.cpp =================================================================== --- /dev/null +++ lib/Object/RelocationResolver.cpp @@ -0,0 +1,305 @@ +//===- RelocationResolver.cpp ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines utilities to resolve relocations in object files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/RelocationResolver.h" + +namespace llvm { +namespace object { + +static int64_t getELFAddend(RelocationRef R) { + Expected AddendOrErr = ELFRelocationRef(R).getAddend(); + handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { + report_fatal_error(EI.message()); + }); + return *AddendOrErr; +} + +static Optional resolveX86_64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_X86_64_NONE: + return A; + case ELF::R_X86_64_64: + case ELF::R_X86_64_DTPOFF32: + case ELF::R_X86_64_DTPOFF64: + return S + getELFAddend(R); + case ELF::R_X86_64_PC32: + return S + getELFAddend(R) - R.getOffset(); + case ELF::R_X86_64_32: + case ELF::R_X86_64_32S: + return (S + getELFAddend(R)) & 0xFFFFFFFF; + } + return None; +} + +static Optional resolveAarch64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_AARCH64_ABS32: { + int64_t Res = S + getELFAddend(R); + if (Res < INT32_MIN || Res > UINT32_MAX) + return None; + return static_cast(Res); + } + case ELF::R_AARCH64_ABS64: + return S + getELFAddend(R); + } + return None; +} + +static Optional resolveBpf(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_BPF_64_32: + return S & 0xFFFFFFFF; + case ELF::R_BPF_64_64: + return S; + } + return None; +} + +static Optional resolveMips64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_MIPS_32: + return (S + getELFAddend(R)) & 0xFFFFFFFF; + case ELF::R_MIPS_64: + return S + getELFAddend(R); + case ELF::R_MIPS_TLS_DTPREL64: + return S + getELFAddend(R) - 0x8000; + } + return None; +} + +static Optional resolvePPC64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_PPC64_ADDR32: + return (S + getELFAddend(R)) & 0xFFFFFFFF; + case ELF::R_PPC64_ADDR64: + return S + getELFAddend(R); + } + return None; +} + +static Optional resolveSystemz(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_390_32: { + int64_t Res = S + getELFAddend(R); + if (Res < INT32_MIN || Res > UINT32_MAX) + return None; + return static_cast(Res); + } + case ELF::R_390_64: + return S + getELFAddend(R); + } + return None; +} + +static Optional resolveSparc64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_SPARC_32: + case ELF::R_SPARC_64: + case ELF::R_SPARC_UA32: + case ELF::R_SPARC_UA64: + return S + getELFAddend(R); + } + return None; +} + +static Optional resolveAmdgpu(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_AMDGPU_ABS32: + case ELF::R_AMDGPU_ABS64: + return S + getELFAddend(R); + } + return None; +} + +static Optional resolveX86(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_386_NONE: + return A; + case ELF::R_386_32: + return S + A; + case ELF::R_386_PC32: + return S - R.getOffset() + A; + } + return None; +} + +static Optional resolvePPC32(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_PPC_ADDR32) + return (S + getELFAddend(R)) & 0xFFFFFFFF; + return None; +} + +static Optional resolveARM(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_ARM_ABS32) { + if ((int64_t)S < INT32_MIN || (int64_t)S > UINT32_MAX) + return None; + return static_cast(S); + } + return None; +} + +static Optional resolveAVR(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_AVR_16: + return (S + getELFAddend(R)) & 0xFFFF; + case ELF::R_AVR_32: + return (S + getELFAddend(R)) & 0xFFFFFFFF; + } + return None; +} + +static Optional resolveLanai(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_LANAI_32) + return (S + getELFAddend(R)) & 0xFFFFFFFF; + return None; +} + +static Optional resolveMips32(RelocationRef R, uint64_t S, int64_t A) { + // FIXME: Take in account implicit addends to get correct results. + uint32_t Rel = R.getType(); + if (Rel == ELF::R_MIPS_32) + return (S + A) & 0xFFFFFFFF; + if (Rel == ELF::R_MIPS_TLS_DTPREL32) + return (S + A) & 0xFFFFFFFF; + return None; +} + +static Optional resolveSparc32(RelocationRef R, uint64_t S, int64_t A) { + uint32_t Rel = R.getType(); + if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) + return S + getELFAddend(R); + return None; +} + +static Optional resolveHexagon(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_HEX_32) + return S + getELFAddend(R); + return None; +} + +static Optional resolveCOFFX86(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case COFF::IMAGE_REL_I386_SECREL: + case COFF::IMAGE_REL_I386_DIR32: + return static_cast(S + A); + default: + return None; + } +} + +static Optional resolveCOFFX86_64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case COFF::IMAGE_REL_AMD64_SECREL: + return static_cast(S + A); + case COFF::IMAGE_REL_AMD64_ADDR64: + return S + A; + default: + return None; + } +} + +static Optional resolveMachOX86_64(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == MachO::X86_64_RELOC_UNSIGNED) + return S; + return None; +} + +static Optional resolveWasm32(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case wasm::R_WASM_FUNCTION_INDEX_LEB: + case wasm::R_WASM_TABLE_INDEX_SLEB: + case wasm::R_WASM_TABLE_INDEX_I32: + case wasm::R_WASM_MEMORY_ADDR_LEB: + case wasm::R_WASM_MEMORY_ADDR_SLEB: + case wasm::R_WASM_MEMORY_ADDR_I32: + case wasm::R_WASM_TYPE_INDEX_LEB: + case wasm::R_WASM_GLOBAL_INDEX_LEB: + case wasm::R_WASM_FUNCTION_OFFSET_I32: + case wasm::R_WASM_SECTION_OFFSET_I32: + case wasm::R_WASM_EVENT_INDEX_LEB: + // For wasm section, its offset at 0 -- ignoring Value + return 0; + } + return None; +} + +RelocationResolver getRelocationResolver(const ObjectFile &Obj) { + if (Obj.isCOFF()) + return Obj.getBytesInAddress() == 4 ? resolveCOFFX86 : resolveCOFFX86_64; + + if (Obj.isELF()) { + if (Obj.getBytesInAddress() == 8) { + switch (Obj.getArch()) { + case Triple::x86_64: + return resolveX86_64; + case Triple::aarch64: + case Triple::aarch64_be: + return resolveAarch64; + case Triple::bpfel: + case Triple::bpfeb: + return resolveBpf; + case Triple::mips64el: + case Triple::mips64: + return resolveMips64; + case Triple::ppc64le: + case Triple::ppc64: + return resolvePPC64; + case Triple::systemz: + return resolveSystemz; + case Triple::sparcv9: + return resolveSparc64; + case Triple::amdgcn: + return resolveAmdgpu; + default: + return nullptr; + } + } + + // 32-bit object file + assert(Obj.getBytesInAddress() == 4 && + "Invalid word size in object file"); + + switch (Obj.getArch()) { + case Triple::x86: + return resolveX86; + case Triple::ppc: + return resolvePPC32; + case Triple::arm: + case Triple::armeb: + return resolveARM; + case Triple::avr: + return resolveAVR; + case Triple::lanai: + return resolveLanai; + case Triple::mipsel: + case Triple::mips: + return resolveMips32; + case Triple::sparc: + return resolveSparc32; + case Triple::hexagon: + return resolveHexagon; + default: + return nullptr; + } + } + + if (Obj.isMachO()) + return Obj.getArch() == Triple::x86_64 ? resolveMachOX86_64 : nullptr; + + if (Obj.isWasm()) + return Obj.getArch() == Triple::wasm32 ? resolveWasm32 : nullptr; + + return nullptr; +} + +} // namespace object +} // namespace llvm