frame

package
v0.0.0-...-eda43a2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2023 License: Apache-2.0 Imports: 5 Imported by: 0

README

Call Frame Information

调试器经常需要查看调用栈中不同栈帧中的状态信息,要想实现此功能,就必须具备**"给定 任意地址后计算出该地址所在的栈帧"**的能力。

实现此功能主要依赖于下面几点:

  • 每个编译单元都由一个CIE描述,每个函数都由一个FDE描述,每个CIE后面跟着一系列的FDEs;

  • 调用栈信息表,表中每行的编码格式如下:

    Loc | CFA | register rules | return address register | architecture
    

    当指定一个地址L1时,遍历FDEs,如果某个FDE的内存地址范围[FDE.initial,FDE.initial+FDE.size] 可以覆盖L1时,说明指令地址L1对应的函数栈帧就找到了。

  • 字节码指令,上面的表非常大,实际上每行机器指令都对应上表中的一行,如果全量存储每行指令执行时的 状态信息,那数据量实在是太大了。 这里的指令可以分为几类:行创建指令、CFA操作指令、寄存器操作指令、架构相关指令。 为了压缩存储,可以由存储整张表转换为只编码存储相邻行的差异,即对有变更的CFA或者register编码。 很自然地,可以通过一系列的字节码指令来代表对CFA或register的操作。这里的字节码指令,由对应的状态机 执行之后,就可以构建出完整的上述的表结构。 但是实际上,并不需要构建完整的表结构,只需要行创建指令创建出的行地址Loc>=L1即可,就可以停下了。

  • 现在这个表结构有了,然后找到第一条Loc>=L1的行,找到其中的CFA以及register计算规则,用来计算出 CFA以及register的值,用以还原上下文信息,以便进一步分析栈帧中的arguments、variables、...

以上,大致就是CFI表结构的构建过程,以及应用了。

Documentation

Overview

Package frame contains data structures and related functions for parsing and searching through Dwarf .debug_frame data.

Index

Constants

View Source
const (
	DW_OP_addr    = 0x03
	DW_OP_const1s = 0x09
)

Operation opcodes

