[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的地址。
posted @ 2026-08-27 21:20  lfree  阅读(2)  评论(0)    收藏  举报