乐于分享
好东西不私藏

DWARF2调试信息全面解析:规范、源码与x86调试实例

DWARF2调试信息全面解析:规范、源码与x86调试实例

基于DWARF 2规范及GDB 8.2源码实现编写

目录

  1. DWARF概述与二进制布局
  2. 调试信息条目与属性
  3. 位置描述
  4. 行号与调用帧信息
  5. GDB源码实现映射
  6. x86实例:DWARF2调试全过程

1. DWARF概述与二进制布局

1.1 概述

DWARF(Debugging With Arbitrary Record Formats)是一种标准的调试信息格式,由编译器生成,供调试器使用。它将源代码级别的程序信息(变量、类型、函数、行号等)编码到目标文件的特定节(section)中,使得调试器能够在机器码和源代码之间建立映射。

版本演进:

版本
年代
关键变化
DWARF 1
1992
初始版本,调试信息存储在 .debug 节
DWARF 21993更紧凑的表示,信息移至 .debug_info;引入LEB128编码、栈式位置表达式
DWARF 3
2005
增加DW_OP_stack_value、DW_OP_implicit_pointer;改进CFI
DWARF 4
2010
增加DW_OP_implicit_value;支持.type单元;改进行号表
DWARF 5
2017
重构行号表格式;增加.loclists/.rnglists节;改进分割DWARF

设计目标:语言无关性(核心调试信息与具体编程语言无关)、紧凑性(LEB128变长编码+缩写表)、可扩展性(允许添加新的标签/属性/操作码)。

1.2 二进制布局

DWARF调试信息分布在ELF文件的多个节中:

ELF文件├── .debug_info      ← 核心调试信息(DIE树)├── .debug_abbrev    ← 缩写表(DIE的"模板"定义)├── .debug_line      ← 行号程序├── .debug_loc       ← 位置列表├── .debug_str       ← 间接字符串表├── .debug_ranges    ← 地址范围列表(DWARF3+)├── .debug_frame     ← 调用帧信息(CFI)├── .debug_aranges   ← 地址范围查找加速表└── .eh_frame        ← GCC扩展的CFI(加载时可用)

每个 .debug_info 节包含一个或多个编译单元,每个编译单元以如下头部开始:

+------------------------+| unit_length            |  4字节(DWARF32)或12字节(DWARF64)+------------------------+| version                |  2字节(= 2 for DWARF2)+------------------------+| debug_abbrev_offset    |  4字节,指向.debug_abbrev中的缩写表+------------------------+| address_size           |  1字节,目标机地址宽度(如4=32bit, 8=64bit)+------------------------+| DIE data ...           |  紧跟第一个DIE

GDB中对应 struct comp_unit_head(dwarf2read.c),关键字段:lengthversionaddr_sizeabbrev_sect_offoffset_sizeinitial_length_size

DWARF2大量使用LEB128变长整数编码以节省空间:

  • ULEB128(无符号):每个字节最高位为延续标志(1=还有后续字节),低7位为有效数据,按小端序拼接
  • SLEB128(有符号):编码方式与ULEB128类似,最后一个字节的最高有效位为符号位
示例:编码 128(0x80)ULEB128: 0x80 0x01  (2字节)  第1字节: 1_0000000 → 延续位=1, 数据=0  第2字节: 0_0000001 → 延续位=0, 数据=1  解码:字节0低7位 × 2^0 + 字节1低7位 × 2^7 = 0 + 128 = 128

2. 调试信息条目与属性

2.1 DIE与缩写表

DWARF调试信息以调试信息条目(Debugging Information Entry, DIE)为基本单位。每个DIE由三部分组成:

  1. 缩写码(Abbreviation Code):ULEB128编码,引用 .debug_abbrev 中的缩写条目
  2. 属性值:根据缩写条目中定义的form依次编码
  3. 子DIE(可选):如果缩写条目标记 has_children = DW_CHILDREN_yes

DIE通过父子关系和兄弟关系组成树形结构

DW_TAG_compile_unit          ← 根DIE├── DW_TAG_subprogram        ← 子DIE (兄弟1)│   ├── DW_TAG_variable      ← 子DIE│   ├── DW_TAG_variable      ← 子DIE│   └── (null DIE)           ← 子DIE终止├── DW_TAG_variable          ← 子DIE (兄弟2)└── (null DIE)               ← 子DIE终止

核心DIE标签:

标签
用途
DW_TAG_compile_unit
0x11
编译单元
DW_TAG_subprogram
0x2e
函数/子程序
DW_TAG_inlined_subroutine
0x1d
内联函数实例
DW_TAG_variable
0x34
变量
DW_TAG_formal_parameter
0x05
函数形参
DW_TAG_lexical_block
0x0b
词法作用域块
DW_TAG_base_type
0x24
基本类型
DW_TAG_pointer_type
0x0f
指针类型
DW_TAG_structure_type
0x13
结构体类型
DW_TAG_union_type
0x17
联合体类型
DW_TAG_enumeration_type
0x04
枚举类型
DW_TAG_typedef
0x16
类型别名

缩写表是DWARF2紧凑性的核心机制。它为每种DIE定义一个"模板",指明该DIE有哪些属性以及每个属性的编码形式(form),这样实际的DIE只需存储缩写码和属性值。.debug_abbrev 节布局:

