Hello, I'm debugging a problem for which kprobes may potentially provide useful information, in particular I would like to examine local registers at some point in the kernel code. Unfortunately, while trying to accomplish that I ran into an issue I can't quite explain: whenever I try to access %fp register (a.k.a. %i6) from kprobe using regs->u_regs[UREG_FP], I get an unaligned value, which makes me think that it's incorrect somehow. Attached is the source for the kernel module I'm trying to use, in particular it does: unsigned long i1 = regs->u_regs[UREG_I1]; unsigned long fp = regs->u_regs[UREG_FP]; unsigned long l1 = ((struct reg_window *)fp)->locals[1]; It produces the following typical output in dmesg: [ 9266.907644] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e38d8 l1=0x (null) [ 9268.820759] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e1c40 l1=0x (null) [ 9268.955814] pre_handler: fp=0xfffff8007e46f6a1 i1=0x00000000ff9e18a0 l1=0x00000000910e5800 [ 9269.088810] pre_handler: fp=0xfffff8007e46f6a1 i1=0x00000000ff9e1930 l1=0x0000000079480000 [ 9269.220502] pre_handler: fp=0xfffff8007e0bb481 i1=0xfffff8007e0bb5e1 l1=0x0000000079480000 [ 9269.236789] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e1ba8 l1=0x (null) [ 9269.288737] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e1c40 l1=0x (null) [ 9269.291008] pre_handler: fp=0xfffff8007ba9f6a1 i1=0x00000000ff9e18a0 l1=0x0000000079480000 [ 9269.291972] pre_handler: fp=0xfffff8007ba9f6a1 i1=0x00000000ff9e1930 l1=0x0000000079480000 [ 9269.299812] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e1ba8 l1=0x (null) [ 9270.620905] log_unaligned: 9 callbacks suppressed [ 9270.710417] Kernel unaligned access at TPC[104be02c] handler_pre+0x1c/0x28 [kprobe_example] [ 9270.845112] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e1c40 l1=0x (null) [ 9270.982455] Kernel unaligned access at TPC[104be02c] handler_pre+0x1c/0x28 [kprobe_example] [ 9271.118699] pre_handler: fp=0xfffff8007f4bb6a1 i1=0x00000000ff9e18a0 l1=0x000000004209d400 [ 9271.256401] Kernel unaligned access at TPC[104be02c] handler_pre+0x1c/0x28 [kprobe_example] [ 9271.394431] pre_handler: fp=0xfffff8007f4bb6a1 i1=0x00000000ff9e1930 l1=0x0000000079480000 [ 9271.400409] Kernel unaligned access at TPC[104be02c] handler_pre+0x1c/0x28 [kprobe_example] [ 9271.400427] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e1ba8 l1=0x (null) [ 9271.812270] Kernel unaligned access at TPC[104be02c] handler_pre+0x1c/0x28 [kprobe_example] [ 9271.953992] pre_handler: fp=0xfffff8007f0676a1 i1=0x00000000ff9e38d8 l1=0x (null) While value of %i1 is believable (in this case it's the stack_start, second argument to sparc_do_fork, and appears to be valid 32-bit userspace address), I can't imagine that %fp can really be unaligned like this, so I have little trust in the %l1 value it's producing. Is it expected and I'm doing something wrong, or do we have an issue with saving %fp value somewhere? Best regards, -- Jurij Smakov jurij@xxxxxxxxx Key: http://www.wooyd.org/pgpkey/ KeyID: C99E03CC
#include <linux/kernel.h> #include <linux/module.h> #include <linux/kprobes.h> static struct kprobe kp = { .symbol_name = "sparc_do_fork", }; /* kprobe pre_handler: called just before the probed instruction is executed */ static int handler_pre(struct kprobe *p, struct pt_regs *regs) { unsigned long i1 = regs->u_regs[UREG_I1]; unsigned long fp = regs->u_regs[UREG_FP]; unsigned long l1 = ((struct reg_window *)fp)->locals[1]; printk(KERN_INFO "pre_handler: fp=0x%p i1=0x%p l1=0x%p\n", (void *) fp, (void *) i1, (void *) l1); return 0; } static void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) { } static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) { /* printk(KERN_INFO "fault_handler: p->addr = 0x%p, trap #%dn", p->addr, trapnr); */ /* Return 0 because we don't handle the fault. */ return 0; } static int __init kprobe_init(void) { int ret; kp.pre_handler = handler_pre; kp.post_handler = handler_post; kp.fault_handler = handler_fault; ret = register_kprobe(&kp); if (ret < 0) { printk(KERN_INFO "register_kprobe failed, returned %d\n", ret); return ret; } printk(KERN_INFO "Planted kprobe at %p\n", kp.addr); return 0; } static void __exit kprobe_exit(void) { unregister_kprobe(&kp); printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr); } module_init(kprobe_init) module_exit(kprobe_exit) MODULE_LICENSE("GPL");