ITPub博客

首页 > 数据库 > Oracle > [20260703]跟踪library cache lock library cache pin的bpftrace脚本转换为bcc脚本

[20260703]跟踪library cache lock library cache pin的bpftrace脚本转换为bcc脚本

原创 Oracle 作者:lfree 时间:2026-07-09 20:57:36 0 删除 编辑

[20260703]跟踪library cache lock library cache pin的bpftrace脚本转换为bcc脚本

--//首先说明bcc的脚本不是我写的,是使用kimi生成,仅仅提供bpftrace脚本。
$ cat lkpn21c.bt
#!/usr/bin/env bpftrace
uprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kgllkal
/ $1 == 0 || pid == $1 /
{
    @lk++;
    printf("kgllkal count %02d -- handle address: %016lx, mode: %d ", @lk, arg2, arg3);
    printf("spid %d ",pid);
    printf("kglnaobj address: %s\n", str(arg2 + 0x1c8, 256));
}

uprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:kglpnal
/ $1 == 0 || pid == $1 /
{
    @pn++;
    printf("kglpnal count %02d -- handle address: %016lx, mode: %d ", @pn, arg2, arg3);
    printf("spid %d ",pid);
    printf("kglnaobj address: %s\n", str(arg2 + 0x1c8, 256));
}

--//希望生成bcc执行脚本。生成脚本保存为lkpn21c 设置权限755后执行。

# chmod 755 ./lkpn21c

--//执行报如下错误:

# ./lkpn21c 3156
Traceback (most recent call last):
  File "/home/oracle/study/202606/./lkpn21c", line 149, in <module>
    b.attach_uprobe(name=oracle_path, sym="kgllkal", fn_name="trace_kgllkal_entry")
  File "/usr/lib/python3.9/site-packages/bcc/__init__.py", line 1462, in attach_uprobe
    fn = self.load_func(fn_name, BPF.KPROBE)
  File "/usr/lib/python3.9/site-packages/bcc/__init__.py", line 535, in load_func
    raise Exception("Unknown program %s" % func_name)
Exception: Unknown program b'trace_kgllkal_entry'

--//将错误提示给kimi分析,给出建议删除前面static。
static int trace_kglpnal_entry(struct pt_regs *ctx)
--//修改为:
int trace_kglpnal_entry(struct pt_regs *ctx)

--//再次执行正常,但是输出乱码。修改
    data.handle = PT_REGS_PARM2(ctx);
    data.mode = PT_REGS_PARM3(ctx);
--//修改如下:
    data.handle = PT_REGS_PARM3(ctx);
    data.mode = PT_REGS_PARM4(ctx);

--//感觉AI应该不会犯这类低级的错误。再次执行正常,另外生成的时间不对,也许是时区导致的问题,取消输出。
--//感觉AI确实厉害,整个过程几乎没写一行代码,虽然存在错误,很快做了更正。

# /home/oracle/study/202606/lkpn21c 3392
Tracing Oracle kgllkal/kglpnal... Press Ctrl-C to stop.
Filter: PID = 3392