+-----------------------------+| Abbreviation Code (ULEB128) |  ← 缩写码 (1, 2, 3, ...)+-----------------------------+| Tag (ULEB128)               |  ← DW_TAG_*+-----------------------------+| Has Children (1 byte)       |  ← DW_CHILDREN_yes(1) / no(0)+-----------------------------+| Attr Name (ULEB128)         |  ← 属性对| Attr Form (ULEB128)         |+-----------------------------+| 0, 0                        |  ← 属性对终止+-----------------------------+

GDB使用 struct abbrev_info 和 struct abbrev_table 表示,通过 abbrev_table_read_table() 读取。

2.2 属性

常用属性一览:

属性
用途
典型Form
DW_AT_name
0x03
符号名
DW_FORM_string / strp
DW_AT_location
0x02
位置表达式或位置列表引用
DW_FORM_block / sec_offset
DW_AT_type
0x49
类型引用
DW_FORM_ref*
DW_AT_byte_size
0x0b
字节大小
DW_FORM_data*
DW_AT_low_pc
 / DW_AT_high_pc
0x11/0x12
PC范围
DW_FORM_addr / data*
DW_AT_stmt_list
0x10
.debug_line偏移
DW_FORM_sec_offset
DW_AT_comp_dir
0x1b
编译目录
DW_FORM_string / strp
DW_AT_language
0x13
源语言
DW_FORM_data*
DW_AT_decl_file
 / DW_AT_decl_line
0x3a/0x3b
声明位置
DW_FORM_data*
DW_AT_external
0x3f
外部可见性
DW_FORM_flag
DW_AT_frame_base
0x40
帧基址位置表达式
DW_FORM_block
DW_AT_sibling
0x01
兄弟DIE偏移
DW_FORM_ref*
DW_AT_const_value
0x1c
常量值
DW_FORM_block / data*
DW_AT_data_member_location
0x38
结构成员偏移
DW_FORM_block / data*
DW_AT_producer
0x25
编译器标识
DW_FORM_string / strp
DW_AT_inline
0x20
内联属性
DW_FORM_data*
DW_AT_abstract_origin
0x31
抽象起源引用
DW_FORM_ref*
DW_AT_specification
0x47
规范声明引用
DW_FORM_ref*
DW_AT_ranges
0x55
范围列表引用
DW_FORM_sec_offset

属性值的Form(编码形式):

Form
含义
DW_FORM_addr
目标地址(addr_size字节)
DW_FORM_block/block1/block2/block4
块(分别用ULEB128/1/2/4字节长度前缀)
DW_FORM_data1/data2/data4/data8
1/2/4/8字节数据
DW_FORM_string
内联空终止字符串
DW_FORM_strp
.debug_str中的4字节偏移
DW_FORM_flag
1字节标志
DW_FORM_sdata
 / DW_FORM_udata
有符号/无符号LEB128
DW_FORM_ref1/ref2/ref4/ref8/ref_udata
CU内引用(不同宽度)
DW_FORM_ref_addr
节内偏移引用
DW_FORM_indirect
间接form(运行时确定)
DW_FORM_sec_offset
节偏移(DWARF3+)
DW_FORM_exprloc
位置表达式(DWARF4+)
DW_FORM_implicit_const
常量编码在缩写表中

属性值语义类别:address(程序地址)、block(位置表达式)、constant(常量)、flag(存在性)、reference(DIE引用)、string(字符串)。

2.3 GDB中的表示

DIE由 struct die_info(dwarf2read.c)表示:

