[20260920]跟踪那个oracle函数调用shmget(整理版本).txt

[20260920]跟踪那个oracle函数调用shmget(整理版本).txt

--//最近测试遇到斜线的问题,导致本地主机无法连接实例,突然想了解共享内存段Key值的计算,肯定是某种hash算法,开始使用
--//ora_hash函数盲猜,根本对不上。使用sqlplus登录连接数据库,确定在调用shmget时已经知道对应的key值,想确定到底那个
--//oracle内部函数调用shmget,测试遇到的问题,当时思路有点乱,重新整理做一个记录。

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.

$ ipcs -m
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 0          oracle     600        10485760   78
0x00000000 1          oracle     600        1140850688 78
0x00000000 2          oracle     600        8388608    78
0xafa94c20 3          oracle     600        2097152    78
--//ipcs -m 的输出key=0xafa94c20。

2.问题提出:
$ strace  -f  -e ipc  sqlplus -s -l / as sysdba <<<"host sleep 1"
strace: Process 3148 attached
[pid  3148] shmget(0xafa94c20, 0, 000)  = 3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[pid  3148] shmctl(3, IPC_STAT, {shm_perm={uid=54321, gid=54321, mode=0600, key=2947107872, cuid=54321, cgid=54321}, shm_segsz=2097152, shm_cpid=2695, shm_lpid=3141, shm_nattch=76, shm_atime=1789890965, shm_dtime=1789890966, shm_ctime=1789890505}) = 0
[pid  3148] shmat(3, NULL, 0)           = 0x7efcb2800000
[pid  3148] shmdt(0x7efcb2800000)       = 0
[pid  3148] shmget(0xafa94c21, 0, 000)  = -1 ENOENT (No such file or directory)
[pid  3148] shmget(0xafa94c22, 0, 000)  = -1 ENOENT (No such file or directory)
[pid  3148] shmget(0xafa94c23, 0, 000)  = -1 ENOENT (No such file or directory)
--//补充说明:不清楚为什么又做了shmget(0xafa94c21, 0, 000),shmget(0xafa94c22, 0, 000),shmget(0xafa94c23, 0, 000)三次尝
--//试失败,hash冲突吗?
--//然后使用shmat attach 共享内存段。
[pid  3148] shmat(3, 0xa6000000, 0)     = 0xa6000000
[pid  3148] shmat(1, 0x61000000, 0)     = 0x61000000
[pid  3148] shmat(2, 0xa5000000, 0)     = 0xa5000000
[pid  3148] shmat(0, 0x60000000, 0)     = 0x60000000
--//做了4次,最后通过跟踪确定参与计算的是/u01/app/oracle/product/21.0.0/dbhome_1book.pga_#$,从内容看似乎与pga相关。难道
--//pga也可以使用类似共享内存段吗?
[pid  3148] shmget(0xa93a2388, 0, 000)  = -1 ENOENT (No such file or directory)
[pid  3148] shmget(0xa93a2389, 0, 000)  = -1 ENOENT (No such file or directory)
[pid  3148] shmget(0xa93a238a, 0, 000)  = -1 ENOENT (No such file or directory)
[pid  3148] shmget(0xa93a238b, 0, 000)  = -1 ENOENT (No such file or directory)
[pid  3148] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x2} ---
strace: Process 3149 attached
[pid  3149] +++ exited with 0 +++
[pid  3147] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3149, si_uid=54321, si_status=0, si_utime=0, si_stime=0} ---

[pid  3148] shmdt(0x61000000)           = 0
[pid  3147] +++ exited with 0 +++
shmdt(0xa5000000)                       = 0
shmdt(0x60000000)                       = 0
shmdt(0xa6000000)                       = 0
+++ exited with 0 +++
--//看下划线调用shmget的第1个参数是0xafa94c20,返回shmid=3.想确定那个oracle内部函数调用shmget.

--//如果监测已经登录的oracle连接进程,无法知道那个oracle内部函数调用shmget.

$ gdb -f sqlplus
GNU gdb (CentOS Stream) 16.3-3.el9
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from sqlplus...
(No debugging symbols found in sqlplus)
(gdb) catch syscall shmget
Catchpoint 1 (syscall 'shmget' [29])
--//使用b shmget 类似。不知道两者存在什么区别。

(gdb) run / as sysdba
Starting program: /u01/app/oracle/product/21.0.0/dbhome_1/bin/sqlplus / as sysdba
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

SQL*Plus: Release 21.0.0.0.0 - Production on Sun Sep 20 16:13:08 2026
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

