GDBは、精度を切り替えフレームによってスタックフレームを登録した後

まず、問題

損傷したコアファイルの一部をデバッグレジスタ・スタックを使用している場合、あなたは分解を通じて、問題の原因を特定する必要があるかもしれませんが、この時点でレジスタの値が必要な手段であるかを決定します。しかし、情報REGのレジスタ・スタック・フレームを通して見たフレーム、によってスタックフレームを切り替えた後、それをレジスタの現在値はありますか?

二、GDB文書化

すべてのスタックフレーム遠くで終了した場合は 、その退避したレジスタを復元。ハードウェア・レジスタの本当の内容を見るために、あなたは(「フレーム0」と)最も内側のフレームを選択する必要があります。
要約すると、いくつかの値は揮発性レジスタと異なる場合がありスタックフレームとエラーの連続蓄積を展開します。それがここに記載されている:もし、外層によってスタックフレーム、揮発性レジスタの値を、より容易これらの不正確。
通常のABI準備金として呼び出し先で保存する必要がなく、いくつかのレジスタは(別名:「コール上書きさ」または「揮発性」レジスタ「の発信者は、保存されました」)。レジスタの値は、以降の被呼者によって変更された場合GDBは、レジスタ(外枠で言い換えれば、)呼び出し前の値を知ることがことが可能ではないかもしれません。GDBは、デバッグ情報から、どこに保存インナーフレーム(「呼び出し先保存」)レジスタ推測情報をくつろいだり、コンパイラによって生成されたマシンコードしようとします。いくつかのレジスタは、「呼び出し側で保存された」(ABIの独自の知識を経由して、またはデバッグ/くつろぐための情報は、明示的にレジスタの値が未定義であると言います)されて保存され、GDBは、レジスタを知っていない場合、GDBは「を表示し、<保存されません> 「レジスタの値として。GDBは、レジスタセーブ大会の知識を持たない目標では、レジスタは呼び出し先によって保存されなかった場合には、次いで、外枠内の値と位置は、内側フレームと同じであると仮定されます。レジスタはコール上書きされている場合、呼び出し側が呼び出しの後にレジスタ内にある、またはそれは気をしている値を復元するためのコードを持っている気にしないか、これは、通常は無害です。あなたが外枠に、このようなレジスタを変更した場合、あなたはまた、内枠に影響を与えることができることを、しかし、注意してください。また、より多くの「外」のフレームは、あなたが見ているで、より多くの可能性が高いコール上書きさレジスタの値は、それが実際に登録したばかりの呼び出し前の値を表していないという意味で、間違っていることがあります

第三に、デバッグ情報を生成

ソースファイルはコンパイラのより完全な情報、生成されたデバッグ情報がより完全であるため、相対的な、それはアセンブリ言語であれば、その後、より制限されることがデバッグ情報を生成します。:この問題を解決するために、実際には、コンパイルもデバッグ情報を生成するコンパイラを助けるために、いくつかの命令を挿入することができます
ジェネリック\ sysdep.h \のglibc-2.10.1 \ sysdeps
の#ifdef __ASSEMBLER__
機能はSYMというこれの最後に/ *マーク。プラットフォームは、使用されるONいくつかは
、正しいデバッグ情報を生成する。* /
END #ifndefの
END(SYM)の#define
の#endif

#ifndefのJUMPTARGET
の#define JUMPTARGET(SYM)SYM
#ENDIF