structdie_info {    ENUM_BITFIELD(dwarf_tag) tag : 16;   // DW_TAG_*unsignedchar num_attrs;             // 属性个数unsignedint abbrev;                 // 缩写码    sect_offset sect_off;                // 在节中的偏移structdie_info *child;// 第一个子DIEstructdie_info *sibling;// 下一个兄弟DIEstructdie_info *parent;// 父DIEstructattributeattrs[1];// 属性数组(柔性数组)};

属性由 struct attribute 表示,访问宏:DW_STRING(attr)DW_UNSND(attr)DW_SND(attr)DW_ADDR(attr)DW_BLOCK(attr)

构建部分符号表时使用精简版 struct partial_die_info,仅保留名称、PC范围、外部性等关键信息。

3. 位置描述

位置描述是DWARF最核心的机制之一,用于回答"变量在哪里"这个问题。

3.1 位置表达式

位置描述有两种形式:位置表达式(变量位置在生命周期内不变,内联在DIE属性中)和位置列表(变量位置随执行变化,存储在 .debug_loc 节中)。

位置表达式基于一个简单的栈机器模型:栈元素大小等于目标机地址大小,每个操作码对栈进行操作,执行完毕后栈顶值即为结果。

寄存器命名与寻址:

操作码
含义
DW_OP_reg0
 ~ DW_OP_reg31
对象在寄存器0~31中
DW_OP_regx
对象在指定寄存器中(ULEB128操作数)
DW_OP_fbreg
帧基址 + SLEB128偏移
DW_OP_breg0
 ~ DW_OP_breg31
寄存器n + SLEB128偏移
DW_OP_bregx
寄存器(ULEB128) + SLEB128偏移

字面量与地址:

操作码
含义
DW_OP_lit0
 ~ DW_OP_lit31
压入常量0~31
DW_OP_addr
压入目标地址
DW_OP_const1u/1s
 ~ DW_OP_const8u/8s
压入1~8字节无符号/有符号常量
DW_OP_constu
 / DW_OP_consts
压入ULEB128/SLEB128常量

栈操作:

操作码
含义
DW_OP_dup
 / DW_OP_drop
复制/弹出栈顶
DW_OP_pick
 / DW_OP_over
复制第n个/第二个栈元素
DW_OP_swap
 / DW_OP_rot
交换栈顶两个/三个元素
DW_OP_deref
 / DW_OP_deref_size
弹出地址,压入该地址处的值

算术/逻辑/控制流:

操作码
含义
DW_OP_plus
 / DW_OP_minus / DW_OP_mul / DW_OP_div / DW_OP_mod
算术运算
DW_OP_and
 / DW_OP_or / DW_OP_xor / DW_OP_not
位运算
DW_OP_shl
 / DW_OP_shr / DW_OP_shra
移位
DW_OP_plus_uconst
加无符号LEB128常量
DW_OP_le/ge/eq/lt/gt/ne
关系比较(结果为0或1)
DW_OP_skip
 / DW_OP_bra
无条件/条件跳转
DW_OP_piece
 / DW_OP_nop
描述变量片段 / 无操作

位置表达式示例:

表达式
含义
DW_OP_reg3
变量在寄存器3中
DW_OP_fbreg -50
变量地址 = 帧基址 - 50
DW_OP_bregx 54 32; DW_OP_deref
间接寻址:*(寄存器54 + 32)
DW_OP_reg3; DW_OP_piece 4; DW_OP_reg10; DW_OP_piece 2
变量拆分:4字节在reg3,2字节在reg10

3.2 位置列表

位置列表存储在 .debug_loc 节中,用于描述位置随生命周期变化的对象。每个条目包含:起始地址结束地址(均相对于CU基址)、位置表达式

特殊情况:起始和结束地址均为0表示列表终止;均为0xFFFFFFFF表示基址选择条目;地址范围未覆盖的部分表示对象不可用。

3.3 GDB中的位置表达式求值

GDB通过 dwarf_expr_context 类(dwarf2expr.c)实现位置表达式求值,核心为 execute_stack_op() 方法。结果类型:

类型
含义
DWARF_VALUE_MEMORY
结果是内存地址
DWARF_VALUE_REGISTER
结果在寄存器中
DWARF_VALUE_STACK
结果在值栈上
DWARF_VALUE_LITERAL
隐式字面量
DWARF_VALUE_OPTIMIZED_OUT
被优化掉
DWARF_VALUE_IMPLICIT_POINTER
隐式指针

位置列表通过 dwarf2_find_location_expression()(dwarf2loc.c)查找,支持标准 .debug_loc.debug_loc.dwo.debug_loclists 三种格式。

4. 行号与调用帧信息

4.1 行号信息

行号信息建立机器指令地址与源代码行号之间的映射,存储在 .debug_line 节中,使用状态机模型编码。

行号程序头关键字段:

字段
含义
unit_length
 / version
总长度 / 版本号(2, 3, 4, 5)
minimum_instruction_length
最小指令长度
default_is_stmt
默认is_stmt值
line_base
 / line_range / opcode_base
特殊操作码参数
standard_opcode_lengths[]
标准操作码的操作数个数
include_dirs[]
 / file_names[]
目录表 / 文件名表

行号状态机寄存器:

寄存器
含义
默认值
address
当前程序地址
0
file
 / line / column
当前文件/行号/列号
1 / 1 / 0
is_stmt
是否为语句开头
default_is_stmt
basic_block
 / end_sequence
基本块/序列结束标志
false
prologue_end
 / epilogue_begin
序言结束/尾声开始标志
false

标准操作码(DW_LNS_*):

操作码
含义
DW_LNS_copy
记录当前状态为一行
DW_LNS_advance_pc
地址前进
DW_LNS_advance_line
行号前进
DW_LNS_set_file
 / DW_LNS_set_column
设置文件/列
DW_LNS_negate_stmt
 / DW_LNS_set_basic_block
翻转is_stmt / 设置basic_block
DW_LNS_const_add_pc
 / DW_LNS_fixed_advance_pc
地址前进(特殊/固定量)
DW_LNS_set_prologue_end
 / DW_LNS_set_epilogue_begin
设置序言结束/尾声开始
DW_LNS_set_isa
设置ISA

扩展操作码(DW_LNE_*):DW_LNE_end_sequence(序列结束)、DW_LNE_set_address(设置地址)、DW_LNE_define_file(定义文件)、DW_LNE_set_discriminator(设置判别器)。

特殊操作码将地址增量和行增量编码在一个字节中:

special_opcode = opcode - opcode_baseaddress_advance = special_opcode / line_rangeline_advance = line_base + (special_opcode % line_range)

4.2 调用帧信息(CFI)

CFI描述如何从当前栈帧回溯到调用者栈帧(unwind),存储在 .debug_frame 或 .eh_frame 节中。

CFI由两种条目组成:

CIE(公共信息条目):包含版本号、增强字符串(如"zR")、代码/数据对齐因子、返回地址寄存器、初始CFI指令序列。

FDE(帧描述条目):包含指向所属CIE的指针、PC范围起始和长度、CFI指令序列。

CFI指令分类:

类别
指令
含义
帧地址
DW_CFA_set_loc
 / DW_CFA_advance_loc*
设置/前进PC位置
CFA定义
DW_CFA_def_cfa
 / def_cfa_sf / def_cfa_register / def_cfa_offset / def_cfa_expression
定义CFA计算方式
寄存器规则
DW_CFA_undefined
 / same_value / offset / offset_extended_sf / val_offset / register / expression / val_expression
寄存器值的来源
状态保存
DW_CFA_remember_state
 / restore_state / nop
保存/恢复寄存器状态

GDB中的CFI数据结构:struct dwarf2_ciestruct dwarf2_fdestruct dwarf2_frame_statestruct dwarf2_frame_state_regenum dwarf2_frame_reg_rule。关键函数:dwarf2_frame_cfa()dwarf2_append_unwinders()

5. GDB源码实现映射

5.1 文件职责与数据流

文件
职责
dwarf2read.h
 / dwarf2read.c
DWARF2核心读取:DIE解析、缩写表、符号构建、行号、类型读取
dwarf2expr.h
 / dwarf2expr.c
DWARF表达式求值引擎(栈机器)
dwarf2loc.h
 / dwarf2loc.c
位置列表处理和变量定位
dwarf2-frame.h
 / dwarf2-frame.c
CFI帧信息处理
dwarf2-frame-tailcall.c
 / .h
尾调用帧处理

核心数据流:

ELF文件加载    │    ▼dwarf2_build_psymtabs_hard()     ← 扫描所有CU,构建部分符号表    │    ├─→ abbrev_table_read_table() / read_partial_die() / 创建partial_symtab    │    ▼psymtab_to_symtab_1()            ← 按需展开完整符号表    │    ├─→ load_full_comp_unit()    │   ├─→ read_die_and_children() → read_full_die_1() / read_attribute()    │   └─→ process_die() → read_file_scope() / read_func_scope() / read_type_die() ...    │    ├─→ dwarf_decode_lines()    │    ▼变量求值    ├─→ dwarf2_evaluate_loc_desc() → execute_stack_op()    ├─→ dwarf2_find_location_expression()    └─→ dwarf2_frame_cfa()

5.2 关键函数索引

函数
文件
用途
read_full_die_1
dwarf2read.c
从缓冲区读取一个完整DIE
read_die_and_children
dwarf2read.c
递归读取DIE及其子DIE
process_die
dwarf2read.c
DIE处理分发器
dwarf2_attr
dwarf2read.c
查找DIE的属性(跟随specification)
read_type_die
dwarf2read.c
按需读取类型DIE
abbrev_table_read_table
dwarf2read.c
读取缩写表
dwarf_decode_lines
dwarf2read.c
解码行号程序
execute_stack_op
dwarf2expr.c
执行DWARF表达式操作码
dwarf2_find_location_expression
dwarf2loc.c
查找PC对应的位置表达式
dwarf2_evaluate_loc_desc
dwarf2loc.c
求值位置描述
dwarf2_frame_cfa
dwarf2-frame.c
计算帧的CFA

6. x86实例:DWARF2调试全过程

本节以一个简单的x86-64 C程序为例,完整展示从编译到GDB调试的DWARF2信息流转过程。

6.1 示例程序与编译

// example.cintadd(int a, int b){int sum = a + b;return sum;}intmain(){int x = 10;int y = 20;int result = add(x, y);return result;}

编译命令:

gcc -gdwarf-2 -O0 -fstack-protector-strong -c example.c -o example.o

-gdwarf-2 指定生成DWARF2格式调试信息,-O0 关闭优化以保证变量在栈上而非寄存器中。

6.2 ELF节布局

readelf -S example.o
  [Nr] Name              Type  [ 1] .text             PROGBITS  [ 5] .debug_info       PROGBITS  [ 7] .debug_abbrev     PROGBITS  [ 8] .debug_loc        PROGBITS  [ 9] .debug_aranges    PROGBITS  [11] .debug_line       PROGBITS  [13] .debug_str        PROGBITS

各节作用:.debug_info 存DIE树,.debug_abbrev 存缩写表,.debug_line 存行号程序,.debug_loc 存位置列表,.debug_str 存间接字符串。

6.3 缩写表解读

readelf --debug-dump=abbrev example.o
  Number TAG   1      DW_TAG_compile_unit    [has children]    DW_AT_producer     DW_FORM_strp    DW_AT_language     DW_FORM_data1    DW_AT_name         DW_FORM_strp    DW_AT_comp_dir     DW_FORM_strp    DW_AT_low_pc       DW_FORM_addr    DW_AT_high_pc      DW_FORM_addr    DW_AT_stmt_list    DW_FORM_data4   2      DW_TAG_subprogram    [has children]    DW_AT_external     DW_FORM_flag    DW_AT_name         DW_FORM_strp    DW_AT_decl_file    DW_FORM_data1    DW_AT_decl_line    DW_FORM_data1    DW_AT_type         DW_FORM_ref4    DW_AT_low_pc       DW_FORM_addr    DW_AT_high_pc      DW_FORM_addr    DW_AT_frame_base   DW_FORM_data4    DW_AT_GNU_all_tail_call_sites DW_FORM_flag    DW_AT_sibling      DW_FORM_ref4   3      DW_TAG_variable    [no children]    DW_AT_name         DW_FORM_string    DW_AT_decl_file    DW_FORM_data1    DW_AT_decl_line    DW_FORM_data1    DW_AT_type         DW_FORM_ref4    DW_AT_location     DW_FORM_block1   4      DW_TAG_variable    [no children]    DW_AT_name         DW_FORM_strp    DW_AT_decl_file    DW_FORM_data1    DW_AT_decl_line    DW_FORM_data1    DW_AT_type         DW_FORM_ref4    DW_AT_location     DW_FORM_block1   5      DW_TAG_base_type    [no children]    DW_AT_byte_size    DW_FORM_data1    DW_AT_encoding     DW_FORM_data1    DW_AT_name         DW_FORM_string   6      DW_TAG_subprogram    [has children]    DW_AT_external     DW_FORM_flag    DW_AT_name         DW_FORM_string    DW_AT_decl_file    DW_FORM_data1    DW_AT_decl_line    DW_FORM_data1    DW_AT_prototyped   DW_FORM_flag    DW_AT_type         DW_FORM_ref4    DW_AT_low_pc       DW_FORM_addr    DW_AT_high_pc      DW_FORM_addr    DW_AT_frame_base   DW_FORM_data4    DW_AT_GNU_all_call_sites DW_FORM_flag   7      DW_TAG_formal_parameter    [no children]    DW_AT_name         DW_FORM_string    DW_AT_decl_file    DW_FORM_data1    DW_AT_decl_line    DW_FORM_data1    DW_AT_type         DW_FORM_ref4    DW_AT_location     DW_FORM_block1

解读要点

  • 缩写1定义编译单元,包含producer/name/low_pc/high_pc/stmt_list等属性
  • 缩写2和6都定义函数(subprogram),区别在于2用strp引用name且有sibling属性,6用内联string且无sibling
  • 缩写2的 DW_AT_frame_base 类型为 DW_FORM_data4,指向 .debug_loc 中的位置列表(而非内联exprloc),因为编译器开启了 -fstack-protector-strong,帧基址随PC位置变化
  • 缩写7定义函数参数,使用 DW_FORM_block1 编码位置表达式

6.4 DIE树解读

readelf --debug-dump=info example.o
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)    <c>   DW_AT_producer    : GNU C11 7.5.0 -mtune=generic -march=x86-64 -gdwarf-2 -O0 -fstack-protector-strong    <10>   DW_AT_language    : 12        (ANSI C99)    <11>   DW_AT_name        : example.c    <15>   DW_AT_comp_dir    : /home/yefei/embedded/temp/case    <19>   DW_AT_low_pc      : 0x0    <21>   DW_AT_high_pc     : 0x47    <29>   DW_AT_stmt_list   : 0x0 <1><2d>: Abbrev Number: 2 (DW_TAG_subprogram)    <2e>   DW_AT_external    : 1    <2f>   DW_AT_name        : main    <33>   DW_AT_decl_file   : 1    <34>   DW_AT_decl_line   : 6    <35>   DW_AT_type        : <0x79>    <39>   DW_AT_low_pc      : 0x1a    <41>   DW_AT_high_pc     : 0x47    <49>   DW_AT_frame_base  : 0x0 (location list)    <4d>   DW_AT_GNU_all_tail_call_sites: 1    <4e>   DW_AT_sibling     : <0x79> <2><52>: Abbrev Number: 3 (DW_TAG_variable)    <53>   DW_AT_name        : x    <55>   DW_AT_decl_file   : 1    <56>   DW_AT_decl_line   : 7    <57>   DW_AT_type        : <0x79>    <5b>   DW_AT_location    : 2 byte block: 91 64    (DW_OP_fbreg: -28) <2><5e>: Abbrev Number: 3 (DW_TAG_variable)    <5f>   DW_AT_name        : y    <61>   DW_AT_decl_file   : 1    <62>   DW_AT_decl_line   : 8    <63>   DW_AT_type        : <0x79>    <67>   DW_AT_location    : 2 byte block: 91 68    (DW_OP_fbreg: -24) <2><6a>: Abbrev Number: 4 (DW_TAG_variable)    <6b>   DW_AT_name        : result    <6f>   DW_AT_decl_file   : 1    <70>   DW_AT_decl_line   : 9    <71>   DW_AT_type        : <0x79>    <75>   DW_AT_location    : 2 byte block: 91 6c    (DW_OP_fbreg: -20) <2><78>: Abbrev Number: 0 <1><79>: Abbrev Number: 5 (DW_TAG_base_type)    <7a>   DW_AT_byte_size   : 4    <7b>   DW_AT_encoding    : 5       (signed)    <7c>   DW_AT_name        : int <1><80>: Abbrev Number: 6 (DW_TAG_subprogram)    <81>   DW_AT_external    : 1    <82>   DW_AT_name        : add    <86>   DW_AT_decl_file   : 1    <87>   DW_AT_decl_line   : 1    <88>   DW_AT_prototyped  : 1    <89>   DW_AT_type        : <0x79>    <8d>   DW_AT_low_pc      : 0x0    <95>   DW_AT_high_pc     : 0x1a    <9d>   DW_AT_frame_base  : 0x60 (location list)    <a1>   DW_AT_GNU_all_call_sites: 1 <2><a2>: Abbrev Number: 7 (DW_TAG_formal_parameter)    <a3>   DW_AT_name        : a    <a5>   DW_AT_decl_file   : 1    <a6>   DW_AT_decl_line   : 1    <a7>   DW_AT_type        : <0x79>    <ab>   DW_AT_location    : 2 byte block: 91 5c    (DW_OP_fbreg: -36) <2><ae>: Abbrev Number: 7 (DW_TAG_formal_parameter)    <af>   DW_AT_name        : b    <b1>   DW_AT_decl_file   : 1    <b2>   DW_AT_decl_line   : 1    <b3>   DW_AT_type        : <0x79>    <b7>   DW_AT_location    : 2 byte block: 91 58    (DW_OP_fbreg: -40) <2><ba>: Abbrev Number: 3 (DW_TAG_variable)    <bb>   DW_AT_name        : sum    <bf>   DW_AT_decl_file   : 1    <c0>   DW_AT_decl_line   : 2    <c1>   DW_AT_type        : <0x79>    <c5>   DW_AT_location    : 2 byte block: 91 6c    (DW_OP_fbreg: -20) <2><c8>: Abbrev Number: 0 <1><c9>: Abbrev Number: 0

