[20260922]gdb下使用catch syscall与break有什么区别.txt

[20260922]gdb下使用catch syscall与break有什么区别.txt

--//对于这2种方式有点混淆,在deepseek提问,给出的解答如下:

一句话总结:break shmget 是用户态函数断点,通常断在 glibc 的 shmget() 包装函数入口;catch syscall shmget 是系统调用捕获
点,断在真正的 shmget 系统调用进入/返回内核的边界。

主要区别:

------------------------------------------------------------------------------------------------------------------------------------
| 对比项  | break shmget                                  | catch syscall shmget                                                   |
|---------|-----------------------------------------------|------------------------------------------------------------------------|
| 类型    | 普通函数断点                                  | 系统调用 catchpoint                                                    |
| 断点位置| 用户态 shmget() 函数入口,一般是 libc wrapper | 系统调用入口/返回处,用户态与内核边界                                  |
| 依赖    | 需要程序/库里有 shmget 符号                   | 需要 GDB 认识 shmget 系统调用名或号,不依赖 libc 符号                  |
| 触发条件| 只有调用 shmget() 函数才触发                  | 任何执行 shmget 系统调用的路径都触发,包括直接 syscall(SYS_shmget, ...)|
| 停几次  | 通常只在函数入口停一次                        | 通常进入系统调用停一次,返回时再停一次                                 |
| 参数查看| 有调试信息时可直接 p key、p size、p shmflg    | 看寄存器,如 x86_64:$rdi、$rsi、$rdx                                  |
| 返回值  | 入口时没有返回值,需 finish 或断在返回点      | 返回停时看 $rax,是内核原始返回值                                      |
| errno   | finish 后 glibc 可能已设置 errno              | 返回停时 glibc 可能还没设置 errno                                      |
| 调用栈  | 用户态调用栈清晰                              | 在内核边界停,用户态栈仍在,但语义不同                                 |
| 性能    | 通常较小                                      | 通常较大,可能拦截所有系统调用事件                                     |
------------------------------------------------------------------------------------------------------------------------------------

--//通过例子验证看看。

1.环境:
SCOTT@book01p> @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 test2.gdb
set pagination off
set logging overwrite on
set logging on

catch syscall shmdt
commands
 silent
 printf "catch syscall shmdt %016x\n",$rdi
# bt 3
 c
 end

break shmdt
commands
 silent
 printf "break shmdt %016x\n",$rdi
# bt 3
 c
 end

SCOTT@book01p> @ spid
==============================
SID                           : 30
SERIAL#                       : 56330
PROCESS                       : 3766
SERVER                        : DEDICATED
SPID                          : 3768
PID                           : 8
P_SERIAL#                     : 15
KILL_COMMAND                  : alter system kill session '30,56330' immediate;
PL/SQL procedure successfully completed.

$ ipcs -m
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 0          oracle     600        10485760   55
0x00000000 1          oracle     600        1140850688 55
0x00000000 2          oracle     600        8388608    55
0xafa94c20 3          oracle     600        2097152    55

 $ pmap -x $(pgrep pmon) | grep -E "SYSV|Address"
Address           Kbytes     RSS   Dirty Mode  Mapping
0000000060000000   10240       0       0 rw-s- SYSV00000000 (deleted)
0000000061000000 1114112       0       0 rw-s- SYSV00000000 (deleted)
00000000a5000000    8192       0       0 rw-s- SYSV00000000 (deleted)
00000000a6000000    2048       0       0 rw-s- SYSVafa94c20 (deleted)

$ strace -Ttt -f  -e shmdt sqlplus -s -l / as sysdba <<<"host sleep 2"
strace: Process 4026 attached
[pid  4026] 09:51:06.687526 shmdt(0x7f96e8c00000) = 0 <0.000234>
[pid  4026] 09:51:06.743821 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x2} ---
strace: Process 4027 attached
[pid  4027] 09:51:09.198328 +++ exited with 0 +++
[pid  4025] 09:51:09.198595 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4027, si_uid=54321, si_status=0, si_utime=0, si_stime=0} ---

