首先需要介绍一下,阅读此文需要有基本的汇编知识。
1、rbp(基址寄存器),rsp(堆栈寄存器),rip(指令寄存器).
2、程序执行时,没有遇到函数调用时,IP自增长,遇到函数调用时,
需要保存bp,ip寄存器到栈上,函数调用结束时,恢复。(这个过程的细节需要很清楚)
(注:因此需要简单描述一下,函数调用时的步骤。
第一,将函数执行完成后的下一条指令的地址存放进当前rsp的位置,(即结束时,ret命令利用此信息恢复rip)
第二,进入函数后,保存当前rsp到rbp寄存器中,原因是rsp需要随时变化(结束时,需要将堆栈位置还原) )
 
两年前,有XX专家,来讲述了一下关于无堆栈信息core文件的定位方法。
没有留下任何文档,也没有讲述原理。
告知了可以使用如下方法来进行排查:
根据寄存器rbp里的地址,对临近区域的内存进行排查,查询出最近的内容为0x004xxxxx的指令,
在gdb中用x/i 0x004xxxxx来查询为何指令(函数)。该函数可能为越界出现问题的地方,可以走查代码来排查。
之后,我也根据此线索推导出了原理,但一直没有形成总结。今天,详细说明此中原委。
 
软件平台:
No LSB modules are available.
Distributor ID:Ubuntu
Description:Ubuntu 12.04.3 LTS
Release:12.04
Codename:precise
 
简单程序如下:
#include <iostream>
using namespace std;
 
void test(int n)
{
    cout << n << endl;
    //rbp
    *(int*)(&n + 1) = 3;
    *(int*)(&n + 2) = 4;
    //rip
    *(int*)(&n + 3) = 4;
 
}
 
void caller()
{
    test(20);
    cout << "caller" << endl;
}
 
int main()
{
    caller();
    cout << "main" << endl;
    return 0;
}
 
----------------------------------------------
(gdb) x/32ux $rbp
0x7fffffffe510:0xffffe520 0x00007fff 0x00400865 0x00000000
0x7fffffffe520:0xffffe530 0x00007fff 0x0040088c 0x00000000
0x7fffffffe530:0x00000000 0x00000000 0xf773876d 0x00007fff
 ----------------------------------------------
(gdb) disas caller
Dump of assembler code for function caller():
   0x0000000000400857 <+0>:push   %rbp
   0x0000000000400858 <+1>:mov    %rsp,%rbp
   0x000000000040085b <+4>:mov    $0x14,%edi
   0x0000000000400860 <+9>:callq  0x400804 <test(int)>
   0x0000000000400865 <+14>:mov    $0x4009fc,%esi
   0x000000000040086a <+19>:mov    $0x601060,%edi
   0x000000000040086f <+24>:callq  0x4006f0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
   0x0000000000400874 <+29>:mov    $0x400710,%esi
   0x0000000000400879 <+34>:mov    %rax,%rdi
   0x000000000040087c <+37>:callq  0x400700 <_ZNSolsEPFRSoS_E@plt>
   0x0000000000400881 <+42>:pop    %rbp
   0x0000000000400882 <+43>:retq 
(gdb) disas main
Dump of assembler code for function main():
   0x0000000000400883 <+0>: push   %rbp
   0x0000000000400884 <+1>: mov    %rsp,%rbp
   0x0000000000400887 <+4>: callq  0x400857 <caller()>
   0x000000000040088c <+9>: mov    $0x400a03,%esi
   0x0000000000400891 <+14>: mov    $0x601060,%edi
   0x0000000000400896 <+19>: callq  0x4006f0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
   0x000000000040089b <+24>: mov    $0x400710,%esi
   0x00000000004008a0 <+29>: mov    %rax,%rdi
   0x00000000004008a3 <+32>: callq  0x400700 <_ZNSolsEPFRSoS_E@plt>
   0x00000000004008a8 <+37>: mov    $0x0,%eax
   0x00000000004008ad <+42>: pop    %rbp
   0x00000000004008ae <+43>: retq
 
根据$rbp表明,当前实际应该是执行到了 main()函数的0x000000000040088c <+9>: mov    $0x400a03,%esi的上一条指令(caller()函数)
的0x0000000000400865 <+14>:mov    $0x4009fc,%esi的上一条0x0000000000400860 <+9>:callq  0x400804 <test(int)>中。
 
在coredump以后。
------------------------------------------------------
(gdb) info register
rax            0x7fffffffe518 140737488348440
rbx            0x0 0
rcx            0x7ffff77fd910 140737345739024
rdx            0x0 0
rsi            0x7ffff7ad1ab0 140737348704944
rdi            0x7ffff7ad0260 140737348698720
rbp            0x400000003 0x400000003
rsp            0x7fffffffe520 0x7fffffffe520
r8             0x7ffff7202740 140737339467584
r9             0x7ffff7202740 140737339467584
r10            0x7fffffffe280 140737488347776
r11            0x7ffff7785c90 140737345248400
r12            0x400720 4196128
r13            0x7fffffffe610 140737488348688
r14            0x0 0
r15            0x0 0
rip            0x4 0x4
eflags         0x216 [ PF AF IF ]
cs             0x33 51
ss             0x2b 43
ds             0x0 0
es             0x0 0
fs             0x0 0
gs             0x0 0
------------------------------------------------------
根据core文件的寄存器信息,可知,bp及ip均已写飞。只能利用sp指针来查询。
------------------------------------------------------
(gdb) x/32ux $rsp
0x7fffffffe520: 0xffffe530 0x00007fff 0x0040088c 0x00000000
(gdb) x/i 0x0040088c
   0x40088c <main()+9>: mov    $0x400a03,%esi