DIE树结构总览:

DW_TAG_compile_unit (example.c, PC: 0x0~0x47)├── DW_TAG_subprogram (main, PC: 0x1a~0x47, frame_base→.debug_loc+0x0)│   ├── DW_TAG_variable (x, loc: DW_OP_fbreg: -28)│   ├── DW_TAG_variable (y, loc: DW_OP_fbreg: -24)│   └── DW_TAG_variable (result, loc: DW_OP_fbreg: -20)├── DW_TAG_base_type (int, 4 bytes, signed)└── DW_TAG_subprogram (add, PC: 0x0~0x1a, frame_base→.debug_loc+0x60)    ├── DW_TAG_formal_parameter (a, loc: DW_OP_fbreg: -36)    ├── DW_TAG_formal_parameter (b, loc: DW_OP_fbreg: -40)    └── DW_TAG_variable (sum, loc: DW_OP_fbreg: -20)

6.5 位置表达式详解

本例中所有变量位置均使用 DW_OP_fbreg 编码,而非 DW_OP_breg6(直接引用rbp)。这是因为编译器开启了 -fstack-protector-strong,帧基址(frame base)在函数序言期间会发生变化,需要通过位置列表描述。

fbreg 与 breg6 的区别:

  • DW_OP_fbreg: offset — 取当前函数的帧基址 + SLEB128偏移。帧基址由 DW_AT_frame_base 属性定义(一个位置列表),其值随PC位置变化
  • DW_OP_breg6: offset — 直接取r6(rbp)寄存器值 + SLEB128偏移,帧基址固定

