每天学点GDB14

在上一篇文章中讲到了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 == 0) {
    if(ptrace(PTRACE_TRACEME) < 0) {
      perror("ptrace");
      _exit(1);
    }
    execvp(argv[1], argv + 1);
    perror("exec");
    _exit(1);
  }
  while(1) {
    int status;
    struct user_regs_struct regs;
    if(waitpid(pid, &status, 0) < 0)
      perror("waitpid");
    if(!WIFSTOPPED(status))
      break;
    if(ptrace(PTRACE_GETREGS, pid, 0, &regs) < 0)
      perror("ptrace/GETREGS");
    printf("%lx %lx\n", regs.eip, regs.esp);
    if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) < 0)
      perror("ptrace/SINGLESTEP");
  }
  return 0;
}

编译

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 0;
}

编译

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:61 8048d40
       __libc_start_main ??:? 8048ea0
         _dl_aux_init ??:? 806e590
         _dl_discover_osversion ??:? 806f3b0
           uname ??:? 80921c0
             ?? ??:0 b77e0414
         index ??:? 805b250
           __x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:66 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:66 8048d70
         strrchr ??:? 808c660
           __x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:66 8048d70
         wcslen ??:? 808eae0
           __x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:66 8048d70
         __rawmemchr ??:? 805bcc0
           __x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:66 8048d70
         memmove ??:? 805b9d0
         __strnlen ??:? 808c620
           __x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:66 8048d70
         strcpy ??:? 805b4d0
         stpcpy ??:? 805bb30
         __pthread_initialize_minimal ??:? 80494d0
           __libc_setup_tls ??:? 8049240
             sbrk ??:? 806cd70
               __brk ??:? 80928e0
                 ?? ??:0 b77e0414
               __brk ??:? 80928e0
                 ?? ??:0 b77e0414
             memcpy ??:? 805bc50
         __libc_init_first ??:? 806f4b0
           __setfpucw ??:? 807ac00
           __libc_init_secure ??:? 806f360
           _dl_non_dynamic_init ??:? 806e7f0
             _dl_get_origin ??:? 809a800
               ?? ??:0 b77e0414
               malloc ??:? 8058f60
                 malloc_hook_ini malloc.o:? 805a020
                   ptmalloc_init.part.7 malloc.o:? 8059c20
                     __linkin_atfork ??:? 806e0f0
                 malloc ??:? 8058f60
                   _int_malloc malloc.o:? 8057060
                     malloc_consolidate malloc.o:? 80560b0
                     malloc_init_state malloc.o:? 80552e0
                     __default_morecore ??:? 805b230
                       sbrk ??:? 806cd70
                         __brk ??:? 80928e0
                           ?? ??:0 b77e0414
                     __default_morecore ??:? 805b230
                       sbrk ??:? 806cd70
                         __brk ??:? 80928e0
                           ?? ??:0 b77e0414
               mempcpy ??:? 805bb00
             getenv ??:? 804e240
               strlen ??:? 805b5f0
             _dl_new_object ??:? 80972a0
               strlen ??:? 805b5f0
               __calloc ??:? 8059720
                 _int_malloc malloc.o:? 8057060
                 __memset_sse2_rep ??:? 805f690
               memcpy ??:? 805bc50
             _dl_setup_hash ??:? 8097150
             strlen ??:? 805b5f0
             malloc ??:? 8058f60
               _int_malloc malloc.o:? 8057060
             memcpy ??:? 805bc50
             _dl_add_to_namespace_list ??:? 8097200
             getenv ??:? 804e240
               strlen ??:? 805b5f0
             _dl_init_paths ??:? 80951f0
               _dl_important_hwcaps ??:? 80991b0
                 malloc ??:? 8058f60
                   _int_malloc malloc.o:? 8057060
                 mempcpy ??:? 805bb00
               malloc ??:? 8058f60
                 _int_malloc malloc.o:? 8057060
               malloc ??:? 8058f60
                 _int_malloc malloc.o:? 8057060
             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:63 8048190
             __x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:66 8048d70
           _init /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crtn.S:40 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:66 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 ??:? 8052470
               _IO_file_overflow ??:? 8052e60
                 _IO_doallocbuf ??:? 8053b10
                   _IO_file_doallocate ??:? 808a730
                     _IO_file_stat ??:? 8051f20
                       ___fxstat64 ??:? 806c300
                         ?? ??:0 b77e0414
                     __mmap ??:? 806ce60
                       ?? ??:0 b77e0414
                     _IO_setb ??:? 8053aa0
                 _IO_new_do_write ??:? 80527b0
               _IO_default_xsputn ??:? 8053bc0
         exit ??:? 804e420
           __run_exit_handlers ??:? 804e320
             __libc_csu_fini ??:? 8049590
               fini sdlerror.o:? 8048b00
               check_free.isra.0 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:66 8048d70
             _fini /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:82 80bec78
               __x86.get_pc_thunk.bx /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crti.S:66 8048d70
             _fini /root/glibc/src/glibc-2.18/csu/../sysdeps/i386/crtn.S:45 80bec87
             _IO_cleanup ??:? 80543b0
               _IO_flush_all_lockp ??:? 8054190
                 _IO_file_overflow ??:? 8052e60
                   _IO_new_do_write ??:? 80527b0
                     new_do_write fileops.o:? 8051100
                       _IO_file_write ??:? 8051f50
                         __write ??:? 806c420
                           ?? ??:0 b77e0414
               _IO_file_setbuf ??:? 8051060
                 _IO_default_setbuf ??:? 8053d10
                   _IO_file_sync ??:? 8053060
                   _IO_setb ??:? 8053aa0
             _Exit ??:? 806ba24
               ?? ??:0 b77e0414