kgllkal count 04 -- handle address: 000000006d5f4b98, mode: 1 kglnaobj address: select * from dept where deptno=25
kglpnal count 02 -- handle address: 000000006d5f4b98, mode: 2 kglnaobj address: select * from dept where deptno=25
kgllkal count 05 -- handle address: 0000000072922f58, mode: 2 kglnaobj address: bookSYSCDB$ROOT
kgllkal count 06 -- handle address: 000000006ddc26b0, mode: 2 kglnaobj address: 1847639831SYSCDB$ROOT
kgllkal count 07 -- handle address: 000000006d7e87f8, mode: 2 kglnaobj address: f9f8a42e053dc04b9d42e6bb0296489b$BUILD$BOOK01P
kgllkal count 08 -- handle address: 000000006d7e85c8, mode: 1 kglnaobj address:
kglpnal count 03 -- handle address: 000000006d7e85c8, mode: 3 kglnaobj address:
kgllkal count 09 -- handle address: 0000000072922f58, mode: 2 kglnaobj address: bookSYSCDB$ROOT
kgllkal count 10 -- handle address: 000000006ddc26b0, mode: 2 kglnaobj address: 1847639831SYSCDB$ROOT
kgllkal count 11 -- handle address: 000000006d941e78, mode: 1 kglnaobj address: f9f8a42e053dc04b9d42e6bb0296489bChild:0BOOK01P
kglpnal count 04 -- handle address: 000000006d941e78, mode: 3 kglnaobj address: f9f8a42e053dc04b9d42e6bb0296489bChild:0BOOK01P
kgllkal count 12 -- handle address: 0000000063e376d0, mode: 1 kglnaobj address: SCOTTBOOK01P
kgllkal count 13 -- handle address: 0000000072922f58, mode: 2 kglnaobj address: bookSYSCDB$ROOT
kgllkal count 14 -- handle address: 000000006ddc26b0, mode: 2 kglnaobj address: 1847639831SYSCDB$ROOT
kgllkal count 15 -- handle address: 0000000063d60ed0, mode: 2 kglnaobj address: DEPTSCOTTBOOK01P@??c
kglpnal count 05 -- handle address: 0000000063d60ed0, mode: 2 kglnaobj address: DEPTSCOTTBOOK01P@??c
kgllkal count 16 -- handle address: 000000006fa2b558, mode: 2 kglnaobj address: 356430430180546253BOOK01P
kglpnal count 06 -- handle address: 000000006fa2b558, mode: 2 kglnaobj address: 356430430180546253BOOK01P
kgllkal count 17 -- handle address: 000000006fa76598, mode: 2 kglnaobj address: 7574277674127661070BOOK01P
kglpnal count 07 -- handle address: 000000006fa76598, mode: 2 kglnaobj address: 7574277674127661070BOOK01P
kgllkal count 18 -- handle address: 000000006fc062c8, mode: 2 kglnaobj address: 4204170303842060717BOOK01P
kglpnal count 08 -- handle address: 000000006fc062c8, mode: 2 kglnaobj address: 4204170303842060717BOOK01P
kgllkal count 19 -- handle address: 000000006fabe748, mode: 2 kglnaobj address: 5467474030038125289BOOK01P
kglpnal count 09 -- handle address: 000000006fabe748, mode: 2 kglnaobj address: 5467474030038125289BOOK01P
kgllkal count 20 -- handle address: 000000006fa76598, mode: 2 kglnaobj address: 7574277674127661070BOOK01P
kglpnal count 10 -- handle address: 000000006fa76598, mode: 2 kglnaobj address: 7574277674127661070BOOK01P

kgllkal count 21 -- handle address: 000000006d5f4b98, mode: 1 kglnaobj address: select * from dept where deptno=25
kgllkal count 22 -- handle address: 000000006d7e85c8, mode: 1 kglnaobj address:
kgllkal count 23 -- handle address: 0000000063d60ed0, mode: 2 kglnaobj address: DEPTSCOTTBOOK01P@??c
kglpnal count 11 -- handle address: 0000000063d60ed0, mode: 2 kglnaobj address: DEPTSCOTTBOOK01P@??c

kgllkal count 24 -- handle address: 000000006d5f4b98, mode: 1 kglnaobj address: select * from dept where deptno=25
kgllkal count 25 -- handle address: 000000006d7e85c8, mode: 1 kglnaobj address:

--//源代码如下:
$ cat lkpn21c
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
BCC script to trace Oracle kgllkal and kglpnal
Equivalent to the bpftrace script:
  uprobe:/u01/app/oracle/.../bin/oracle:kgllkal
  / $1 == 0 || pid == $1 /
  {
      @lk++;
      printf("kgllkal count %02d -- handle address: %016lx, mode: %d ", @lk, arg2, arg3);
      printf("kglnaobj address: %s\n", str(arg2 + 0x1c8, 256));
  }

Usage: sudo python3 trace_oracle_kgl.py [PID]
"""

from bcc import BPF
import sys
import ctypes as ct

# Parse PID from command line
target_pid = int(sys.argv[1]) if len(sys.argv) > 1 else 0

# BPF C program
bpf_text = r"""
#include <uapi/linux/ptrace.h>

struct data_t {
    u64 ts;
    u32 pid;
    u32 tid;
    u64 handle;
    u64 mode;
    u64 count;
    char type[8];       // "kgllkal" or "kglpnal"
    char obj[256];      // object name from kglnaobj
};

BPF_PERF_OUTPUT(events);

// Global counters (single-element arrays in map)
BPF_ARRAY(lk_counter, u64, 1);
BPF_ARRAY(pn_counter, u64, 1);

// NOTE: do NOT use 'static' for functions attached by attach_uprobe,
// otherwise BCC cannot find the program and raises:
// Exception: Unknown program b'trace_kgllkal_entry'

