zoukankan      html  css  js  c++  java
  • dwarf是如何处理栈帧的?

    dwarf是如何处理栈帧的?

    DW_AT_frame_base 表明函数栈帧的起始点

     95 < 1><0x000000ca>    DW_TAG_subprogram
     96                       DW_AT_external              yes(1)
     97                       DW_AT_name                  "funcb"
     98                       DW_AT_decl_file             0x00000001 /home/hon/codebox/gcc/sleep.c
     99                       DW_AT_decl_line             0x0000000d
    100                       DW_AT_prototyped            yes(1)
    101                       DW_AT_type                  <0x00000049>
    102                       DW_AT_low_pc                0x004009f4
    103                       DW_AT_high_pc               <offset-from-lowpc>25
    104                       DW_AT_  _base        ,    len 0x0001: 9c: DW_OP_call_frame_cfa
    105                       DW_AT_GNU_all_tail_call_sitesyes(1)
    106                       DW_AT_sibling               <0x000000f8>

    栈帧的起始点,这个起始点,

    对于调试器可以定位到的每一个地址,都会制定当前栈帧到变量间的偏移。疑问是DW_OP_call_frame_cfa是啥意思

    最关键的是eh_frame段,怎么样读取eh_frame的内容?readelf -Wwf xx  

    使用gdb调试程序

    (gdb) i f  ----------------> 函数funca处的断点
    Stack level 0, frame at 0x7fffffffdb40:
     rip = 0x400a0d in funca (sleep.c:16); saved rip = 0x400a4b
     called by frame at 0x7fffffffdb70    <----------这个就是栈的基地址了
     source language c.
     Arglist at 0x7fffffffdb30, args: a=0
     Locals at 0x7fffffffdb30, Previous frame's sp is 0x7fffffffdb40
     Saved registers:
      rip at 0x7fffffffdb38
    (gdb) c 
    Continuing.
    
    Breakpoint 2, funcb (b=124) at sleep.c:13
    13	int funcb(int b) {
    (gdb) i f -------------》函数funcb处的断点
    Stack level 0, frame at 0x7fffffffdb20:
     rip = 0x4009f4 in funcb (sleep.c:13); saved rip = 0x400a20
     called by frame at 0x7fffffffdb40
     source language c.
     Arglist at 0x7fffffffdb10, args: b=124
     Locals at 0x7fffffffdb10, Previous frame's sp is 0x7fffffffdb20
     Saved registers:
      rip at 0x7fffffffdb18
    (gdb) c
    Continuing.
    
    Breakpoint 1, funcc (a=53) at sleep.c:5
    5	int funcc(int a) {
    (gdb) i f ------------》函数funcc处的断点
    Stack level 0, frame at 0x7fffffffdb00:
     rip = 0x4009ae in funcc (sleep.c:5); saved rip = 0x400a07
     called by frame at 0x7fffffffdb20
     source language c.
     Arglist at 0x7fffffffdaf0, args: a=53
     Locals at 0x7fffffffdaf0, Previous frame's sp is 0x7fffffffdb00
     Saved registers:
      rip at 0x7fffffffdaf8
    

      然后把整个函数调用栈打印出来

    看一下此时的栈帧结果是啥子吧,此时rsp是在0x7ffffffffdaf8处,

    0x0000000000400a07 处是funcb的返回地址;funb函数中有三个8字节是作为自己的参数的,其中只有一个形参放在了地址:mov    %edi,0xc(%rsp) 中,从这里我们知道funcb的栈底应该是0x7fffffffdb20

    (gdb) x/60x $sp
    0x7fffffffdaf8:	0x00400a07	
    0x00000000
             0x00000000
            0x00000000 0x7fffffffdb08: 0x00000077
              0x00171717
              0x006c9fb0
              0x00000000 0x7fffffffdb18: 0x00400a20
    0x00000000
    0x006cf6b0
    0x00000000
    0x7fffffffdb28: 0x00000001 0x00171717 0x00000020 0x00000000 0x7fffffffdb38: 0x00400a4b 0x00000000 0x00000140 0x00000000 0x7fffffffdb48: 0x00123456 0x00171717 0x006cf668 0x00000000 0x7fffffffdb58: 0x00294b6d 0x00000000 0x00000000 0x00000000 0x7fffffffdb68: 0x00400add 0x00000000 0x00000000 0x00000000 0x7fffffffdb78: 0x0000000a 0x00000002 0xffffdbf0 0x00171717 0x7fffffffdb88: 0x00123456 0x00000000 0x00000000 0x00000000 0x7fffffffdb98: 0x00000003 0x00000000 0xffffdda8 0x00007fff 0x7fffffffdba8: 0x00000004 0x00000000 0x00000002 0x00000000 0x7fffffffdbb8: 0x00000006 0x00000000 0x7ffffa00 0x00000003 0x7fffffffdbc8: 0x000027ab 0x00000000 0xf7ffd2f4 0x00007fff 0x7fffffffdbd8: 0x00000001 0x00000000 0x00000001 0x00000000

      按照之前的说法,栈的基址是指ebp指向的地方,ebp指向的地方是old ebp,然后是返回地址,在gdb中输出的栈信息中call by frame中

    当使用-fomit-stack-pointer去编译程序的时候,程序在整个执行过程中esp的值是不会变的,所以只要是抓到了一个函数,那么这个函数的esp是固定的

  • 相关阅读:
    彻底理解Python中的yield
    python红包随机生成(隔板法)
    闭包的作用
    logging模块
    Python的datetime模块分析
    坑集系列
    Goertzel Algorith(戈策尔算法)用于检出特定输入频率
    Java学习个人笔记(一)配置java环境变量(Feb04,2013 )
    使用Gnu gprof进行Linux平台下的程序分析
    关于微编程(Microprogramming)的简史
  • 原文地址:https://www.cnblogs.com/honpey/p/9326957.html
Copyright © 2011-2022 走看看