发布于: 2024-4-28最后更新: 2024-5-20字数 00 分钟

type
status
date
slug
summary
tags
category
icon
password

1 Introduction

  • Understanding the overall process by which most major systems and infrastructure software is built and executed today
    • how symbols in high-level languages are resolved to addresses and constants in machine code
    • the coordination of linker and loader, particularly in systems exploiting virtual address spaces
    • how linkers allocate space for variables and functions, including the role of symbol tables
  • Become proficient as a software engineer at the intermediate level in the C language when separate compilation is used for medium and large programs
    • separate compilation and the role of header files in creating modular code
    • common mistakes
    • best practices when declaring and defining functions and variables
    • the role and purpose of static libraries
    • the role and purpose of dynamic libraries
    • the purpose of whole program link-time optimization
    • the implications of virtual address space layout for debugging program faults
    • how to use common tools such as nm, objdump, etc

2 Compiler and Assembler

  • Preprocessor performs textual insertion of include files
  • Compiler resolves the following symbolic names:
    • Local automatic variables, function parameters
    • Field names in structures
  • Assembler resolves certain labels for relative branches
  • The resulting relocatable .o file still retains symbolic names for all functions and variables that are global in extent
 

2.1 Relocatable Object Files — Text Section

  • Contain multiple sections
  • Each section is laid out starting as if starting at 0
  • Contains relocation records: placeholders and meta information about how to patch them up once actual addresses are known
 

2.2 Executable and Linkable Format(ELF)

  • ELF is a standard format for relocatable object files, executables, and shared objects(dynamic libraries) used in System V and derived systems, include Linux
  • Other formats include Mach-O(OSX), PE(Windows), a.out
  • Provides the link between compiler → Linker → loader
  • Carries all information needed by the next tool; also debugging and exception handling information
  • Extensive tool support
  • Details in /usr/include/elf.h
readelf -a main.o
readelf -a main

2.2.1 ELF Header

ELF文件中的ELF Header是文件的开始部分,它包含了关于二进制文件的全局信息,例如文件类型、架构、入口点等。让我们一起看一下它的字段及其含义:
字段
说明
e_ident
This is a array, Details will show below
e_type
0(No file type) 1(Relocatable file) 2(Executable file) 3(Shared object file) 4(Core file) 5(Number of defined types) 0xfe00(OS-specific range start) 0xfeff(OS-specific range end) 0xff00(Processor-specific range start) 0xffff(Processor-specific range end)
e_machine
See /usr/include/elf.h for details
e_version
0(Invalid ELF version) 1(Current version)
e_entry
Entry point virtual address
e_phoff
Program header table file offset
e_shoff
Section header table file offset
e_flags
这个字段包含了一些处理器特定的标志。对于一些特定类型的处理器,这些标志可能会影响或者改变代码的执行
e_ehsize
这个字段表示ELF头部(ELF Header)的大小
e_phentsize
这个字段表示程序头表中的一个条目的大小
e_phnum
这个字段表示程序头表中的条目数量
e_shentsize
这个字段表示节头表中的一个条目的大小
e_shnum
这个字段表示节头表中的条目数量
e_shstrndx
这个字段包含了节头字符串表(Section Header String Table)的节头表索引。这些字段组合在一起描述了ELF文件的结构和定位文件中的关键设计元素
e_ident
struct member
index
meaning
EI_MAG0
0-3
File identification —— 7f 45 4c 46 mean “ELF”
EI_CLASS
4
File class 1(32-bit objects) 2(64-bit objects)
EI_DATA
5
Data encoding 0(Invalid data encoding) 1(2's complement, little endian) 2(2's complement, big endian)
EI_VERSION
6
File version —— Value must be EV_CURRENT
EI_OSABI
7
OS ABI 0(UNIX System V ABI) 1(HP-UX) 2(NetBSD) 3(Object uses GNU/LINUX ELF extensions) 6(Sun Solaris) 7(IBM AIX) 8(SGI Irix) 9(FreeBSD) 10(Compaq TRU64 UNIX) 11(Novell Modesto) 12(OpenBSD) 64(ARM EABI) 97(ARM) 255(Standalone (embedded) application)
EI_ABIVERSION
8
ABI Version
EI_PAD
9-15
Padding bytes
Field
Meaning
e_ident
Magic,Class, Data, Version,OS/ABI, ABI Version
e_type
Type
e_machine
Machine
e_version
Version
e_entry
Entry point address
e_phoff
Start of program headers
e_shoff
Start of section headers
e_flags
Flags
e_ehsize
Size of this header
e_phentsize
Size of program headers
e_phnum
Number of program headers
e_shentsize
Size of section headers
e_shnum
Number of section headers
e_shstrndx
Section header string table index

2.2.2 Program Header Table

紧随 ELF Header 之后的是 Program Header Table,包含了多个 Program Header,每个 Program Header 描述了一个段的信息,这些段用于进程映射。

2.2.3 Sections