int trace_kgllkal_entry(struct pt_regs *ctx)
{
    u32 pid = bpf_get_current_pid_tgid() >> 32;

    // Filter by PID if specified
    u32 filter_pid = FILTER_PID;
    if (filter_pid != 0 && pid != filter_pid) {
        return 0;
    }

    struct data_t data = {};
    data.ts = bpf_ktime_get_ns();
    data.pid = pid;
    data.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
    data.handle = PT_REGS_PARM3(ctx);
    data.mode = PT_REGS_PARM4(ctx);

    // Increment global counter
    u32 idx = 0;
    u64 *cnt = lk_counter.lookup(&idx);
    if (cnt) {
        data.count = *cnt + 1;
        lk_counter.update(&idx, &data.count);
    } else {
        data.count = 1;
        u64 init = 1;
        lk_counter.update(&idx, &init);
    }

    // Set type
    __builtin_memcpy(data.type, "kgllkal", 8);

    // Read object name from handle + 0x1c8 offset (user memory)
    u64 obj_addr = data.handle + 0x1c8;
    bpf_probe_read_user_str(&data.obj, sizeof(data.obj), (void *)obj_addr);

    events.perf_submit(ctx, &data, sizeof(data));
    return 0;
}

int trace_kglpnal_entry(struct pt_regs *ctx)
{
    u32 pid = bpf_get_current_pid_tgid() >> 32;

    // Filter by PID if specified
    u32 filter_pid = FILTER_PID;
    if (filter_pid != 0 && pid != filter_pid) {
        return 0;
    }

    struct data_t data = {};
    data.ts = bpf_ktime_get_ns();
    data.pid = pid;
    data.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
    data.handle = PT_REGS_PARM2(ctx);
    data.mode = PT_REGS_PARM3(ctx);

    // Increment global counter
    u32 idx = 0;
    u64 *cnt = pn_counter.lookup(&idx);
    if (cnt) {
        data.count = *cnt + 1;
        pn_counter.update(&idx, &data.count);
    } else {
        data.count = 1;
        u64 init = 1;
        pn_counter.update(&idx, &init);
    }

    // Set type
    __builtin_memcpy(data.type, "kglpnal", 8);

    // Read object name from handle + 0x1c8 offset (user memory)
    u64 obj_addr = data.handle + 0x1c8;
    bpf_probe_read_user_str(&data.obj, sizeof(data.obj), (void *)obj_addr);

    events.perf_submit(ctx, &data, sizeof(data));
    return 0;
}
"""

# Replace FILTER_PID with actual value
bpf_text = bpf_text.replace('FILTER_PID', str(target_pid))

# Load BPF program
b = BPF(text=bpf_text)

# Attach uprobes
oracle_path = "/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle"

b.attach_uprobe(name=oracle_path, sym="kgllkal", fn_name="trace_kgllkal_entry")
b.attach_uprobe(name=oracle_path, sym="kglpnal", fn_name="trace_kglpnal_entry")

# Define output structure matching struct data_t
class Data(ct.Structure):
    _fields_ = [
        ("ts", ct.c_ulonglong),
        ("pid", ct.c_uint),
        ("tid", ct.c_uint),
        ("handle", ct.c_ulonglong),
        ("mode", ct.c_ulonglong),
        ("count", ct.c_ulonglong),
        ("type", ct.c_char * 8),
        ("obj", ct.c_char * 256),
    ]

# Print header
print("Tracing Oracle kgllkal/kglpnal... Press Ctrl-C to stop.")
if target_pid:
    print("Filter: PID = {}".format(target_pid))
print()

# Process events
def print_event(cpu, data, size):
    event = ct.cast(data, ct.POINTER(Data)).contents

    # Convert nanoseconds to HH:MM:SS
    secs = event.ts // 1000000000
    hh = int(secs // 3600 % 24)
    mm = int(secs // 60 % 60)
    ss = int(secs % 60)
    ts_str = "{:02d}:{:02d}:{:02d}".format(hh, mm, ss)

    obj_str = event.obj.decode('utf-8', 'replace').strip('\x00')
    type_str = event.type.decode('utf-8', 'replace').strip('\x00')

    print("{} count {:02d} -- handle address: {:016x}, mode: {} kglnaobj address: {}".format(
        type_str,
        event.count,
        event.handle,
        event.mode,
        obj_str
    ))

# Open perf buffer
b["events"].open_perf_buffer(print_event)

# Poll
while True:
    try:
        b.perf_buffer_poll()
    except KeyboardInterrupt:
        print("\n\nDone.")
        break

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-3175590/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7969264