mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
[dwarfdump] Make debug_frame dump actually useful.
This adds support for pretty-printing instruction operands. The new output looks like: 00000000 00000010 ffffffff CIE Version: 1 Augmentation: Code alignment factor: 1 Data alignment factor: -4 Return address column: 8 DW_CFA_def_cfa: reg4 +4 DW_CFA_offset: reg8 -4 DW_CFA_nop: DW_CFA_nop: 00000014 00000010 00000000 FDE cie=00000000 pc=00000000...00000022 DW_CFA_advance_loc: 3 DW_CFA_def_cfa_offset: +12 DW_CFA_nop: git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230551 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0a7d07b87b
commit
e9e16aa4a5
@ -8,7 +8,9 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -267,16 +269,147 @@ private:
|
||||
uint64_t AddressRange;
|
||||
CIE *LinkedCIE;
|
||||
};
|
||||
|
||||
/// \brief Types of operands to CF instructions.
|
||||
enum OperandType {
|
||||
OT_Unset,
|
||||
OT_None,
|
||||
OT_Address,
|
||||
OT_Offset,
|
||||
OT_FactoredCodeOffset,
|
||||
OT_SignedFactDataOffset,
|
||||
OT_UnsignedFactDataOffset,
|
||||
OT_Register,
|
||||
OT_Expression
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// \brief Initialize the array describing the types of operands.
|
||||
static ArrayRef<OperandType[2]> getOperandTypes() {
|
||||
static OperandType OpTypes[DW_CFA_restore+1][2];
|
||||
|
||||
#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
|
||||
do { \
|
||||
OpTypes[OP][0] = OPTYPE0; \
|
||||
OpTypes[OP][1] = OPTYPE1; \
|
||||
} while (0)
|
||||
#define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
|
||||
#define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
|
||||
|
||||
DECLARE_OP1(DW_CFA_set_loc, OT_Address);
|
||||
DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
|
||||
DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
|
||||
DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
|
||||
DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
|
||||
DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
|
||||
DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
|
||||
DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
|
||||
DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
|
||||
DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
|
||||
DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
|
||||
DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
|
||||
DECLARE_OP1(DW_CFA_undefined, OT_Register);
|
||||
DECLARE_OP1(DW_CFA_same_value, OT_Register);
|
||||
DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
|
||||
DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
|
||||
DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
|
||||
DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
|
||||
DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
|
||||
DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
|
||||
DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
|
||||
DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
|
||||
DECLARE_OP1(DW_CFA_restore, OT_Register);
|
||||
DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
|
||||
DECLARE_OP0(DW_CFA_remember_state);
|
||||
DECLARE_OP0(DW_CFA_restore_state);
|
||||
DECLARE_OP0(DW_CFA_GNU_window_save);
|
||||
DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
|
||||
DECLARE_OP0(DW_CFA_nop);
|
||||
|
||||
#undef DECLARE_OP0
|
||||
#undef DECLARE_OP1
|
||||
#undef DECLARE_OP2
|
||||
return OpTypes;
|
||||
}
|
||||
|
||||
static ArrayRef<OperandType[2]> OpTypes = getOperandTypes();
|
||||
|
||||
/// \brief Print \p Opcode's operand number \p OperandIdx which has
|
||||
/// value \p Operand.
|
||||
static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx,
|
||||
uint64_t Operand, uint64_t CodeAlignmentFactor,
|
||||
int64_t DataAlignmentFactor) {
|
||||
assert(OperandIdx < 2);
|
||||
OperandType Type = OpTypes[Opcode][OperandIdx];
|
||||
|
||||
switch (Type) {
|
||||
case OT_Unset:
|
||||
OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
|
||||
if (const char *OpcodeName = CallFrameString(Opcode))
|
||||
OS << " " << OpcodeName;
|
||||
else
|
||||
OS << format(" Opcode %x", Opcode);
|
||||
break;
|
||||
case OT_None:
|
||||
break;
|
||||
case OT_Address:
|
||||
OS << format(" %" PRIx64, Operand);
|
||||
break;
|
||||
case OT_Offset:
|
||||
// The offsets are all encoded in a unsigned form, but in practice
|
||||
// consumers use them signed. It's most certainly legacy due to
|
||||
// the lack of signed variants in the first Dwarf standards.
|
||||
OS << format(" %+" PRId64, int64_t(Operand));
|
||||
break;
|
||||
case OT_FactoredCodeOffset: // Always Unsigned
|
||||
if (CodeAlignmentFactor)
|
||||
OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
|
||||
else
|
||||
OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
|
||||
break;
|
||||
case OT_SignedFactDataOffset:
|
||||
if (DataAlignmentFactor)
|
||||
OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
|
||||
else
|
||||
OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
|
||||
break;
|
||||
case OT_UnsignedFactDataOffset:
|
||||
if (DataAlignmentFactor)
|
||||
OS << format(" %" PRId64, Operand * DataAlignmentFactor);
|
||||
else
|
||||
OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
|
||||
break;
|
||||
case OT_Register:
|
||||
OS << format(" reg%d", Operand);
|
||||
break;
|
||||
case OT_Expression:
|
||||
OS << " expression";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameEntry::dumpInstructions(raw_ostream &OS) const {
|
||||
// TODO: at the moment only instruction names are dumped. Expand this to
|
||||
// dump operands as well.
|
||||
uint64_t CodeAlignmentFactor = 0;
|
||||
int64_t DataAlignmentFactor = 0;
|
||||
const CIE *Cie = dyn_cast<CIE>(this);
|
||||
|
||||
if (!Cie)
|
||||
Cie = cast<FDE>(this)->getLinkedCIE();
|
||||
if (Cie) {
|
||||
CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
|
||||
DataAlignmentFactor = Cie->getDataAlignmentFactor();
|
||||
}
|
||||
|
||||
for (const auto &Instr : Instructions) {
|
||||
uint8_t Opcode = Instr.Opcode;
|
||||
if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
|
||||
Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
|
||||
OS << " " << CallFrameString(Opcode) << ":\n";
|
||||
OS << " " << CallFrameString(Opcode) << ":";
|
||||
for (unsigned i = 0; i < Instr.Ops.size(); ++i)
|
||||
printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
|
||||
DataAlignmentFactor);
|
||||
OS << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,22 +6,22 @@
|
||||
|
||||
; FRAMES: 00000000 00000010 ffffffff CIE
|
||||
; FRAMES: Version: 1
|
||||
; FRAMES: DW_CFA_def_cfa
|
||||
; FRAMES-NEXT: DW_CFA_offset
|
||||
; FRAMES-NEXT: DW_CFA_nop
|
||||
; FRAMES-NEXT: DW_CFA_nop
|
||||
; FRAMES: DW_CFA_def_cfa: reg4 +4
|
||||
; FRAMES-NEXT: DW_CFA_offset: reg8 -4
|
||||
; FRAMES-NEXT: DW_CFA_nop:
|
||||
; FRAMES-NEXT: DW_CFA_nop:
|
||||
|
||||
; FRAMES: 00000014 00000010 00000000 FDE cie=00000000 pc=00000000...00000022
|
||||
; FRAMES: DW_CFA_advance_loc
|
||||
; FRAMES-NEXT: DW_CFA_def_cfa_offset
|
||||
; FRAMES-NEXT: DW_CFA_nop
|
||||
; FRAMES: DW_CFA_advance_loc: 3
|
||||
; FRAMES-NEXT: DW_CFA_def_cfa_offset: +12
|
||||
; FRAMES-NEXT: DW_CFA_nop:
|
||||
|
||||
; FRAMES: 00000028 00000014 00000000 FDE cie=00000000 pc=00000030...00000080
|
||||
; FRAMES: DW_CFA_advance_loc
|
||||
; FRAMES-NEXT: DW_CFA_def_cfa_offset
|
||||
; FRAMES-NEXT: DW_CFA_offset
|
||||
; FRAMES-NEXT: DW_CFA_advance_loc
|
||||
; FRAMES-NEXT: DW_CFA_def_cfa_register
|
||||
; FRAMES: DW_CFA_advance_loc: 1
|
||||
; FRAMES-NEXT: DW_CFA_def_cfa_offset: +8
|
||||
; FRAMES-NEXT: DW_CFA_offset: reg5 -8
|
||||
; FRAMES-NEXT: DW_CFA_advance_loc: 2
|
||||
; FRAMES-NEXT: DW_CFA_def_cfa_register: reg5
|
||||
|
||||
; FRAMES-NOT: CIE
|
||||
; FRAMES-NOT: FDE
|
||||
|
Loading…
Reference in New Issue
Block a user