实际上,Linux的调试方法非常多,针对不同的问题,不同的场景,不同的应用,都有不同的方法。很难去概括。本篇文章主要涉及本专栏还没有涵盖,但是的确有很重要的方法。本文主要包括动态库注入调试;使用ltrace命令处理动态库的调试;使用strace调试系统调用的问题;Valgrind的简要介绍。

1. 动态库注入

如何排除其他library的调用问题?动态库注入(library injection)有可能会让你事半功倍。

一个大型的软件系统,会用到非常多的动态库。那么如果该动态库的一个api调用出了问题,而调用该api的地方非常非常多,不同的调用都分散的记录在不同的log里。那么,如何快速的找到是哪个调用者出的问题? 当然我们可以通过动态库注入的方式去调试。

下面的代码hook了两个常见的函数memcpy和socket:

void _init(void)
{
mtrace();
printf("HOOKing: hello\n");
} void _fini(void)
{
printf("HOOKing: goodbye\n");
} typedef void* (*real_memcpy)(void*, const void*, size_t);
void *memcpy( void *dest, const void*src, size_t size)
{
real_memcpy real = dlsym((void*)-1, "memcpy");
printf("Coping from %p to %p, size %d\n", src,dest,size); return real(dest, src, size);
}
typedef int (*real_socket)(int socket_family, int socket_type, int protocol); int socket(int socket_family, int socket_type, int protocol)
{
printf(" SOCKET family %d, SOCKET type %d, SOECKT protocol %d", socket_family, socket_type, protocol); real_socket sock = dlsym((void*)-1, "socket"); return sock(socket_family, socket_type, protocol );
}

将上述代码编译成动态库后,需要指定环境变量LD_PRELOAD为上述动态库。它的作用是强制load指定的动态库,即使不需要它。你可以在上面的动态库里添加你想要的任何函数。

2. ltrace

ltrace能够跟踪进程的库函数调用,它会显现出哪个库函数被调用。

还是使用hello,world进行简单的了解吧:

#include <stdio.h>
int main ()
{
printf("Hello world!\n");
return 0;
}

使用ltrace + 命令可以启动对任何程序的调试,上述hello world的ltrace为:

