mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[lld-macho][nfc] Create Relocations.{h,cpp} for relocation-specific code
This more closely mirrors the structure of lld-ELF. Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D98384
This commit is contained in:
parent
1752f28506
commit
5433a79176
@ -39,7 +39,7 @@ struct ARM64 : TargetInfo {
|
||||
uint64_t entryAddr) const override;
|
||||
|
||||
void relaxGotLoad(uint8_t *loc, uint8_t type) const override;
|
||||
const TargetInfo::RelocAttrs &getRelocAttrs(uint8_t type) const override;
|
||||
const RelocAttrs &getRelocAttrs(uint8_t type) const override;
|
||||
uint64_t getPageSize() const override { return 16 * 1024; }
|
||||
};
|
||||
|
||||
@ -52,8 +52,8 @@ struct ARM64 : TargetInfo {
|
||||
// are weird -- it results in the value of the GOT slot being written, instead
|
||||
// of the address. Let's not support it unless we find a real-world use case.
|
||||
|
||||
const TargetInfo::RelocAttrs &ARM64::getRelocAttrs(uint8_t type) const {
|
||||
static const std::array<TargetInfo::RelocAttrs, 11> relocAttrsArray{{
|
||||
const RelocAttrs &ARM64::getRelocAttrs(uint8_t type) const {
|
||||
static const std::array<RelocAttrs, 11> relocAttrsArray{{
|
||||
#define B(x) RelocAttrBits::x
|
||||
{"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) |
|
||||
B(DYSYM8) | B(BYTE4) | B(BYTE8)},
|
||||
@ -73,7 +73,7 @@ const TargetInfo::RelocAttrs &ARM64::getRelocAttrs(uint8_t type) const {
|
||||
}};
|
||||
assert(type < relocAttrsArray.size() && "invalid relocation type");
|
||||
if (type >= relocAttrsArray.size())
|
||||
return TargetInfo::invalidRelocAttrs;
|
||||
return invalidRelocAttrs;
|
||||
return relocAttrsArray[type];
|
||||
}
|
||||
|
||||
|
@ -36,14 +36,14 @@ struct X86_64 : TargetInfo {
|
||||
uint64_t entryAddr) const override;
|
||||
|
||||
void relaxGotLoad(uint8_t *loc, uint8_t type) const override;
|
||||
const TargetInfo::RelocAttrs &getRelocAttrs(uint8_t type) const override;
|
||||
const RelocAttrs &getRelocAttrs(uint8_t type) const override;
|
||||
uint64_t getPageSize() const override { return 4 * 1024; }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
const TargetInfo::RelocAttrs &X86_64::getRelocAttrs(uint8_t type) const {
|
||||
static const std::array<TargetInfo::RelocAttrs, 10> relocAttrsArray{{
|
||||
const RelocAttrs &X86_64::getRelocAttrs(uint8_t type) const {
|
||||
static const std::array<RelocAttrs, 10> relocAttrsArray{{
|
||||
#define B(x) RelocAttrBits::x
|
||||
{"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) |
|
||||
B(DYSYM8) | B(BYTE4) | B(BYTE8)},
|
||||
@ -60,7 +60,7 @@ const TargetInfo::RelocAttrs &X86_64::getRelocAttrs(uint8_t type) const {
|
||||
}};
|
||||
assert(type < relocAttrsArray.size() && "invalid relocation type");
|
||||
if (type >= relocAttrsArray.size())
|
||||
return TargetInfo::invalidRelocAttrs;
|
||||
return invalidRelocAttrs;
|
||||
return relocAttrsArray[type];
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ add_lld_library(lldMachO2
|
||||
ObjC.cpp
|
||||
OutputSection.cpp
|
||||
OutputSegment.cpp
|
||||
Relocations.cpp
|
||||
SymbolTable.cpp
|
||||
Symbols.cpp
|
||||
SyntheticSections.cpp
|
||||
|
@ -203,7 +203,7 @@ static InputSection *findContainingSubsection(SubsectionMap &map,
|
||||
|
||||
static bool validateRelocationInfo(InputFile *file, const section_64 &sec,
|
||||
relocation_info rel) {
|
||||
const TargetInfo::RelocAttrs &relocAttrs = target->getRelocAttrs(rel.r_type);
|
||||
const RelocAttrs &relocAttrs = target->getRelocAttrs(rel.r_type);
|
||||
bool valid = true;
|
||||
auto message = [relocAttrs, file, sec, rel, &valid](const Twine &diagnostic) {
|
||||
valid = false;
|
||||
|
@ -36,7 +36,7 @@ uint64_t InputSection::getVA() const { return parent->addr + outSecOff; }
|
||||
|
||||
static uint64_t resolveSymbolVA(uint8_t *loc, const lld::macho::Symbol &sym,
|
||||
uint8_t type) {
|
||||
const TargetInfo::RelocAttrs &relocAttrs = target->getRelocAttrs(type);
|
||||
const RelocAttrs &relocAttrs = target->getRelocAttrs(type);
|
||||
if (relocAttrs.hasAttr(RelocAttrBits::BRANCH)) {
|
||||
if (sym.isInStubs())
|
||||
return in.stubs->addr + sym.stubsIndex * target->stubSize;
|
||||
|
@ -9,9 +9,10 @@
|
||||
#ifndef LLD_MACHO_INPUT_SECTION_H
|
||||
#define LLD_MACHO_INPUT_SECTION_H
|
||||
|
||||
#include "Relocations.h"
|
||||
|
||||
#include "lld/Common/LLVM.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
|
||||
namespace lld {
|
||||
@ -23,19 +24,6 @@ class OutputSection;
|
||||
class Symbol;
|
||||
class Defined;
|
||||
|
||||
struct Reloc {
|
||||
uint8_t type = llvm::MachO::GENERIC_RELOC_INVALID;
|
||||
bool pcrel = false;
|
||||
uint8_t length = 0;
|
||||
// The offset from the start of the subsection that this relocation belongs
|
||||
// to.
|
||||
uint32_t offset = 0;
|
||||
// Adding this offset to the address of the referent symbol or subsection
|
||||
// gives the destination that this relocation refers to.
|
||||
uint64_t addend = 0;
|
||||
llvm::PointerUnion<Symbol *, InputSection *> referent = nullptr;
|
||||
};
|
||||
|
||||
class InputSection {
|
||||
public:
|
||||
virtual ~InputSection() = default;
|
||||
|
42
lld/MachO/Relocations.cpp
Normal file
42
lld/MachO/Relocations.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
//===- Relocations.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Relocations.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace lld;
|
||||
using namespace lld::macho;
|
||||
|
||||
bool macho::validateSymbolRelocation(const Symbol *sym,
|
||||
const InputSection *isec, const Reloc &r) {
|
||||
const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);
|
||||
bool valid = true;
|
||||
auto message = [relocAttrs, sym, isec, &valid](const Twine &diagnostic) {
|
||||
valid = false;
|
||||
return (relocAttrs.name + " relocation " + diagnostic + " for `" +
|
||||
sym->getName() + "' in " + toString(isec))
|
||||
.str();
|
||||
};
|
||||
|
||||
if (relocAttrs.hasAttr(RelocAttrBits::TLV) != sym->isTlv())
|
||||
error(message(Twine("requires that variable ") +
|
||||
(sym->isTlv() ? "not " : "") + "be thread-local"));
|
||||
if (relocAttrs.hasAttr(RelocAttrBits::DYSYM8) && isa<DylibSymbol>(sym) &&
|
||||
r.length != 3)
|
||||
error(message("has width " + std::to_string(1 << r.length) +
|
||||
" bytes, but must be 8 bytes"));
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
const RelocAttrs macho::invalidRelocAttrs{"INVALID", RelocAttrBits::_0};
|
74
lld/MachO/Relocations.h
Normal file
74
lld/MachO/Relocations.h
Normal file
@ -0,0 +1,74 @@
|
||||
//===- Relocations.h --------------------------------------------*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_MACHO_RELOCATIONS_H
|
||||
#define LLD_MACHO_RELOCATIONS_H
|
||||
|
||||
#include "llvm/ADT/BitmaskEnum.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace lld {
|
||||
namespace macho {
|
||||
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
|
||||
|
||||
class Symbol;
|
||||
class InputSection;
|
||||
|
||||
enum class RelocAttrBits {
|
||||
_0 = 0, // invalid
|
||||
PCREL = 1 << 0, // Value is PC-relative offset
|
||||
ABSOLUTE = 1 << 1, // Value is an absolute address or fixed offset
|
||||
BYTE4 = 1 << 2, // 4 byte datum
|
||||
BYTE8 = 1 << 3, // 8 byte datum
|
||||
EXTERN = 1 << 4, // Can have an external symbol
|
||||
LOCAL = 1 << 5, // Can have a local symbol
|
||||
ADDEND = 1 << 6, // *_ADDEND paired prefix reloc
|
||||
SUBTRAHEND = 1 << 7, // *_SUBTRACTOR paired prefix reloc
|
||||
BRANCH = 1 << 8, // Value is branch target
|
||||
GOT = 1 << 9, // References a symbol in the Global Offset Table
|
||||
TLV = 1 << 10, // References a thread-local symbol
|
||||
DYSYM8 = 1 << 11, // Requires DySym width to be 8 bytes
|
||||
LOAD = 1 << 12, // Relaxable indirect load
|
||||
POINTER = 1 << 13, // Non-relaxable indirect load (pointer is taken)
|
||||
UNSIGNED = 1 << 14, // *_UNSIGNED relocs
|
||||
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ (1 << 15) - 1),
|
||||
};
|
||||
// Note: SUBTRACTOR always pairs with UNSIGNED (a delta between two symbols).
|
||||
|
||||
struct RelocAttrs {
|
||||
llvm::StringRef name;
|
||||
RelocAttrBits bits;
|
||||
bool hasAttr(RelocAttrBits b) const { return (bits & b) == b; }
|
||||
};
|
||||
|
||||
struct Reloc {
|
||||
uint8_t type = llvm::MachO::GENERIC_RELOC_INVALID;
|
||||
bool pcrel = false;
|
||||
uint8_t length = 0;
|
||||
// The offset from the start of the subsection that this relocation belongs
|
||||
// to.
|
||||
uint32_t offset = 0;
|
||||
// Adding this offset to the address of the referent symbol or subsection
|
||||
// gives the destination that this relocation refers to.
|
||||
uint64_t addend = 0;
|
||||
llvm::PointerUnion<Symbol *, InputSection *> referent = nullptr;
|
||||
};
|
||||
|
||||
bool validateSymbolRelocation(const Symbol *, const InputSection *,
|
||||
const Reloc &);
|
||||
|
||||
extern const RelocAttrs invalidRelocAttrs;
|
||||
|
||||
} // namespace macho
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
@ -7,40 +7,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Target.h"
|
||||
#include "InputSection.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace lld;
|
||||
using namespace lld::macho;
|
||||
|
||||
const TargetInfo::RelocAttrs TargetInfo::invalidRelocAttrs{"INVALID",
|
||||
RelocAttrBits::_0};
|
||||
|
||||
bool TargetInfo::validateSymbolRelocation(const Symbol *sym,
|
||||
const InputSection *isec,
|
||||
const Reloc &r) {
|
||||
const RelocAttrs &relocAttrs = getRelocAttrs(r.type);
|
||||
bool valid = true;
|
||||
auto message = [relocAttrs, sym, isec, &valid](const Twine &diagnostic) {
|
||||
valid = false;
|
||||
return (relocAttrs.name + " relocation " + diagnostic + " for `" +
|
||||
sym->getName() + "' in " + toString(isec))
|
||||
.str();
|
||||
};
|
||||
|
||||
if (relocAttrs.hasAttr(RelocAttrBits::TLV) != sym->isTlv())
|
||||
error(message(Twine("requires that variable ") +
|
||||
(sym->isTlv() ? "not " : "") + "be thread-local"));
|
||||
if (relocAttrs.hasAttr(RelocAttrBits::DYSYM8) && isa<DylibSymbol>(sym) &&
|
||||
r.length != 3)
|
||||
error(message("has width " + std::to_string(1 << r.length) +
|
||||
" bytes, but must be 8 bytes"));
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
TargetInfo *macho::target = nullptr;
|
||||
|
@ -9,6 +9,8 @@
|
||||
#ifndef LLD_MACHO_TARGET_H
|
||||
#define LLD_MACHO_TARGET_H
|
||||
|
||||
#include "Relocations.h"
|
||||
|
||||
#include "llvm/ADT/BitmaskEnum.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
@ -23,7 +25,6 @@ LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
|
||||
class Symbol;
|
||||
class DylibSymbol;
|
||||
class InputSection;
|
||||
struct Reloc;
|
||||
|
||||
enum : uint64_t {
|
||||
// We are currently only supporting 64-bit targets since macOS and iOS are
|
||||
@ -33,36 +34,8 @@ enum : uint64_t {
|
||||
MaxAlignmentPowerOf2 = 32,
|
||||
};
|
||||
|
||||
enum class RelocAttrBits {
|
||||
_0 = 0, // invalid
|
||||
PCREL = 1 << 0, // Value is PC-relative offset
|
||||
ABSOLUTE = 1 << 1, // Value is an absolute address or fixed offset
|
||||
BYTE4 = 1 << 2, // 4 byte datum
|
||||
BYTE8 = 1 << 3, // 8 byte datum
|
||||
EXTERN = 1 << 4, // Can have an external symbol
|
||||
LOCAL = 1 << 5, // Can have a local symbol
|
||||
ADDEND = 1 << 6, // *_ADDEND paired prefix reloc
|
||||
SUBTRAHEND = 1 << 7, // *_SUBTRACTOR paired prefix reloc
|
||||
BRANCH = 1 << 8, // Value is branch target
|
||||
GOT = 1 << 9, // References a symbol in the Global Offset Table
|
||||
TLV = 1 << 10, // References a thread-local symbol
|
||||
DYSYM8 = 1 << 11, // Requires DySym width to be 8 bytes
|
||||
LOAD = 1 << 12, // Relaxable indirect load
|
||||
POINTER = 1 << 13, // Non-relaxable indirect load (pointer is taken)
|
||||
UNSIGNED = 1 << 14, // *_UNSIGNED relocs
|
||||
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ (1 << 15) - 1),
|
||||
};
|
||||
// Note: SUBTRACTOR always pairs with UNSIGNED (a delta between two symbols).
|
||||
|
||||
class TargetInfo {
|
||||
public:
|
||||
struct RelocAttrs {
|
||||
llvm::StringRef name;
|
||||
RelocAttrBits bits;
|
||||
bool hasAttr(RelocAttrBits b) const { return (bits & b) == b; }
|
||||
};
|
||||
static const RelocAttrs invalidRelocAttrs;
|
||||
|
||||
virtual ~TargetInfo() = default;
|
||||
|
||||
// Validate the relocation structure and get its addend.
|
||||
@ -97,8 +70,6 @@ public:
|
||||
bool validateRelocationInfo(llvm::MemoryBufferRef,
|
||||
const llvm::MachO::section_64 &sec,
|
||||
llvm::MachO::relocation_info);
|
||||
bool validateSymbolRelocation(const Symbol *, const InputSection *isec,
|
||||
const Reloc &);
|
||||
void prepareSymbolRelocation(Symbol *, const InputSection *, const Reloc &);
|
||||
|
||||
uint32_t cpuType;
|
||||
|
@ -444,7 +444,7 @@ public:
|
||||
|
||||
static void prepareSymbolRelocation(lld::macho::Symbol *sym,
|
||||
const InputSection *isec, const Reloc &r) {
|
||||
const TargetInfo::RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);
|
||||
const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);
|
||||
|
||||
if (relocAttrs.hasAttr(RelocAttrBits::BRANCH)) {
|
||||
prepareBranchTarget(sym);
|
||||
@ -484,8 +484,7 @@ void Writer::scanRelocations() {
|
||||
if (auto *undefined = dyn_cast<Undefined>(sym))
|
||||
treatUndefinedSymbol(*undefined);
|
||||
// treatUndefinedSymbol() can replace sym with a DylibSymbol; re-check.
|
||||
if (!isa<Undefined>(sym) &&
|
||||
target->validateSymbolRelocation(sym, isec, r))
|
||||
if (!isa<Undefined>(sym) && validateSymbolRelocation(sym, isec, r))
|
||||
prepareSymbolRelocation(sym, isec, r);
|
||||
} else {
|
||||
assert(r.referent.is<InputSection *>());
|
||||
|
Loading…
Reference in New Issue
Block a user