结合汇编验证(以add函数为例):

add:   0:   push   %rbp                ; 保存旧rbp   1:   mov    %rsp,%rbp           ; 建立新帧基址   4:   mov    %edi,-0x14(%rbp)    ; a入栈 → rbp-0x14 = rbp-20   7:   mov    %esi,-0x18(%rbp)    ; b入栈 → rbp-0x18 = rbp-24   a:   mov    -0x14(%rbp),%edx   d:   mov    -0x18(%rbp),%eax  10:   add    %edx,%eax  12:   mov    %eax,-0x4(%rbp)     ; sum → rbp-0x4 = rbp-4  15:   mov    -0x4(%rbp),%eax  18:   pop    %rbp  19:   ret

DIE中记录:a = DW_OP_fbreg: -36,b = DW_OP_fbreg: -40,sum = DW_OP_fbreg: -20

为什么偏移与汇编不一致?因为 DW_OP_fbreg 使用帧基址而非rbp。根据6.7节的CFI分析,序言后CFA = rbp + 16,而 DW_AT_frame_base 位置列表在序言后的值等于CFA,因此:

DW_OP_fbreg: -36 → frame_base + (-36) = (rbp + 16) - 36 = rbp - 20 ✓ 与汇编中-0x14一致DW_OP_fbreg: -40 → frame_base + (-40) = (rbp + 16) - 40 = rbp - 24 ✓ 与汇编中-0x18一致DW_OP_fbreg: -20 → frame_base + (-20) = (rbp + 16) - 20 = rbp - 4  ✓ 与汇编中-0x4一致

