C++调试工具
GDB 适合用于调试代码逻辑错误和程序崩溃,二者结合使用可以大大提高错误排查效率
Valgrind 和 Memcheck 更适合用于检查程序的内存问题,如内存泄漏、非法内存访问等。
GFlags 是 VS 中自带的内存检查工具
gprof 是一个GNU项目中的性能分析工具,用于分析C和C++程序的函数调用图和每个函数的CPU使用时间
perf:这是Linux下的一个性能分析工具,可以收集CPU使用情况、缓存命中率、分支预测错误等多种性能数据。
在C++中进行代码覆盖率分析可以使用工具如gcov和lcov
Google Test 是由 Google 的测试技术团队开发的 C++ 测试框架,也被称为 gtest。
CppUnit是一个专门为C++设计的单元测试框架,它基于JUnit框架的概念,提供了类似的机制和工具,用于编写和运行C++的单元测试。
内存检查工具
valgrind 默认使用memcheck工具,就是默认参数—tools=memcheck
Memcheck 会监控程序的每一个内存访问
检测内存泄漏、越界访问等问题,从而防止程序崩溃
内存泄露(leak): 内存泄漏是指程序中分配的内存未能被释放
内存溢出(Memory Overflow) 请求分配的内存超过了系统所能提供的内存大小或者进程所能使用的内存大小
漏报告分为4类:
definitely lost: 明确泄漏,程序失去了对该内存块的引用。
indirectly lost: 间接泄漏,某些泄漏的内存块引用了这些内存块。
possibly lost : 可能泄漏,程序可能丢失了对内存块的引用,或者这块内存还在使用但未释放。
still reachable: 程序退出时仍然可达,但未释放的内存块。
堆栈跟踪
in use at exit:
total heap usage:
使用 file 解决类型问题
使用 ldd 探索依赖性
使用 readelf 解析并提取ELF库文件 查看 ELF头部 (elf_header)的详细信息
使用 dd 命令用于读取、转换并输出数据’
使用 nm -D 选项要求nm解析动态符号表
使用 strings 来查看二进制文件中的字符串,包括Linux操作系统上的任何其他文件 strings只输出4个或者4个字符以上的字
使用 strace和ltrace 跟踪系统调用和库文件调用
使用 objdump 检查指令集行为 objdump -a
使用 GDB 转储动态字符串缓冲区
strace
valgrind
十六进制转储工具 xxd
内存检测原理
内存的检测原理。一般情况下,常规关注的内存问题有:内存泄露、内存越界、双重释放、野指针访问。
内存检测,一般是配合Hook API技术完成的,所谓Hook API,本质就是交换函数地址,
内存检测的本质,核心就在于对 malloc 和 free 函数的监听处理,做了一些额外的工作完成的
new和delete的底层也是通过调用 malloc/free 函数完成的
内存越界:所谓内存越界,就是对内存的读写访问,超出了它的分配范围
1. 内存栈区: 存放局部变量名;
2. 内存堆区: 存放new或者malloc出来的对象;
3. 常数区: 存放局部变量或者全局变量的值;
4. 静态区: 用于存放全局变量或者静态变量;
5. 代码区:二进制代码。
data又可分为读写(RW)区域和只读(RO)区域
栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等
堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事
block 由一系列大小相等的内存块组成。分配内存时先在block中分配,如果block占满则从heap区中分配
一个程序被加载到内存中,这块内存首先就存在两种属性:静态分配内存和动态分配内存。
静态分配内存:是在程序编译和链接时就确定好的内存。
动态分配内存:是在程序加载、调入、执行的时候分配/回收的内存。
C++编译器提出了符号修饰(mangled name)。
符号修饰实质上是原始函数名称与函数参数编码的组合。这样,函数的每个版本都会获得唯一的名称,并且链接器也不会对重载的函数产生歧义
C++编程
代码覆盖率就是测试过程中已经被执行过的代码占准备测试总代码量的比例和程度
单元测试(Unit Testing)是一种编程方法,用于验证代码中的最小可测试单元(通常是函数、方法或模块)是否按照预期工作。
vDSO 全称为 virtual dynamic shared object
linux-vdso.so.1 不是一个实实在在的文件
vsyscall
vdso 是vsyscall的主要替代方案,全称是Virtual Dynamic Shared Object. 这是一个虚拟动态链接库
用户空间和内核空间之间,有一个叫做Syscall(系统调用, system call)的中间层,是连接用户态和内核态的桥梁
/proc/self/maps
不同的进程访问该目录时获得的信息是不同的 内容等价于/proc/本进程pid/
proc/self/目录来获取自己的系统信息,而不用每次都获取pid
通过实践来培养编程技能
libstdc++是Linux系统中常用的两个库文件 ibstdc++ gcc
libc是Linux下原来的标准C库,后来 glibc eglibc的主要特性是为了更好的支持嵌入式架构
C语言标准库(glibc)、数学库(libm)、线程库(libpthread)、动态链接库(ld.so)等
linux
: a.out(assembler and link editor output 汇编器和链接编辑器的输出)、
COFF (Common Object File Format 通用对象文件格式)、
ELF (Executable and Linking Format 可执行和链接格式)
为段 (Segment)或节(Section) 并调用函数 mmap()把段内容加载到内存中
:编译(compile)、连接(link,也可称为链接、联接)、加载(load)
ELF 文件有三种类型:
可重定位文件:也就是通常称的目标文件,后缀为.o。
共享文件:也就是通常称的库文件,后缀为.so。
可执行文件:本文主要讨论的文件格 式
Core dump(core),运行过程中崩溃时自动生成,用于调试
file :
某个文件的基本类型,例如究竟文件时属于 ASCII 或者是 data 文件,或者是 binary 类型,
且其中有没有使用到 共享库(share library) 等等的信息,就可以利用 file 这个命令来查看。
第一个最后显示的是 stripped 第二个是 not stripped 。而且对于同样名字的动态库
elf格式中符号表的内容会比a.out格式的丰富的多。
但是这些符号表可以用 strip工具去除,这样的话这个文件就无法让debug程序跟踪了,但是会生成比较小的可执行文件
strip命令是一个强大且实用的工具,主要用于去除可执行文件、共享库文件(.so文件)以及目标文件(.o文件)中的符号表和调试信息
直接用于二进制文件的处
共享库(so(shared object)) 动态链接库(SHARED LIBRARIES)
readelf -h pie_binary | grep Type:
ELF 64-bit LSB shared object
ELF 64-bit LSB executable,
.so(Shared Object)文
注:“LSB executable”(ET_EXEC)和"LSB shared object"(ET_DYN)的区别是什么?
在Linux内核/动态加载程序中
ET_EXEC与ET_DYN的主要作用是
通知可执行文件是否可以通过ASLR放置在随机存储器中。
GCC在编译时,默认会增加-pie选项,使得生成的ELF是ET_DYN的。
PIE可执行文件是DYN的,它们可以被地址随机化,就像共享库so一样。
可执行文件可共享
LSB shared object可以执行的原因主要是因为它利用了Linux系统的动态链接机制和ELF格式的灵活性,
使得共享库文件既可以在编译时被链接为可执行文件,
也可以在运行时被动态链接器加载和执行
对于.a文件,用file命令查看,只能.a: current ar archive
------解决方案--------------------------------------------------------
objdump -a xx.a
# 生成共享库
add_library(mylib SHARED ${SOURCES})
add_library(libhello SHARED hello.c) #生成动态库文件
add_library(libhello STATIC hello.c) #生成静态库文件
target_link_libraries 命令为目标指定依赖库,在本例中 hello.c 被编译为库文件,并将其链接进 hello 程 序。
使用 file 解决类型问题
使用 ldd 探索依赖性
使用 readelf 解析并提取ELF库文件 查看 ELF头部 (elf_header)的详细信息
使用 dd 命令用于读取、转换并输出数据’
使用 nm -D 选项要求nm解析动态符号表
使用 strings 来查看二进制文件中的字符串,包括Linux操作系统上的任何其他文件 strings只输出4个或者4个字符以上的字
使用 strace和ltrace 跟踪系统调用和库文件调用
使用 objdump 检查指令集行为 objdump -a
使用 GDB 转储动态字符串缓冲区
strace
valgrind
可执行文件外,
动态链接库(DDL,Dynamic Linking Library)、静态链接库(Static Linking Library) 均采用可执行文件格式存储。
它们在Window下均按照PE-COFF格式存储;
Linux下均按照ELF格式存储。只是文件名后缀不同而已。
动态链接库:Windows的.dll、Linux的.so
静态链接库:Windows的.lib、Linux的.a
可重定位文件(Relocatable File):ETL_REL。一般为.o文件。可以被链接成可执行文件或共享目标文件。静态链接库属于可重定位文件。
可执行文件(Executable File):ET_EXEC。可以直接执行的程序。
共享目标文件(Shared Object File):ET_DYN。一般为.so文件。有两种情况可以使用
链接器将其与其他可重定位文件、共享目标文件链接成新的目标文件;
动态链接器将其与其他共享目标文件、结合一个可执行文件,创建进程映像。
参考
https://www.cnblogs.com/lqerio/p/12110482.html
成为一名二进制分析师需要用到的Linux二进制分析工具有哪些? https://zhuanlan.zhihu.com/p/429283972
标签:可执行文件,文件,二进制,使用,ELF,C++,内存,Linux
From: https://www.cnblogs.com/ytwang/p/18577215