[Detaching after fork from child process 3388]

Connected to:
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SYS@book>
--//根本不行。

3.其他最先想到建立bpftrace脚本:
# cat shmget.bt
tracepoint:syscalls:sys_enter_shmget
//uprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgmget
/ pid == $1 || $1 == 0 /
{
    @stacks[ustack, comm] = count();
}

END
{
   printf("\n=== Top Stacks (sample count) ===\n");
   print(@stacks);
   clear(@stacks);
}

# bpftrace shmget.bt 0
Attached 2 probes
^C
=== Top Stacks (sample count) ===
@stacks[
        shmget+14
        skgmlocate+261
        skgmattach_primaryseg+234
        skgmattach_nondeferareas+313
        ksm_attach_sga+300
        ksmlsge_phaseone+449
        opimai_init+284
        opimai_real+356
        ssthrdmain+412
        main+292
        __libc_start_call_main+128
, oracle]: 4
@stacks[
        shmget+14
        skgmlocate+261
        skgmattach_primaryseg+234
        skgmattach_nondeferareas+313
        skgmattach+36
        ksmnfy+11816
        kscnfy+1212
        opiino+106
        opiodr+1256
        opidrv+1067
        sou2o+165
        opimai_real+400
        ssthrdmain+412
        main+292
        __libc_start_call_main+128
, oracle]: 4

--//一共执行8次,与前面strace跟踪可以对上.可以看出整个调用栈使用的函数.
--//注:实际上少了一个函数sskgmget.应该是skgmlocate调用sskgmget,sskgmget调用shmget.
--//后面+的数字是偏移量,反汇编代码很容易确定.

(gdb) disassemble skgmlocate
Dump of assembler code for function skgmlocate:
   0x0000000005790b80 <+0>:     xchg   %ax,%ax
   0x0000000005790b82 <+2>:     push   %rbp
   0x0000000005790b83 <+3>:     mov    %rsp,%rbp
   0x0000000005790b86 <+6>:     push   %r12
   0x0000000005790b88 <+8>:     push   %r13
   0x0000000005790b8a <+10>:    push   %r14
   0x0000000005790b8c <+12>:    push   %r15
   0x0000000005790b8e <+14>:    push   %rbx
...
   0x0000000005790c78 <+248>:   mov    -0x40(%rbp),%rdx
   0x0000000005790c7c <+252>:   mov    -0x50(%rbp),%r9
   0x0000000005790c80 <+256>:   call   0x57a67c0 <sskgmget>
   0x0000000005790c85 <+261>:   mov    %eax,%r9d
--//基本可以确定调用sskgmget调用shmget函数。

--//查看调用栈的函数skgmattach_primaryseg,反汇编skgmattach_primaryseg.

(gdb) disassemble skgmattach_primaryseg
Dump of assembler code for function skgmattach_primaryseg:
   0x00000000057905e0 <+0>:     xchg   %ax,%ax
   0x00000000057905e2 <+2>:     push   %rbp
   0x00000000057905e3 <+3>:     mov    %rsp,%rbp
   0x00000000057905e6 <+6>:     push   %r12
   0x00000000057905e8 <+8>:     push   %r13
   0x00000000057905ea <+10>:    push   %r14
   0x00000000057905ec <+12>:    push   %r15
   0x00000000057905ee <+14>:    push   %rbx
   0x00000000057905ef <+15>:    sub    $0x128,%rsp
   0x00000000057905f6 <+22>:    mov    %rdx,%r12
   0x00000000057905f9 <+25>:    mov    %rdi,%rbx
   0x00000000057905fc <+28>:    mov    %r12,%rdi
   0x00000000057905ff <+31>:    mov    %rsi,%r15
   0x0000000005790602 <+34>:    xor    %eax,%eax
   0x0000000005790604 <+36>:    mov    %rcx,-0x38(%rbp)
   0x0000000005790608 <+40>:    mov    0x100(%r12),%rsi
   0x0000000005790610 <+48>:    movl   $0xffffffff,-0x30(%rbp)
   0x0000000005790617 <+55>:    mov    %rax,-0x48(%rbp)
   0x000000000579061b <+59>:    movl   $0x0,-0x2c(%rbp)
   0x0000000005790622 <+66>:    mov    %rax,-0x40(%rbp)
   0x0000000005790626 <+70>:    call   0x57909b0 <skgmhash>
...

--//可以大致猜测计算使用skgmhash函数.

