[20260824]bpftrace的str和buf函数使用问题.txt

[20260824]bpftrace的str和buf函数使用问题.txt

--//使用bpftrace脚本使用str与buf函数遇到的问题,通过例子说明问题:

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.

$ bpftrace -V
bpftrace v0.24.2

2.测试bpftrace脚本:
$ cat dc_hash.bt
BEGIN
{
    printf("Tracing Oracle kgghash... Target PID: %d\n", $1);
    printf("Hit Ctrl-C to stop.\n\n");
}

uprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kqrhsh
/ $1 == 0 || pid == $1 /
{
        printf("\nkrqhsh Begin\n");
}

uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kqrhsh
/ $1 == 0 || pid == $1 /
{
        printf("krqhsh End\n");
}


uprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kgghash
/ $1 == 0 || pid == $1 /
{
    @kgg++;
    @is_kgg[pid] = 1;
//  printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x hash_text_ascii = ", strftime("%H:%M:%S", nsecs), @kgg, pid,str(arg0,arg1+1),arg1,arg2);
//      print(buf(str(arg0,arg1+1),arg1));
//  printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x \n", strftime("%H:%M:%S", nsecs), @kgg, pid,buf(str(arg0,arg1+1),arg1), arg1,arg2);
  printf("xxxx = %s %s %s\n",str(arg0,arg1),str(arg0,arg1+1),buf(arg0,arg1));

  printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x \n", strftime("%H:%M:%S", nsecs), @kgg, pid,buf(str(arg0,arg1+1),arg1), arg1,arg2);
//    printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x \n", strftime("%H:%M:%S", nsecs), @kgg, pid,buf(arg0,arg1), arg1,arg2);
}

uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kgghash
/ $1 == 0 || pid == $1 /
{
    if (@is_kgg[pid] == 1) {
        printf("[%s] kgghash #%02d pid=%d return hash_value=%016lx %ld %016lx %d\n", strftime("%H:%M:%S", nsecs), @kgg,pid, retval, retval, retval%32768,retval%32768);
        delete(@is_kgg[pid]);
    }
}

END
{
    printf("\nTotal kgghash: %d\n", @kgg);
    delete(@kgg);

}

--//执行:
SYS@book> @ spid
==============================
SID                           : 2
SERIAL#                       : 12100
PROCESS                       : 3218
SERVER                        : DEDICATED
SPID                          : 3219
PID                           : 8
P_SERIAL#                     : 9
KILL_COMMAND                  : alter system kill session '2,12100' immediate;
PL/SQL procedure successfully completed.

--//执行select sid from v$mystat  where rownum=1;多次,在使用bpftrace脚本跟踪。
SYS@book> select sid from v$mystat  where rownum=1;
       SID
----------
         2

--//执行输出如下:
# bpftrace ./dc_hash.bt 3219
Attached 6 probes
Tracing Oracle kgghash... Target PID: 3219
Hit Ctrl-C to stop.

xxxx = CDB$ROO CDB$ROOT CDB$ROOT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[09:30:16] kgghash #01 pid=3219 hash_text=CDB$ROOT length=8 seed=0
[09:30:16] kgghash #01 pid=3219 return hash_value=000000001eee6512 518939922 0000000000006512 25874
--//看下划线,arg1=8,str(arg0,arg1)的输出仅仅CDB$ROO,长度7。而修改为str(arg0,arg1+1),才是完整的输出。
--//可以看出str 参数2实际上输出长度 是 参数2-1.
--//而buf函数的输出参数2就是输出的长度,不过长度不足可以发现补充\x00,可以自行测试。

krqhsh Begin
xxxx =   \xc3\xc0\xff\xff
[09:30:16] kgghash #02 pid=3219 hash_text=\xc3\xc0\xff\xff length=4 seed=0
[09:30:16] kgghash #02 pid=3219 return hash_value=00000000f28adaf8 4069186296 0000000000005af8 23288
xxxx = CDB$ROO CDB$ROOT CDB$ROOT
[09:30:16] kgghash #03 pid=3219 hash_text=CDB$ROOT length=8 seed=f28adaf8
[09:30:16] kgghash #03 pid=3219 return hash_value=0000000046ad9a7a 1185782394 0000000000001a7a 6778
krqhsh End

krqhsh Begin
xxxx =   \xc3\xc0\xff\xff
[09:30:16] kgghash #04 pid=3219 hash_text=\xc3\xc0\xff\xff length=4 seed=0
[09:30:16] kgghash #04 pid=3219 return hash_value=00000000f28adaf8 4069186296 0000000000005af8 23288
xxxx = CDB$ROO CDB$ROOT CDB$ROOT
[09:30:16] kgghash #05 pid=3219 hash_text=CDB$ROOT length=8 seed=f28adaf8
[09:30:16] kgghash #05 pid=3219 return hash_value=0000000046ad9a7a 1185782394 0000000000001a7a 6778
krqhsh End