View Source
const (
	DW_OP_const2u = 0x0a
	DW_OP_const2s = 0x0b
	DW_OP_const4u = iota
	DW_OP_const4s
	DW_OP_const8u
	DW_OP_const8s
	DW_OP_constu
	DW_OP_consts
	DW_OP_dup
	DW_OP_drop
	DW_OP_over
	DW_OP_pick
	DW_OP_swap
	DW_OP_rot
	DW_OP_xderef
	DW_OP_abs
	DW_OP_and
	DW_OP_div
	DW_OP_minus
	DW_OP_mod
	DW_OP_mul
	DW_OP_neg
	DW_OP_not
	DW_OP_or
	DW_OP_plus
	DW_OP_plus_uconst
	DW_OP_shl
	DW_OP_shr
	DW_OP_shra
	DW_OP_xor
	DW_OP_skip
	DW_OP_bra
	DW_OP_eq
	DW_OP_ge
	DW_OP_gt
	DW_OP_le
	DW_OP_lt
	DW_OP_ne
)
View Source
const (
	DW_OP_lit0 = 0x30
	DW_OP_lit1 = 0x31
	DW_OP_lit2 = iota
	DW_OP_lit3
	DW_OP_lit4
	DW_OP_lit5
	DW_OP_lit6
	DW_OP_lit7
	DW_OP_lit8
	DW_OP_lit9
	DW_OP_lit10
	DW_OP_lit11
	DW_OP_lit12
	DW_OP_lit13
	DW_OP_lit14
	DW_OP_lit15
	DW_OP_lit16
	DW_OP_lit17
	DW_OP_lit18
	DW_OP_lit19
	DW_OP_lit20
	DW_OP_lit21
	DW_OP_lit22
	DW_OP_lit23
	DW_OP_lit24
	DW_OP_lit25
	DW_OP_lit26
	DW_OP_lit27
	DW_OP_lit28
	DW_OP_lit29
	DW_OP_lit30
	DW_OP_lit31
	DW_OP_reg0
	DW_OP_reg1
	DW_OP_reg2
	DW_OP_reg3
	DW_OP_reg4
	DW_OP_reg5
	DW_OP_reg6
	DW_OP_reg7
	DW_OP_reg8
	DW_OP_reg9
	DW_OP_reg10
	DW_OP_reg11
	DW_OP_reg12
	DW_OP_reg13
	DW_OP_reg14
	DW_OP_reg15
	DW_OP_reg16
	DW_OP_reg17
	DW_OP_reg18
	DW_OP_reg19
	DW_OP_reg20
	DW_OP_reg21
	DW_OP_reg22
	DW_OP_reg23
	DW_OP_reg24
	DW_OP_reg25
	DW_OP_reg26
	DW_OP_reg27
	DW_OP_reg28
	DW_OP_reg29
	DW_OP_reg30
	DW_OP_reg31
	DW_OP_breg0
	DW_OP_breg1
	DW_OP_breg2
	DW_OP_breg3
	DW_OP_breg4
	DW_OP_breg5
	DW_OP_breg6
	DW_OP_breg7
	DW_OP_breg8
	DW_OP_breg9
	DW_OP_breg10
	DW_OP_breg11
	DW_OP_breg12
	DW_OP_breg13
	DW_OP_breg14
	DW_OP_breg15
	DW_OP_breg16
	DW_OP_breg17
	DW_OP_breg18
	DW_OP_breg19
	DW_OP_breg20
	DW_OP_breg21
	DW_OP_breg22
	DW_OP_breg23
	DW_OP_breg24
	DW_OP_breg25
	DW_OP_breg26
	DW_OP_breg27
	DW_OP_breg28
	DW_OP_breg29
	DW_OP_breg30
	DW_OP_breg31
	DW_OP_regx
	DW_OP_fbreg
	DW_OP_bregx
	DW_OP_piece
	DW_OP_deref_size
	DW_OP_xderef_size
	DW_OP_nop
	DW_OP_push_object_address
	DW_OP_call2
	DW_OP_call4
	DW_OP_call_ref
	DW_OP_form_tls_address
	DW_OP_call_frame_cfa
	DW_OP_bit_piece

	DW_OP_lo_user = 0xe0
	DW_OP_hi_user = 0xff
)
View Source
const (
	DW_CFA_nop                = 0x0        // No ops
	DW_CFA_set_loc            = 0x01       // op1: address
	DW_CFA_advance_loc1       = iota       // op1: 1-bytes delta
	DW_CFA_advance_loc2                    // op1: 2-byte delta
	DW_CFA_advance_loc4                    // op1: 4-byte delta
	DW_CFA_offset_extended                 // op1: ULEB128 register, op2: ULEB128 offset
	DW_CFA_restore_extended                // op1: ULEB128 register
	DW_CFA_undefined                       // op1: ULEB128 register
	DW_CFA_same_value                      // op1: ULEB128 register
	DW_CFA_register                        // op1: ULEB128 register, op2: ULEB128 register
	DW_CFA_remember_state                  // No ops
	DW_CFA_restore_state                   // No ops
	DW_CFA_def_cfa                         // op1: ULEB128 register, op2: ULEB128 offset
	DW_CFA_def_cfa_register                // op1: ULEB128 register
	DW_CFA_def_cfa_offset                  // op1: ULEB128 offset
	DW_CFA_def_cfa_expression              // op1: BLOCK
	DW_CFA_expression                      // op1: ULEB128 register, op2: BLOCK
	DW_CFA_offset_extended_sf              // op1: ULEB128 register, op2: SLEB128 BLOCK
	DW_CFA_def_cfa_sf                      // op1: ULEB128 register, op2: SLEB128 offset
	DW_CFA_def_cfa_offset_sf               // op1: SLEB128 offset
	DW_CFA_val_offset                      // op1: ULEB128, op2: ULEB128
	DW_CFA_val_offset_sf                   // op1: ULEB128, op2: SLEB128
	DW_CFA_val_expression                  // op1: ULEB128, op2: BLOCK
	DW_CFA_lo_user            = 0x1c       // op1: BLOCK
	DW_CFA_hi_user            = 0x3f       // op1: ULEB128 register, op2: BLOCK
	DW_CFA_advance_loc        = (0x1 << 6) // High 2 bits: 0x1, low 6: delta
	DW_CFA_offset             = (0x2 << 6) // High 2 bits: 0x2, low 6: register
	DW_CFA_restore            = (0x3 << 6) // High 2 bits: 0x3, low 6: register
)