GDB求值 DW_OP_fbreg: -28 的内部过程(对应 execute_stack_op()):

  1. 读取操作码 DW_OP_fbreg(0x91),得知需要取帧基址加SLEB128偏移
  2. 读取SLEB128操作数:-28
  3. 从当前DIE所属的 DW_TAG_subprogram 获取 DW_AT_frame_base(位置列表偏移0x0)
  4. 通过 dwarf2_find_location_expression() 查找当前PC对应的位置表达式,结果为 CFA (= rbp + 16)
  5. 计算 (rbp + 16) + (-28) = rbp - 12
  6. 结果类型为 DWARF_VALUE_MEMORY,GDB从该内存地址读取4字节得到变量值

6.6 行号信息解读

readelf --debug-dump=line example.o
  Offset:                      0x0  Length:                      65  DWARF Version:               3  Prologue Length:             32  Minimum Instruction Length:  1  Initial value of 'is_stmt':  1  Line Base:                   -5  Line Range:                  14  Opcode Base:                 13 The Directory Table is empty. The File Name Table (offset 0x1c):  Entry  Dir  Time  Size  Name  1      0    0     0     example.c Line Number Statements:  [0x2a]  Extended opcode 2: set Address to 0x0  [0x35]  Copy  [0x36]  Special opcode 146: advance Address by 10 to 0xa and Line by 1 to 2  [0x37]  Special opcode 160: advance Address by 11 to 0x15 and Line by 1 to 3  [0x38]  Special opcode 48: advance Address by 3 to 0x18 and Line by 1 to 4  [0x39]  Special opcode 35: advance Address by 2 to 0x1a and Line by 2 to 6  [0x3a]  Special opcode 118: advance Address by 8 to 0x22 and Line by 1 to 7  [0x3b]  Special opcode 104: advance Address by 7 to 0x29 and Line by 1 to 8  [0x3c]  Special opcode 104: advance Address by 7 to 0x30 and Line by 1 to 9  [0x3d]  Advance PC by constant 17 to 0x41  [0x3e]  Special opcode 20: advance Address by 1 to 0x42 and Line by 1 to 10  [0x3f]  Special opcode 48: advance Address by 3 to 0x45 and Line by 1 to 11  [0x40]  Advance PC by 2 to 0x47  [0x42]  Extended opcode 1: End of Sequence