krqhsh Begin
xxxx =   \xfa\xc3\xff\xff
[09:30:16] kgghash #06 pid=3219 hash_text=\xfa\xc3\xff\xff length=4 seed=0
[09:30:16] kgghash #06 pid=3219 return hash_value=00000000368bf4a4 915141796 00000000000074a4 29860
xxxx = CDB$ROO CDB$ROOT CDB$ROOT
[09:30:16] kgghash #07 pid=3219 hash_text=CDB$ROOT length=8 seed=368bf4a4
[09:30:16] kgghash #07 pid=3219 return hash_value=0000000040d79a79 1087871609 0000000000001a79 6777
krqhsh End

krqhsh Begin
xxxx =   \xfa\xc3\xff\xff
[09:30:16] kgghash #08 pid=3219 hash_text=\xfa\xc3\xff\xff length=4 seed=0
[09:30:16] kgghash #08 pid=3219 return hash_value=00000000368bf4a4 915141796 00000000000074a4 29860
xxxx = CDB$ROO CDB$ROOT CDB$ROOT
[09:30:16] kgghash #09 pid=3219 hash_text=CDB$ROOT length=8 seed=368bf4a4
[09:30:16] kgghash #09 pid=3219 return hash_value=0000000040d79a79 1087871609 0000000000001a79 6777
krqhsh End
xxxx =

         \x0b\x00\x01\x00\x00\x00\x00\x00
[09:30:16] kgghash #10 pid=3219 hash_text=\x0b\x00\x00\x00\x00\x00\x00\x00 length=8 seed=0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[09:30:16] kgghash #10 pid=3219 return hash_value=00000000ceb5d99e 3468024222 000000000000599e 22942
^C
Total kgghash: 10
--//看xxxx出现折行,不过最后ascii码的输出是\x0b\x00\x01\x00\x00\x00\x00\x00,而下划线行输出
--//\x0b\x00\x00\x00\x00\x00\x00\x00. 两者存在完全不同。

--//执行的是buf(str(arg0,arg1+1),arg1),str(arg0,arg1+1),arg0地址指向的字符串包含\x00,导致被截断变成\x0b,
--//再执行buf时补齐变成了\x0b\x00\x00\x00\x00\x00\x00\x00,写代码有点画蛇添足了。直接写buf(arg0,arg1)就可以了。

--//修改后的脚本如下:
$ cat dc_hash.bt
BEGIN
{
    printf("Tracing Oracle kgghash... Target PID: %d\n", $1);
    printf("Hit Ctrl-C to stop.\n\n");
}

uprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kqrhsh
/ $1 == 0 || pid == $1 /
{
        printf("\nkrqhsh Begin\n");
}

uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kqrhsh
/ $1 == 0 || pid == $1 /
{
        printf("krqhsh End\n");
}


uprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kgghash
/ $1 == 0 || pid == $1 /
{
    @kgg++;
    @is_kgg[pid] = 1;
//  printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x hash_text_ascii = ", strftime("%H:%M:%S", nsecs), @kgg, pid,str(arg0,arg1+1),arg1,arg2);
//      print(buf(str(arg0,arg1+1),arg1));
//  printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x \n", strftime("%H:%M:%S", nsecs), @kgg, pid,buf(str(arg0,arg1+1),arg1), arg1,arg2);
//  printf("xxxx = %s %s %s\n",str(arg0,arg1),str(arg0,arg1+1),buf(arg0,arg1));

//  printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x \n", strftime("%H:%M:%S", nsecs), @kgg, pid,buf(str(arg0,arg1+1),arg1), arg1,arg2);
    printf("[%s] kgghash #%02d pid=%d hash_text=%s length=%d seed=%x \n", strftime("%H:%M:%S", nsecs), @kgg, pid,buf(arg0,arg1), arg1,arg2);
}

uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kgghash
/ $1 == 0 || pid == $1 /
{
    if (@is_kgg[pid] == 1) {
        printf("[%s] kgghash #%02d pid=%d return hash_value=%016lx %ld %016lx %d\n", strftime("%H:%M:%S", nsecs), @kgg,pid, retval, retval, retval%32768,retval%32768);
        delete(@is_kgg[pid]);
    }
}

END
{
    printf("\nTotal kgghash: %d\n", @kgg);
    delete(@kgg);

}


posted @ 2026-08-27 21:19  lfree  阅读(4)  评论(0)    收藏  举报