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


0x7fffffffdb58: 0x004005ba  0x00000000  0x00000000  0x00000000 <-----funcb的栈帧 [0x7fffffffdb60, 0x7fffffffdb80],其中a=0x1a,其中这个栈的栈底是返回地址4005d
0x7fffffffdb68: 0x00000000  0x0000001a  0x00000000  0x00000000         0x4005d8,是函数funca的返回地址,然后往上就逐渐是各种局部变量
0x7fffffffdb78: 0x004005d8  0x00000000  0x00400470  0x00000000
0x7fffffffdb88: 0xffffdd90  0x00000019  0x00000000  0x00000000    <-----funca的栈帧,这个栈帧[0x7fffffffdb80, 0x7fffffffdba0], 其中a=0x19  
0x7fffffffdb98: 0x0040060d  0x00000000  0x00000000  0x00000000 <----add的栈帧stack frame [0x7fffffffdba0,0x7ffffffdbd0],其中a=0x18,b=0x27 
0x7fffffffdba8: 0x00000028  0x00000018  0x00000001  0x00000000 
0x7fffffffdbb8: 0x00000040  0x00000000  0x6562b026  0x00000000
0x7fffffffdbc8: 0x0040069f  0x00000000  0xffffdd60  0x00007fff
0x7fffffffdbd8: 0xf7dee923  0x00000002  0x00000000  0x00000017
0x7fffffffdbe8: 0x00000027  0x00000000  0x00000000  0x00000000
0x7fffffffdbf8: 0x00000003  0x00000000  0xffffdda8  0x00007fff
0x7fffffffdc08: 0x00000000  0x00000000  0x00400750  0x00000000
0x7fffffffdc18: 0xf7de7ab0  0x00007fff  0x000000ff  0x00000000
0x7fffffffdc28: 0xff000000  0x00000000  0x00000000  0x00000000
0x7fffffffdc38: 0x00000000  0x00000000  0x00000000  0x00000000

所以说一个栈的栈帧,最开始是上一个函数的返回地址,以及本函数的堆栈
gdb中显示出来的栈帧的信息中,“Stack frame at 0x7fffffffdb80” 都是指栈帧的基地址。

(gdb) info frame 1
Stack frame at 0x7fffffffdb80:
 rip = 0x4005ba in funcb (sleep.c:15); saved rip = 0x4005d8
 called by frame at 0x7fffffffdba0, caller of frame at 0x7fffffffdb60
 source language c.
 Arglist at 0x7fffffffdb58, args: a=26
 Locals at 0x7fffffffdb58, Previous frame‘s sp is 0x7fffffffdb80
 Saved registers:
  rip at 0x7fffffffdb78
(gdb) info frame 2
Stack frame at 0x7fffffffdba0:
 rip = 0x4005d8 in funca (sleep.c:19); saved rip = 0x40060d
 called by frame at 0x7fffffffdbd0, caller of frame at 0x7fffffffdb80
 source language c.
 Arglist at 0x7fffffffdb78, args: a=25
 Locals at 0x7fffffffdb78, Previous frame‘s sp is 0x7fffffffdba0
 Saved registers:
  rip at 0x7fffffffdb98
(gdb) info frame 3
Stack frame at 0x7fffffffdbd0:
 rip = 0x40060d in add (sleep.c:27); saved rip = 0x40069f
 called by frame at 0x7fffffffdcb0, caller of frame at 0x7fffffffdba0
 source language c.
 Arglist at 0x7fffffffdb98, args: a=24, b=40
 Locals at 0x7fffffffdb98, Previous frame‘s sp is 0x7fffffffdbd0
 Saved registers:
  rip at 0x7fffffffdbc8
(gdb) info frame 4
Stack frame at 0x7fffffffdcb0:
 rip = 0x40069f in print (sleep.c:35); saved rip = 0x4006c7
 called by frame at 0x7fffffffdcc0, caller of frame at 0x7fffffffdbd0
 source language c.
 Arglist at 0x7fffffffdbc8, args: i=2
 Locals at 0x7fffffffdbc8, Previous frame‘s sp is 0x7fffffffdcb0
 Saved registers:
  rip at 0x7fffffffdca8

以函数funca->funcb来看一一下函数的调用过程

