Path: blob/main/contrib/llvm-project/lld/MachO/Relocations.cpp
34869 views
//===- Relocations.cpp ----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Relocations.h"9#include "ConcatOutputSection.h"10#include "Symbols.h"11#include "SyntheticSections.h"12#include "Target.h"1314#include "lld/Common/ErrorHandler.h"1516using namespace llvm;17using namespace lld;18using namespace lld::macho;1920static_assert(sizeof(void *) != 8 || sizeof(Reloc) == 24,21"Try to minimize Reloc's size; we create many instances");2223InputSection *Reloc::getReferentInputSection() const {24if (const auto *sym = referent.dyn_cast<Symbol *>()) {25if (const auto *d = dyn_cast<Defined>(sym))26return d->isec();27return nullptr;28} else {29return referent.get<InputSection *>();30}31}3233bool macho::validateSymbolRelocation(const Symbol *sym,34const InputSection *isec, const Reloc &r) {35const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);36bool valid = true;37auto message = [&](const Twine &diagnostic) {38valid = false;39return (isec->getLocation(r.offset) + ": " + relocAttrs.name +40" relocation " + diagnostic)41.str();42};4344if (relocAttrs.hasAttr(RelocAttrBits::TLV) != sym->isTlv())45error(message(Twine("requires that symbol ") + sym->getName() + " " +46(sym->isTlv() ? "not " : "") + "be thread-local"));4748return valid;49}5051// Given an offset in the output buffer, figure out which ConcatInputSection (if52// any) maps to it. At the same time, update the offset such that it is relative53// to the InputSection rather than to the output buffer.54//55// Obtaining the InputSection allows us to have better error diagnostics.56// However, many of our relocation-handling methods do not take the InputSection57// as a parameter. Since we are already passing the buffer offsets to our Target58// methods, this function allows us to emit better errors without threading an59// additional InputSection argument through the call stack.60//61// This is implemented as a slow linear search through OutputSegments,62// OutputSections, and finally the InputSections themselves. However, this63// function should be called only on error paths, so some overhead is fine.64InputSection *macho::offsetToInputSection(uint64_t *off) {65for (OutputSegment *seg : outputSegments) {66if (*off < seg->fileOff || *off >= seg->fileOff + seg->fileSize)67continue;6869const std::vector<OutputSection *> §ions = seg->getSections();70size_t osecIdx = 0;71for (; osecIdx < sections.size(); ++osecIdx)72if (*off < sections[osecIdx]->fileOff)73break;74assert(osecIdx > 0);75// We should be only calling this function on offsets that belong to76// ConcatOutputSections.77auto *osec = cast<ConcatOutputSection>(sections[osecIdx - 1]);78*off -= osec->fileOff;7980size_t isecIdx = 0;81for (; isecIdx < osec->inputs.size(); ++isecIdx) {82const ConcatInputSection *isec = osec->inputs[isecIdx];83if (*off < isec->outSecOff)84break;85}86assert(isecIdx > 0);87ConcatInputSection *isec = osec->inputs[isecIdx - 1];88*off -= isec->outSecOff;89return isec;90}91return nullptr;92}9394void macho::reportRangeError(void *loc, const Reloc &r, const Twine &v,95uint8_t bits, int64_t min, uint64_t max) {96std::string hint;97uint64_t off = reinterpret_cast<const uint8_t *>(loc) - in.bufferStart;98const InputSection *isec = offsetToInputSection(&off);99std::string locStr = isec ? isec->getLocation(off) : "(invalid location)";100if (auto *sym = r.referent.dyn_cast<Symbol *>())101hint = "; references " + toString(*sym);102error(locStr + ": relocation " + target->getRelocAttrs(r.type).name +103" is out of range: " + v + " is not in [" + Twine(min) + ", " +104Twine(max) + "]" + hint);105}106107void macho::reportRangeError(void *loc, SymbolDiagnostic d, const Twine &v,108uint8_t bits, int64_t min, uint64_t max) {109// FIXME: should we use `loc` somehow to provide a better error message?110std::string hint;111if (d.symbol)112hint = "; references " + toString(*d.symbol);113error(d.reason + " is out of range: " + v + " is not in [" + Twine(min) +114", " + Twine(max) + "]" + hint);115}116117const RelocAttrs macho::invalidRelocAttrs{"INVALID", RelocAttrBits::_0};118119120