[20260824]gdb的使用问题.txt
[20260824]gdb的使用问题.txt
--//想写一个gdb脚本跟踪oracle kqrhsh函数的调用,实际上以前也遇到类似情况,做一个记录:
1.环境:
SYS@book> @ ver2
==============================
PORT_STRING : x86_64/Linux 2.4.xx
VERSION : 21.0.0.0.0
BANNER : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID : 0
PL/SQL procedure successfully completed.
2.建立测试脚本:
$ cat dc_hash_test.gdb
set pagination off
break kqrhsh
commands
silent
printf "=== kqrhsh BEGIN ===\n"
continue
end
break kqrhsh
#break *0x000000001501a2df
commands
silent
finish
printf "=== kqrhsh END ===\n\n"
continue
end
3.测试:
--//session 1:
SYS@book> @ spid
==============================
SID : 30
SERIAL# : 900
PROCESS : 3156
SERVER : DEDICATED
SPID : 3157
PID : 8
P_SERIAL# : 6
KILL_COMMAND : alter system kill session '30,900' immediate;
PL/SQL procedure successfully completed.
SYS@book> select sid from v$mystat where rownum=1;
SID
----------
30
--//window 1:
$ gdb -f -p 3157 -x dc_hash_test.gdb
...
Breakpoint 1 at 0x1501a260
Breakpoint 2 at 0x1501a260
(gdb) c
Continuing.
=== kqrhsh BEGIN ===
=== kqrhsh BEGIN ===
=== kqrhsh BEGIN ===
=== kqrhsh BEGIN ===
--//看不见=== kqrhsh END ===
--//我开始理解2个断点地址一样,gdb选择第1个断点执行。
--//注解第1个断点代码。
$ cat dc_hash_test.gdb
set pagination off
#break kqrhsh
#commands
# silent
# printf "=== kqrhsh BEGIN ===\n"
# continue
#end
break kqrhsh
#break *0x000000001501a2df
commands
silent
finish
printf "=== kqrhsh END ===\n\n"
continue
end
--//重复测试:
(gdb) delete break 1
(gdb) delete break 2
(gdb) source dc_hash_test.gdb
Breakpoint 3 at 0x1501a260
(gdb) c
Continuing.
0x0000000015018bd7 in kqrpre2 ()
(gdb) c
Continuing.
0x0000000015018bd7 in kqrpre2 ()
(gdb) c
Continuing.
0x0000000015018bd7 in kqrpre2 ()
(gdb) c
Continuing.
--//执行gdb选择第2个断点执行,但是finish后后面的printf代码并没有执行。看了一些文档gdb对于这类情况并没有特别好的解决方
--//法。
(gdb) disassemble kqrhsh
Dump of assembler code for function kqrhsh:
0x000000001501a260 <+0>: xchg %ax,%ax
0x000000001501a262 <+2>: push %rbp
0x000000001501a263 <+3>: mov %rsp,%rbp
0x000000001501a266 <+6>: push %r12
0x000000001501a268 <+8>: push %r13
0x000000001501a26a <+10>: push %r14
0x000000001501a26c <+12>: push %rbx
0x000000001501a26d <+13>: sub $0x30,%rsp
0x000000001501a271 <+17>: mov %rdi,%r12
0x000000001501a274 <+20>: movzwl %dx,%ebx
0x000000001501a277 <+23>: mov %rsi,%r13
0x000000001501a27a <+26>: mov %r13,%rdi
0x000000001501a27d <+29>: xor %edx,%edx
0x000000001501a27f <+31>: mov %fs:0x0,%r14
0x000000001501a288 <+40>: mov 0x10(%r12),%rax
0x000000001501a28d <+45>: movzwl (%rax,%rbx,2),%esi
0x000000001501a291 <+49>: call 0x15320570 <kgghash>
0x000000001501a296 <+54>: mov %eax,%r8d
0x000000001501a299 <+57>: mov -0xed90(%r14),%rcx
0x000000001501a2a0 <+64>: test %rcx,%rcx
0x000000001501a2a3 <+67>: je 0x1501a5bf <kqrhsh+863>
0x000000001501a2a9 <+73>: cmpb $0x0,0x74d(%rcx)
0x000000001501a2b0 <+80>: je 0x1501a2cb <kqrhsh+107>
0x000000001501a2b2 <+82>: movzbl 0x74d(%rcx),%esi
0x000000001501a2b9 <+89>: lea 0x70c(%rcx),%rdi
0x000000001501a2c0 <+96>: mov %r8d,%edx
0x000000001501a2c3 <+99>: call 0x15320570 <kgghash>
0x000000001501a2c8 <+104>: mov %eax,%r8d
0x000000001501a2cb <+107>: test %r8d,%r8d
0x000000001501a2ce <+110>: je 0x1501a2e0 <kqrhsh+128>
0x000000001501a2d0 <+112>: mov %r8d,%eax
0x000000001501a2d3 <+115>: lea -0x20(%rbp),%rsp
0x000000001501a2d7 <+119>: pop %rbx
0x000000001501a2d8 <+120>: pop %r14
0x000000001501a2da <+122>: pop %r13
0x000000001501a2dc <+124>: pop %r12
0x000000001501a2de <+126>: pop %rbp
0x000000001501a2df <+127>: ret
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x000000001501a2e0 <+128>: mov $0x16b4eb10,%edi
0x000000001501a2e5 <+133>: mov $0x8,%esi
0x000000001501a2ea <+138>: xor %edx,%edx
....
--//通过反汇编导致执行ret的指令,记下前面地址。修改dc_hash_test.gdb文件如下:
$ cat dc_hash_test.gdb
set pagination off
break kqrhsh
commands
silent
printf "=== kqrhsh BEGIN ===\n"
continue
end
break *0x000000001501a2df
commands
silent
printf "=== kqrhsh END ===\n\n"
continue
end
--//注:记住删除finish那行。
--//window 1:
(gdb) delete break 3
(gdb) source dc_hash_test.gdb
Breakpoint 4 at 0x1501a260
Breakpoint 5 at 0x1501a2df
--//再次执行,OK。
(gdb) c
Continuing.
=== kqrhsh BEGIN ===
=== kqrhsh END ===
=== kqrhsh BEGIN ===
=== kqrhsh END ===
=== kqrhsh BEGIN ===
=== kqrhsh END ===
=== kqrhsh BEGIN ===
=== kqrhsh END ===
--//这样的缺点就是调式代码写死了,要反汇编知道ret的地址。
--//想写一个gdb脚本跟踪oracle kqrhsh函数的调用,实际上以前也遇到类似情况,做一个记录:
1.环境:
SYS@book> @ ver2
==============================
PORT_STRING : x86_64/Linux 2.4.xx
VERSION : 21.0.0.0.0
BANNER : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID : 0
PL/SQL procedure successfully completed.
2.建立测试脚本:
$ cat dc_hash_test.gdb
set pagination off
break kqrhsh
commands
silent
printf "=== kqrhsh BEGIN ===\n"
continue
end
break kqrhsh
#break *0x000000001501a2df
commands
silent
finish
printf "=== kqrhsh END ===\n\n"
continue
end
3.测试:
--//session 1:
SYS@book> @ spid
==============================
SID : 30
SERIAL# : 900
PROCESS : 3156
SERVER : DEDICATED
SPID : 3157
PID : 8
P_SERIAL# : 6
KILL_COMMAND : alter system kill session '30,900' immediate;
PL/SQL procedure successfully completed.
SYS@book> select sid from v$mystat where rownum=1;
SID
----------
30
--//window 1:
$ gdb -f -p 3157 -x dc_hash_test.gdb
...
Breakpoint 1 at 0x1501a260
Breakpoint 2 at 0x1501a260
(gdb) c
Continuing.
=== kqrhsh BEGIN ===
=== kqrhsh BEGIN ===
=== kqrhsh BEGIN ===
=== kqrhsh BEGIN ===
--//看不见=== kqrhsh END ===
--//我开始理解2个断点地址一样,gdb选择第1个断点执行。
--//注解第1个断点代码。
$ cat dc_hash_test.gdb
set pagination off
#break kqrhsh
#commands
# silent
# printf "=== kqrhsh BEGIN ===\n"
# continue
#end
break kqrhsh
#break *0x000000001501a2df
commands
silent
finish
printf "=== kqrhsh END ===\n\n"
continue
end
--//重复测试:
(gdb) delete break 1
(gdb) delete break 2
(gdb) source dc_hash_test.gdb
Breakpoint 3 at 0x1501a260
(gdb) c
Continuing.
0x0000000015018bd7 in kqrpre2 ()
(gdb) c
Continuing.
0x0000000015018bd7 in kqrpre2 ()
(gdb) c
Continuing.
0x0000000015018bd7 in kqrpre2 ()
(gdb) c
Continuing.
--//执行gdb选择第2个断点执行,但是finish后后面的printf代码并没有执行。看了一些文档gdb对于这类情况并没有特别好的解决方
--//法。
(gdb) disassemble kqrhsh
Dump of assembler code for function kqrhsh:
0x000000001501a260 <+0>: xchg %ax,%ax
0x000000001501a262 <+2>: push %rbp
0x000000001501a263 <+3>: mov %rsp,%rbp
0x000000001501a266 <+6>: push %r12
0x000000001501a268 <+8>: push %r13
0x000000001501a26a <+10>: push %r14
0x000000001501a26c <+12>: push %rbx
0x000000001501a26d <+13>: sub $0x30,%rsp
0x000000001501a271 <+17>: mov %rdi,%r12
0x000000001501a274 <+20>: movzwl %dx,%ebx
0x000000001501a277 <+23>: mov %rsi,%r13
0x000000001501a27a <+26>: mov %r13,%rdi
0x000000001501a27d <+29>: xor %edx,%edx
0x000000001501a27f <+31>: mov %fs:0x0,%r14
0x000000001501a288 <+40>: mov 0x10(%r12),%rax
0x000000001501a28d <+45>: movzwl (%rax,%rbx,2),%esi
0x000000001501a291 <+49>: call 0x15320570 <kgghash>
0x000000001501a296 <+54>: mov %eax,%r8d
0x000000001501a299 <+57>: mov -0xed90(%r14),%rcx
0x000000001501a2a0 <+64>: test %rcx,%rcx
0x000000001501a2a3 <+67>: je 0x1501a5bf <kqrhsh+863>
0x000000001501a2a9 <+73>: cmpb $0x0,0x74d(%rcx)
0x000000001501a2b0 <+80>: je 0x1501a2cb <kqrhsh+107>
0x000000001501a2b2 <+82>: movzbl 0x74d(%rcx),%esi
0x000000001501a2b9 <+89>: lea 0x70c(%rcx),%rdi
0x000000001501a2c0 <+96>: mov %r8d,%edx
0x000000001501a2c3 <+99>: call 0x15320570 <kgghash>
0x000000001501a2c8 <+104>: mov %eax,%r8d
0x000000001501a2cb <+107>: test %r8d,%r8d
0x000000001501a2ce <+110>: je 0x1501a2e0 <kqrhsh+128>
0x000000001501a2d0 <+112>: mov %r8d,%eax
0x000000001501a2d3 <+115>: lea -0x20(%rbp),%rsp
0x000000001501a2d7 <+119>: pop %rbx
0x000000001501a2d8 <+120>: pop %r14
0x000000001501a2da <+122>: pop %r13
0x000000001501a2dc <+124>: pop %r12
0x000000001501a2de <+126>: pop %rbp
0x000000001501a2df <+127>: ret
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x000000001501a2e0 <+128>: mov $0x16b4eb10,%edi
0x000000001501a2e5 <+133>: mov $0x8,%esi
0x000000001501a2ea <+138>: xor %edx,%edx
....
--//通过反汇编导致执行ret的指令,记下前面地址。修改dc_hash_test.gdb文件如下:
$ cat dc_hash_test.gdb
set pagination off
break kqrhsh
commands
silent
printf "=== kqrhsh BEGIN ===\n"
continue
end
break *0x000000001501a2df
commands
silent
printf "=== kqrhsh END ===\n\n"
continue
end
--//注:记住删除finish那行。
--//window 1:
(gdb) delete break 3
(gdb) source dc_hash_test.gdb
Breakpoint 4 at 0x1501a260
Breakpoint 5 at 0x1501a2df
--//再次执行,OK。
(gdb) c
Continuing.
=== kqrhsh BEGIN ===
=== kqrhsh END ===
=== kqrhsh BEGIN ===
=== kqrhsh END ===
=== kqrhsh BEGIN ===
=== kqrhsh END ===
=== kqrhsh BEGIN ===
=== kqrhsh END ===
--//这样的缺点就是调式代码写死了,要反汇编知道ret的地址。
浙公网安备 33010602011771号