00000000004005a2 <funcb>:
  4005a2:   48 83 ec 18             sub    $0x18,%rsp    rsp这个时候的值就确定了
  4005a6:   89 7c 24 0c             mov    %edi,0xc(%rsp)
  4005aa:   83 44 24 0c 01          addl   $0x1,0xc(%rsp)
  4005af:   8b 44 24 0c             mov    0xc(%rsp),%eax
  4005b3:   89 c7                   mov    %eax,%edi
  4005b5:   e8 ac ff ff ff          callq  400566 <funcc>
  4005ba:   90                      nop
  4005bb:   48 83 c4 18             add    $0x18,%rsp
  4005bf:   c3                      retq   

00000000004005c0 <funca>:
  4005c0:   48 83 ec 18             sub    $0x18,%rsp
  4005c4:   89 7c 24 0c             mov    %edi,0xc(%rsp)
  4005c8:   83 44 24 0c 01          addl   $0x1,0xc(%rsp)
  4005cd:   8b 44 24 0c             mov    0xc(%rsp),%eax
  4005d1:   89 c7                   mov    %eax,%edi
  4005d3:   e8 ca ff ff ff          callq  4005a2 <funcb>  callq是push ip;rsp++
  4005d8:   90                      nop
  4005d9:   48 83 c4 18             add    $0x18,%rsp
  4005dd:   c3                      retq

dwarf当中存储的信息是啥样子的呢?

< 1><0x000000ca>    DW_TAG_subprogram
                      DW_AT_external              yes(1)
                      DW_AT_name                  "funcb"
                      DW_AT_decl_file             0x00000001 /home/hon/codebox/gcc/sleep.c
                      DW_AT_decl_line             0x0000000d
                      DW_AT_prototyped            yes(1)
                      DW_AT_type                  <0x00000049>
                      DW_AT_low_pc                0x004005a2
                      DW_AT_high_pc               <offset-from-lowpc>30
                      DW_AT_frame_base            len 0x0001: 9c: DW_OP_call_frame_cfa
                      DW_AT_GNU_all_tail_call_sitesyes(1)
                      DW_AT_sibling               <0x000000f8>
< 2><0x000000eb>      DW_TAG_formal_parameter
                        DW_AT_name                  "a"
                        DW_AT_decl_file             0x00000001 /home/hon/codebox/gcc/sleep.c
                        DW_AT_decl_line             0x0000000d
                        DW_AT_type                  <0x00000049>
                        DW_AT_location              len 0x0002: 916c: DW_OP_fbreg -20

funca中的信息是啥样子的?

< 1><0x000000f8>    DW_TAG_subprogram
                      DW_AT_external              yes(1)
                      DW_AT_name                  "funca"
                      DW_AT_decl_file             0x00000001 /home/hon/codebox/gcc/sleep.c
                      DW_AT_decl_line             0x00000011
                      DW_AT_prototyped            yes(1)
                      DW_AT_type                  <0x00000049>
                      DW_AT_low_pc                0x004005c0
                      DW_AT_high_pc               <offset-from-lowpc>30
                      DW_AT_frame_base            len 0x0001: 9c: DW_OP_call_frame_cfa
                      DW_AT_GNU_all_tail_call_sitesyes(1)
                      DW_AT_sibling               <0x00000126>
< 2><0x00000119>      DW_TAG_formal_parameter
                        DW_AT_name                  "a"
                        DW_AT_decl_file             0x00000001 /home/hon/codebox/gcc/sleep.c
                        DW_AT_decl_line             0x00000011
                        DW_AT_type                  <0x00000049>
                        DW_AT_location              len 0x0002: 916c: DW_OP_fbreg -20

原文地址:https://www.cnblogs.com/honpey/p/9349874.html

时间: 2024-10-18 06:55:25

使用gdb查看栈帧的情况, 没有ebp的相关文章

函数的调用过程(栈帧)

1.什么是栈帧? 栈帧也叫过程活动记录,是编译器用来实现函数调用过程的一种数据结构.C语言中,每个栈帧对应着一个未运行完的函数.从逻辑上讲,栈帧就是一个函数执行的环境:函数调用框架.函数参数.函数的局部变量.函数执行完后返回到哪里等等.栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址). 2.Add()函数的调用过程 我们以Add()函数为例深入的研究一

