在c语言的代码中,变量都是需要指定变量的类型,要讲清楚变量类型是什么需要先讲清楚 程序与计算机硬件之间的关系。程序其实是数据结构
与算法
的组合,其中的数据结构主要是数据,数据对应到代码中就是各个变量(这里将变量常量等统一称作变量来看待),算法指的是程序中的判断逻辑和基本的数学计算,其实程序中的逻辑判断本质上也是计算(计算机中的计算其实是 布尔运算 其可以支持程序中的逻辑判断和数学计算)。
上一篇讲了 ptmalloc 在初始化的过程中做的一些准备工作 主要是内存的申请,这里主要是基于初始化的数据格式对内存进行分配、回收管理。重点是 各种 bin的使用,其如同缓存 减少程序频繁的内存申请操作 对内核的调用(毕竟需要且到内核态执行代码)。
阅读全文glibc中的malloc方法其实是映射到 __libc_malloc
的,其通过ASM的符号表的形式来实现
1 | strong_alias (__libc_malloc, __malloc) strong_alias (__libc_malloc, malloc) |
dbg 是一个调试工具,这里记录下他是如何实现对源代码的调试的。一般情况下,在IDE中配置好调试配置,然后在源代码中打断点就可以进行调试了。需要的配置是 1. 指定调试工具 2. 指定运行的可执行文件。那问题是,调试软件gdb
是如何将 可执行文件与源代码文件对应起来的呢?
gdb 原理
gcc编译器的过程是 源代码 -> 预处理代码 -> 汇编代码 -> 目标码
在这个过程中从目标码到源代码的对应关系是被记录下来的,通过gcc -g
参数会将这些对应关系记录下来。
我们在运行程序的时候,可以通过在源代码中指定的断点信息 (哪个文件的哪一行) ,通过编译过程产生的对应关系,找到可执行文件的执行处。
使用 gcc -g
编译的可执行文件 中会包含源代码信息,可以通过gdb读取到这些信息 以php为例进行演示如下
1 | >gdb |
下一步要做的就是干预可执行文件的执行过程了,这个就需要依赖gdb
来实现。gdb
的主要实现是通过系统函数 ptrace
对执行的进程进行侵入式的干预。
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data)
参数说明
类型 | 参数 | 作用 |
---|---|---|
enum __ptrace_request | request [PTRACE_TRACEME PTRACE_ATTACH PTRACE_DETACH] | 执行的动作 |
pid_t | pid | 要跟踪的进程id |
void * | addr | 要监控的内存地址 |
void * | data | 存放读写数据 |
gdb通过这个方法对执行的线程进行捕获,截获发送到被追踪程序信号。
gdb实现了两个形式的断点:
- 通过gdb 启动进程, gdb作为父进程对监控进程进行监控
- gdb通过
ptrace(PTRACE_ATTACH, 被监控程序的)
使自己成为被监控程序的父进程
mac上无法使用gdb的原因
在mac上使用gdb
的时候会报错
1 | Unable to find Mach task port for process-id xxxx: (os/kern) failure (0x5). |
这是由于 mac
系统的保护机制,禁止一个进程对另一个进程有强烈的干预操作,他推荐自己家的 lldb
来替代 gdb
。
要使用gdb
就要对其进行证书授权,方式请参照参考链接
遇到 During startup program terminated with signal SIG113, Real-time event xxx
这个错误的话,同样是系统的保护机制 需要关闭下 系统的 SIP 保护机制,配置如下
1 | #file .gdbinit |
vscode调试php内核代码
在调试php内核代码的时候 一直使用 CLion
进行,中间遇到很多问题,换 vscode
方便多了,调试c代码需要一个 插件 C/C++
就可以了。vscode
主要需要配置的地方是两个地方 一个是 task
的配置(配置文件 task.json
), 一个是 launch
的配置(配置文件 launch.json
),其中 task.json
跟代码的调试并无关,他相当于IDE提供的一个自定义命令 可以在IDE中执行自定义命令,跟调试相关的是 launch.json
这个文件
1 | { |
其中 “request” 可选的值有 launch
和 attach
launch
通过调试程序启动可执行程序,以父进程的形式对被跟踪程序进行监控
attach
这是通过将调试进程通过附加的形式,成为正在执行的进程的父进程来实现监听,所以这里是需要给出一个被监听进程的id的,配置应该增加
1 | { |
参考链接
GDB调试原理——ptrace系统调用
将源程序和汇编指令映射起来
MAC上使用gdb
VSCode Debugging
对于linux上大多数软件包的编译过程都是 configure
make
make install
三个步骤来完成,具体分析下这些过程。其中configure
是一个shell脚本,用来生成文件 Makefile
,这个文件是下一步make
过程需要用到的配置文件,用来生成源代码文件中的依赖关系,通过文件的修改时间来决定哪些文件有变动需要调用gcc
重新编译到目标文件并最终链接成二进制文件。make install
的过程主要是将编译完成的文件拷贝到指定的文件夹(或者安装目录),这个安装路径是通过 configure --prefix=[path]
来定义的 默认一般为 /usr/local/bin
。
gcc 是*unix
系统上常用的c代码编译器,编译器做的事情其实像是在翻译
,接下来简单介绍下gcc的简单实用方法