1f5febef2SRui Ueyama //===- EhFrame.cpp -------------------------------------------------------===//
2f5febef2SRui Ueyama //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f5febef2SRui Ueyama //
7f5febef2SRui Ueyama //===----------------------------------------------------------------------===//
8f5febef2SRui Ueyama //
9f5febef2SRui Ueyama // .eh_frame section contains information on how to unwind the stack when
10f5febef2SRui Ueyama // an exception is thrown. The section consists of sequence of CIE and FDE
11f5febef2SRui Ueyama // records. The linker needs to merge CIEs and associate FDEs to CIEs.
12f5febef2SRui Ueyama // That means the linker has to understand the format of the section.
13f5febef2SRui Ueyama //
14f5febef2SRui Ueyama // This file contains a few utility functions to read .eh_frame contents.
15f5febef2SRui Ueyama //
16f5febef2SRui Ueyama //===----------------------------------------------------------------------===//
17f5febef2SRui Ueyama
18f5febef2SRui Ueyama #include "EhFrame.h"
198629752cSRui Ueyama #include "Config.h"
20531df4fcSEugene Leviant #include "InputSection.h"
21531df4fcSEugene Leviant #include "Relocations.h"
22ef61d85fSFangrui Song #include "Target.h"
23b8a59c8aSBob Haarman #include "lld/Common/ErrorHandler.h"
24ee173718SRui Ueyama #include "lld/Common/Strings.h"
25264b5d9eSZachary Turner #include "llvm/BinaryFormat/Dwarf.h"
26f5febef2SRui Ueyama #include "llvm/Object/ELF.h"
27f5febef2SRui Ueyama
28f5febef2SRui Ueyama using namespace llvm;
29f5febef2SRui Ueyama using namespace llvm::ELF;
30f5febef2SRui Ueyama using namespace llvm::dwarf;
31f5febef2SRui Ueyama using namespace llvm::object;
3207837b8fSFangrui Song using namespace lld;
3307837b8fSFangrui Song using namespace lld::elf;
34f5febef2SRui Ueyama
35531df4fcSEugene Leviant namespace {
368629752cSRui Ueyama class EhReader {
37531df4fcSEugene Leviant public:
EhReader(InputSectionBase * s,ArrayRef<uint8_t> d)383837f427SRui Ueyama EhReader(InputSectionBase *s, ArrayRef<uint8_t> d) : isec(s), d(d) {}
39531df4fcSEugene Leviant uint8_t getFdeEncoding();
4021b4f806SFangrui Song bool hasLSDA();
41531df4fcSEugene Leviant
42531df4fcSEugene Leviant private:
failOn(const P * loc,const Twine & msg)433837f427SRui Ueyama template <class P> void failOn(const P *loc, const Twine &msg) {
443837f427SRui Ueyama fatal("corrupted .eh_frame: " + msg + "\n>>> defined in " +
45ae1ba619SFangrui Song isec->getObjMsg((const uint8_t *)loc - isec->rawData.data()));
46531df4fcSEugene Leviant }
47531df4fcSEugene Leviant
48531df4fcSEugene Leviant uint8_t readByte();
493837f427SRui Ueyama void skipBytes(size_t count);
50531df4fcSEugene Leviant StringRef readString();
51531df4fcSEugene Leviant void skipLeb128();
52531df4fcSEugene Leviant void skipAugP();
5321b4f806SFangrui Song StringRef getAugmentation();
54531df4fcSEugene Leviant
553837f427SRui Ueyama InputSectionBase *isec;
563837f427SRui Ueyama ArrayRef<uint8_t> d;
57531df4fcSEugene Leviant };
58531df4fcSEugene Leviant }
59531df4fcSEugene Leviant
60f5febef2SRui Ueyama // Read a byte and advance D by one byte.
readByte()618629752cSRui Ueyama uint8_t EhReader::readByte() {
623837f427SRui Ueyama if (d.empty())
633837f427SRui Ueyama failOn(d.data(), "unexpected end of CIE");
643837f427SRui Ueyama uint8_t b = d.front();
653837f427SRui Ueyama d = d.slice(1);
663837f427SRui Ueyama return b;
67f5febef2SRui Ueyama }
68f5febef2SRui Ueyama
skipBytes(size_t count)693837f427SRui Ueyama void EhReader::skipBytes(size_t count) {
703837f427SRui Ueyama if (d.size() < count)
713837f427SRui Ueyama failOn(d.data(), "CIE is too small");
723837f427SRui Ueyama d = d.slice(count);
73531df4fcSEugene Leviant }
74531df4fcSEugene Leviant
7598bdbdaeSRui Ueyama // Read a null-terminated string.
readString()768629752cSRui Ueyama StringRef EhReader::readString() {
773837f427SRui Ueyama const uint8_t *end = llvm::find(d, '\0');
783837f427SRui Ueyama if (end == d.end())
793837f427SRui Ueyama failOn(d.data(), "corrupted CIE (failed to read string)");
803837f427SRui Ueyama StringRef s = toStringRef(d.slice(0, end - d.begin()));
813837f427SRui Ueyama d = d.slice(s.size() + 1);
823837f427SRui Ueyama return s;
8398bdbdaeSRui Ueyama }
8498bdbdaeSRui Ueyama
85f5febef2SRui Ueyama // Skip an integer encoded in the LEB128 format.
86f5febef2SRui Ueyama // Actual number is not of interest because only the runtime needs it.
87f5febef2SRui Ueyama // But we need to be at least able to skip it so that we can read
88f5febef2SRui Ueyama // the field that follows a LEB128 number.
skipLeb128()898629752cSRui Ueyama void EhReader::skipLeb128() {
903837f427SRui Ueyama const uint8_t *errPos = d.data();
913837f427SRui Ueyama while (!d.empty()) {
923837f427SRui Ueyama uint8_t val = d.front();
933837f427SRui Ueyama d = d.slice(1);
943837f427SRui Ueyama if ((val & 0x80) == 0)
95f5febef2SRui Ueyama return;
96f5febef2SRui Ueyama }
973837f427SRui Ueyama failOn(errPos, "corrupted CIE (failed to read LEB128)");
98f5febef2SRui Ueyama }
99f5febef2SRui Ueyama
getAugPSize(unsigned enc)1003837f427SRui Ueyama static size_t getAugPSize(unsigned enc) {
1013837f427SRui Ueyama switch (enc & 0x0f) {
102f5febef2SRui Ueyama case DW_EH_PE_absptr:
103f5febef2SRui Ueyama case DW_EH_PE_signed:
1043837f427SRui Ueyama return config->wordsize;
105f5febef2SRui Ueyama case DW_EH_PE_udata2:
106f5febef2SRui Ueyama case DW_EH_PE_sdata2:
107f5febef2SRui Ueyama return 2;
108f5febef2SRui Ueyama case DW_EH_PE_udata4:
109f5febef2SRui Ueyama case DW_EH_PE_sdata4:
110f5febef2SRui Ueyama return 4;
111f5febef2SRui Ueyama case DW_EH_PE_udata8:
112f5febef2SRui Ueyama case DW_EH_PE_sdata8:
113f5febef2SRui Ueyama return 8;
114f5febef2SRui Ueyama }
115531df4fcSEugene Leviant return 0;
116f5febef2SRui Ueyama }
117f5febef2SRui Ueyama
skipAugP()1188629752cSRui Ueyama void EhReader::skipAugP() {
1193837f427SRui Ueyama uint8_t enc = readByte();
1203837f427SRui Ueyama if ((enc & 0xf0) == DW_EH_PE_aligned)
1213837f427SRui Ueyama failOn(d.data() - 1, "DW_EH_PE_aligned encoding is not supported");
1223837f427SRui Ueyama size_t size = getAugPSize(enc);
1233837f427SRui Ueyama if (size == 0)
1243837f427SRui Ueyama failOn(d.data() - 1, "unknown FDE encoding");
1253837f427SRui Ueyama if (size >= d.size())
1263837f427SRui Ueyama failOn(d.data() - 1, "corrupted CIE");
1273837f427SRui Ueyama d = d.slice(size);
128f5febef2SRui Ueyama }
129f5febef2SRui Ueyama
getFdeEncoding(EhSectionPiece * p)13007837b8fSFangrui Song uint8_t elf::getFdeEncoding(EhSectionPiece *p) {
1313837f427SRui Ueyama return EhReader(p->sec, p->data()).getFdeEncoding();
132531df4fcSEugene Leviant }
133f5febef2SRui Ueyama
hasLSDA(const EhSectionPiece & p)13421b4f806SFangrui Song bool elf::hasLSDA(const EhSectionPiece &p) {
13521b4f806SFangrui Song return EhReader(p.sec, p.data()).hasLSDA();
13621b4f806SFangrui Song }
13721b4f806SFangrui Song
getAugmentation()13821b4f806SFangrui Song StringRef EhReader::getAugmentation() {
139531df4fcSEugene Leviant skipBytes(8);
1403837f427SRui Ueyama int version = readByte();
1413837f427SRui Ueyama if (version != 1 && version != 3)
1423837f427SRui Ueyama failOn(d.data() - 1,
1433837f427SRui Ueyama "FDE version 1 or 3 expected, but got " + Twine(version));
144f5febef2SRui Ueyama
1453837f427SRui Ueyama StringRef aug = readString();
146f5febef2SRui Ueyama
14798bdbdaeSRui Ueyama // Skip code and data alignment factors.
148531df4fcSEugene Leviant skipLeb128();
149531df4fcSEugene Leviant skipLeb128();
150f5febef2SRui Ueyama
151f5febef2SRui Ueyama // Skip the return address register. In CIE version 1 this is a single
152f5febef2SRui Ueyama // byte. In CIE version 3 this is an unsigned LEB128.
1533837f427SRui Ueyama if (version == 1)
154531df4fcSEugene Leviant readByte();
155f5febef2SRui Ueyama else
156531df4fcSEugene Leviant skipLeb128();
15721b4f806SFangrui Song return aug;
15821b4f806SFangrui Song }
159f5febef2SRui Ueyama
getFdeEncoding()16021b4f806SFangrui Song uint8_t EhReader::getFdeEncoding() {
161f5febef2SRui Ueyama // We only care about an 'R' value, but other records may precede an 'R'
162f5febef2SRui Ueyama // record. Unfortunately records are not in TLV (type-length-value) format,
163f5febef2SRui Ueyama // so we need to teach the linker how to skip records for each type.
16421b4f806SFangrui Song StringRef aug = getAugmentation();
1653837f427SRui Ueyama for (char c : aug) {
1663837f427SRui Ueyama if (c == 'R')
167531df4fcSEugene Leviant return readByte();
168d30d4619SFangrui Song if (c == 'z')
169531df4fcSEugene Leviant skipLeb128();
170d30d4619SFangrui Song else if (c == 'L')
171531df4fcSEugene Leviant readByte();
172d30d4619SFangrui Song else if (c == 'P')
173d30d4619SFangrui Song skipAugP();
174*f6b1bfb7SFlorian Mayer else if (c != 'B' && c != 'S' && c != 'G')
1753837f427SRui Ueyama failOn(aug.data(), "unknown .eh_frame augmentation string: " + aug);
176f5febef2SRui Ueyama }
177f5febef2SRui Ueyama return DW_EH_PE_absptr;
178f5febef2SRui Ueyama }
17921b4f806SFangrui Song
hasLSDA()18021b4f806SFangrui Song bool EhReader::hasLSDA() {
18121b4f806SFangrui Song StringRef aug = getAugmentation();
18221b4f806SFangrui Song for (char c : aug) {
18321b4f806SFangrui Song if (c == 'L')
18421b4f806SFangrui Song return true;
18521b4f806SFangrui Song if (c == 'z')
18621b4f806SFangrui Song skipLeb128();
18721b4f806SFangrui Song else if (c == 'P')
18821b4f806SFangrui Song skipAugP();
18921b4f806SFangrui Song else if (c == 'R')
19021b4f806SFangrui Song readByte();
191*f6b1bfb7SFlorian Mayer else if (c != 'B' && c != 'S' && c != 'G')
19221b4f806SFangrui Song failOn(aug.data(), "unknown .eh_frame augmentation string: " + aug);
19321b4f806SFangrui Song }
19421b4f806SFangrui Song return false;
19521b4f806SFangrui Song }
196