gdb通过frame切换栈帧之后寄存器是否准确

一.问题 在使用寄存器调试一些堆栈破坏的core文件时,可能需要通过反汇编来确定问题的原因,而此时确定寄存器的值就是一个必要的手段.但是,在通过frame切换栈帧之后,通过info reg看到的寄存器就是该栈帧当前的寄存器值吗? 二.gdb的文档说明 if all stack frames farther in were exited and their saved registers restored. In order to see the true contents of hardware

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

事情的起因是这样的,之前同事的代码有一个内存池出现了没有回收的情况.也就是是Pop出来的对象没有Push回去,情况很难复现,所以在Pop里的打印日志,跟踪是谁调用了它,我想在GDB调试里可以追踪调用的栈帧,那也一定有方法实现.首先上网搜索了一下,并没有结果!还好代码量不是很多,只能用最笨的方法,在每个调用Pop的地方,传参,把调用的文件,行号作为字符串传进去,在日志里打印!忙活完了,总感觉一定是有方法可以实现查看调用栈帧的,于是在QQ群里的问了下,果然有这方面经验的同学给出了答案! 主要是通过b

Linux 下函数栈帧分析

1.关于栈 对于程序,编译器会对其分配一段内存,在逻辑上可以分为代码段,数据段,堆,栈 代码段:保存程序文本,指令指针EIP就是指向代码段,可读可执行不可写 数据段:保存初始化的全局变量和静态变量,可读可写不可执行 BSS:未初始化的全局变量和静态变量 堆(Heap):动态分配内存,向地址增大的方向增长,可读可写可执行 栈(Stack):存放局部变量,函数参数,当前状态,函数调用信息等,向地址减小的方向增长,非常非常重要,可读可写可执行.如下图所示: 首先必须明确一点也是非常重要的一点,栈是向下

C函数调用机制及栈帧指针

转载: http://bbs.csdn.net/topics/90317145 http://blog.chinaunix.net/uid-26817832-id-3347227.html 帧指针 和栈指针到底是什么,有什么联系吗 FP帧指针指向帧头 SP栈指针指向栈顶 大部分现代计算机系统使用栈来给进程传递参数并且存储局部变量.栈是一种在进程映象内存的高地址内的后进先出(LIFO)的缓冲区.当程序调用一个函数时 一个新的"栈帧"会被创建.这个栈帧包含着传递给函数的各种参数和一些动态的

gdb查看core实用指令

1.$sudo gdb binpath corepath 2.bt 查看调用堆栈 3.f 5...假设断的代码在栈号为5这里 4.info locals 查看局部变量 5.info args 查看函数参数的值 6.info catch 查看异常 7.info r  查看寄存器 8.up,down切栈帧.. 注意locals,args等这些都跟当前栈帧是同步的

栈帧啊栈帧

栈帧!栈帧!今天就把栈帧给弄清楚!有一个函数调用关系-->main  -->print    -->add      -->funca        -->funcb          -->funcc在函数funcc函数处设置断点,由于用户态栈是由高到低扩展:当函数执行到(gdb) print $sp$1 = (void *) 0x7fffffffdb78然后打印出内存,0x7fffffffdb78:*0xffffdb90  0x00007fff  0x0040056

Linux中程序的栈帧分析以及修改函数地址

下面有一段代码: #include <stdio.h> #include <unistd.h> #include <stdlib.h> void fun() {    printf("i am the evil func\n");    exit(1); } int fun1(int a,int b) {     int *p=&a;     p--;     *p=fun;     int c=0xcccc;     return c; }

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

转载自地址:http://blog.csdn.net/zsy2020314/article/details/9429707       今天突然想分析一下函数在相互调用过程中栈帧的变化,还是想尽量以比较清晰的思路把这一过程描述出来,关于c函数调用原理的理解是很重要的. 1.关于栈 首先必须明确一点也是非常重要的一点,栈是向下生长的,所谓向下生长是指从内存高地址->低地址的路径延伸,那么就很明显了,栈有栈底和栈顶,那么栈顶的地址要比栈底低.对x86体系的CPU而言,其中 ---> 寄存器ebp(