4.其他方法:
--//看了一些文档,发现如果strace版本足够高支持-k参数显示调用堆栈,加入--stack-trace-frame-limit=3参数显示前3个。
 $ strace  -Ttt -f  -k --stack-trace-frame-limit=3 -e shmget  sqlplus -s -l / as sysdba <<<"host sleep 2"
strace: Process 4995 attached
[pid  4995] 16:42:15.397617 shmget(0xafa94c20, 0, 000) = 7 <0.000050>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
--//strace 跟踪可以显示sskgmget,skgmlocate+0x104 0x104=260,与前面bpftrace出现1个偏移。
0x104
[pid  4995] 16:42:15.428965 shmget(0xafa94c21, 0, 000) = -1 ENOENT (No such file or directory) <0.000043>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
[pid  4995] 16:42:15.457011 shmget(0xafa94c22, 0, 000) = -1 ENOENT (No such file or directory) <0.000071>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
[pid  4995] 16:42:15.457278 shmget(0xafa94c23, 0, 000) = -1 ENOENT (No such file or directory) <0.000096>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
[pid  4995] 16:42:15.487191 shmget(0xa93a2388, 0, 000) = -1 ENOENT (No such file or directory) <0.000053>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
[pid  4995] 16:42:15.510547 shmget(0xa93a2389, 0, 000) = -1 ENOENT (No such file or directory) <0.000048>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
[pid  4995] 16:42:15.510785 shmget(0xa93a238a, 0, 000) = -1 ENOENT (No such file or directory) <0.000045>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
[pid  4995] 16:42:15.511006 shmget(0xa93a238b, 0, 000) = -1 ENOENT (No such file or directory) <0.000061>
 > /usr/lib64/libc.so.6(shmget+0xe) [0x111d5e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgmget+0x61) [0x57a6821]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgmlocate+0x104) [0x5790c84]
 > too many stack frames
[pid  4995] 16:42:15.532521 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x2} ---
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(slrac_can_access+0x1e) [0x1533043e]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(slaac_int+0x5a) [0x153300aa]
 > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgds_step_fast+0x3c) [0x153377ec]
 > too many stack frames
strace: Process 4998 attached
[pid  4998] 16:42:17.982119 +++ exited with 0 +++
[pid  4994] 16:42:17.982614 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4998, si_uid=54321, si_status=0, si_utime=0, si_stime=0} ---
 > /usr/lib64/libc.so.6(wait4+0x1a) [0xda1ba]
 > /u01/app/oracle/product/21.0.0/dbhome_1/lib/libsqlplus.so(safidcl+0x2eb) [0xb43cb]
 > /u01/app/oracle/product/21.0.0/dbhome_1/lib/libsqlplus.so(aficmd+0xb6b) [0x4318b]
 > too many stack frames

[pid  4994] 16:42:18.025387 +++ exited with 0 +++
16:42:18.050207 +++ exited with 0 +++

5.继续查资料:

$ objdump -d /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle | grep -A3 '<shmget@plt>'
0000000000e8b700 <shmget@plt>:
  e8b700:       ff 25 72 0c 37 19       jmpq   *0x19370c72(%rip)        # 1a1fc378 <shmget@GLIBC_2.2.5>
  e8b706:       68 6c 00 00 00          pushq  $0x6c
  e8b70b:       e9 20 f9 ff ff          jmpq   e8b030 <.plt>
--
 57a681d:       e8 de 4e 6e fb          callq  e8b700 <shmget@plt>
 57a6822:       83 f8 ff                cmp    $0xffffffff,%eax
 57a6825:       75 2c                   jne    57a6853 <sskgmget+0x93>
 57a6827:       c7 03 f5 69 00 00       movl   $0x69f5,(%rbx)
--
 57a695b:       e8 a0 4d 6e fb          callq  e8b700 <shmget@plt>
 57a6960:       4c 8b 5d b8             mov    -0x48(%rbp),%r11
 57a6964:       4c 8b 95 40 fd ff ff    mov    -0x2c0(%rbp),%r10
 57a696b:       89 45 c0                mov    %eax,-0x40(%rbp)
--
 5a0c80b:       e8 f0 ee 47 fb          callq  e8b700 <shmget@plt>
 5a0c810:       83 f8 ff                cmp    $0xffffffff,%eax
 5a0c813:       0f 85 0d 02 00 00       jne    5a0ca26 <dbnest_attach_int+0x366>
 5a0c819:       89 9d b8 eb ff ff       mov    %ebx,-0x1448(%rbp)