__libc_start_main(0x8048354, 1, 0xbf869aa4, 0x8048390, 0x8048380 <unfinished ...>
puts("Hello world!"Hello world!
) = 13
+++ exited (status 0) +++

其实ltrace是一个不用去阅读库的实现代码,而去学习库的整体调用栈的很好的方式。当然了结合代码你可以得到更加详细的实现。

3. strace

strace会跟踪程序系统调用。所以如果是由于程序的系统调用出问题的话,使用strace可以很快的进行问题定位。上述hello world的strace输出为:

execve("./hello", ["./hello"], [/* 30 vars */]) = 0
brk(0) = 0x83d4000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f8a000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=80846, ...}) = 0
mmap2(NULL, 80846, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f76000
close(3) = 0
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000?\270"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1576952, ...}) = 0
mmap2(0xb6e000, 1295780, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6e000
mmap2(0xca5000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x137) = 0xca5000
mmap2(0xca8000, 9636, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xca8000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f75000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7f756c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xca5000, 8192, PROT_READ) = 0
mprotect(0xb6a000, 4096, PROT_READ) = 0
munmap(0xb7f76000, 80846) = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f89000
write(1, "Hello world!\n", 13Hello world!
) = 13
exit_group(0) = ?
Process 2874 detached

可以看到strace的输出非常丰富。

4. Valgrind

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。

Valgrind包括如下一些工具:

  1. Memcheck。这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。这也是本文将重点介绍的部分。
  2. Callgrind。它主要用来检查程序中函数调用过程中出现的问题。
  3. Cachegrind。它主要用来检查程序中缓存使用出现的问题。
  4. Helgrind。它主要用来检查多线程程序中出现的竞争问题。
  5. Massif。它主要用来检查程序中堆栈使用中出现的问题。
  6. Extension。可以利用core提供的功能,自己编写特定的内存调试工具。

IBM Developer有一篇很好的文章:https://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/

Linux Debugging(六): 动态库注入、ltrace、strace、Valgrind的更多相关文章

  1. linux静态与动态库创建及使用实例

    一,gcc基础语法: 基本语法结构:(由以下四部分组成) gcc -o 可执行文件名 依赖文件集(*.c/*.o) 依赖库文件及其头文件集(由-I或-L与-l指明) gcc 依赖文件集(*.c/*.o ...

  2. linux下so动态库一些不为人知的秘密

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.    基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些 ...

  3. linux下so动态库一些不为人知的秘密(上)

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.        基本上每一个linux 程序都至少会有一个动态库,查看某个程序使 ...

  4. Linux中的动态库和静态库(.a/.la/.so/.o)

    Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序编译的过程 .o文件(目标文件) 创建atoi.o 使用atoi. ...

  5. Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf 动态库的后缀为*.so 静态库的后缀为 libxxx.a ldconfig 目录名

    Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf  动态库的后缀为*.so  静态库的后缀为 libxxx.a   ldconfig   目录名 转载自:http://b ...

  6. 【转】分析Linux和windows动态库

    原文地址:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Lin ...

  7. linux下so动态库一些不为人知的秘密(转)

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些动态库, ...

  8. Linux和windows动态库

    转载:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 态链接库技术实现和设计程序常用的技术,在Windows和Linux系 统中 ...

  9. linux下so动态库一些不为人知的秘密(中二)

    继续上一篇< linux下so动态库一些不为人知的秘密(中) >介绍so搜索路径,还有一个类似于-path,叫LD_RUN_PATH环境变量, 它也是把路径编译进可执行文件内,不同的是它只 ...

随机推荐

  1. 字符串的最长回文串:Manacher’s Algorithm

    题目链接:Longest Palindromic Substring 1. 问题描述 Given a string S, find the longest palindromic substring ...

  2. ios html5 audio 不能自动播放

    //修复ios 浏览器不能自动播放音频的问题 在加载时创建新的audio 用的时候更换src即可 Xut.fix = Xut.fix||{}; if (Xut.plat.isBrowser & ...

  3. Windows转Linux总结(附带常用Linux命令-LinuxMint)

    这是我在Linux系统下写的第一篇博客,花了一周的时间从Windows系统转到Linux并且可以完成日常操作,能在Linux系统下完成开发,运用各种开发工具,写各种语言小程序和JavaEE. 经过这一 ...

  4. eclipse安装和配置Gradle插件

    配置: 首先下载Gradle:https://gradle.org/gradle-download/ 设置Gradle环境变量: GRADLE_HOME %GRADLE_HOME%\bin" ...

  5. C++笔记007:易犯错误模型——类中为什么需要成员函数

    先看源码,在VS2010环境下无法编译通过,在VS2013环境下可以编译通过,并且可以运行,只是运行结果并不是我们期待的结果. 最初通过MyCircle类定义对象c1时,为对象分配内存空间,r没有初始 ...

  6. JDBC:从原理到应用

    一.是为何物 1.概念 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用J ...

  7. jQuery 效果 – 动画

    在使用jQuery动画时,你可能想要实现更加丰富的效果,那么你可以通过使用 jQuery animate() 方法自定义动画来达到目的,具体的使用方法如下文所述. jQuery animate() 方 ...

  8. 存出和载入Docker镜像

    存出镜像 如果要导出镜像到本地文件,可以使用 docker save 命令. $ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL ...

  9. ngx.ctx

    https://github.com/openresty/lua-nginx-module#ngxctx 要点 生命周期和请求一致 每个请求的ngx.ctx是相互独立的,包括ngx.location. ...

  10. VirtualBox: Resize a Fedora, CentOS, or Windows Dynamic Guest Virtual Disk (VDI) in VirtualBox

    Here's the scenario: you've set up Dynamically Allocated Storage for the hard drive on your Guest VM ...