(gdb) disas main
Dump of assembler code for function main():
   0x0000000000400883 <+0>: push   %rbp
   0x0000000000400884 <+1>: mov    %rsp,%rbp
   0x0000000000400887 <+4>: callq  0x400857 <caller()>
   0x000000000040088c <+9>: mov    $0x400a03,%esi
------------------------------------------------------
由此,可以查出是core在了main函数中。
 
例子使用的最简单的,实际测试时,会有多层调用,但是原理不变。
 
限制:如果越界的长度超过了函数调用堆栈的长度,本方法则不再可用。
 
以后补个图。今天就到这里了
 
 

core文件无堆栈信息定位的思路的更多相关文章

  1. GDB调试之core文件(如何定位到Segment fault)

    core dump又叫核心转储,当程序运行过程中发生异常,程序异常退出时,由操作系统把程序当前的内存状况存储在一个core文件中,叫core dump.(内部实现是:linux系统中内存越界会收到SI ...

  2. Core文件作用、设置及用法

    http://blog.csdn.net/lanmolei814/article/details/45201693 ====================================== 1.C ...

  3. 如何设置、查看以及调试core文件

    http://blog.csdn.net/xiaoxiaoniaoer1/article/details/7740820 1.core文件的生成开关和大小限制--------------------- ...

  4. Linux上调试core文件(Good)

    coredump文件 什么是coredump? 通常情况下coredmp包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息等.可以理解为把程序工作的当前状态存储成一个文件.许多程序和操作系统出 ...

  5. GDB调试core文件(2)

    使用gdb和core dump迅速定位段错误 关键字:gdb.段错误.core dump 一.什么是core dump core:内存.核心的意思: dump:抛出,扔出: core dump:前提: ...

  6. GDB Core,gdb 调试大全,core文件调试

    编译: gcc -g -o hello hello.c gdb 调试: 基本 gdb 命令. 命 令 描 述 小结:常用的gdb命令 backtrace 显示程序中的当前位置和表示如何到达当前位置的栈 ...

  7. Linux 如何使用gdb 查看core堆栈信息

    转载:http://blog.csdn.net/mergerly/article/details/41994207 core dump 一般是在segmentation fault(段错误)的情况下产 ...

  8. 如何在没有core文件的情况下用dmesg+addr2line定位段错误

    前言 在现网环境下,程序奔溃后不一定会留下core文件,原因有很多,比如存储空间不足就是其中一个常见的原因.此时我们只能依据linux记录的错误日志来定位问题. 涉及linux命令 本文涉及以下几条命 ...

  9. Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

    原文地址:http://www.javatang.com 前一段时间上线的系统升级之后,出现了严重的高CPU的问题,于是开始了一系列的优化处理之中,现在将这个过程做成一个系列的文章. 基本概念 在对J ...

随机推荐

  1. DoTA与人生

    一个dota菜鸟的人生感悟                接触Dota有了快3年之久,3年里可以经历很多东西,经历了很多东西之后就会有很多的感悟,有些感悟抽象的表达不出来,但是借助于dota,可以间接 ...

  2. 8VC Venture Cup 2016 - Elimination Round G. Raffles 线段树

    G. Raffles 题目连接: http://www.codeforces.com/contest/626/problem/G Description Johnny is at a carnival ...

  3. iOS 日志管理异常捕获组件LFLogManager

    一.功能 1.分级打印保存 解决一大堆重要.不重要打印信息在控制台混为一团的尴尬局面.可设置仅打印某级别及以上的信息.分为5类打印: DDLogError(@"打印并保存特别重要信息&quo ...

  4. word标题编号变成黑块

    把光标放置在黑块的后面 在键盘上按左方向键,则黑块变灰色(为选中状态) 然后ctrl+shift+s, 出现窗口“apply styles" 点击"reapply", 搞 ...

  5. BOOST 实用手册(摘录自校友博客)

    1. 序言 现在学的东西很容易忘记,写这篇文章的目的是能让我在需要时快速找回当时的感觉.  Let's BOOST THE WORLD . 2. 编译:VC2005注意 在 属性->C/C++- ...

  6. 关停后Bitfinex放贷初探

    据说Bitfinex放贷平均日息可达0.1%,现在就此做一番调研: 真的很先进,利率也像牌价一样挂卖: 1.美元利率为0.06%/天 2.美元利率最高,数币较低 参考资料:不买比特币也能赚钱,Bitf ...

  7. ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法

    在IE9,或IE10中ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法   把弹出框嵌入到jquery dialog中.可以解决 I did: // javascript f ...

  8. saltstack常用语法

    一.常用语法 1.添加用户 示例1: #添加zabbix用户和组 zabbix: group.present: - name: zabbix - gid: 1001 user.present: - f ...

  9. POJ 2664 Prerequisites?(简单题)

    [题意简述]:k:已经选择的科目数:m:选择的科目类别:c:能够选择的科目数.r:要求最少选择的科目数量 在输入的k和m以下的一行是选择的科目号. 比如: 3 2 //3是他选择了3科.2表示选择了两 ...

  10. 【转】php中的会话机制(2)

    原文:https://segmentfault.com/a/1190000000468220 发现,在调用session_start()的时候, session_start() 里面应该是有调用类似 ...