[pid  4025] 09:51:09.217364 +++ exited with 0 +++
09:51:09.233104 shmdt(0x61000000)       = 0 <0.000244>
09:51:09.233551 shmdt(0xa5000000)       = 0 <0.000135>
09:51:09.233903 shmdt(0x60000000)       = 0 <0.000250>
09:51:09.234368 shmdt(0xa6000000)       = 0 <0.000264>
09:51:09.248707 +++ exited with 0 +++
--//退出执行会调用4次shmdt操作。

$ gdb -f -p 4098 -x test2.gdb
...
Catchpoint 1 (syscall 'shmdt' [67])
Breakpoint 2 at 0x7f34e3911d20: file ../sysdeps/unix/sysv/linux/shmdt.c, line 28.
(gdb) c
Continuing.
break shmdt 0000000061000000
catch syscall shmdt 0000000061000000
catch syscall shmdt 0000000061000000
break shmdt 00000000a5000000
catch syscall shmdt 00000000a5000000
catch syscall shmdt 00000000a5000000
break shmdt 0000000060000000
catch syscall shmdt 0000000060000000
catch syscall shmdt 0000000060000000
break shmdt 00000000a6000000
catch syscall shmdt 00000000a6000000
catch syscall shmdt 00000000a6000000

--//可以看出先调用的是break shmdt,然后call syscall shmdt。
--//call syscall在进入退出时都执行1次。

--//如果执行bt 3,输出如下:
Catchpoint 1 (syscall 'shmdt' [67])
Breakpoint 2 at 0x7f3b61d11d20: file ../sysdeps/unix/sysv/linux/shmdt.c, line 28.
(gdb) c
Continuing.
break shmdt 0000000061000000
#0  shmdt (shmaddr=0x61000000) at ../sysdeps/unix/sysv/linux/shmdt.c:28
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
catch syscall shmdt 0000000061000000
#0  shmdt (shmaddr=0x61000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
catch syscall shmdt 0000000061000000
#0  shmdt (shmaddr=0x61000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
break shmdt 00000000a5000000
#0  shmdt (shmaddr=0xa5000000) at ../sysdeps/unix/sysv/linux/shmdt.c:28
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
catch syscall shmdt 00000000a5000000
#0  shmdt (shmaddr=0xa5000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
catch syscall shmdt 00000000a5000000
#0  shmdt (shmaddr=0xa5000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
break shmdt 0000000060000000
#0  shmdt (shmaddr=0x60000000) at ../sysdeps/unix/sysv/linux/shmdt.c:28
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
catch syscall shmdt 0000000060000000
#0  shmdt (shmaddr=0x60000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
catch syscall shmdt 0000000060000000
#0  shmdt (shmaddr=0x60000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x00000000057941a2 in skgmdtmany ()
break shmdt 00000000a6000000
#0  shmdt (shmaddr=0xa6000000) at ../sysdeps/unix/sysv/linux/shmdt.c:28
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x0000000005794346 in skgmdtprimary ()
catch syscall shmdt 00000000a6000000
#0  shmdt (shmaddr=0xa6000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x0000000005794346 in skgmdtprimary ()
catch syscall shmdt 00000000a6000000
#0  shmdt (shmaddr=0xa6000000) at ../sysdeps/unix/sysv/linux/shmdt.c:30
#1  0x00000000057a5d00 in sskgmdt ()
#2  0x0000000005794346 in skgmdtprimary ()

$ nl -ba /usr/src/debug/glibc-2.34-270.el9.x86_64/sysdeps/unix/sysv/linux/shmdt.c
     1  /* Copyright (C) 1995-2021 Free Software Foundation, Inc.
     2     This file is part of the GNU C Library.
     3     Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
     4
     5     The GNU C Library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9
    10     The GNU C Library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with the GNU C Library; if not, see
    17     <https://www.gnu.org/licenses/>.  */
    18
    19  #include <ipc_priv.h>
    20  #include <sysdep.h>
    21  #include <errno.h>
    22
    23  /* Detach shared memory segment starting at address specified by SHMADDR
    24     from the caller's data segment.  */
    25
    26  int
    27  shmdt (const void *shmaddr)
    28  {
~~~~~~~
    29  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
    30    return INLINE_SYSCALL_CALL (shmdt, shmaddr);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    31  #else
    32    return INLINE_SYSCALL_CALL (ipc, IPCOP_shmdt, 0, 0, 0, shmaddr);
    33  #endif
    34  }


posted @ 2026-09-22 21:10  lfree  阅读(4)  评论(0)    收藏  举报