Instructions used to recreate the table from the .debug_frame data.

Variables

This section is empty.

Functions

func DwarfEndian

func DwarfEndian(infoSec []byte) binary.ByteOrder

DwarfEndian determines the endianness of the DWARF by using the version number field in the debug_info section Trick borrowed from "debug/dwarf".New()

Types

type CommonInformationEntry

type CommonInformationEntry struct {
	Length                uint32
	CIE_id                uint32
	Version               uint8
	Augmentation          string
	CodeAlignmentFactor   uint64
	DataAlignmentFactor   int64
	ReturnAddressRegister uint64
	InitialInstructions   []byte
	// contains filtered or unexported fields
}

CommonInformationEntry represents a Common Information Entry in the Dwarf .debug_frame section.

type DWRule

type DWRule struct {
	Rule       Rule
	Offset     int64
	Reg        uint64
	Expression []byte
}

DWRule wrapper of rule defined for register values.

type ErrNoFDEForPC

type ErrNoFDEForPC struct {
	PC uint64
}

ErrNoFDEForPC FDE for PC not found error

func (*ErrNoFDEForPC) Error

func (err *ErrNoFDEForPC) Error() string

type FrameContext

type FrameContext struct {
	CFA  DWRule
	Regs map[uint64]DWRule

	RetAddrReg uint64

	RegsV []uint64
	// contains filtered or unexported fields
}

FrameContext wrapper of FDE context

func (*FrameContext) ExecuteUntilPC

func (frame *FrameContext) ExecuteUntilPC(instructions []byte)

ExecuteUntilPC execute DWARF instructions.

type FrameDescriptionEntries

type FrameDescriptionEntries []*FrameDescriptionEntry

func Parse

func Parse(data []byte, order binary.ByteOrder, staticBase uint64, ptrSize int) FrameDescriptionEntries

Parse takes in data (a byte slice) and returns FrameDescriptionEntries, which is a slice of FrameDescriptionEntry. Each FrameDescriptionEntry has a pointer to CommonInformationEntry.

func (FrameDescriptionEntries) Append

Append appends otherFDEs to fdes and returns the result.

func (FrameDescriptionEntries) FDEForPC

FDEForPC returns the Frame Description Entry for the given PC.

type FrameDescriptionEntry

type FrameDescriptionEntry struct {
	Length       uint32
	CIE          *CommonInformationEntry
	Instructions []byte
	// contains filtered or unexported fields
}

FrameDescriptionEntry represents a Frame Descriptor Entry in the Dwarf .debug_frame section.

func (*FrameDescriptionEntry) Begin

func (fde *FrameDescriptionEntry) Begin() uint64

Begin returns address of first location for this frame.

func (*FrameDescriptionEntry) Cover

func (fde *FrameDescriptionEntry) Cover(addr uint64) bool

Cover returns whether or not the given address is within the bounds of this frame.

func (*FrameDescriptionEntry) End

func (fde *FrameDescriptionEntry) End() uint64

End returns address of last location for this frame.

func (*FrameDescriptionEntry) EstablishFrame

func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext

EstablishFrame set up frame for the given PC.

type Rule

type Rule byte

Rule rule defined for register values.

const (
	RuleUndefined Rule = iota
	RuleSameVal
	RuleOffset
	RuleValOffset
	RuleRegister
	RuleExpression
	RuleValExpression
	RuleArchitectural
	RuleCFA          // Value is rule.Reg + rule.Offset
	RuleFramePointer // Value is stored at address rule.Reg + rule.Offset, but only if it's less than the current CFA, otherwise same value
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL