31 using namespace dwarf;
40 while (*Offset < EndOffset) {
41 uint8_t Opcode = Data.
getU8(Offset);
52 "Invalid primary CFI opcode 0x%" PRIx8,
54 case DW_CFA_advance_loc:
56 addInstruction(Primary, Op1);
59 addInstruction(Primary, Op1, Data.
getULEB128(Offset));
67 "Invalid extended CFI opcode 0x%" PRIx8,
70 case DW_CFA_remember_state:
71 case DW_CFA_restore_state:
72 case DW_CFA_GNU_window_save:
74 addInstruction(Opcode);
78 addInstruction(Opcode, Data.
getAddress(Offset));
80 case DW_CFA_advance_loc1:
82 addInstruction(Opcode, Data.
getU8(Offset));
84 case DW_CFA_advance_loc2:
86 addInstruction(Opcode, Data.
getU16(Offset));
88 case DW_CFA_advance_loc4:
90 addInstruction(Opcode, Data.
getU32(Offset));
92 case DW_CFA_restore_extended:
93 case DW_CFA_undefined:
94 case DW_CFA_same_value:
95 case DW_CFA_def_cfa_register:
96 case DW_CFA_def_cfa_offset:
97 case DW_CFA_GNU_args_size:
99 addInstruction(Opcode, Data.
getULEB128(Offset));
101 case DW_CFA_def_cfa_offset_sf:
103 addInstruction(Opcode, Data.
getSLEB128(Offset));
105 case DW_CFA_offset_extended:
106 case DW_CFA_register:
108 case DW_CFA_val_offset: {
115 addInstruction(Opcode, op1, op2);
118 case DW_CFA_offset_extended_sf:
119 case DW_CFA_def_cfa_sf:
120 case DW_CFA_val_offset_sf: {
125 addInstruction(Opcode, op1, op2);
128 case DW_CFA_def_cfa_expression: {
130 addInstruction(Opcode, 0);
136 *Offset += ExprLength;
139 case DW_CFA_expression:
140 case DW_CFA_val_expression: {
143 addInstruction(Opcode, RegNum, 0);
149 *Offset += BlockLength;
165 static OperandType OpTypes[DW_CFA_restore+1][2];
166 static bool Initialized =
false;
172 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 174 OpTypes[OP][0] = OPTYPE0; \ 175 OpTypes[OP][1] = OPTYPE1; \ 177 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 178 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 181 DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
182 DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
183 DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
184 DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
185 DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
186 DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
187 DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
190 DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
191 DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
194 DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
195 DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
196 DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
197 DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
198 DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
199 DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
200 DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
201 DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
220 unsigned OperandIdx, uint64_t Operand)
const {
222 uint8_t Opcode = Instr.
Opcode;
223 OperandType
Type = getOperandTypes()[Opcode][OperandIdx];
227 OS <<
" Unsupported " << (OperandIdx ?
"second" :
"first") <<
" operand to";
229 if (!OpcodeName.empty())
230 OS <<
" " << OpcodeName;
232 OS <<
format(
" Opcode %x", Opcode);
238 OS <<
format(
" %" PRIx64, Operand);
244 OS <<
format(
" %+" PRId64, int64_t(Operand));
246 case OT_FactoredCodeOffset:
247 if (CodeAlignmentFactor)
248 OS <<
format(
" %" PRId64, Operand * CodeAlignmentFactor);
250 OS <<
format(
" %" PRId64
"*code_alignment_factor" , Operand);
252 case OT_SignedFactDataOffset:
253 if (DataAlignmentFactor)
254 OS <<
format(
" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
256 OS <<
format(
" %" PRId64
"*data_alignment_factor" , int64_t(Operand));
258 case OT_UnsignedFactDataOffset:
259 if (DataAlignmentFactor)
260 OS <<
format(
" %" PRId64, Operand * DataAlignmentFactor);
262 OS <<
format(
" %" PRId64
"*data_alignment_factor" , Operand);
265 OS <<
format(
" reg%" PRId64, Operand);
276 unsigned IndentLevel)
const {
277 for (
const auto &Instr : Instructions) {
278 uint8_t Opcode = Instr.
Opcode;
281 OS.
indent(2 * IndentLevel);
283 for (
unsigned i = 0; i < Instr.
Ops.
size(); ++i)
284 printOperand(OS, MRI, IsEH, Instr, i, Instr.
Ops[i]);
294 OS <<
" Augmentation: \"" << Augmentation <<
"\"\n";
297 OS <<
format(
" Segment desc size: %u\n",
300 OS <<
format(
" Code alignment factor: %u\n", (
uint32_t)CodeAlignmentFactor);
301 OS <<
format(
" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
302 OS <<
format(
" Return address column: %d\n", (int32_t)ReturnAddressRegister);
304 OS <<
format(
" Personality Address: %016" PRIx64
"\n", *Personality);
305 if (!AugmentationData.empty()) {
306 OS <<
" Augmentation data: ";
307 for (uint8_t Byte : AugmentationData)
308 OS << ' ' << hexdigit(Byte >> 4) <<
hexdigit(Byte & 0xf);
312 CFIs.dump(OS, MRI, IsEH);
318 (int32_t)LinkedCIEOffset);
319 OS <<
format(
"cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset,
323 OS <<
format(
" LSDA Address: %016" PRIx64
"\n", *LSDAAddress);
324 CFIs.dump(OS, MRI, IsEH);
329 bool IsEH, uint64_t EHFrameAddress)
330 : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
337 for (
int i = 0; i < Length; ++i) {
338 uint8_t c = Data.
getU8(&Offset);
349 const char *ErrorMsg) {
352 OS <<
format(ErrorMsg, StartOffset);
364 bool IsDWARF64 =
false;
365 uint64_t Length = Data.
getU32(&Offset);
368 if (Length == UINT32_MAX) {
373 Length = Data.
getU64(&Offset);
386 Id = Data.
getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
392 const char *Augmentation = Data.
getCStr(&Offset);
393 StringRef AugmentationString(Augmentation ? Augmentation :
"");
397 uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.
getU8(&Offset);
398 uint64_t CodeAlignmentFactor = Data.
getULEB128(&Offset);
399 int64_t DataAlignmentFactor = Data.
getSLEB128(&Offset);
400 uint64_t ReturnAddressRegister =
415 for (
unsigned i = 0, e = AugmentationString.
size(); i != e; ++i) {
416 switch (AugmentationString[i]) {
419 "Unknown augmentation character in entry at %lx");
421 LSDAPointerEncoding = Data.
getU8(&Offset);
426 "Duplicate personality in entry at %lx");
427 PersonalityEncoding = Data.
getU8(&Offset);
429 &Offset, *PersonalityEncoding,
430 EHFrameAddress ? EHFrameAddress + Offset : 0);
434 FDEPointerEncoding = Data.
getU8(&Offset);
442 "'z' must be the first character at %lx");
445 AugmentationLength = Data.
getULEB128(&Offset);
446 StartAugmentationOffset =
Offset;
447 EndAugmentationOffset = Offset +
448 static_cast<uint32_t>(*AugmentationLength);
457 if (AugmentationLength.
hasValue()) {
458 if (Offset != EndAugmentationOffset)
459 ReportError(StartOffset,
"Parsing augmentation data at %lx failed");
461 AugmentationData = Data.
getData().
slice(StartAugmentationOffset,
462 EndAugmentationOffset);
466 auto Cie = llvm::make_unique<CIE>(
467 StartOffset, Length,
Version, AugmentationString, AddressSize,
468 SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor,
469 ReturnAddressRegister, AugmentationData, FDEPointerEncoding,
470 LSDAPointerEncoding, Personality, PersonalityEncoding, Arch);
471 CIEs[StartOffset] = Cie.get();
472 Entries.emplace_back(std::move(Cie));
475 uint64_t CIEPointer =
Id;
476 uint64_t InitialLocation = 0;
477 uint64_t AddressRange = 0;
479 CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
485 "Parsing FDE data at %lx failed due to missing CIE");
489 EHFrameAddress ? EHFrameAddress +
Offset : 0)) {
490 InitialLocation = *Val;
498 if (!AugmentationString.
empty()) {
500 uint64_t AugmentationLength = Data.
getULEB128(&Offset);
503 Offset +
static_cast<uint32_t>(AugmentationLength);
509 EHFrameAddress ? Offset + EHFrameAddress : 0);
512 if (Offset != EndAugmentationOffset)
513 ReportError(StartOffset,
"Parsing augmentation data at %lx failed");
520 Entries.emplace_back(
new FDE(StartOffset, Length, CIEPointer,
521 InitialLocation, AddressRange,
522 Cie, LSDAAddress, Arch));
526 Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) {
530 if (Offset != EndStructureOffset)
531 ReportError(StartOffset,
"Parsing entry instructions at %lx failed");
538 [](
const std::unique_ptr<FrameEntry> &
E,
540 if (It != Entries.end() && (*It)->getOffset() ==
Offset)
548 if (
auto *Entry = getEntryAtOffset(*Offset))
549 Entry->dump(OS, MRI, IsEH);
554 for (
const auto &Entry : Entries)
555 Entry->dump(OS, MRI, IsEH);
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
DWARFDebugFrame(Triple::ArchType Arch, bool IsEH=false, uint64_t EHFrameAddress=0)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset)
Parse and store a sequence of CFI instructions from Data, starting at *Offset and ending at EndOffset...
An entry in either debug_frame or eh_frame.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK
uint32_t getLSDAPointerEncoding() const
StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch)
std::string toString(Error E)
Write all error messages (if any) in E to a string.
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)
char hexdigit(unsigned X, bool LowerCase=false)
hexdigit - Return the hexadecimal character for the given number X (which should be less than 16)...
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, Optional< uint64_t > Offset) const
Dump the section data into the given stream.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
unsigned const MachineRegisterInfo * MRI
DWARF Frame Description Entry (FDE)
The instances of the Type class are immutable: once they are created, they are never changed...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
uint32_t getFDEPointerEncoding() const
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, unsigned IndentLevel=1) const
const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const override
Dump the instructions in this CFI fragment.
const uint32_t DW_CIE_ID
Special ID values that distinguish a CIE from a FDE in DWARF CFI.
static ErrorSuccess success()
Create a success value.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const override
Dump the instructions in this CFI fragment.
DWARF Common Information Entry (CIE)
This file contains constants used for implementing Dwarf debug support.
#define DECLARE_OP1(OP, OPTYPE0)
#define LLVM_ATTRIBUTE_NORETURN
StringRef getAugmentationString() const
An instruction consists of a DWARF CFI opcode and an optional sequence of operands.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, uint32_t Offset, int Length)
Lightweight error class with error context and mandatory checking.
Optional< DWARFExpression > Expression
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
#define LLVM_ATTRIBUTE_UNUSED
void parse(DWARFDataExtractor Data)
Parse the section from raw data.
static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, const char *ErrorMsg)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
const uint64_t DW64_CIE_ID