[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 }
--//对于这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 }
浙公网安备 33010602011771号