GDB执行行号状态机后建立的地址-行号映射:

PC
源码行
源码内容
0x0
1
int add(int a, int b) {
0xa
2
int sum = a + b;
0x15
3
return sum;
0x18
4
}
0x1a
6
int main() {
0x22
7
int x = 10;
0x29
8
int y = 20;
0x30
9
int result = add(x, y);
0x42
10
return result;
0x45
11
}

当GDB收到当前PC值(如0x25),通过行号表查找:0x25落在[0x22, 0x29)区间,对应源码第7行 int x = 10;,这就是 list 命令能显示对应源码的原理。

6.7 CFI解读

readelf --debug-dump=frames example.o
00000000 0000000000000014 00000000 CIE  Version:               1  Augmentation:          "zR"  Code alignment factor: 1  Data alignment factor: -8  Return address column: 16  Augmentation data:     1b  DW_CFA_def_cfa: r7 (rsp) ofs 8  DW_CFA_offset: r16 (rip) at cfa-8  DW_CFA_nop  DW_CFA_nop00000018 000000000000001c 0000001c FDE cie=00000000 pc=0000000000000000..000000000000001a  DW_CFA_advance_loc: 1 to 0000000000000001  DW_CFA_def_cfa_offset: 16  DW_CFA_offset: r6 (rbp) at cfa-16  DW_CFA_advance_loc: 3 to 0000000000000004  DW_CFA_def_cfa_register: r6 (rbp)  DW_CFA_advance_loc: 21 to 0000000000000019  DW_CFA_def_cfa: r7 (rsp) ofs 8  DW_CFA_nop  DW_CFA_nop  DW_CFA_nop00000038 000000000000001c 0000003c FDE cie=00000000 pc=000000000000001a..0000000000000047  DW_CFA_advance_loc: 1 to 000000000000001b  DW_CFA_def_cfa_offset: 16  DW_CFA_offset: r6 (rbp) at cfa-16  DW_CFA_advance_loc: 3 to 000000000000001e  DW_CFA_def_cfa_register: r6 (rbp)  DW_CFA_advance_loc: 40 to 0000000000000046  DW_CFA_def_cfa: r7 (rsp) ofs 8  DW_CFA_nop  DW_CFA_nop  DW_CFA_nop

CIE解读: 增强字符串"zR"表示使用 .eh_frame 格式(DW_CFA_offset使用DW_ARC_offset64)。初始CFA = rsp + 8,返回地址(rip)保存在CFA-8处。

add函数FDE解读(pc=0x0~0x1a):

PC
指令
CFA
说明
0x0
(入口)
rsp + 8
从CIE继承
0x1
push rbp
rsp + 16
rsp减8,CFA偏移调整为16
0x4
mov rsp,rbp
rbp + 16
def_cfa_register改为rbp,偏移不变
0x19
(epilogue)
rsp + 8
还原为rsp+8,准备ret

关键点:序言完成后 CFA = rbp + 16,而非 rbp + 0。这是因为 def_cfa_register 只更换寄存器,不改变偏移量。push rbp使rsp减8,CFA从rsp+8变为rsp+16;mov rsp,rbp后,CFA = rbp + 16。