在 ELF 文件中,Sections 是实际的数据或代码块。典型的 Sections 包括 .text(代码段)、.data(数据段)、.bss(未初始化数据段)、.rodata(只读数据段)、.symtab(符号表)、.strtab(字符串表)等。

2.2.4 Section Header Table

Section Header Table 位于 ELF 文件的末尾或其他位置,它描述了各个 Section 的具体信息,例如大小、位置、类型等。

2.2.5 完整的 ELF 文件结构

下面是将所有部分结合在一起的完整示意图:
以上通过文字描述和分阶段的Mermaid示意图展示了ELF文件的结构,每个部分的具体作用和位置都清晰展示出来。
ELF header
Program header table(required for EXE)
.text section
.data section
.bss section
.symtab
.rel.text
.rel.data
.debug
Section header table(required for relocatables)
ELF文件中的.symtab部分是符号表,它存储着程序中定义或引用的符号的信息,每一个符号都对应着符号表中的一个条目。每个条目都包含以下字段:
字段
说明
st_name
这是符号名的索引,指向字符串表(`.strtab` 部分)中的一个位置,那个位置保存了此符号的名称
st_value
这个字段的意义视符号的类型和关联性而定。对于函数符号,它是函数的入口地址。对于全局变量或静态变量,它是变量的地址
st_size
这个字段指示符号的大小。对于函数符号,它是函数代码的大小。对于变量符号,它是变量的大小
st_info
这个字段包含符号的类型和绑定(关联性)信息。例如,符号可以是一个函数、一个对象(如全局变量)等。符号的绑定可以是局部的(不可以被其他对象文件访问),全局的(可以被其他对象文件访问),或者是弱的(如果其他对象文件定义了同名的全局符号,那么这个弱符号就不起作用)
st_other
这个字段在标准ELF文件中未定义,通常不使用
st_shndx
这个字段包含了一个节头表索引,指出符号定义在哪个段或节。例如,函数符号通常在.text段内,全局变量和静态变量通常在.data或.bss段内
以上就是.symtab符号表中每一项的各个字段的含义。在一些处理或者解析ELF文件的工具中,你可以直接看到这些字段的值,从而得知程序中函数或变量的相关信息。
 

GDB

Start

Command
Meaning
gdb object
Normal start, load executable file
gdb object core
Debug for executable + core file
gdb object pid
Debug for running process
gdb
Normal start, need manual loading file
gdb -tui
Start gdb text ui (exchange CLI/TUI by ctrl-x ctrl-a)

Help

Command
Meaning
help
List command categories
help running
View help information for a category
help run
View run help
help info
List the commands related to viewing the running status of the program
help info line
List help for a specific running status command
help show
List GDB status related commands
help show commands
List help for show command

Breakpoints

Command
Meaning
break main
对函数 main 设置一个断点,可简写为 b main
break 101
对源代码的行号设置断点,可简写为 b 101
break basic.c:101
对源代码和行号设置断点
break basic.c:foo
对源代码和函数名设置断点
break *0x00400448
对内存地址 0x00400448 设置断点
info breakpoints
列出当前的所有断点信息,可简写为 info break
delete 1
按编号删除一个断点
delete
删除所有断点
clear
删除在当前行的断点
clear function
删除函数断点
clear line
删除行号断点
clear basic.c:101
删除文件名和行号的断点
clear basic.c:main
删除文件名和函数名的断点
clear *0x00400448
删除内存地址的断点
disable 2
禁用某断点,但是部删除
enable 2
允许某个之前被禁用的断点,让它生效
rbreak {regexpr}
匹配正则的函数前断点,如 ex_* 将断点 ex_ 开头的函数
tbreak function/line
临时断点
hbreak function/line
硬件断点
ignore {id} {count}
忽略某断点 N-1 次
condition {id} {expr}
条件断点,只有在条件生效时才发生
condition 2 i == 20
2号断点只有在 i == 20 条件为真时才生效
watch {expr}
对变量设置监视点
info watchpoints
显示所有观察点
catch exec
断点在exec事件,即子进程的入口地址

Run program

Command
Meaning
run
运行程序
run {args}
以某参数运行程序
run < file
以某文件为标准输入运行程序
run < <(cmd)
以某命令的输出作为标准输入运行程序
run <<< $(cmd)
以某命令的输出作为标准输入运行程序
set args {args} ...
设置运行的参数
show args
显示当前的运行参数
cont
继续运行,可简写为 c
step
单步进入,碰到函数会进去
step {count}
单步多少次
next
单步跳过,碰到函数不会进入
next {count}
单步多少次
CTRL+C
发送 SIGINT 信号,中止当前运行的程序
attach {process-id}
链接上当前正在运行的进程,开始调试
detach
断开进程链接
finish
结束当前函数的运行
until
持续执行直到代码行号大于当前行号(跳出循环)
until {line}
持续执行直到执行到某行
kill
杀死当前运行的函数

Stack frame

Command
Meaning
bt
print backtrace
frame
print current running stack frame
up
向上移动栈帧(向着 main 函数)
down
向下移动栈帧(远离 main 函数)
info locals
打印帧内的相关变量
info args
打印函数的参数