/ * Makros eh_frame情報をほどく生成します。* /
HAVE_ASM_CFI_DIRECTIVES IFDEF#
はcfi_startprocの.cfi_startprocの定義
#はcfi_endprocの.cfi_endprocの定義
#は(オフREG)cfi_def_cfaを定義.cfi_def_cfa REGオフ
#.cfi_def_cfa_register REGのcfi_def_cfa_register(REG)を定義
#はcfi_def_cfa_offset(オフ)を定義オフ.cfi_def_cfa_offset
(#はcfi_adjust_cfa_offsetを定義オフ)がオフ.cfi_adjust_cfa_offset
オフ#は、cfi_offset(REG、オフ).cfi_offset REGを定義
#はcfi_rel_offset(REG、オフ).cfi_rel_offset REGを定義オフ、
#はcfi_register(R1、R2)を定義.cfi_register R1、R2
#cfi_return_columnを定義する(REG) .cfi_return_columnのREGの
#はcfi_restore(REG).cfi_restore REGを定義します
#cfi_same_value(REG)を定義.cfi_same_value REG
#定義(REG)のREG .cfi_undefined cfi_undefined
#はcfi_remember_state .cfi_remember_stateの定義
cfi_restore_state .cfi_restore_state定義し位
cfi_window_save .cfi_window_saveを#定義

スキャン機能のプロローグを復元するために4つ、gdbのスタックフレーム

機能が開始されるとの情報が存在しない場合に眺め、GDBデバッグの実装の観点から、それだけでスキャンコマンドをプッシュします。
7.7-GDB \ GDB \ i386- tdep.c
静的CORE_ADDRの
i386_analyze_prologue(構造体*のgdbarchのgdbarch、
CORE_ADDR PC、CORE_ADDRのcurrent_pc、
構造体i386_frame_cache *キャッシュ)
{
PC = i386_skip_noop(PC)、
PC = i386_follow_jump(gdbarch、PC)、
PC = i386_analyze_struct_return(PC、current_pc、キャッシュ);
PC = i386_skip_probe(PC);
PC = i386_analyze_stack_align(PC、current_pc、キャッシュ);
PC = i386_analyze_frame_setup(gdbarch、PC、current_pc、キャッシュ);
i386_analyze_register_saves(PC、current_pc、キャッシュ)を返します。
}
静的CORE_ADDRの
i386_analyze_register_saves(CORE_ADDR PC、CORE_ADDRのcurrent_pc、
構造体i386_frame_cache *キャッシュ)
{
CORE_ADDR = 0をオフセット。
gdb_byteオペアンプ。
私はint型。

もし(cache->地元> 0)
のオフセット- = cache->地元の人々 。
用(i = 0; iは<8 && PC <current_pc; iは++)
{
IF(target_read_code(PC、&OP、1))
復帰PC。
もし(OP <0x50を|| OP> 0x57)
ブレーク。

オフセット- = 4。
cache-> saved_regs [OP - 0x50を] =オフセット。
cache-> sp_offset + = 4。
PC ++;
}

PCを返します。
}

レジスタの下で5つのテストの回復

試験方法は、フレームのコアレジスタが発生上面図にそれまで第一のスタックフレームの上面図およびブレークポイントレジスタに、コアを製造するためのものである
ハリー@ tsecer:CAT -n gdbframe.cppを
1つの#include <STDLIB.H>
2の#include < string.hの>
3。
4 int型のmain(int型ARGC、CHAR * ARGV [])。
5 {
6 PADDRチャー* = NULL;。
。7 IF(ARGC> 0)
。8 {
9 PADDR =(チャー*)のmalloc(0x100の);
10}
11他(ARGC> 2)IF
12 {で
13 PADDR =(チャー*)のmalloc(0x200から)である;
14}
15(I ++はI = 0をint型; Iは、0x100のを<)
{16
17 PADDR [-i] = 0;
18れます}
。19フリー(PADDR);
20 0を返すことで、
21}である
ハリー@ tsecer:G ++ -g gdbframe.cpp
tsecer @ハリー:GDB ./a.out
GNUのGDB(GDB)のRed Hat Enterprise Linux(7.2-75.el6)
著作権(C)2010 Free Software Foundationが、株式会社の
ライセンスGPLv3の+:GNU GPLバージョン3以降<http://gnu.org/licenses/gpl.html >
これはフリーソフトウェアです:あなたはそれを変更して再配布は自由です。
無保証は、法律で認められている範囲内に、ありません。「ショーのコピー」と入力
し、詳細については、「ショーの保証を」。
このGDBは、 "i686の-のredhat-のlinux-gnuの"として設定されました。
バグの報告方法については、以下を参照してください。
<http://www.gnu.org/software/gdb/bugs/> ...
/home/tsecer/CodeTest/gdbframe/a.out...doneからシンボルを読み込みます。
(GDB)19 B
ブレークポイント1 0x804850eで:ファイルgdbframe.cpp、ライン19
(GDB)R
プログラムの開始:

1ブレークポイント、メイン(ARGC = 1、ARGV = 0xbffff4c4)gdbframe.cppで:19
19フリー(PADDR)。
別のdebuginfos欠落、使用:のdebuginfo-インストールのglibc-2.12-1.149.el6.i686のlibgcc-4.4.7-11.el6.i686のlibstdc ++ - 4.4.7-11.el6.i686
(GDB)情報REG
EAX 0x8049f00 134520576
ECX 0x109 265
EDXの0x0の0
EBX 0x7e2ff4 8269812
ESP 0xbffff3f0 0xbffff3f0
EBP 0xbffff418 0xbffff418
ESI 0x0の0
のEDIは0x0 0
EIP 0x804850e 0x804850e <メイン(INT、CHAR **)+ 106>
EFLAGS 0x200246 [PF ZF IF ID]
CS 0x73 115
SS 123 0x7Bと
のDS 0x7Bと123個の
ES 0x7Bと123個
のFSは0x0 0
GS 0x33の51
C(GDB)
継続。
*** glibcの検出*** /home/tsecer/CodeTest/gdbframe/a.out:無料():無効なポインタ:0x0804a008 ***
=======バックトレース:=========
/lib/libc.so.6[0x6c1b91]
/home/tsecer/CodeTest/gdbframe/a.out[0x804851a]
/lib/libc.so.6(__libc_start_main+0xe6)[0x667d36]
/ホーム/ tsecer / CodeTest / gdbframe /a.out[0x8048411]
=======メモリマップ:========
00110000から00111000 R-XP 00000000 0時0 [VDSO]
0062b000-00649000 R-XP 00000000 8:02 135171 /lib/ld-2.12.so
00649000-0064a000 R - P 0001d000 8:02 135171 /lib/ld-2.12.so
0064a000-0064b000 RW-P 0001e000 8:02 135171 /lib/ld-2.12.so
00651000-007e1000 R-XP 00000000 8:02 135262 /lib/libc-2.12.so
007e1000-007e3000 R - P0019万8時02 135262 /lib/libc-2.12.so
007e3000-007e4000 RW-P 00192000 8時02分135262 /lib/libc-2.12.so
007e4000-007e7000 RW-P 00000000午前0時00 0
00818000から00840000 R-XP 00000000 8時02分135278 /lib/libm-2.12.so
0084万-00841000 R - P 00027000 8:02 135278 /lib/libm-2.12.so
00841000から00842000 RW-P 00028000 8:02 135278 /lib/libm-2.12.so
059be000-059db000 R-XP 00000000 8:02 135303 / LIB / libgcc_s-4.4.7-20120601.so.1
059db000-059dc000 RW-P 0001d000 8:02 135303 /lib/libgcc_s-4.4.7-20120601.so.1
059fa000-05adb000 R-XP 00000000 8:02 284438 / USR / libに/のlibstdc ++ so.6.0.13。
05adb000-05adf000 R - P 000e0000 8時02 284438 /usr/lib/libstdc++.so.6.0.13
05adf000-05ae1000 RW-P 000e4000 8時02 284438は/ usr / libに/libstdc++.so.6.0.13
05ae1000-05ae7000 RW-P 00000000 0時00分0
08048000-08049000 R-XP 00000000 8:02 302465 /home/tsecer/CodeTest/gdbframe/a.out
08049000-0804a000 RW-P 00000000 8:02 302465 /home/tsecer/CodeTest/gdbframe/a.out
0804a000-0806b000 RW -p 00000000午前0時0 [ヒープ]
b7fee000-b7ff1000のRW-P 00000000午前0時0
b7ffe000-b8000000 RW-P 00000000午前0時0
bffeb000-C0000000 RW-P 00000000午前0時0 [スタック]

プログラムは中止、信号SIGABRTを受けました。
__kernel_vsyscallで0x00110424()
BT(GDB)
__kernel_vsyscall位0 0x00110424()
レイズ第1位0x0067b871()/lib/libc.so.6から
アボート位2 0x0067d14a()/lib/libc.so.6のから
#3 __libc_messageで0x006bb735()/lib/libc.so.6から
malloc_printerr位4 0x006c1b91()/lib/libc.so.6から
19:gdbframe.cppで主に#5 0x0804851a(ARGC = 1、ARGV = 0xbffff4c4)
(GDB)F 5
gdbframe.cppで#主に5 0x0804851a(ARGC = 1、ARGV = 0xbffff4c4):19
19フリー(PADDR)。
(GDB)情報REGの
EAXは0x0 0
ECX 0x539f 21407
EDX 0x6に6
EBX 0x7e2ff4 8269812
ESP 0xbffff3f0 0xbffff3f0
EBP 0xbffff418 0xbffff418
ESIの0x0の0
のEDIは0x0 0
EIP 0x804851a 0x804851a <メイン(INT、CHAR **)+ 118>
EFLAGS 0x200246 [PF ZF IF ID]
CS 0x73 115
SS 123 0x7Bと
DS 0x7Bと123個の
ES 0x7Bと123個
のFSは0x0 0
GS 0x33の51
(GDB)

揮発性レジスタEAX、ECX、EDXの値が正しく復元されていないことがわかるレジスタのアウトプットコンペア
@ハリーtsecer:diffの現在のフレーム
1,3c1,3
<EAX 0x0の0
<ECX 0x539f 21407
。<EDXの0x6にを6
---
> EAX 0x8049f00 134 520 576
> 265 0x109 ECX
> 0は0x0 EDX
9c9
<0x804851a 0x804851a EIP <メイン(INT、CHAR **)+ 1 18>
---
> EIP 0x804850e 0x804850e <メイン(INT、CHAR **)+ 106>
tsecer @ハリー:

第六に、なぜ回復することはできません

(......)の場合

{
$ EAX = X
}

{
$ EAX = Y
}
funccall();
呼び出しがどの分岐に行くことである前に、フレームによってfunccallリターンを想定し、この時点では分からない、EAXレジスタを復元することは不可能です。プッシュと呼ばれている。むしろ揮発性レジスタ機能は、プロローグで保存されますので、回復は比較的簡単です。

おすすめ

転載: www.cnblogs.com/tsecer/p/11371549.html