在上一篇文章中讲到了ptrace,那么我们完全可以用ptrace来写一个非常简单的trace工具,用以trace程序的具体运行过程。

用它可以很清楚的回答,使用glibc编译后的hello world是从什么地方开始运行的。

(注:本文内容根据“A really simple tracing debugger"翻译而来,具体链接见参考资料一节)

itrace.c

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h> #include <sys/user.h>
#include <sys/ptrace.h> int main(int argc, char **argv)
{
int pid = fork();
if(pid == ) {
if(ptrace(PTRACE_TRACEME) < ) {
perror("ptrace");
_exit();
}
execvp(argv[], argv + );
perror("exec");
_exit();
}
while() {
int status;
struct user_regs_struct regs;
if(waitpid(pid, &status, ) < )
perror("waitpid");
if(!WIFSTOPPED(status))
break;
if(ptrace(PTRACE_GETREGS, pid, , &regs) < )
perror("ptrace/GETREGS");
printf("%lx %lx\n", regs.eip, regs.esp);
if(ptrace(PTRACE_SINGLESTEP, pid, , ) < )
perror("ptrace/SINGLESTEP");
}
return ;
}

编译

gcc -m32 itrace.c -o itrace

译者注: -m32表示编译成32位格式,如果是在64位机器上,不需要加此选项,同时将itrace.c源码中的eip和esp转换为rip,rsp.

hellow.c

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

编译

gcc -static -o hellow hellow.c

译者注: itrace保持一致,itrace如果是按32位格式来编译的,此处也应该一样。

测试运行

./itrace ./hellow | addr2line -e ./hellow -f | grep -v "??\|:?" | uniq

说明如下

addr2line 是将地址转换为相应的源码

运行的结果很长,所以就不打算没有贴出来了。

treeify

为了让运行结果在显示的时候能够更好的反映出调用关系,根据堆栈(%esp)中的信息采用python脚本将其层次化的打印出来。

import subprocess
import sys def read():
for line in sys.stdin:
try:
regs = [int(x, 16) for x in line.split(" ")]
yield {"eip": regs[0], "esp": regs[1]}
# Ignore lines interspersed with other output!
except (ValueError, IndexError):
pass def addr2line(iterable):
proc = subprocess.Popen(["addr2line", "-e", sys.argv[1], "-f"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for regs in iterable:
proc.stdin.write("%x\n" % regs["eip"])
a = proc.stdout.readline().rstrip("\n")
b = proc.stdout.readline().rstrip("\n")
regs["func"] = "%s %s" % (a, b)
yield regs def entry_points(iterable):
funcs = {}
# We treat the first address we see for the function as its entry
# point, and only report those entries from this point on.
for regs in iterable:
func = regs["func"].split(":")[0]
if funcs.setdefault(func, regs["eip"]) == regs["eip"]:
yield regs def add_nesting(iterable):
stack = [2 ** 64]
for regs in iterable:
stack_pos = regs["esp"]
if stack_pos < stack[-1]:
stack.append(stack_pos)
while stack_pos > stack[-1]:
stack.pop()
regs["indent"] = " " * len(stack)
yield regs for x in add_nesting(entry_points(addr2line(read()))):
print x["indent"], x["func"], "%x" % x["eip"]

运行

./itrace ./hellow|python2 ./treeify.py ./hellow

测试结果

     _start /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/start.S: 8048d40
__libc_start_main ??:? 8048ea0
_dl_aux_init ??:? 806e590
_dl_discover_osversion ??:? 806f3b0
uname ??:? 80921c0
?? ??: b77e0414
index ??:? 805b250
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
__init_cpu_features ??:? 806f570
strncasecmp_l ??:? 80b5ac0
strcmp ??:? 805b460
memset ??:? 805ba70
strcasecmp_l ??:? 805bc10
bcmp ??:? 805b6b0
strstr ??:? 806b080
memchr ??:? 808ce90
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
strrchr ??:? 808c660
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
wcslen ??:? 808eae0
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
__rawmemchr ??:? 805bcc0
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
memmove ??:? 805b9d0
__strnlen ??:? 808c620
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
strcpy ??:? 805b4d0
stpcpy ??:? 805bb30
__pthread_initialize_minimal ??:? 80494d0
__libc_setup_tls ??:?
sbrk ??:? 806cd70
__brk ??:? 80928e0
?? ??: b77e0414
__brk ??:? 80928e0
?? ??: b77e0414
memcpy ??:? 805bc50
__libc_init_first ??:? 806f4b0
__setfpucw ??:? 807ac00
__libc_init_secure ??:? 806f360
_dl_non_dynamic_init ??:? 806e7f0
_dl_get_origin ??:? 809a800
?? ??: b77e0414
malloc ??:? 8058f60
malloc_hook_ini malloc.o:? 805a020
ptmalloc_init.part. malloc.o:? 8059c20
__linkin_atfork ??:? 806e0f0
malloc ??:? 8058f60
_int_malloc malloc.o:?
malloc_consolidate malloc.o:? 80560b0
malloc_init_state malloc.o:? 80552e0
__default_morecore ??:? 805b230
sbrk ??:? 806cd70
__brk ??:? 80928e0
?? ??: b77e0414
__default_morecore ??:? 805b230
sbrk ??:? 806cd70
__brk ??:? 80928e0
?? ??: b77e0414
mempcpy ??:? 805bb00
getenv ??:? 804e240
strlen ??:? 805b5f0
_dl_new_object ??:? 80972a0
strlen ??:? 805b5f0
__calloc ??:?
_int_malloc malloc.o:?
__memset_sse2_rep ??:? 805f690
memcpy ??:? 805bc50
_dl_setup_hash ??:?
strlen ??:? 805b5f0
malloc ??:? 8058f60
_int_malloc malloc.o:?
memcpy ??:? 805bc50
_dl_add_to_namespace_list ??:?
getenv ??:? 804e240
strlen ??:? 805b5f0
_dl_init_paths ??:? 80951f0
_dl_important_hwcaps ??:? 80991b0
malloc ??:? 8058f60
_int_malloc malloc.o:?
mempcpy ??:? 805bb00
malloc ??:? 8058f60
_int_malloc malloc.o:?
malloc ??:? 8058f60
_int_malloc malloc.o:?
getenv ??:? 804e240
strlen ??:? 805b5f0
getenv ??:? 804e240
strlen ??:? 805b5f0
getenv ??:? 804e240
strlen ??:? 805b5f0
getenv ??:? 804e240
strlen ??:? 805b5f0
getenv ??:? 804e240
strlen ??:? 805b5f0
__init_misc ??:? 806dd90
__strrchr_sse2_bsf ??:? 808d830
__ctype_init ??:? 807abb0
__cxa_atexit ??:? 804e5d0
__new_exitfn ??:? 804e440
__libc_csu_init ??:? 80494f0
_init /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
_init /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crtn.S: 80481ae
frame_dummy crtstuff.c:? 8048e20
__register_frame_info_bases ??:? 80bd5a0
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
register_tm_clones crtstuff.c:? 8048db0
init_cacheinfo cacheinfo.o:? 8048b10
handle_intel cacheinfo.o:? 806b380
intel_check_word cacheinfo.o:? 806b0b0
intel_check_word cacheinfo.o:? 806b0b0
intel_check_word cacheinfo.o:? 806b0b0
intel_check_word cacheinfo.o:? 806b0b0
handle_intel cacheinfo.o:? 806b380
intel_check_word cacheinfo.o:? 806b0b0
intel_check_word cacheinfo.o:? 806b0b0
_setjmp ??:? 804d970
main ??:? 8048e7c
puts ??:? 804f350
strlen ??:? 805b5f0
_IO_new_file_xsputn ??:?
_IO_file_overflow ??:? 8052e60
_IO_doallocbuf ??:? 8053b10
_IO_file_doallocate ??:? 808a730
_IO_file_stat ??:? 8051f20
___fxstat64 ??:? 806c300
?? ??: b77e0414
__mmap ??:? 806ce60
?? ??: b77e0414
_IO_setb ??:? 8053aa0
_IO_new_do_write ??:? 80527b0
_IO_default_xsputn ??:? 8053bc0
exit ??:? 804e420
__run_exit_handlers ??:? 804e320
__libc_csu_fini ??:?
fini sdlerror.o:? 8048b00
check_free.isra. sdlerror.o:? 80a6f30
__do_global_dtors_aux crtstuff.c:? 8048df0
deregister_tm_clones crtstuff.c:? 8048d80
__deregister_frame_info_bases ??:? 80bd7c0
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
_fini /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 80bec78
__x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S: 8048d70
_fini /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crtn.S: 80bec87
_IO_cleanup ??:? 80543b0
_IO_flush_all_lockp ??:?
_IO_file_overflow ??:? 8052e60
_IO_new_do_write ??:? 80527b0
new_do_write fileops.o:?
_IO_file_write ??:? 8051f50
__write ??:? 806c420
?? ??: b77e0414
_IO_file_setbuf ??:?
_IO_default_setbuf ??:? 8053d10
_IO_file_sync ??:?
_IO_setb ??:? 8053aa0
_Exit ??:? 806ba24
?? ??: b77e0414

参考资料

  1. http://lackingrhoticity.blogspot.ca/2009/05/really-simple-tracing-debugger.html

每天学点GDB14的更多相关文章

  1. 【Python五篇慢慢弹】快速上手学python

    快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...

  2. 跟Unity3D学代码优化

    今天我们来聊聊如何跟Unity学代码优化,准确地说,是通过学习Unity的IL2CPP技术的优化策略,应用到我们的日常逻辑开发中. 做过Unity开发的同学想必对IL2CPP都很清楚,简单地说,IL2 ...

  3. 重学hadoop技术

    最近因为做了些和hadoop相关的项目(虽然主要是运维),但是这段经历让我对hadoop的实际运用有了更加深入的理解. 相比以前自学hadoop,因为没有实战场景以及良好的大数据学习氛围,现在回顾下的 ...

  4. 《学技术练英语》PPT分享

    之前做的一个PPT,分享给博客园的同学. 下载地址: 学技术练英语.pdf 技术是靠自己去学的,学技术不能仅仅是看书看博客,最好是有实践,不管是做实验去验证,还是写各种代码去玩各种特性,还是造轮子都是 ...

  5. 前端学HTTP之数据传输

    × 目录 [1]客户机处理 [2]集线器处理 [3]路由器1处理[4]路由器2处理[5]交换机处理[6]服务器处理[7]反向传输 前面的话 上一篇中,介绍了网络基础.本文将详细介绍客户机在浏览网页ab ...

  6. 前端学HTTP之网络基础

    × 目录 [1]网络 [2]OSI [3]TCP/IP 前面的话 HTTP协议对于前端工程师是非常重要的.我们在浏览网站时,访问的每一个WEB页面都需要使用HTTP协议实现.如果不了解HTTP协议,就 ...

  7. Mina、Netty、Twisted一起学(八):HTTP服务器

    HTTP协议应该是目前使用最多的应用层协议了,用浏览器打开一个网站就是使用HTTP协议进行数据传输. HTTP协议也是基于TCP协议,所以也有服务器和客户端.HTTP客户端一般是浏览器,当然还有可能是 ...

  8. 一起学微软Power BI系列-使用技巧(2)连接Excel数据源错误解决方法

    上一篇文章一起学微软Power BI系列-使用技巧(1)连接Oracle与Mysql数据库中,我们介绍了Power BI Desktop中连接Oracle和Mysql的方法,其实说到底还是驱动的问题, ...

  9. 开始学nodejs —— 调试篇

    新学习一种技术,肯定会遇到很多坑,我们需要找到这些坑,弄清楚这些坑出现的原因和其中的原理.这种操作就叫做调试. 程序调试的方法和工具多种多样,在这里我总结一下我在学习nodejs的过程中,学到的和用到 ...

随机推荐

  1. CodeIgniter报错: You must use the "set" method to update an entry

    I'm using codeigniter/datamapper to develop an inviocing application and I'm getting an error that i ...

  2. 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))

    解决办法:在项目属性里设置“生成”=>“目标平台”为x86而不是默认的ANY CPU.

  3. PHP 5.4中的traits特性

    Trait 是 PHP5. 中的新特性,是 PHP 多重继承的一种解决方案.例如,需要同时继承两个 Abstract Class, 这将会是件很麻烦的事情,Trait 就是为了解决这个问题. 简单使用 ...

  4. eclipse 中的 jar file 和 runnable jar file的区别

    转自于:http://blog.csdn.net/lijiecong/article/details/6266234 java最难学的就是角落的东东了,不愧叫做java平台.搜索了一把总算明白了. 直 ...

  5. Codeforces Round #352 (Div. 2) C. Recycling Bottles 贪心

    C. Recycling Bottles   It was recycling day in Kekoland. To celebrate it Adil and Bera went to Centr ...

  6. cocos2dx游戏开发——微信打飞机学习笔记(七)——Enemy的搭建

    一.文件创建~ Enemy.h Enemy.cpp 二.How to do? 由于我是已经完成成个游戏的功能,所以我会将游戏中enemy所需要的很多功能基本上都先考虑到了,如果大家自己在做的时候也许没 ...

  7. org.apache.log4j与org.apache.commons.logging这两个包有什么区别

    apache common logging是一种log的框架接口,它本身并不实现log记录的功能,而是在运行时动态查找目前存在的日志库,调用相关的日志函数,从而隐藏具体的日志实现log4j是具体的日志 ...

  8. DedeCMS让{dede:list}标签支持weight权重排序

    1.找到"根目录\include\arc.listview.class.php"文件. 2.修改代码:在文件第727行处添加按weight排序判断代码(红色部分为新添加代码). / ...

  9. Android UDP

    一.UDP协议全称是用户数据报协议 ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议. 1.UDP是一个无连接协议,传输数据之前源端和终端不建立连接: 2.不维护连接状态,包括收发状态等 ...

  10. servlet中cookie的使用

    ---恢复内容开始--- Cookie是存储在客户端计算机上的文本文件,并保留了它们的各种信息跟踪的目的. Java Servlet透明支持HTTP Cookie. 涉及标识返回用户有三个步骤: 服务 ...