参考资料

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

 

转载于:https://www.cnblogs.com/hseagle/p/3304826.html

<think>好的,我现在需要帮助用户确定每天应该花多少时间学习之前提到的UNIX环境高级编程的基础知识。用户已经得到了一个详细的学习路线,现在他们想知道每天应该投入多少时间。 首先,我需要回顾用户之前的提问历史。用户最初询问了学习APUE前需要哪些基础知识,现在跟进询问学习时间安排。这说明用户可能已经开始规划学习,并希望有一个明确的时间管理策略。 用户可能的情况是,他们可能是学生、自学者或转行人士,希望通过系统学习进入系统编程领域。他们可能已经有部分基础,但需要巩固,或者完全是新手。用户的需求是高效学习,同时平衡其他生活或工作责任,所以需要具体的时间建议。 接下来,我需要分析用户的具体问题:每天学习多长时间合适?这可能涉及到学习效率、内容分解、避免疲劳等因素。用户可能希望一个可持续的计划,而不是短期的强度过高的安排。 在之前的回复中,我分阶段推荐了不同的学习内容,现在需要将这些阶段分解到每日学习中。例如,用户可能需要知道每个阶段需要多少周,每天多少小时,以及如何分配理论学习与实践时间。 需要考虑的因素包括:总学习时间(2-3个月)、不同阶段的时间分配(基础期、进阶期、实战期)、每日学习时间与休息的平衡。此外,用户可能有不同的学习速度,所以建议要有一定的灵活性。 可能还需要提醒用户避免过度学习,防止疲劳,保持持续进步。例如,建议采用番茄工作法,每天分段学习,并强调实践的重要性,如每天写代码的时间比例。 还需要考虑不同学习者的背景。如果用户已经有C语言基础,可能基础期可以缩短;如果是新手,则需要更多时间。因此,可能需要给出一个范围,并建议用户根据自身情况调整。 最后,要确保建议具体可行,比如将每日时间分为理论学习和实践,每周安排复习时间,以及如何检测学习效果。同时,推荐一些时间管理工具或方法,帮助用户保持节奏。</think>根据学习目标和知识基础的不同,每日学习时长可参考以下分段方案(以零基础学习者为基准): --- ### 一、**时间分配原则** 1. **黄金比例**:理论(听课/读书)与实践(写代码/操作命令)按 **1:2** 分配 (例如:1小时读书 → 配套2小时写代码) 2. **防遗忘机制**:每天用 **15分钟** 复习前日内容(如重画进程状态转换图) 3. **可持续性**:每周预留 **1天缓冲期** 用于补漏或休息 --- ### 二、**具体阶段规划** #### ▶ **阶段1:C语言强化(3-4周)** - **每日投入**:2-3小时 - 早间30分钟:精读《C和指针》重点章节(如指针与数组关系) - 晚间90分钟:实现1个系统级代码(如用`malloc`模拟内存碎片化现象) - 周末加餐:用GDB调试复杂指针错误(如双重释放问题) #### ▶ **阶段2:操作系统理论(2-3周)** - **每日投入**:1.5小时理论 + 1小时实践 - 通过`fork()`创建多级子进程,用`pstree`观察进程树 - 用`mmap`实现进程间共享内存(对比`shmget`差异) - 推荐工具:`htop`实时观察内存变化 #### ▶ **阶段3:UNIX环境实战(4-6周)** - **每日投入**:3小时(侧重动手) - 早晨通勤:用手机SSH连接Linux服务器练习命令(如`lsof`分析文件描述符泄漏) - 深度实践:逐步实现简化版Shell(需处理信号、管道、重定向) - 典型案例:用`inotify`监控文件系统事件并触发自定义动作 --- ### 三、**高效学习策略** 1. **对抗碎片化** - 用`tmux`分屏同时打开:左侧写代码 → 右侧测试 → 下方`man`手册 - 禁止在多任务间切换(如学信号处理时专注`sigaction`结构体) 2. **记忆强化技巧** - 为每个系统调用创建速查卡片: $$ \text{卡片正面:open()功能} \\ \text{背面:O\_CREAT与O\_EXCL组合的原子性保证} $$ - 用`strace -f gcc hello.c`观察编译过程的系统调用链 3. **防疲劳建议** - 每45分钟用`watch -n 1 'cat /proc/loadavg'`监控系统负载(同步放松眼睛) - 高强度调试后,用`cmatrix`或`bastet`(俄罗斯方块终端版)短暂放松 --- ### 四、**进度自测表** | 学习周 | 达标标志 | 检测方法 | |--------|-------------------------------------|------------------------------| | 第2周 | 能手动解析ELF文件头 | 用`readelf -h /bin/ls`验证 | | 第4周 | 实现带信号处理的守护进程 | 通过`kill -SIGHUP`测试稳定性 | | 第6周 | 能解释`ls -l`输出的全部字段来源 | 对照`struct stat`成员逐一说明| --- ### 五、**灵活调整建议** - **加速方案**(有编程经验者): 每天追加1小时专题突破(如集中3天专攻`epoll`模型) - **减速方案**(遇核心难点时): 对多线程同步等复杂主题,可延长单日学习至4小时,但需搭配: ```c // 用Valgrind检测死锁示例 valgrind --tool=helgrind ./your_thread_program ``` --- 坚持6-8周后,你会自然产生"想用`poll()`优化IO"或"尝试修改文件权限掩码"的条件反射,此时即可顺畅进入《UNIX环境高级编程》的核心章节学习。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值