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是固定的

dwarf是如何处理栈帧的?的更多相关文章

  1. dwarf是怎样处理的栈帧?

    dwarf是如何处理的栈帧呢? 首先看下非dwarf的情况是如何处理栈帧的: 1 3623804982590 0x3e90 [0xb0]: PERF_RECORD_SAMPLE(IP, 0x1): 1 ...

  2. 再看perf是如何通过dwarf处理栈帧的

    从结构体stack_dump入手, util/unwind-libunwind-local.c 中有函数access_mem #0 access_mem (as=0x1f65bd0, addr=140 ...

  3. 使用gdb查看栈帧的情况, 没有ebp

    0x7fffffffdb58: 0x004005ba  0x00000000  0x00000000  0x00000000 <-----funcb的栈帧 [0x7fffffffdb60, 0x ...

  4. 图解JVM字节码执行引擎之栈帧结构

    一.执行引擎      “虚拟机”的概念是相对于“物理机”而言的,这两种“机器”都有执行代码的能力.物理机的执行引擎是直接建立在硬件处理器.物理寄存器.指令集和操作系统层面的:而“虚拟机”的执行引擎是 ...

  5. 栈帧%ebp,%esp详解

    首先应该明白,栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部( ...

  6. c函数调用过程原理及函数栈帧分析

    转载自地址:http://blog.csdn.net/zsy2020314/article/details/9429707       今天突然想分析一下函数在相互调用过程中栈帧的变化,还是想尽量以比 ...

  7. Linux下追踪函数调用,打印栈帧

    事情的起因是这样的,之前同事的代码有一个内存池出现了没有回收的情况.也就是是Pop出来的对象没有Push回去,情况很难复现,所以在Pop里的打印日志,跟踪是谁调用了它,我想在GDB调试里可以追踪调用的 ...

  8. Linux - 函数的栈帧

    栈帧(stack frame),机器用栈来传递过程参数,存储返回信息,保存寄存器用于以后恢复,以及本地存储.为单个过程(函数调用)分配的那部分栈称为栈帧.栈帧其实是两个指针寄存器, 寄存器%ebp为帧 ...

  9. JAVA栈帧

    简介 Java栈是一块线程私有的内存空间.java堆和程序数据相关,java栈就是和线程执行密切相关的,线程的执行的基本行为是函数调用,每次函数调用的数据都是通过java栈来传递的. Java栈与数据 ...

随机推荐

  1. Go语言入门(一)特性、安装、环境搭建、第一个程序等

    Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性.谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发Go,是因为过去10多年间软件开发的难度令人沮 ...

  2. 关于 VirtualBox6 下的 Win10 虚拟机 与 宿主机 共享文件

    1. 概述 需要在 宿主机 和 虚拟机 之间交换文件 复制粘贴 貌似不太好使 2. 问题 设置了共享文件夹之后, 找不到目录 3. 环境 宿主机 OS Win10 开启了 网络发现 略 虚拟机 OS ...

  3. 【blockly教程】第二章 Blockly编程基础

    2.1 Blockly的数据类型 2.1.1 数据的含义  在计算机程序的世界里,程序的基本任务就是处理数据,无论是数值还是文字.图像.图形.声音.视频等信息,如果要在计算机中处理的话,就必须将它们转 ...

  4. MySQL高级第二章——索引优化分析

    一.SQL性能下降原因 1.等待时间长?执行时间长? 可能原因: 查询语句写的不行 索引失效(单值索引.复合索引) CREATE INDEX index_user_name ON user(name) ...

  5. codechef Table Game(博弈)

    题意 题目链接 很难概括.. Sol (因为比赛还没结束,所以下面讲的可能是“非官方”“正解”) maya这题我前前后后 断断续续的做了一个星期才A掉.CC一场challenge出两道打表题可有点过分 ...

  6. 人脸检测库libfacedetection介绍

    libfacedetection是于仕琪老师放到GitHub上的二进制库,没有源码,它的License是MIT,可以商用.目前只提供了windows 32和64位的release动态库,主页为http ...

  7. P1209 [USACO1.3]修理牛棚 Barn Repair

    P1209 [USACO1.3]修理牛棚 Barn Repair 题目描述 在一个夜黑风高,下着暴风雨的夜晚,farmer John的牛棚的屋顶.门被吹飞了. 好在许多牛正在度假,所以牛棚没有住满. ...

  8. 「日常训练」Uncle Tom's Inherited Land*(HDU-1507)

    题意与分析 题意是这样的:给你一个\(N\times M\)的图,其中有一些点不能放置\(1\times 2\)大小的矩形,矩形可以横着放可以竖着放,问剩下的格子中,最多能够放多少个矩形. 注意到是\ ...

  9. Windows运行机理——窗口和句柄

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以进行了搬运和个人加工 1. 窗口 窗口是Windows应用程序中一个非常重要的元素,一个Wi ...

  10. 180609-Spring之事件驱动机制的简单使用

    文章链接:https://liuyueyi.github.io/hexblog/hexblog/2018/06/09/180609-Spring之事件驱动机制的简单使用/ Spring之事件驱动机制的 ...