xref: /freebsd/contrib/llvm-project/lld/ELF/EhFrame.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- EhFrame.cpp -------------------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // .eh_frame section contains information on how to unwind the stack when
10*0b57cec5SDimitry Andric // an exception is thrown. The section consists of sequence of CIE and FDE
11*0b57cec5SDimitry Andric // records. The linker needs to merge CIEs and associate FDEs to CIEs.
12*0b57cec5SDimitry Andric // That means the linker has to understand the format of the section.
13*0b57cec5SDimitry Andric //
14*0b57cec5SDimitry Andric // This file contains a few utility functions to read .eh_frame contents.
15*0b57cec5SDimitry Andric //
16*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
17*0b57cec5SDimitry Andric 
18*0b57cec5SDimitry Andric #include "EhFrame.h"
19*0b57cec5SDimitry Andric #include "Config.h"
20*0b57cec5SDimitry Andric #include "InputSection.h"
21*0b57cec5SDimitry Andric #include "Relocations.h"
22*0b57cec5SDimitry Andric #include "Target.h"
23*0b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h"
24*0b57cec5SDimitry Andric #include "lld/Common/Strings.h"
25*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
26*0b57cec5SDimitry Andric #include "llvm/Object/ELF.h"
27*0b57cec5SDimitry Andric 
28*0b57cec5SDimitry Andric using namespace llvm;
29*0b57cec5SDimitry Andric using namespace llvm::ELF;
30*0b57cec5SDimitry Andric using namespace llvm::dwarf;
31*0b57cec5SDimitry Andric using namespace llvm::object;
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric using namespace lld;
34*0b57cec5SDimitry Andric using namespace lld::elf;
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric namespace {
37*0b57cec5SDimitry Andric class EhReader {
38*0b57cec5SDimitry Andric public:
39*0b57cec5SDimitry Andric   EhReader(InputSectionBase *s, ArrayRef<uint8_t> d) : isec(s), d(d) {}
40*0b57cec5SDimitry Andric   size_t readEhRecordSize();
41*0b57cec5SDimitry Andric   uint8_t getFdeEncoding();
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric private:
44*0b57cec5SDimitry Andric   template <class P> void failOn(const P *loc, const Twine &msg) {
45*0b57cec5SDimitry Andric     fatal("corrupted .eh_frame: " + msg + "\n>>> defined in " +
46*0b57cec5SDimitry Andric           isec->getObjMsg((const uint8_t *)loc - isec->data().data()));
47*0b57cec5SDimitry Andric   }
48*0b57cec5SDimitry Andric 
49*0b57cec5SDimitry Andric   uint8_t readByte();
50*0b57cec5SDimitry Andric   void skipBytes(size_t count);
51*0b57cec5SDimitry Andric   StringRef readString();
52*0b57cec5SDimitry Andric   void skipLeb128();
53*0b57cec5SDimitry Andric   void skipAugP();
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric   InputSectionBase *isec;
56*0b57cec5SDimitry Andric   ArrayRef<uint8_t> d;
57*0b57cec5SDimitry Andric };
58*0b57cec5SDimitry Andric }
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric size_t elf::readEhRecordSize(InputSectionBase *s, size_t off) {
61*0b57cec5SDimitry Andric   return EhReader(s, s->data().slice(off)).readEhRecordSize();
62*0b57cec5SDimitry Andric }
63*0b57cec5SDimitry Andric 
64*0b57cec5SDimitry Andric // .eh_frame section is a sequence of records. Each record starts with
65*0b57cec5SDimitry Andric // a 4 byte length field. This function reads the length.
66*0b57cec5SDimitry Andric size_t EhReader::readEhRecordSize() {
67*0b57cec5SDimitry Andric   if (d.size() < 4)
68*0b57cec5SDimitry Andric     failOn(d.data(), "CIE/FDE too small");
69*0b57cec5SDimitry Andric 
70*0b57cec5SDimitry Andric   // First 4 bytes of CIE/FDE is the size of the record.
71*0b57cec5SDimitry Andric   // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
72*0b57cec5SDimitry Andric   // but we do not support that format yet.
73*0b57cec5SDimitry Andric   uint64_t v = read32(d.data());
74*0b57cec5SDimitry Andric   if (v == UINT32_MAX)
75*0b57cec5SDimitry Andric     failOn(d.data(), "CIE/FDE too large");
76*0b57cec5SDimitry Andric   uint64_t size = v + 4;
77*0b57cec5SDimitry Andric   if (size > d.size())
78*0b57cec5SDimitry Andric     failOn(d.data(), "CIE/FDE ends past the end of the section");
79*0b57cec5SDimitry Andric   return size;
80*0b57cec5SDimitry Andric }
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric // Read a byte and advance D by one byte.
83*0b57cec5SDimitry Andric uint8_t EhReader::readByte() {
84*0b57cec5SDimitry Andric   if (d.empty())
85*0b57cec5SDimitry Andric     failOn(d.data(), "unexpected end of CIE");
86*0b57cec5SDimitry Andric   uint8_t b = d.front();
87*0b57cec5SDimitry Andric   d = d.slice(1);
88*0b57cec5SDimitry Andric   return b;
89*0b57cec5SDimitry Andric }
90*0b57cec5SDimitry Andric 
91*0b57cec5SDimitry Andric void EhReader::skipBytes(size_t count) {
92*0b57cec5SDimitry Andric   if (d.size() < count)
93*0b57cec5SDimitry Andric     failOn(d.data(), "CIE is too small");
94*0b57cec5SDimitry Andric   d = d.slice(count);
95*0b57cec5SDimitry Andric }
96*0b57cec5SDimitry Andric 
97*0b57cec5SDimitry Andric // Read a null-terminated string.
98*0b57cec5SDimitry Andric StringRef EhReader::readString() {
99*0b57cec5SDimitry Andric   const uint8_t *end = llvm::find(d, '\0');
100*0b57cec5SDimitry Andric   if (end == d.end())
101*0b57cec5SDimitry Andric     failOn(d.data(), "corrupted CIE (failed to read string)");
102*0b57cec5SDimitry Andric   StringRef s = toStringRef(d.slice(0, end - d.begin()));
103*0b57cec5SDimitry Andric   d = d.slice(s.size() + 1);
104*0b57cec5SDimitry Andric   return s;
105*0b57cec5SDimitry Andric }
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric // Skip an integer encoded in the LEB128 format.
108*0b57cec5SDimitry Andric // Actual number is not of interest because only the runtime needs it.
109*0b57cec5SDimitry Andric // But we need to be at least able to skip it so that we can read
110*0b57cec5SDimitry Andric // the field that follows a LEB128 number.
111*0b57cec5SDimitry Andric void EhReader::skipLeb128() {
112*0b57cec5SDimitry Andric   const uint8_t *errPos = d.data();
113*0b57cec5SDimitry Andric   while (!d.empty()) {
114*0b57cec5SDimitry Andric     uint8_t val = d.front();
115*0b57cec5SDimitry Andric     d = d.slice(1);
116*0b57cec5SDimitry Andric     if ((val & 0x80) == 0)
117*0b57cec5SDimitry Andric       return;
118*0b57cec5SDimitry Andric   }
119*0b57cec5SDimitry Andric   failOn(errPos, "corrupted CIE (failed to read LEB128)");
120*0b57cec5SDimitry Andric }
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric static size_t getAugPSize(unsigned enc) {
123*0b57cec5SDimitry Andric   switch (enc & 0x0f) {
124*0b57cec5SDimitry Andric   case DW_EH_PE_absptr:
125*0b57cec5SDimitry Andric   case DW_EH_PE_signed:
126*0b57cec5SDimitry Andric     return config->wordsize;
127*0b57cec5SDimitry Andric   case DW_EH_PE_udata2:
128*0b57cec5SDimitry Andric   case DW_EH_PE_sdata2:
129*0b57cec5SDimitry Andric     return 2;
130*0b57cec5SDimitry Andric   case DW_EH_PE_udata4:
131*0b57cec5SDimitry Andric   case DW_EH_PE_sdata4:
132*0b57cec5SDimitry Andric     return 4;
133*0b57cec5SDimitry Andric   case DW_EH_PE_udata8:
134*0b57cec5SDimitry Andric   case DW_EH_PE_sdata8:
135*0b57cec5SDimitry Andric     return 8;
136*0b57cec5SDimitry Andric   }
137*0b57cec5SDimitry Andric   return 0;
138*0b57cec5SDimitry Andric }
139*0b57cec5SDimitry Andric 
140*0b57cec5SDimitry Andric void EhReader::skipAugP() {
141*0b57cec5SDimitry Andric   uint8_t enc = readByte();
142*0b57cec5SDimitry Andric   if ((enc & 0xf0) == DW_EH_PE_aligned)
143*0b57cec5SDimitry Andric     failOn(d.data() - 1, "DW_EH_PE_aligned encoding is not supported");
144*0b57cec5SDimitry Andric   size_t size = getAugPSize(enc);
145*0b57cec5SDimitry Andric   if (size == 0)
146*0b57cec5SDimitry Andric     failOn(d.data() - 1, "unknown FDE encoding");
147*0b57cec5SDimitry Andric   if (size >= d.size())
148*0b57cec5SDimitry Andric     failOn(d.data() - 1, "corrupted CIE");
149*0b57cec5SDimitry Andric   d = d.slice(size);
150*0b57cec5SDimitry Andric }
151*0b57cec5SDimitry Andric 
152*0b57cec5SDimitry Andric uint8_t elf::getFdeEncoding(EhSectionPiece *p) {
153*0b57cec5SDimitry Andric   return EhReader(p->sec, p->data()).getFdeEncoding();
154*0b57cec5SDimitry Andric }
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric uint8_t EhReader::getFdeEncoding() {
157*0b57cec5SDimitry Andric   skipBytes(8);
158*0b57cec5SDimitry Andric   int version = readByte();
159*0b57cec5SDimitry Andric   if (version != 1 && version != 3)
160*0b57cec5SDimitry Andric     failOn(d.data() - 1,
161*0b57cec5SDimitry Andric            "FDE version 1 or 3 expected, but got " + Twine(version));
162*0b57cec5SDimitry Andric 
163*0b57cec5SDimitry Andric   StringRef aug = readString();
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric   // Skip code and data alignment factors.
166*0b57cec5SDimitry Andric   skipLeb128();
167*0b57cec5SDimitry Andric   skipLeb128();
168*0b57cec5SDimitry Andric 
169*0b57cec5SDimitry Andric   // Skip the return address register. In CIE version 1 this is a single
170*0b57cec5SDimitry Andric   // byte. In CIE version 3 this is an unsigned LEB128.
171*0b57cec5SDimitry Andric   if (version == 1)
172*0b57cec5SDimitry Andric     readByte();
173*0b57cec5SDimitry Andric   else
174*0b57cec5SDimitry Andric     skipLeb128();
175*0b57cec5SDimitry Andric 
176*0b57cec5SDimitry Andric   // We only care about an 'R' value, but other records may precede an 'R'
177*0b57cec5SDimitry Andric   // record. Unfortunately records are not in TLV (type-length-value) format,
178*0b57cec5SDimitry Andric   // so we need to teach the linker how to skip records for each type.
179*0b57cec5SDimitry Andric   for (char c : aug) {
180*0b57cec5SDimitry Andric     if (c == 'R')
181*0b57cec5SDimitry Andric       return readByte();
182*0b57cec5SDimitry Andric     if (c == 'z') {
183*0b57cec5SDimitry Andric       skipLeb128();
184*0b57cec5SDimitry Andric       continue;
185*0b57cec5SDimitry Andric     }
186*0b57cec5SDimitry Andric     if (c == 'P') {
187*0b57cec5SDimitry Andric       skipAugP();
188*0b57cec5SDimitry Andric       continue;
189*0b57cec5SDimitry Andric     }
190*0b57cec5SDimitry Andric     if (c == 'L') {
191*0b57cec5SDimitry Andric       readByte();
192*0b57cec5SDimitry Andric       continue;
193*0b57cec5SDimitry Andric     }
194*0b57cec5SDimitry Andric     failOn(aug.data(), "unknown .eh_frame augmentation string: " + aug);
195*0b57cec5SDimitry Andric   }
196*0b57cec5SDimitry Andric   return DW_EH_PE_absptr;
197*0b57cec5SDimitry Andric }
198