Code viewing

Command
Meaning
list 101
显示第 101 行周围 10行代码
list 1,10
显示 1 到 10 行代码
list main
显示函数周围代码
list basic.c:main
显示另外一个源代码文件的函数周围代码
list -
重复之前 10 行代码
list *0x22e4
显示特定地址的代码
cd dir
切换当前目录
pwd
显示当前目录
search {regexpr}
向前进行正则搜索
reverse-search {regexp}
向后进行正则搜索
dir {dirname}
增加源代码搜索路径
dir
复位源代码搜索路径(清空)
show directories
显示源代码路径

Data viewing

Command
Meaning
print {expression}
打印表达式,并且增加到打印历史
print /x {expression}
十六进制输出,print 可以简写为 p
print array[i]@count
打印数组范围
print $
打印之前的变量
print *$->next
打印 list
print $1
输出打印历史里第一条
print ::gx
将变量可视范围(scope)设置为全局
print 'basic.c'::gx
打印某源代码里的全局变量,(gdb 4.6)
print /x &main
打印函数地址
x *0x11223344
显示给定地址的内存数据
x /nfu {address}
打印内存数据,n是多少个,f是格式,u是单位大小
x /10xb *0x11223344
按十六进制打印内存地址 0x11223344 处的十个字节
x/x &gx
按十六进制打印变量 gx,x和斜杆后参数可以连写
x/4wx &main
按十六进制打印位于 main 函数开头的四个 long
x/gf &gd1
打印 double 类型
help x
查看关于 x 命令的帮助
info locals
打印本地局部变量
info functions {regexp}
打印函数名称
info variables {regexp}
打印全局变量名称
ptype name
查看类型定义,比如 ptype FILE,查看 FILE 结构体定义
whatis {expression}
查看表达式的类型
set var = {expression}
变量赋值
display {expression}
在单步指令后查看某表达式的值
undisplay
删除单步后对某些值的监控
info display
显示监视的表达式
show values
查看记录到打印历史中的变量的值 (gdb 4.0)
info history
查看打印历史的帮助 (gdb 3.5)

File operations

Command
Meaning
file {object}
加载新的可执行文件供调试
file
放弃可执行和符号表信息
symbol-file {object}
仅加载符号表
exec-file {object}
指定用于调试的可执行文件(非符号表)
core-file {core}
加载 core 用于分析

Signal control

Command
Meaning
info signals
打印信号设置
handle {signo} {actions}
设置信号的调试行为
handle INT print
信号发生时打印信息
handle INT noprint
信号发生时不打印信息
handle INT stop
信号发生时中止被调试程序
handle INT nostop
信号发生时不中止被调试程序
handle INT pass
调试器接获信号,不让程序知道
handle INT nopass
调试起不接获信号
signal signo
继续并将信号转移给程序
signal 0
继续但不把信号给程序

Thread debug

Command
Meaning
info threads
查看当前线程和 id
thread {id}
切换当前调试线程为指定 id 的线程
break {line} thread all
所有线程在指定行号处设置断点
thread apply {id..} cmd
指定多个线程共同执行 gdb 命令
thread apply all cmd
所有线程共同执行 gdb 命令
set schedule-locking ?
调试一个线程时,其他线程是否执行
set non-stop on/off
调试一个线程时,其他线程是否运行
set pagination on/off
调试一个线程时,分页是否停止
set target-async on/off
同步或者异步调试,是否等待线程中止的信息

Process debug

Command
Meaning
info inferiors
查看当前进程和 id
inferior {id}
切换某个进程
kill inferior {id...}
杀死某个进程
set detach-on-fork on/off
设置当进程调用fork时gdb是否同时调试父子进程
set follow-fork-mode parent/child
设置当进程调用fork时是否进入子进程

Assembly debug

Command
Meaning
info registers
打印普通寄存器
info all-registers
打印所有寄存器
print/x $pc
打印单个寄存器
stepi
指令级别单步进入
nexti
指令级别单步跳过
display/i $pc
监控寄存器(每条单步完以后会自动打印值)
x/x &gx
十六进制打印变量
info line 22
打印行号为 22 的内存地址信息
info line *0x2c4e
打印给定内存地址对应的源代码和行号信息
disassemble {addr}
对地址进行反汇编,比如 disassemble 0x2c4e

Others

Command
Meaning
show commands
显示历史命令 (gdb 4.0)
info editing
显示历史命令 (gdb 3.5)
ESC-CTRL-J
切换到 Vi 命令行编辑模式
set history expansion on
允许类 c-shell 的历史
break class::member
在类成员处设置断点
list class:member
显示类成员代码
ptype class
查看类包含的成员
print *this
查看 this 指针
define command ... end
定义用户命令
<return>
直接按回车执行上一条指令
shell {command} [args]
执行 shell 命令
source {file}
从文件加载 gdb 命令
quit
退出 gdb
 

公告
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎体验 ChatGPT Next 🎉