diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/autoconf-nameidata.c | 4 | ||||
-rw-r--r-- | runtime/autoconf-x86-uniregs.c | 6 | ||||
-rw-r--r-- | runtime/loc2c-runtime.h | 32 | ||||
-rw-r--r-- | runtime/procfs.c | 6 | ||||
-rw-r--r-- | runtime/regs.c | 79 | ||||
-rw-r--r-- | runtime/regs.h | 5 | ||||
-rw-r--r-- | runtime/stack-i386.c | 4 | ||||
-rw-r--r-- | runtime/staprun/ChangeLog | 5 | ||||
-rw-r--r-- | runtime/staprun/staprun_funcs.c | 2 | ||||
-rw-r--r-- | runtime/staprun/symbols.c | 13 | ||||
-rw-r--r-- | runtime/uprobes/uprobes.c | 72 |
11 files changed, 209 insertions, 19 deletions
diff --git a/runtime/autoconf-nameidata.c b/runtime/autoconf-nameidata.c new file mode 100644 index 00000000..c1d02400 --- /dev/null +++ b/runtime/autoconf-nameidata.c @@ -0,0 +1,4 @@ +#include <linux/namei.h> + +struct nameidata nd __attribute__ ((unused)) = {.path={(void *)0}}; + diff --git a/runtime/autoconf-x86-uniregs.c b/runtime/autoconf-x86-uniregs.c new file mode 100644 index 00000000..25729c22 --- /dev/null +++ b/runtime/autoconf-x86-uniregs.c @@ -0,0 +1,6 @@ +#include <asm/ptrace.h> + +#if defined (__i386__) || defined (__x86_64__) +struct pt_regs regs = {.ax = 0x0}; +#endif + diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index 8dbff764..4674e399 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -75,7 +75,37 @@ }) -#if defined __i386__ +#if defined (STAPCONF_X86_UNIREGS) && defined (__i386__) + +#define dwarf_register_0(regs) regs->ax +#define dwarf_register_1(regs) regs->cx +#define dwarf_register_2(regs) regs->dx +#define dwarf_register_3(regs) regs->bx +#define dwarf_register_4(regs) ((long) ®s->sp) +#define dwarf_register_5(regs) regs->bp +#define dwarf_register_6(regs) regs->si +#define dwarf_register_7(regs) regs->di + +#elif defined (STAPCONF_X86_UNIREGS) && defined (__x86_64__) + +#define dwarf_register_0(regs) regs->ax +#define dwarf_register_1(regs) regs->dx +#define dwarf_register_2(regs) regs->cx +#define dwarf_register_3(regs) regs->bx +#define dwarf_register_4(regs) regs->si +#define dwarf_register_5(regs) regs->di +#define dwarf_register_6(regs) regs->bp +#define dwarf_register_7(regs) regs->sp +#define dwarf_register_8(regs) regs->r8 +#define dwarf_register_9(regs) regs->r9 +#define dwarf_register_10(regs) regs->r10 +#define dwarf_register_11(regs) regs->r11 +#define dwarf_register_12(regs) regs->r12 +#define dwarf_register_13(regs) regs->r13 +#define dwarf_register_14(regs) regs->r14 +#define dwarf_register_15(regs) regs->r15 + +#elif defined __i386__ /* The stack pointer is unlike other registers. When a trap happens in kernel mode, it is not saved in the trap frame (struct pt_regs). diff --git a/runtime/procfs.c b/runtime/procfs.c index eb0f845c..1b1d5447 100644 --- a/runtime/procfs.c +++ b/runtime/procfs.c @@ -87,8 +87,14 @@ int _stp_mkdir_proc_module(void) goto done; } } else { + #ifdef STAPCONF_NAMEIDATA_CLEANUP + _stp_proc_stap = PDE(nd.path.dentry->d_inode); + path_put (&nd.path); + + #else _stp_proc_stap = PDE(nd.dentry->d_inode); path_release (&nd); + #endif } _stp_proc_root = proc_mkdir(THIS_MODULE->name, _stp_proc_stap); diff --git a/runtime/regs.c b/runtime/regs.c index bc717695..5e08e376 100644 --- a/runtime/regs.c +++ b/runtime/regs.c @@ -33,7 +33,13 @@ unsigned long _stp_ret_addr (struct pt_regs *regs) { -#ifdef __x86_64__ +#if defined (STAPCONF_X86_UNIREGS) && (defined (__x86_64__) || defined (__i386__)) + unsigned long *ra = (unsigned long *)regs->sp; + if (ra) + return *ra; + else + return 0; +#elif defined (__x86_64__) unsigned long *ra = (unsigned long *)regs->rsp; if (ra) return *ra; @@ -77,7 +83,76 @@ unsigned long _stp_ret_addr (struct pt_regs *regs) */ #define _stp_probe_addr_r(ri) (ri->rp->kp.addr) -#ifdef __x86_64__ +#if defined (STAPCONF_X86_UNIREGS) && defined (__x86_64__) + +void _stp_print_regs(struct pt_regs * regs) +{ + unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; + unsigned int fsindex,gsindex; + unsigned int ds,cs,es; + + _stp_printf("RIP: %016lx\nRSP: %016lx EFLAGS: %08lx\n", regs->ip, regs->sp, regs->flags); + _stp_printf("RAX: %016lx RBX: %016lx RCX: %016lx\n", + regs->ax, regs->bx, regs->cx); + _stp_printf("RDX: %016lx RSI: %016lx RDI: %016lx\n", + regs->dx, regs->si, regs->di); + _stp_printf("RBP: %016lx R08: %016lx R09: %016lx\n", + regs->bp, regs->r8, regs->r9); + _stp_printf("R10: %016lx R11: %016lx R12: %016lx\n", + regs->r10, regs->r11, regs->r12); + _stp_printf("R13: %016lx R14: %016lx R15: %016lx\n", + regs->r13, regs->r14, regs->r15); + + asm("movl %%ds,%0" : "=r" (ds)); + asm("movl %%cs,%0" : "=r" (cs)); + asm("movl %%es,%0" : "=r" (es)); + asm("movl %%fs,%0" : "=r" (fsindex)); + asm("movl %%gs,%0" : "=r" (gsindex)); + + rdmsrl(MSR_FS_BASE, fs); + rdmsrl(MSR_GS_BASE, gs); + rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); + + asm("movq %%cr0, %0": "=r" (cr0)); + asm("movq %%cr2, %0": "=r" (cr2)); + asm("movq %%cr3, %0": "=r" (cr3)); + asm("movq %%cr4, %0": "=r" (cr4)); + + _stp_printf("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", + fs,fsindex,gs,gsindex,shadowgs); + _stp_printf("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); + _stp_printf("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); +} + + #elif defined (STAPCONF_X86_UNIREGS) && defined (__i386__) + +void _stp_print_regs(struct pt_regs * regs) +{ + unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; + + _stp_printf ("EIP: %08lx\n",regs->ip); + _stp_printf ("ESP: %08lx\n",regs->sp); + _stp_printf ("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", + regs->ax,regs->bx,regs->cx,regs->dx); + _stp_printf ("ESI: %08lx EDI: %08lx EBP: %08lx", + regs->si, regs->di, regs->bp); + _stp_printf (" DS: %04x ES: %04x\n", + 0xffff & regs->ds,0xffff & regs->es); + + __asm__("movl %%cr0, %0": "=r" (cr0)); + __asm__("movl %%cr2, %0": "=r" (cr2)); + __asm__("movl %%cr3, %0": "=r" (cr3)); + /* This could fault if %cr4 does not exist */ + __asm__("1: movl %%cr4, %0 \n" + "2: \n" + ".section __ex_table,\"a\" \n" + ".long 1b,2b \n" + ".previous \n" + : "=r" (cr4): "0" (0)); + _stp_printf ("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); +} + +#elif defined (__x86_64__) void _stp_print_regs(struct pt_regs * regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; diff --git a/runtime/regs.h b/runtime/regs.h index 0887d628..c1e2344b 100644 --- a/runtime/regs.h +++ b/runtime/regs.h @@ -11,8 +11,11 @@ #ifndef _REGS_H_ /* -*- linux-c -*- */ #define _REGS_H_ +#if defined (STAPCONF_X86_UNIREGS) && (defined (__x86_64__) || defined (__i386__)) +#define REG_IP(regs) regs->ip +#define REG_SP(regs) regs->sp -#ifdef __x86_64__ +#elif defined (__x86_64__) #define REG_IP(regs) regs->rip #define REG_SP(regs) regs->rsp diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index 3675fc97..d73f4c84 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -21,7 +21,11 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) #ifdef CONFIG_FRAME_POINTER { + #ifdef STAPCONF_X86_UNIREGS + unsigned long ebp = regs->bp; + #elif unsigned long ebp = regs->ebp; + #endif while (_stp_valid_stack_ptr(context, (unsigned long)ebp)) { addr = *(unsigned long *)(ebp + 4); diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog index 3f373863..53545db2 100644 --- a/runtime/staprun/ChangeLog +++ b/runtime/staprun/ChangeLog @@ -1,3 +1,8 @@ +2008-01-21 Martin Hunt <hunt@redhat.com> + + * symbols.c (send_module): Simplify and use new send_data() function to keep + longword alignment. + 2008-01-14 Martin Hunt <hunt@redhat.com> PR4037 and fixes to better synchronize staprun and stapio. diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index ebf05b34..d1bba3f8 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -16,8 +16,6 @@ #include <grp.h> #include <pwd.h> -void cleanup(int rc); - void setup_staprun_signals(void) { struct sigaction a; diff --git a/runtime/staprun/symbols.c b/runtime/staprun/symbols.c index 5a4855b3..e33ee624 100644 --- a/runtime/staprun/symbols.c +++ b/runtime/staprun/symbols.c @@ -12,9 +12,8 @@ #include "staprun.h" /* send symbol data */ -static int send_data(void *data, int len) +static int send_data(int32_t type, void *data, int len) { - int32_t type = STP_SYMBOLS; if (write(control_channel, &type, 4) <= 0) return -1; return write(control_channel, data, len); @@ -158,11 +157,9 @@ static int send_module (char *mname) { char data[65536]; int len; - *(int32_t *)data = STP_MODULE; - len = get_sections(mname, data + sizeof(int32_t), - sizeof(data) - sizeof(int32_t)); + len = get_sections(mname, data, sizeof(data)); if (len > 0) { - if (write(control_channel, data, len + sizeof(int32_t)) <= 0) { + if (send_data(STP_MODULE, data, len) < 0) { _err("Loading of module %s failed. Exiting...\n", mname); return -1; } @@ -296,11 +293,11 @@ int do_kernel_symbols(void) goto err; /* send syms */ - if (send_data(syms, num_syms*struct_symbol_size) < 0) + if (send_data(STP_SYMBOLS, syms, num_syms*struct_symbol_size) < 0) goto err; /* send data */ - if (send_data(data_base, dataptr-data_base) < 0) + if (send_data(STP_SYMBOLS, data_base, dataptr-data_base) < 0) goto err; free(data_base); diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c index 50930709..501c4298 100644 --- a/runtime/uprobes/uprobes.c +++ b/runtime/uprobes/uprobes.c @@ -42,8 +42,14 @@ #define MAX_SSOL_SLOTS 1024 +#ifdef NO_ACCESS_PROCESS_VM_EXPORT +static int __access_process_vm(struct task_struct *tsk, unsigned long addr, + void *buf, int len, int write); +#define access_process_vm __access_process_vm +#else extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); +#endif static int utask_fake_quiesce(struct uprobe_task *utask); static void uprobe_release_ssol_vma(struct uprobe_process *uproc); @@ -1601,7 +1607,7 @@ static u32 uprobe_report_signal(struct utrace_attached_engine *engine, int hit_uretprobe_trampoline = 0; int registrations_deferred = 0; - utask = rcu_dereference((struct uprobe_task *)engine->data); + utask = (struct uprobe_task *)rcu_dereference(engine->data); BUG_ON(!utask); if (info->si_signo != BREAKPOINT_SIGNAL && @@ -1785,7 +1791,7 @@ static u32 uprobe_report_quiesce(struct utrace_attached_engine *engine, struct uprobe_task *utask; struct uprobe_process *uproc; - utask = rcu_dereference((struct uprobe_task *)engine->data); + utask = (struct uprobe_task *)rcu_dereference(engine->data); BUG_ON(!utask); uproc = utask->uproc; if (current == utask->quiesce_master) { @@ -1886,7 +1892,7 @@ static u32 uprobe_report_exit(struct utrace_attached_engine *engine, struct uprobe_probept *ppt; int utask_quiescing; - utask = rcu_dereference((struct uprobe_task *)engine->data); + utask = (struct uprobe_task *)rcu_dereference(engine->data); uproc = utask->uproc; uprobe_get_process(uproc); @@ -1965,7 +1971,7 @@ static u32 uprobe_report_clone(struct utrace_attached_engine *engine, struct uprobe_process *uproc; struct uprobe_task *ptask, *ctask; - ptask = rcu_dereference((struct uprobe_task *)engine->data); + ptask = (struct uprobe_task *)rcu_dereference(engine->data); uproc = ptask->uproc; /* @@ -2054,7 +2060,7 @@ static u32 uprobe_report_exec(struct utrace_attached_engine *engine, struct uprobe_task *utask; int uproc_freed; - utask = rcu_dereference((struct uprobe_task *)engine->data); + utask = (struct uprobe_task *)rcu_dereference(engine->data); uproc = utask->uproc; uprobe_get_process(uproc); @@ -2267,5 +2273,61 @@ static void zap_uretprobe_instances(struct uprobe *u, } #endif /* CONFIG_URETPROBES */ +#ifdef NO_ACCESS_PROCESS_VM_EXPORT +/* + * Some kernel versions export everything that uprobes.ko needs except + * access_process_vm, so we copied and pasted it here. Fortunately, + * everything it calls is exported. + */ +#include <linux/pagemap.h> +#include <asm/cacheflush.h> +static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) +{ + struct mm_struct *mm; + struct vm_area_struct *vma; + struct page *page; + void *old_buf = buf; + + mm = get_task_mm(tsk); + if (!mm) + return 0; + + down_read(&mm->mmap_sem); + /* ignore errors, just check how much was sucessfully transfered */ + while (len) { + int bytes, ret, offset; + void *maddr; + + ret = get_user_pages(tsk, mm, addr, 1, + write, 1, &page, &vma); + if (ret <= 0) + break; + + bytes = len; + offset = addr & (PAGE_SIZE-1); + if (bytes > PAGE_SIZE-offset) + bytes = PAGE_SIZE-offset; + + maddr = kmap(page); + if (write) { + copy_to_user_page(vma, page, addr, + maddr + offset, buf, bytes); + set_page_dirty_lock(page); + } else { + copy_from_user_page(vma, page, addr, + buf, maddr + offset, bytes); + } + kunmap(page); + page_cache_release(page); + len -= bytes; + buf += bytes; + addr += bytes; + } + up_read(&mm->mmap_sem); + mmput(mm); + + return buf - old_buf; +} +#endif #include "uprobes_arch.c" MODULE_LICENSE("GPL"); |