DWARF op code

Posted by zhuizhuhaomeng Blog on October 20, 2023

elf 中 debug 相关的节

  • .debug_abbrev - Abbreviations used in the .debug_info section
  • .debug_aranges - Lookup table for mapping addresses to compilation units
  • .debug_frame - Call frame information
  • .debug_info - The core DWARF information section
  • .debug_line - Line number information
  • .debug_loc - Location lists used in DW_AT_location attributes
  • .debug_macinfo - Macro information
  • .debug_pubnames - Lookup table for mapping object and function names to compilation units
  • .debug_pubtypes - Lookup table for mapping type names to compilation units
  • .debug_ranges - Address ranges used in DW_AT_ranges attributes
  • .debug_str - String table used in .debug_info

DW_OP_fbreg

DW_OP_fbreg 是 DWARF(调试信息格式)中的一种操作码(opcode),用于计算基于帧指针的相对地址。它通常与调试信息中的位置表达式一起使用,用于定位变量或表达式的地址。

DW_OP_fbreg 表示 “frame base relative”,即相对于帧基址的偏移量。帧基址是指当前函数的堆栈帧的基址,可以用于访问函数的局部变量和参数。

使用 DW_OP_fbreg,可以构建一个位置表达式,以表示变量相对于帧基址的偏移量。例如,假设存在一个局部变量 x,可以使用以下位置表达式来计算它的地址:

1
DW_OP_fbreg <offset>

其中 <offset>x 相对于帧基址的偏移量。调试器在解释这个位置表达式时,会使用当前函数的帧基址,并将 <offset> 添加到帧基址上,从而计算出变量 x 的地址。

请注意,DW_OP_fbreg 是相对于帧基址的偏移量,而不是绝对地址。这意味着调试器需要知道当前函数的帧基址,才能正确计算变量的地址。帧基址的获取方式可能因调试器和目标平台而异。

DW_OP_call_frame_cfa

DW_OP_call_frame_cfa 是 DWARF(调试信息格式)中的一种操作码(opcode),用于计算调用帧的规范位置(Call Frame Address,CFA)。

CFA 是一个虚拟地址,表示当前函数的调用帧的基址。调用帧是一个栈帧,包含函数调用期间的局部变量、参数和其他相关信息。

使用 DW_OP_call_frame_cfa,可以构建一个位置表达式,以表示变量相对于调用帧的偏移量。例如,假设存在一个局部变量 x,可以使用以下位置表达式来计算它的地址:

1
2
DW_OP_call_frame_cfa
DW_OP_plus_uconst <offset>

其中 <offset>x 相对于调用帧的偏移量。调试器在解释这个位置表达式时,首先获取当前函数的调用帧地址(CFA),然后将 <offset> 添加到 CFA 上,从而计算出变量 x 的地址。

请注意,DW_OP_call_frame_cfa 是相对于调用帧的偏移量,而不是绝对地址。这意味着调试器需要正确地解析和计算调用帧,以获得正确的 CFA,并将偏移量添加到 CFA 上,从而计算变量的地址。

使用 DW_OP_call_frame_cfa 可以在调试过程中定位和访问当前函数的局部变量和参数。然而,获取调用帧地址和计算相对偏移量是复杂的操作,可能因调试器和目标平台而异。

DW_OP_piece

DW_OP_piece 是 DWARF(调试信息格式)中的一种操作码(opcode),用于指定一个复合类型(如结构体或联合体)中的一个片段的大小。

当使用 DW_OP_piece 时,它通常与位置表达式指令(如 DW_OP_addr、DW_OP_fbreg 等)一起使用,用于指定复合类型中每个片段的大小。这对于在调试过程中定位和访问复合类型的特定片段是非常有用的。

DW_OP_piece 的使用方式如下:

1
DW_OP_piece <size>

其中 <size> 是片段的大小,以字节为单位。

在位置表达式中,可以根据需要使用多个 DW_OP_piece 操作码来描述复合类型的不同片段。这样,调试器可以根据每个片段的大小来计算地址,并定位和访问复合类型的特定部分。

以下是一个示例,说明如何使用 DW_OP_piece 来描述一个结构体的不同片段:

1
2
3
DW_OP_piece 4     ; 第一个片段的大小为 4 字节
DW_OP_piece 2     ; 第二个片段的大小为 2 字节
DW_OP_piece 8     ; 第三个片段的大小为 8 字节

在这个示例中,结构体被划分为三个片段,分别具有不同的大小。调试器可以使用这些 DW_OP_piece 指令来计算每个片段的地址,并在调试过程中访问结构体的特定部分。

需要注意的是,DW_OP_piece 操作码仅用于指定大小,并不直接提供地址计算功能。它通常与其他位置表达式指令一起使用,以计算最终的地址。

好文共赏

想要了解调试器是怎么工作的,那么应该学习 这个序列的文章。

https://eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1/ https://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints https://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information

英文的看起来速度慢一点,那么可以看这里别人翻译好的中文版。

https://godorz.info/2011/02/how-debuggers-work-part-1/ https://godorz.info/2011/02/how-debuggers-work-part-2-breakpoints/ https://godorz.info/2011/02/how-debuggers-work-part-3-debugging-information/