[ARM] Prevent generating NEON stack accesses under MVE.
[llvm-complete.git] / tools / llvm-readobj / DwarfCFIEHPrinter.h
blobfdd01e122830cc5cf6c1c80838b2fba98b0f18bb
1 //===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer -----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
10 #define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
12 #include "Error.h"
13 #include "llvm-readobj.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/BinaryFormat/Dwarf.h"
16 #include "llvm/Object/ELF.h"
17 #include "llvm/Object/ELFTypes.h"
18 #include "llvm/Object/ELFObjectFile.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"
28 namespace llvm {
29 namespace DwarfCFIEH {
31 template <typename ELFT>
32 class PrinterContext {
33 ScopedPrinter &W;
34 const object::ELFObjectFile<ELFT> *ObjF;
36 void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size) const;
38 void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const;
40 public:
41 PrinterContext(ScopedPrinter &W, const object::ELFObjectFile<ELFT> *ObjF)
42 : W(W), ObjF(ObjF) {}
44 void printUnwindInformation() const;
47 template <class ELFT>
48 static const typename object::ELFObjectFile<ELFT>::Elf_Shdr *
49 findSectionByAddress(const object::ELFObjectFile<ELFT> *ObjF, uint64_t Addr) {
50 auto Sections = ObjF->getELFFile()->sections();
51 if (Error E = Sections.takeError())
52 reportError(std::move(E), ObjF->getFileName());
54 for (const auto &Shdr : *Sections)
55 if (Shdr.sh_addr == Addr)
56 return &Shdr;
57 return nullptr;
60 template <typename ELFT>
61 void PrinterContext<ELFT>::printUnwindInformation() const {
62 const object::ELFFile<ELFT> *Obj = ObjF->getELFFile();
63 const typename ELFT::Phdr *EHFramePhdr = nullptr;
65 auto PHs = Obj->program_headers();
66 if (Error E = PHs.takeError())
67 reportError(std::move(E), ObjF->getFileName());
69 for (const auto &Phdr : *PHs) {
70 if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
71 EHFramePhdr = &Phdr;
72 if (Phdr.p_memsz != Phdr.p_filesz)
73 reportError(object::createError(
74 "p_memsz does not match p_filesz for GNU_EH_FRAME"),
75 ObjF->getFileName());
76 break;
80 if (EHFramePhdr)
81 printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr,
82 EHFramePhdr->p_memsz);
84 auto Sections = Obj->sections();
85 if (Error E = Sections.takeError())
86 reportError(std::move(E), ObjF->getFileName());
88 for (const auto &Shdr : *Sections) {
89 auto SectionName = Obj->getSectionName(&Shdr);
90 if (Error E = SectionName.takeError())
91 reportError(std::move(E), ObjF->getFileName());
93 if (*SectionName == ".eh_frame")
94 printEHFrame(&Shdr);
98 template <typename ELFT>
99 void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset,
100 uint64_t EHFrameHdrAddress,
101 uint64_t EHFrameHdrSize) const {
102 ListScope L(W, "EH_FRAME Header");
103 W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);
104 W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset);
105 W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize);
107 const object::ELFFile<ELFT> *Obj = ObjF->getELFFile();
108 const auto *EHFrameHdrShdr = findSectionByAddress(ObjF, EHFrameHdrAddress);
109 if (EHFrameHdrShdr) {
110 auto SectionName = Obj->getSectionName(EHFrameHdrShdr);
111 if (Error E = SectionName.takeError())
112 reportError(std::move(E), ObjF->getFileName());
114 W.printString("Corresponding Section", *SectionName);
117 DataExtractor DE(
118 StringRef(reinterpret_cast<const char *>(Obj->base()) + EHFrameHdrOffset,
119 EHFrameHdrSize),
120 ELFT::TargetEndianness == support::endianness::little,
121 ELFT::Is64Bits ? 8 : 4);
123 DictScope D(W, "Header");
124 uint64_t Offset = 0;
126 auto Version = DE.getU8(&Offset);
127 W.printNumber("version", Version);
128 if (Version != 1)
129 reportError(
130 object::createError("only version 1 of .eh_frame_hdr is supported"),
131 ObjF->getFileName());
133 uint64_t EHFramePtrEnc = DE.getU8(&Offset);
134 W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc);
135 if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
136 reportError(object::createError("unexpected encoding eh_frame_ptr_enc"),
137 ObjF->getFileName());
139 uint64_t FDECountEnc = DE.getU8(&Offset);
140 W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);
141 if (FDECountEnc != dwarf::DW_EH_PE_udata4)
142 reportError(object::createError("unexpected encoding fde_count_enc"),
143 ObjF->getFileName());
145 uint64_t TableEnc = DE.getU8(&Offset);
146 W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
147 if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
148 reportError(object::createError("unexpected encoding table_enc"),
149 ObjF->getFileName());
151 auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;
152 W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);
154 auto FDECount = DE.getUnsigned(&Offset, 4);
155 W.printNumber("fde_count", FDECount);
157 unsigned NumEntries = 0;
158 uint64_t PrevPC = 0;
159 while (Offset + 8 <= EHFrameHdrSize && NumEntries < FDECount) {
160 DictScope D(W, std::string("entry ") + std::to_string(NumEntries));
162 auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
163 W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC);
164 auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
165 W.startLine() << format("address: 0x%" PRIx64 "\n", Address);
167 if (InitialPC < PrevPC)
168 reportError(object::createError("initial_location is out of order"),
169 ObjF->getFileName());
171 PrevPC = InitialPC;
172 ++NumEntries;
176 template <typename ELFT>
177 void PrinterContext<ELFT>::printEHFrame(
178 const typename ELFT::Shdr *EHFrameShdr) const {
179 uint64_t Address = EHFrameShdr->sh_addr;
180 uint64_t ShOffset = EHFrameShdr->sh_offset;
181 W.startLine() << format(".eh_frame section at offset 0x%" PRIx64
182 " address 0x%" PRIx64 ":\n",
183 ShOffset, Address);
184 W.indent();
186 const object::ELFFile<ELFT> *Obj = ObjF->getELFFile();
187 auto Result = Obj->getSectionContents(EHFrameShdr);
188 if (Error E = Result.takeError())
189 reportError(std::move(E), ObjF->getFileName());
191 auto Contents = Result.get();
192 DWARFDataExtractor DE(
193 StringRef(reinterpret_cast<const char *>(Contents.data()),
194 Contents.size()),
195 ELFT::TargetEndianness == support::endianness::little,
196 ELFT::Is64Bits ? 8 : 4);
197 DWARFDebugFrame EHFrame(Triple::ArchType(ObjF->getArch()), /*IsEH=*/true,
198 /*EHFrameAddress=*/Address);
199 EHFrame.parse(DE);
201 for (const auto &Entry : EHFrame) {
202 if (const auto *CIE = dyn_cast<dwarf::CIE>(&Entry)) {
203 W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n",
204 Address + CIE->getOffset(),
205 CIE->getLength());
206 W.indent();
208 W.printNumber("version", CIE->getVersion());
209 W.printString("augmentation", CIE->getAugmentationString());
210 W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor());
211 W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor());
212 W.printNumber("return_address_register", CIE->getReturnAddressRegister());
214 W.getOStream() << "\n";
215 W.startLine() << "Program:\n";
216 W.indent();
217 CIE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
218 W.unindent();
220 W.unindent();
221 W.getOStream() << "\n";
223 } else if (const auto *FDE = dyn_cast<dwarf::FDE>(&Entry)) {
224 W.startLine() << format("[0x%" PRIx64 "] FDE length=%" PRIu64
225 " cie=[0x%" PRIx64 "]\n",
226 Address + FDE->getOffset(),
227 FDE->getLength(),
228 Address + FDE->getLinkedCIE()->getOffset());
229 W.indent();
231 W.startLine() << format("initial_location: 0x%" PRIx64 "\n",
232 FDE->getInitialLocation());
233 W.startLine()
234 << format("address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n",
235 FDE->getAddressRange(),
236 FDE->getInitialLocation() + FDE->getAddressRange());
238 W.getOStream() << "\n";
239 W.startLine() << "Program:\n";
240 W.indent();
241 FDE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
242 W.unindent();
244 W.unindent();
245 W.getOStream() << "\n";
246 } else {
247 llvm_unreachable("unexpected DWARF frame kind");
251 W.unindent();
257 #endif