GDB回溯调用栈的过程(假设当前在add函数中,PC=0x10):

  1. 根据PC=0x10找到add的FDE,执行CFI指令,得出CFA = rbp + 16
  2. 返回地址:CFA-8处的值(即rbp+8处,存放call add时压入的返回地址)
  3. 旧rbp:CFA-16处的值(即rbp+0处,存放push rbp保存的旧rbp)
  4. 返回地址指向main中0x3f(call add之后),结合行号表定位到源码第9行
  5. 以旧rbp为新的CFA基址,继续回溯main的栈帧

6.8 完整调试流程串联

以 break main; run; print x; backtrace 为例,展示GDB内部如何利用DWARF2各节:

用户操作           GDB内部动作                              使用的DWARF节───────────────   ──────────────────────────────────────   ──────────────────break main        1. 查找符号"main"                         .debug_info (DW_TAG_subprogram)                  2. 获取 DW_AT_low_pc = 0x1a               .debug_info                  3. 在地址0x1a处设置断点run               (程序运行到断点,PC=0x1a)print x           1. 查找变量"x"                            .debug_info (DW_TAG_variable)                  2. 获取 DW_AT_location                    .debug_info                     = DW_OP_fbreg: -28                  3. 查找当前PC对应的frame_base             .debug_loc (offset 0x0)                     → CFA = rbp + 16                  4. 求值: (rbp+16) + (-28) = rbp-12        dwarf2expr.c (execute_stack_op)                  5. 读取内存rbp-12处的4字节                 → 10                  6. 输出: $1 = 10backtrace         1. 获取当前PC=0x1a,查找FDE               .eh_frame (FDE)                  2. 执行CFI指令,计算CFA = rbp+16                  3. 读取CFA-8得到返回地址(main中0x3f)                  4. 读取CFA-16得到旧rbp(main的rbp)                  5. 返回地址0x3f结合行号表                  .debug_line                     → example.c:9                  6. 继续回溯main的栈帧(无更多调用者)                  7. 输出:                     #0  add (a=10, b=20) at example.c:2                     #1  main () at example.c:9

整个流程中,DWARF2各节各司其职:

DWARF节
在调试中的作用
.debug_info
查找符号(函数名、变量名),获取地址范围和位置描述
.debug_abbrev
解码.debug_info中的DIE结构
.debug_line
PC地址到源码行号的映射
.debug_loc
提供fbref所需的帧基址位置列表(变量定位和CFI的关键桥梁)
.eh_frame
栈帧回溯(CFA计算、返回地址定位)
.debug_str
存储较长的字符串(文件名、编译器标识等)

附录A:DWARF2与DWARF3/4/5主要差异速查

特性
DWARF2
DWARF3
DWARF4
DWARF5
位置表达式结果
仅地址
+ DW_OP_stack_value
+ DW_OP_implicit_value
无重大变化
位置列表
.debug_loc
同左
同左
.debug_loclists
范围列表
-
.debug_ranges
同左
.debug_rnglists
类型单元
-
-
.debug_types
合并到 .debug_info
分割DWARF
-
-
实验性
正式支持 .dwo/.dwp
行号表格式
原始
同左
+ header_length修正
全新格式
CFI版本
1
1
4
无变化
字符串
string/strp
同左
同左
+ DW_FORM_line_strp

附录B:常用readelf/objdump命令

# 查看DWARF调试信息节readelf -S <elf_file> | grep debug# 查看DIE树readelf --debug-dump=info <elf_file># 查看缩写表readelf --debug-dump=abbrev <elf_file># 查看行号信息readelf --debug-dump=line <elf_file># 查看位置列表readelf --debug-dump=loc <elf_file># 查看CFI帧信息readelf --debug-dump=frames <elf_file># 查看地址范围readelf --debug-dump=aranges <elf_file># 查看字符串表readelf --debug-dump=str <elf_file># 使用objdump查看DWARF信息objdump --dwarf=info <elf_file>objdump --dwarf=frames <elf_file>

参考文献

  1. DWARF 2.0.0 Specification: https://dwarfstd.org/doc/dwarf-2.0.0.pdf

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-21 05:07:23 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/954095.html
  2. 运行时间 : 0.164135s [ 吞吐率:6.09req/s ] 内存消耗:4,901.55kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=48b89ead5a2e399a63cb5de70d069096
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 4.22 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 10.56 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.11 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000758s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001323s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000385s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000297s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000862s ]
  6. SELECT * FROM `set` [ RunTime:0.000295s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001108s ]
  8. SELECT * FROM `article` WHERE `id` = 954095 LIMIT 1 [ RunTime:0.000735s ]
  9. UPDATE `article` SET `lasttime` = 1787260043 WHERE `id` = 954095 [ RunTime:0.008067s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000250s ]
  11. SELECT * FROM `article` WHERE `id` < 954095 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000545s ]
  12. SELECT * FROM `article` WHERE `id` > 954095 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000391s ]
  13. SELECT * FROM `article` WHERE `id` < 954095 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.011361s ]
  14. SELECT * FROM `article` WHERE `id` < 954095 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.019729s ]
  15. SELECT * FROM `article` WHERE `id` < 954095 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.011039s ]
0.168179s