--
 5a0c84f:       e8 ac ee 47 fb          callq  e8b700 <shmget@plt>
 5a0c854:       83 f8 ff                cmp    $0xffffffff,%eax
 5a0c857:       0f 84 ad 01 00 00       je     5a0ca0a <dbnest_attach_int+0x34a>
 5a0c85d:       4c 8d 05 cc 72 8b 14    lea    0x148b72cc(%rip),%r8        # 1a2c3b30 <dbnest_root_shmid>
--
    13310426:   e8 d5 b2 b7 ed          callq  e8b700 <shmget@plt>
    1331042b:   89 c3                   mov    %eax,%ebx
    1331042d:   83 fb ff                cmp    $0xffffffff,%ebx
    13310430:   0f 84 35 01 00 00       je     1331056b <sskgtlp_create_shmseg+0x25b>
--
    13b280b0:   e8 4b 36 36 ed          callq  e8b700 <shmget@plt>
    13b280b5:   89 c7                   mov    %eax,%edi
    13b280b7:   41 89 3c 24             mov    %edi,(%r12)
    13b280bb:   83 ff ff                cmp    $0xffffffff,%edi
--
    13b6fe1e:   e8 dd b8 31 ed          callq  e8b700 <shmget@plt>
    13b6fe23:   41 89 c7                mov    %eax,%r15d
    13b6fe26:   41 83 ff ff             cmp    $0xffffffff,%r15d
    13b6fe2a:   0f 84 37 01 00 00       je     13b6ff67 <sskgsdsegmap+0x307>
--
    14557b46:   e8 b5 3b 93 ec          callq  e8b700 <shmget@plt>
    14557b4b:   89 45 c0                mov    %eax,-0x40(%rbp)
    14557b4e:   83 7d c0 00             cmpl   $0x0,-0x40(%rbp)
    14557b52:   0f 8d 68 02 00 00       jge    14557dc0 <snlpcss+0x4a0>
--//执行非常慢。

(gdb) x/3i 0x57a681d
   0x57a681d <sskgmget+93>:     call   0xe8b700 <shmget@plt>
   0x57a6822 <sskgmget+98>:     cmp    $0xffffffff,%eax
   0x57a6825 <sskgmget+101>:    jne    0x57a6853 <sskgmget+147>

--//也可以执行如下获得那个函数调用shmget。
(gdb) info symbol 0x57a681d
sskgmget + 93 in section .text of /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle   

(gdb) x/3i 0x5a0c80b
   0x5a0c80b <dbnest_attach_int+331>:   call   0xe8b700 <shmget@plt>
   0x5a0c810 <dbnest_attach_int+336>:   cmp    $0xffffffff,%eax
   0x5a0c813 <dbnest_attach_int+339>:   jne    0x5a0ca26 <dbnest_attach_int+870>

(gdb) x/3i 0x13310426
   0x13310426 <sskgtlp_create_shmseg+278>:      call   0xe8b700 <shmget@plt>
   0x1331042b <sskgtlp_create_shmseg+283>:      mov    %eax,%ebx
   0x1331042d <sskgtlp_create_shmseg+285>:      cmp    $0xffffffff,%ebx

(gdb) x/3i 0x13b280b0
   0x13b280b0 <peshmopg_Open_And_Attach_Shm_Segment+240>:       call   0xe8b700 <shmget@plt>
   0x13b280b5 <peshmopg_Open_And_Attach_Shm_Segment+245>:       mov    %eax,%edi
   0x13b280b7 <peshmopg_Open_And_Attach_Shm_Segment+247>:       mov    %edi,(%r12)

(gdb) x/3i 0x13b6fe1e
   0x13b6fe1e <sskgsdsegmap+446>:       call   0xe8b700 <shmget@plt>
   0x13b6fe23 <sskgsdsegmap+451>:       mov    %eax,%r15d
   0x13b6fe26 <sskgsdsegmap+454>:       cmp    $0xffffffff,%r15d

(gdb) x/3i 0x14557b46
   0x14557b46 <snlpcss+550>:    call   0xe8b700 <shmget@plt>
   0x14557b4b <snlpcss+555>:    mov    %eax,-0x40(%rbp)
   0x14557b4e <snlpcss+558>:    cmpl   $0x0,-0x40(%rbp)
   
--//这样就知道这些函数sskgmget,dbnest_attach_int,sskgtlp_create_shmseg,peshmopg_Open_And_Attach_Shm_Segment,
--//sskgsdsegmap,snlpcss调用shmget。

6.小结:
最简单的方法还是使用strace -k或者建立bpftrace脚本。

posted @ 2026-09-21 21:27  lfree  阅读(6)  评论(0)    收藏  举报