diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -43,9 +43,6 @@ std::vector parseSections(ArrayRef); - void parseRelocations(const llvm::MachO::section_64 &, - std::vector &relocs); - private: const Kind fileKind; }; diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -142,39 +142,14 @@ else isec->align = 1 << sec.align; isec->flags = sec.flags; + isec->relOff = sec.reloff; + isec->nReloc = sec.nreloc; ret.push_back(isec); } return ret; } -void InputFile::parseRelocations(const section_64 &sec, - std::vector &relocs) { - auto *buf = reinterpret_cast(mb.getBufferStart()); - ArrayRef relInfos( - reinterpret_cast(buf + sec.reloff), - sec.nreloc); - - for (const any_relocation_info &anyRel : relInfos) { - Reloc r; - if (anyRel.r_word0 & R_SCATTERED) { - error("TODO: Scattered relocations not supported"); - } else { - auto rel = reinterpret_cast(anyRel); - r.type = rel.r_type; - r.offset = rel.r_address; - r.addend = target->getImplicitAddend(buf + sec.offset + r.offset, r.type); - if (rel.r_extern) - r.target = symbols[rel.r_symbolnum]; - else { - error("TODO: Non-extern relocations are not supported"); - continue; - } - } - relocs.push_back(r); - } -} - ObjFile::ObjFile(MemoryBufferRef mb) : InputFile(ObjKind, mb) { auto *buf = reinterpret_cast(mb.getBufferStart()); auto *hdr = reinterpret_cast(mb.getBufferStart()); @@ -219,16 +194,6 @@ symbols.push_back(make(name, isec, value)); } } - - // The relocations may refer to the symbols, so we parse them after we have - // the symbols loaded. - if (!sections.empty()) { - auto it = sections.begin(); - for (const section_64 &sec : objSections) { - parseRelocations(sec, (*it)->relocs); - ++it; - } - } } DylibFile::DylibFile(MemoryBufferRef mb) : InputFile(DylibKind, mb) { diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -22,13 +22,6 @@ class OutputSegment; class Symbol; -struct Reloc { - uint8_t type; - uint32_t addend; - uint32_t offset; - llvm::PointerUnion target; -}; - class InputSection { public: virtual ~InputSection() = default; @@ -40,6 +33,7 @@ // Unneeded sections are omitted entirely (header and body). virtual bool isNeeded() const { return true; } virtual void writeTo(uint8_t *buf); + ArrayRef relocations() const; InputFile *file = nullptr; OutputSegment *parent = nullptr; @@ -55,7 +49,10 @@ uint32_t sectionIndex = 0; uint32_t flags = 0; - std::vector relocs; + // Relocation data offset in the input file. + uint32_t relOff = 0; + // Number of relocation entries. + uint32_t nReloc = 0; }; extern std::vector inputSections; diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -7,9 +7,13 @@ //===----------------------------------------------------------------------===// #include "InputSection.h" +#include "InputFiles.h" #include "OutputSegment.h" +#include "SymbolTable.h" #include "Symbols.h" #include "Target.h" + +#include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "llvm/Support/Endian.h" @@ -28,23 +32,40 @@ if (!data.empty()) memcpy(buf, data.data(), data.size()); - for (Reloc &r : relocs) { + for (const any_relocation_info &anyRel : relocations()) { + if (anyRel.r_word0 & R_SCATTERED) + fatal("TODO: Scattered relocations not supported"); + + auto rel = reinterpret_cast(anyRel); + uint32_t addend = + target->getImplicitAddend(buf + rel.r_address, rel.r_type); uint64_t va = 0; - if (auto *s = r.target.dyn_cast()) { - if (auto *dylibSymbol = dyn_cast(s)) { - va = target->getDylibSymbolVA(*dylibSymbol, r.type); - } else { + if (rel.r_extern) { + Symbol *s = file->symbols[rel.r_symbolnum]; + if (auto *dylibSymbol = dyn_cast(s)) + va = target->getDylibSymbolVA(*dylibSymbol, rel.r_type); + else va = s->getVA(); - } - } else if (auto *isec = r.target.dyn_cast()) { - va = isec->addr; } else { - llvm_unreachable("Unknown relocation target"); + fatal("TODO: Non-extern relocations are not supported"); } - uint64_t val = va + r.addend; - if (1) // TODO: handle non-pcrel relocations - val -= addr + r.offset; - target->relocateOne(buf + r.offset, r.type, val); + uint64_t val = va + addend; + if (rel.r_pcrel) + val -= addr + rel.r_address; + else + fatal("TODO: handle non-pcrel relocations"); + + target->relocateOne(buf + rel.r_address, rel.r_type, val); } } + +ArrayRef InputSection::relocations() const { + // Synthetic sections will not have a corresponding InputFile. + if (file == nullptr) + return {}; + + return {reinterpret_cast( + file->mb.getBufferStart() + relOff), + nReloc}; +} diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -339,11 +339,19 @@ } void Writer::scanRelocations() { - for (InputSection *sect : inputSections) - for (Reloc &r : sect->relocs) - if (auto *s = r.target.dyn_cast()) + for (InputSection *isec : inputSections) { + for (const any_relocation_info &anyRel : isec->relocations()) { + if (anyRel.r_word0 & R_SCATTERED) + fatal("TODO: Scattered relocations not supported"); + + auto rel = reinterpret_cast(anyRel); + if (rel.r_extern) { + Symbol *s = isec->file->symbols[rel.r_symbolnum]; if (auto *dylibSymbol = dyn_cast(s)) - target->prepareDylibSymbolRelocation(*dylibSymbol, r.type); + target->prepareDylibSymbolRelocation(*dylibSymbol, rel.r_type); + } + } + } } void Writer::createLoadCommands() {