blob: 5a1eef1d007d8e2c623acce63e8a148f9dd0a4d7 [file] [log] [blame]
Rafael Auler86fb7bf2018-03-08 00:46:53 +00001//===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
11#define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
12
13#include "Error.h"
Benjamin Kramer7bbcd1d2018-03-12 15:02:59 +000014#include "llvm-readobj.h"
Rafael Auler86fb7bf2018-03-08 00:46:53 +000015#include "llvm/ADT/STLExtras.h"
16#include "llvm/BinaryFormat/Dwarf.h"
17#include "llvm/Object/ELF.h"
18#include "llvm/Object/ELFTypes.h"
19#include "llvm/Support/Casting.h"
20#include "llvm/Support/ScopedPrinter.h"
21#include "llvm/Support/Debug.h"
22#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
23#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
24#include "llvm/Support/Endian.h"
25#include "llvm/Support/Format.h"
26#include "llvm/Support/type_traits.h"
27
28namespace llvm {
29namespace DwarfCFIEH {
30
31template <typename ELFT>
32class PrinterContext {
33 ScopedPrinter &W;
Luke Cheeseman8e5676b2018-09-27 16:47:30 +000034 const object::ELFFile<ELFT> *Obj;
Rafael Auler86fb7bf2018-03-08 00:46:53 +000035
36 void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size) const;
37
38 void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const;
39
40public:
Luke Cheeseman8e5676b2018-09-27 16:47:30 +000041 PrinterContext(ScopedPrinter &W, const object::ELFFile<ELFT> *Obj)
42 : W(W), Obj(Obj) {}
Rafael Auler86fb7bf2018-03-08 00:46:53 +000043
44 void printUnwindInformation() const;
45};
46
47template <class ELFO>
48static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj,
49 uint64_t Addr) {
50 auto Sections = Obj->sections();
51 if (Error E = Sections.takeError())
52 reportError(toString(std::move(E)));
53
54 for (const auto &Shdr : *Sections)
55 if (Shdr.sh_addr == Addr)
56 return &Shdr;
57 return nullptr;
58}
59
60template <typename ELFT>
61void PrinterContext<ELFT>::printUnwindInformation() const {
62 const typename ELFT::Phdr *EHFramePhdr = nullptr;
63
64 auto PHs = Obj->program_headers();
65 if (Error E = PHs.takeError())
66 reportError(toString(std::move(E)));
67
68 for (const auto &Phdr : *PHs) {
69 if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
70 EHFramePhdr = &Phdr;
71 if (Phdr.p_memsz != Phdr.p_filesz)
72 reportError("p_memsz does not match p_filesz for GNU_EH_FRAME");
73 break;
74 }
75 }
76
77 if (EHFramePhdr)
78 printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr,
79 EHFramePhdr->p_memsz);
80
81 auto Sections = Obj->sections();
82 if (Error E = Sections.takeError())
83 reportError(toString(std::move(E)));
84
85 for (const auto &Shdr : *Sections) {
86 auto SectionName = Obj->getSectionName(&Shdr);
87 if (Error E = SectionName.takeError())
88 reportError(toString(std::move(E)));
89
90 if (*SectionName == ".eh_frame")
91 printEHFrame(&Shdr);
92 }
93}
94
95template <typename ELFT>
96void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset,
97 uint64_t EHFrameHdrAddress,
98 uint64_t EHFrameHdrSize) const {
99 ListScope L(W, "EH_FRAME Header");
100 W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);
101 W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset);
102 W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize);
103
104 const auto *EHFrameHdrShdr = findSectionByAddress(Obj, EHFrameHdrAddress);
105 if (EHFrameHdrShdr) {
106 auto SectionName = Obj->getSectionName(EHFrameHdrShdr);
107 if (Error E = SectionName.takeError())
108 reportError(toString(std::move(E)));
109
110 W.printString("Corresponding Section", *SectionName);
111 }
112
113 DataExtractor DE(
114 StringRef(reinterpret_cast<const char *>(Obj->base()) + EHFrameHdrOffset,
115 EHFrameHdrSize),
116 ELFT::TargetEndianness == support::endianness::little,
117 ELFT::Is64Bits ? 8 : 4);
118
119 DictScope D(W, "Header");
120 uint32_t Offset = 0;
121
122 auto Version = DE.getU8(&Offset);
123 W.printNumber("version", Version);
124 if (Version != 1)
125 reportError("only version 1 of .eh_frame_hdr is supported");
126
127 uint64_t EHFramePtrEnc = DE.getU8(&Offset);
128 W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc);
129 if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
130 reportError("unexpected encoding eh_frame_ptr_enc");
131
132 uint64_t FDECountEnc = DE.getU8(&Offset);
133 W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);
134 if (FDECountEnc != dwarf::DW_EH_PE_udata4)
135 reportError("unexpected encoding fde_count_enc");
136
137 uint64_t TableEnc = DE.getU8(&Offset);
138 W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
139 if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
140 reportError("unexpected encoding table_enc");
141
142 auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;
143 W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);
144
145 auto FDECount = DE.getUnsigned(&Offset, 4);
146 W.printNumber("fde_count", FDECount);
147
148 unsigned NumEntries = 0;
149 uint64_t PrevPC = 0;
150 while (Offset + 8 <= EHFrameHdrSize && NumEntries < FDECount) {
151 DictScope D(W, std::string("entry ") + std::to_string(NumEntries));
152
153 auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
154 W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC);
155 auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
156 W.startLine() << format("address: 0x%" PRIx64 "\n", Address);
157
158 if (InitialPC < PrevPC)
159 reportError("initial_location is out of order");
160
161 PrevPC = InitialPC;
162 ++NumEntries;
163 }
164}
165
166template <typename ELFT>
167void PrinterContext<ELFT>::printEHFrame(
168 const typename ELFT::Shdr *EHFrameShdr) const {
169 uint64_t Address = EHFrameShdr->sh_addr;
170 uint64_t ShOffset = EHFrameShdr->sh_offset;
171 W.startLine() << format(".eh_frame section at offset 0x%" PRIx64
172 " address 0x%" PRIx64 ":\n",
173 ShOffset, Address);
174 W.indent();
175
176 auto Result = Obj->getSectionContents(EHFrameShdr);
177 if (Error E = Result.takeError())
178 reportError(toString(std::move(E)));
179
180 auto Contents = Result.get();
181 DWARFDataExtractor DE(
182 StringRef(reinterpret_cast<const char *>(Contents.data()),
183 Contents.size()),
184 ELFT::TargetEndianness == support::endianness::little,
185 ELFT::Is64Bits ? 8 : 4);
Luke Cheeseman8e5676b2018-09-27 16:47:30 +0000186 DWARFDebugFrame EHFrame(/*IsEH=*/true, /*EHFrameAddress=*/Address);
Rafael Auler86fb7bf2018-03-08 00:46:53 +0000187 EHFrame.parse(DE);
188
189 for (const auto &Entry : EHFrame) {
190 if (const auto *CIE = dyn_cast<dwarf::CIE>(&Entry)) {
191 W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n",
192 Address + CIE->getOffset(),
193 CIE->getLength());
194 W.indent();
195
196 W.printNumber("version", CIE->getVersion());
197 W.printString("augmentation", CIE->getAugmentationString());
198 W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor());
199 W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor());
200 W.printNumber("return_address_register", CIE->getReturnAddressRegister());
201
202 W.getOStream() << "\n";
203 W.startLine() << "Program:\n";
204 W.indent();
205 CIE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
206 W.unindent();
207
208 W.unindent();
209 W.getOStream() << "\n";
210
211 } else if (const auto *FDE = dyn_cast<dwarf::FDE>(&Entry)) {
212 W.startLine() << format("[0x%" PRIx64 "] FDE length=%" PRIu64
213 " cie=[0x%" PRIx64 "]\n",
214 Address + FDE->getOffset(),
215 FDE->getLength(),
216 Address + FDE->getLinkedCIE()->getOffset());
217 W.indent();
218
219 W.startLine() << format("initial_location: 0x%" PRIx64 "\n",
220 FDE->getInitialLocation());
221 W.startLine()
222 << format("address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n",
223 FDE->getAddressRange(),
224 FDE->getInitialLocation() + FDE->getAddressRange());
225
226 W.getOStream() << "\n";
227 W.startLine() << "Program:\n";
228 W.indent();
229 FDE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
230 W.unindent();
231
232 W.unindent();
233 W.getOStream() << "\n";
234 } else {
235 llvm_unreachable("unexpected DWARF frame kind");
236 }
237 }
238
239 W.unindent();
240}
241
242}
243}
244
245#endif