Path: blob/main/contrib/llvm-project/lld/MachO/EhFrame.h
34870 views
//===- EhFrame.h ------------------------------------------------*- C++ -*-===//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#ifndef LLD_MACHO_EH_FRAME_H9#define LLD_MACHO_EH_FRAME_H1011#include "InputSection.h"12#include "Relocations.h"1314#include "lld/Common/LLVM.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/PointerUnion.h"17#include "llvm/ADT/SmallVector.h"1819/*20* NOTE: The main bulk of the EH frame parsing logic is in InputFiles.cpp as it21* is closely coupled with other file parsing logic; EhFrame.h just contains a22* few helpers.23*/2425/*26* === The EH frame format ===27*28* EH frames can either be Common Information Entries (CIEs) or Frame29* Description Entries (FDEs). CIEs contain information that is common amongst30* several FDEs. Each FDE contains a pointer to its CIE. Thus all the EH frame31* entries together form a forest of two-level trees, with CIEs as the roots32* and FDEs as the leaves. Note that a CIE must precede the FDEs which point33* to it.34*35* A CIE comprises the following fields in order:36* 1. Length of the entry (4 or 12 bytes)37* 2. CIE offset (4 bytes; always 0 for CIEs)38* 3. CIE version (byte)39* 4. Null-terminated augmentation string40* 5-8. LEB128 values that we don't care about41* 9. Augmentation data, to be interpreted using the aug string42* 10. DWARF instructions (ignored by LLD)43*44* An FDE comprises of the following:45* 1. Length of the entry (4 or 12 bytes)46* 2. CIE offset (4 bytes pcrel offset that points backwards to this FDE's CIE)47* 3. Function address (pointer-sized pcrel offset)48* 4. (std::optional) Augmentation data length49* 5. (std::optional) LSDA address (pointer-sized pcrel offset)50* 6. DWARF instructions (ignored by LLD)51*/52namespace lld::macho {5354class EhReader {55public:56EhReader(const ObjFile *file, ArrayRef<uint8_t> data, size_t dataOff)57: file(file), data(data), dataOff(dataOff) {}58size_t size() const { return data.size(); }59// Read and validate the length field.60uint64_t readLength(size_t *off) const;61// Skip the length field without doing validation.62void skipValidLength(size_t *off) const;63uint8_t readByte(size_t *off) const;64uint32_t readU32(size_t *off) const;65uint64_t readPointer(size_t *off, uint8_t size) const;66StringRef readString(size_t *off) const;67void skipLeb128(size_t *off) const;68void failOn(size_t errOff, const Twine &msg) const;6970private:71const ObjFile *file;72ArrayRef<uint8_t> data;73// The offset of the data array within its section. Used only for error74// reporting.75const size_t dataOff;76};7778// The EH frame format, when emitted by llvm-mc, consists of a number of79// "abs-ified" relocations, i.e. relocations that are implicitly encoded as80// pcrel offsets in the section data. The offsets refer to the locations of81// symbols in the input object file. When we ingest these EH frames, we convert82// these implicit relocations into explicit Relocs.83//84// These pcrel relocations are semantically similar to X86_64_RELOC_SIGNED_4.85// However, we need this operation to be cross-platform, and ARM does not have a86// similar relocation that is applicable. We therefore use the more verbose (but87// more generic) subtractor relocation to encode these pcrel values. ld6488// appears to do something similar -- its `-r` output contains these explicit89// subtractor relocations.90class EhRelocator {91public:92EhRelocator(InputSection *isec) : isec(isec) {}9394// For the next two methods, let `PC` denote `isec address + off`.95// Create relocs writing the value of target - PC to PC.96void makePcRel(uint64_t off,97llvm::PointerUnion<Symbol *, InputSection *> target,98uint8_t length);99// Create relocs writing the value of PC - target to PC.100void makeNegativePcRel(uint64_t off,101llvm::PointerUnion<Symbol *, InputSection *> target,102uint8_t length);103// Insert the new relocations into isec->relocs.104void commit();105106private:107InputSection *isec;108// Insert new relocs here so that we don't invalidate iterators into the109// existing relocs vector.110SmallVector<Reloc, 6> newRelocs;111};112113} // namespace lld::macho114115#endif116117118