动态加载过程与 PLT、GOT 表

(TODO 补充关于编译时重定位、运行时重定位、PLT/GOT 表的背景知识) 本文将展示动态加载的过程,相关函数的地址如何在运行时被重定位,以及 PLT/GOT 表在其中的发挥的作用。以下面这段代码为例: 1#include <stdio.h> 2 3int main() 4{ 5 printf("Hey man!\n"); 6 return 0; 7} 编译 之前着实没想到,为了更好地展现 PLT/GOT 的过程,要在编译这块做这么多额外工作。 首先要添加 -fno-pie 和 -no-pie 两个选项,否则 GOT 里的函数地址会在 main() 执行前就被调整好,原本的过程就体现不出来了。这是从这 …

Linux 内核问题调试手段——QEMU 专题

VM 启动后没有输出?莫慌~ 一般而言,在运行 qemu-system-xxx 启动虚拟机后,我们希望在主机的当前终端上看到内核的启动日志,并在虚拟机启动后用该终端直接操作虚拟机。然而有时,当前终端在运行了 qemu-system-xxx 后却毫无动静。此时,在确认内核可以正常启动的前提下,要去确认几件事情: 当前终端对 QEMU 虚拟机而言是什么设备; 当前内核使用的 /dev/console 指向了哪个设备。 先找到一个可用的虚拟机终端(比如通过 VNC 连接的方式),然后向 /dev/{console,tty{,S}{0,1,...}} 等物理终端设备文件逐个尝试输入一些内容,看看哪个文件能让主机的当前终端有输出1。确定了是哪 …

ELF 调试器示例代码

这份调试器的示例代码来自《Learning Linux Binary Analysis》 书中第三章的“A simple ptrace-based debugger”一节,添加了一些调试打印和关于代码细节的注释。其他相关内容可查阅此书。 1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <unistd.h> 5#include <fcntl.h> 6#include <errno.h> 7#include <signal.h> 8#include …

用 GDB 调试动态链接库

前言 写本文的目的是为了记录一个【基于 GDB 对动态链接库(DSO1)的错误进行调试】的过程,重要的内容包括: 获取进程发生错误时的状态; 查看进程在该状态下的内存分布; 在 GDB 中用正确地址加载符号表,以恢复函数调用堆栈。 本文主要参考了 Ubuntu Wiki 上的这篇博文 。按照其版权及许可证要求,本文采用 Creative Commons Attribution-ShareAlike 3.0 进行许可。 Hybris 简介 Libhybris 是一种关于 libc 库兼容问题的解决方案,让我们在基于 GNU C Library (Glibc)的系统上2可以运行用 Bionic 编译的库(主要是 Android …