Skip to content

Commit

Permalink
Add the ability to extract the unwind rows from DWARF Call Frame Info…
Browse files Browse the repository at this point in the history
…rmation.

This patch adds the ability to evaluate the state machine for CIE and FDE unwind objects and produce a UnwindTable with all UnwindRow objects needed to unwind registers. It will also dump the UnwindTable for each CIE and FDE when dumping DWARF .debug_frame or .eh_frame sections in llvm-dwarfdump or llvm-objdump. This allows users to see what the unwind rows actually look like for a given CIE or FDE instead of just seeing a list of opcodes.

This patch adds new classes: UnwindLocation, RegisterLocations, UnwindRow, and UnwindTable.

UnwindLocation is a class that describes how to unwind a register or Call Frame Address (CFA).

RegisterLocations is a class that tracks registers and their UnwindLocations. It gets populated when parsing the DWARF call frame instruction opcodes for a unwind row. The registers are mapped from their register numbers to the UnwindLocation in a map.

UnwindRow contains the result of evaluating a row of DWARF call frame instructions for the CIE, or a row from a FDE. The CIE can produce a set of initial instructions that each FDE that points to that CIE will use as the seed for the state machine when parsing FDE opcodes. A UnwindRow for a CIE will not have a valid address, whille a UnwindRow for a FDE will have a valid address.

The UnwindTable is a class that contains a sorted (by address) vector of UnwindRow objects and is the result of parsing all opcodes in a CIE, or FDE. Parsing a CIE should produce a UnwindTable with a single row. Parsing a FDE will produce a UnwindTable with one or more UnwindRow objects where all UnwindRow objects have valid addresses. The rows in the UnwindTable will be sorted from lowest Address to highest after parsing the state machine, or an error will be returned if the table isn't sorted. To parse a UnwindTable clients can use the following methods:

    static Expected<UnwindTable> UnwindTable::create(const CIE *Cie);
    static Expected<UnwindTable> UnwindTable::create(const FDE *Fde);

A valid table will be returned if the DWARF call frame instruction opcodes have no encoding errors. There are a few things that can go wrong during the evaluation of the state machine and these create functions will catch and return them.

Differential Revision: https://reviews.llvm.org/D89845
  • Loading branch information
clayborg committed Jan 28, 2021
1 parent bacf9cf commit f8122d3
Show file tree
Hide file tree
Showing 8 changed files with 2,121 additions and 10 deletions.
373 changes: 372 additions & 1 deletion llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
Expand Up @@ -80,7 +80,7 @@ class DWARFExpression {
friend class DWARFExpression::iterator;
uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
Description Desc;
bool Error;
bool Error = false;
uint64_t EndOffset;
uint64_t Operands[2];
uint64_t OperandEndOffsets[2];
Expand Down Expand Up @@ -157,6 +157,8 @@ class DWARFExpression {

bool verify(DWARFUnit *U);

bool operator==(const DWARFExpression &RHS) const;

private:
DataExtractor Data;
uint8_t AddressSize;
Expand Down

0 comments on commit f8122d3

Please sign in to comment.