diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2008-05-14 14:35:48 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-05-14 14:35:48 -0400 |
commit | 0fe2b97c7b967d833b5588dbf1ef763bb4440ed3 (patch) | |
tree | fcce9345c9ebacb7d5bc1f510f155bfdcea08dc4 | |
parent | a007b4068d20af2d4488d54bf3ef2edbf47f2f06 (diff) | |
parent | c3799d720b60bd74a60de4addcd0d77a90f7842a (diff) | |
download | systemtap-steved-0fe2b97c7b967d833b5588dbf1ef763bb4440ed3.tar.gz systemtap-steved-0fe2b97c7b967d833b5588dbf1ef763bb4440ed3.tar.xz systemtap-steved-0fe2b97c7b967d833b5588dbf1ef763bb4440ed3.zip |
Merge commit 'origin/master' into pr6429-comp-unwindsyms
* commit 'origin/master':
PR 5955 - Accept ; terminated globals
Factored returnval() out of returnstr(), for use in dwarfless probing.
Converted more aliases to use arg numbers instead of names. In particular,
Revert "PR6487: extend blacklist with relay/timer subsystem"
Add syscalls_by_pid.meta, syscalls_by_proc.meta,
PR6487: extend blacklist with relay/timer subsystem
Adjust iotime.meta description.
* iotime.meta: New.
Fix for PR 6500.
Update ChangeLog
* sleeptime.meta, wait4time.meta: New.
systemtap.examples futexes.meta change futex.stp to futexes.stp.
In ioblock.stp ioblock.end set bytes_done depending on kernel version.
PR6492: make listing mode warning-free
PR5648: Fix unaligned access warning in stp_print_flush on ia64
PR5648: Fix memcpy's endianess issue.
futexes.meta, nettop.meta, pf2.meta: New.
Clean up output.
35 files changed, 905 insertions, 540 deletions
@@ -1,11 +1,31 @@ -2008-05-06 Jim Keniston <jkenisto@us.ibm.com> +2008-05-13 Ananth N Mavinakayanahalli <ananth@in.ibm.com> + PR 5955. + * parse.cxx (parser::parse_global): accept ";" terminated globals + * NEWS - update documentation + * testsuite/systemtap.base/global_vars.(stp/exp) - supporting tests + * testsuite/parseko/twenty(four/five).stp - supporting tests +2008-05-12 Jim Keniston <jkenisto@us.ibm.com> + + PR 4311 - Function boundary tracing without debuginfo: Phase II + Merged dwarfless branch into mainline. But first... + * runtime/regs.c: Removed register name:value lookup facility. + Moved basically all register-lookup code to the i686 and x86_64 + registers.stp tapsets. Args stuff shared between i386 and + x86_64 remains in regs.c. + * tapset/{i686,x86_64}/registers.stp: Moved register-lookup + code from runtime/regs.c to here. + +2008-05-12 Jim Keniston <jkenisto@us.ibm.com> + + (2008-05-06 in dwarfless branch) PR 4311 - Function boundary tracing without debuginfo: Phase II * stapfuncs.5.in: Added sections on CPU REGISTERS and NUMBERED FUNCTION ARGUMENTS. -2008-05-05 Jim Keniston <jkenisto@us.ibm.com> +2008-05-12 Jim Keniston <jkenisto@us.ibm.com> + (2008-05-05 in dwarfless branch) PR 4311 - Function boundary tracing without debuginfo: Phase II * runtime/regs.c: Added register name:value lookup facility. Added support for register and arg lookup for i386 and x86_64. @@ -16,8 +36,9 @@ * tapset/nd_syscall.stp: syscall.stp migrating toward numbered args rather than named args. -2008-04-18 Jim Keniston <jkenisto@us.ibm.com> +2008-05-12 Jim Keniston <jkenisto@us.ibm.com> + (2008-04-18 in dwarfless branch) PR 4311 - Function boundary tracing without debuginfo: Phase I * tapsets.cxx: Major rework of dwflpp, dwarf_query, and related code to make do with elf info if dwarf info is absent, or @@ -28,6 +49,12 @@ * hash.cxx, session.h, stap.1.in: Added --kelf, --kmap, --ignore-vmlinux, and --ignore-dwarf. * testsuite/{semok,semko}/nodwf*.stp + +2008-05-07 Frank Ch. Eigler <fche@elastic.org> + + PR 6492. + * main.cxx (main): let -l imply -w. + 2008-05-05 Frank Ch. Eigler <fche@elastic.org> PR 444886. From <crquan@gmail.com>: @@ -26,6 +26,11 @@ probe process(PID).syscall.return { } probe process("PATH").syscall.return { } +- Globals now accept ; terminators + + global odds, evens; + global little[10], big[5]; + * What's new in version 0.6 - A copy of the systemtap tutorial and language reference guide @@ -549,6 +549,7 @@ main (int argc, char * const argv []) break; case 'l': + s.suppress_warnings = true; s.listing_mode = true; s.last_pass = 2; if (have_script) @@ -559,6 +560,7 @@ main (int argc, char * const argv []) } cmdline_script = string("probe ") + string(optarg) + " {}"; have_script = true; + break; case 0: switch (long_opt) @@ -1215,6 +1215,9 @@ parser::parse_global (vector <vardecl*>& globals, vector<probe*>&) t = peek (); } + if (t && t->type == tok_operator && t->content == ";") // termination + next(); + if (t && t->type == tok_operator && t->content == ",") // next global { next (); diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 8410b918..aab6a862 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,25 @@ +2008-05-08 David Smith <dsmith@redhat.com> + + PR 6500. + * task_finder.c (__stp_utrace_task_finder_report_exec): Moved + attach logic to __stp_utrace_attach_match_filename(). + (__stp_utrace_attach_match_filename): New function. + (__stp_utrace_task_finder_report_clone): Calls + __stp_utrace_attach_match_filename() to attach to newly cloned + threads. + +2008-05-06 Masami Hiramatsu <mhiramat@redhat.com> + + PR 5648 + * print_old.c (stp_print_flush): Fix unaligned access warning on + ia64. + * print_new.c (stp_print_flush): Ditto. + +2008-05-06 Masami Hiramatsu <mhiramat@redhat.com> + + PR 5648 + * vsprintf.c (_stp_vsnprintf): Fix memcpy's endianess issue. + 2008-05-05 Frank Ch. Eigler <fche@elastic.org> PR 6481. diff --git a/runtime/print_new.c b/runtime/print_new.c index 75bbd82b..07af2e33 100644 --- a/runtime/print_new.c +++ b/runtime/print_new.c @@ -40,11 +40,13 @@ void EXPORT_FN(stp_print_flush) (_stp_pbuf *pb) else atomic_inc (&_stp_transport_failures); #else - struct _stp_trace *t = relay_reserve(_stp_utt->rchan, sizeof(*t) + len); - if (likely(t)) { - t->sequence = _stp_seq_inc(); - t->pdu_len = len; - memcpy((void *) t + sizeof(*t), pb->buf, len); + void *buf = relay_reserve(_stp_utt->rchan, + sizeof(struct _stp_trace) + len); + if (likely(buf)) { + struct _stp_trace t = { .sequence = _stp_seq_inc(), + .pdu_len = len}; + memcpy(buf, &t, sizeof(t)); // prevent unaligned access + memcpy(buf + sizeof(t), pb->buf, len); } else atomic_inc (&_stp_transport_failures); #endif diff --git a/runtime/print_old.c b/runtime/print_old.c index 5ee050b5..5c117e5f 100644 --- a/runtime/print_old.c +++ b/runtime/print_old.c @@ -35,11 +35,13 @@ void EXPORT_FN(stp_print_flush) (_stp_pbuf *pb) else atomic_inc (&_stp_transport_failures); #else - struct _stp_trace *t = relay_reserve(_stp_utt->rchan, sizeof(*t) + len); - if (likely(t)) { - t->sequence = _stp_seq_inc(); - t->pdu_len = len; - memcpy((void *) t + sizeof(*t), pb->buf, len); + void *buf = relay_reserve(_stp_utt->rchan, + sizeof(struct _stp_trace) + len); + if (likely(buf)) { + struct _stp_trace t = { .sequence = _stp_seq_inc(), + .pdu_len = len}; + memcpy(buf, &t, sizeof(t)); // prevent unaligned access + memcpy(buf + sizeof(t), pb->buf, len); } else atomic_inc (&_stp_transport_failures); #endif diff --git a/runtime/regs.c b/runtime/regs.c index 2daeaa3c..5821f7e7 100644 --- a/runtime/regs.c +++ b/runtime/regs.c @@ -383,317 +383,60 @@ void _stp_print_regs(struct pt_regs * regs) #endif -/* - * (Theoretically) arch-independent scheme for binary lookup of register - * values (from pt_regs) by register name. A register may be called by - * more than one name. - */ -struct _stp_register_desc { - const char *name; - unsigned short size; // in bytes - unsigned short offset; // in bytes, from start of pt_regs -}; - -struct _stp_register_table { - struct _stp_register_desc *registers; - unsigned nr_registers; - unsigned nr_slots; // capacity -}; - -static DEFINE_SPINLOCK(_stp_register_table_lock); -static void _stp_populate_register_table(void); - -/* - * If the named register is in the list, return its slot number and *found=1. - * Else *found=0 and return the slot number where the name should be inserted. - */ -static int _stp_lookup_register(const char *name, - struct _stp_register_table *table, int *found) -{ - unsigned begin, mid, end; - - *found = 0; - end = table->nr_registers; - if (end == 0) - return 0; - begin = 0; - mid = -1; - for (;;) { - int cmp; - int prev_mid = mid; - mid = (begin + end) / 2; - if (mid == prev_mid) - break; - cmp = strcmp(name, table->registers[mid].name); - if (cmp == 0) { - *found = 1; - return mid; - } else if (cmp < 0) - end = mid; - else - begin = mid; - } - if (begin == 0 && strcmp(name, table->registers[0].name) < 0) - return 0; - return begin + 1; -} - -/* - * If found, return 1 and the size and/or offset in the pt_regs array. - * Else return 0. - */ -static int _stp_find_register(const char *name, - struct _stp_register_table *table, size_t *size, size_t *offset) -{ - int slot, found; - if (unlikely(table->nr_registers == 0)) { - unsigned long flags; - /* - * Should we do this at the beginning of time to avoid - * the possibility of spending too long in a handler? - */ - spin_lock_irqsave(&_stp_register_table_lock, flags); - if (table->nr_registers == 0) - _stp_populate_register_table(); - spin_unlock_irqrestore(&_stp_register_table_lock, flags); - } - slot = _stp_lookup_register(name, table, &found); - if (found) { - if (size) - *size = table->registers[slot].size; - if (offset) - *offset = table->registers[slot].offset; - return 1; - } - return 0; -} - -/* - * Add name to the register-lookup table. Note that the name pointer - * is merely copied, not strdup-ed. - */ -void _stp_add_register(const char *name, struct _stp_register_table *table, - size_t size, size_t offset) -{ - int idx, found; - struct _stp_register_desc *slot; - - idx = _stp_lookup_register(name, table, &found); - if (found) - _stp_error("stap runtime internal error: " - "register name %s used twice\n", name); - if (table->nr_registers >= table->nr_slots) - _stp_error("stap runtime internal error: " - "register table overflow\n"); - slot = &table->registers[idx]; - - // Move the slots later in the array out of the way. - if (idx < table->nr_registers) - memmove(slot+1, slot, - sizeof(*slot) * (table->nr_registers - idx)); - table->nr_registers++; - slot->name = name; - slot->size = size; - slot->offset = offset; -} - -#if defined(__i386__) || defined(__x86_64__) -/* - * This register set is used for i386 kernel and apps, and for 32-bit apps - * running on x86_64. For the latter case, this allows the user to use - * things like reg("eax") as well as the standard x86_64 pt_regs names. - */ - -/* - * x86_64 and i386 are especially ugly because the pt_reg member names - * changed as part of the x86 merge. We allow (and use, as needed) - * either the pre-merge name or the post-merge name. - */ - -// I count 32 different names, but add a fudge factor. -static struct _stp_register_desc i386_registers[32+8]; -static struct _stp_register_table i386_register_table = { - .registers = i386_registers, - .nr_slots = ARRAY_SIZE(i386_registers) -}; - -/* - * sizeof(long) is indeed what we want here, for both i386 and x86_64. - * Unlike function args, x86_64 pt_regs is the same even if the int3 - * was in an -m32 app. - */ -#define ADD_PT_REG(name, member) \ - _stp_add_register(name, &i386_register_table, \ - sizeof(long), offsetof(struct pt_regs, member)) -#define ADD2NAMES(nm1, nm2, member) \ - do { \ - ADD_PT_REG(nm1, member); \ - ADD_PT_REG(nm2, member); \ - } while (0) - -#ifdef STAPCONF_X86_UNIREGS -/* Map "ax" and "eax" to regs->ax, and "cs" and "xcs" to regs->cs */ -#define ADD_EREG(nm) ADD2NAMES(#nm, "e" #nm, nm) -#define ADD_XREG(nm) ADD2NAMES(#nm, "x" #nm, nm) -#define ADD_FLAGS_REG() ADD_EREG(flags) -#define EREG(nm, regs) ((regs)->nm) -#define RREG(nm, regs) ((regs)->nm) +/* Function arguments */ -#else /* ! STAPCONF_X86_UNIREGS */ +#define _STP_REGPARM 0x8000 +#define _STP_REGPARM_MASK ((_STP_REGPARM) - 1) -#ifdef __i386__ -#define ADD_EREG(nm) ADD2NAMES(#nm, "e" #nm, e##nm) -#define ADD_XREG(nm) ADD2NAMES(#nm, "x" #nm, x##nm) -#define ADD_FLAGS_REG() ADD_EREG(flags) -#define EREG(nm, regs) ((regs)->e##nm) -#else /* __x86_64__ */ /* - * Map "eax" to regs->rax and "xcs" to regs->cs. Other mappings are - * handled in x86_64_register_table. + * x86_64 and i386 are especially ugly because: + * 1) the pt_reg member names changed as part of the x86 merge. We use + * either the pre-merge name or the post-merge name, as needed. + * 2) -m32 apps on x86_64 look like i386 apps, so we need to support + * those semantics on both i386 and x86_64. */ -#define ADD_EREG(nm) ADD_PT_REG("e" #nm, r##nm) -#define ADD_XREG(nm) ADD_PT_REG("x" #nm, nm) -#define ADD_FLAGS_REG() ADD2NAMES("flags", "eflags", eflags) -/* Note: After a store to %eax, %rax holds the ZERO-extended %eax. */ -#define EREG(nm, regs) ((regs)->r##nm) -#define RREG(nm, regs) ((regs)->r##nm) -#endif /* __x86_64__ */ - -#endif /* ! STAPCONF_X86_UNIREGS */ -static void _stp_populate_i386_register_table(void) -{ - /* - * The order here is the same as in i386 struct pt_regs. - * It's a different order from x86_64 pt_regs; but that doesn't - * matter -- even when compiling for x86_64 -- because the - * offsets are determined by offsetof(), not the calling order. - */ - ADD_EREG(bx); - ADD_EREG(cx); - ADD_EREG(dx); - ADD_EREG(si); - ADD_EREG(di); - ADD_EREG(bp); - ADD_EREG(ax); #ifdef __i386__ - ADD_XREG(ds); - ADD_XREG(es); - ADD_XREG(fs); - /* gs not saved */ -#endif #ifdef STAPCONF_X86_UNIREGS - ADD2NAMES("orig_ax", "orig_eax", orig_ax); +#define EREG(nm, regs) ((regs)->nm) #else -#ifdef __i386__ - ADD2NAMES("orig_ax", "orig_eax", orig_eax); -#else /* __x86_64__ */ - ADD2NAMES("orig_ax", "orig_eax", orig_rax); +#define EREG(nm, regs) ((regs)->e##nm) #endif -#endif /* STAPCONF_X86_UNIREGS */ - ADD_EREG(ip); - ADD_XREG(cs); - ADD_FLAGS_REG(); - ADD_EREG(sp); - ADD_XREG(ss); -} -/* - * For x86_64, this gets a copy of the saved 64-bit register (e.g., regs->rax). - * After a store to %eax, %rax holds the ZERO-extended %eax. - */ -static long -_stp_get_reg32_by_name(const char *name, struct pt_regs *regs) +static long _stp_get_sp(struct pt_regs *regs) { - size_t offset = 0; - long value; // works for i386 or x86_64 - BUG_ON(!name); - if (!regs) - _stp_error("Register values not available in this context.\n"); -#ifdef __i386__ - if (!user_mode(regs)) { - /* esp and ss aren't saved on trap from kernel mode. */ - if (!strcmp(name,"esp") || !strcmp(name, "sp")) - return (long) &EREG(sp, regs); - if (!strcmp(name,"xss") || !strcmp(name, "ss")) { - /* - * Assume ss register hasn't changed since we took - * the trap. - */ - unsigned short ss; - asm volatile("movw %%ss, %0" : : "m" (ss)); - return ss; - } - } -#endif - if (!_stp_find_register(name, &i386_register_table, NULL, &offset)) - _stp_error("Unknown register name: %s\n", name); - (void) memcpy(&value, ((char*)regs) + offset, sizeof(value)); - return value; + if (!user_mode(regs)) + return (long) &EREG(sp, regs); + return EREG(sp, regs); } -#endif /* __i386__ || __x86_64__ */ - -#ifdef __i386__ -static void _stp_populate_register_table(void) +static int _stp_get_regparm(int regparm, struct pt_regs *regs) { - _stp_populate_i386_register_table(); + if (regparm == 0) { + /* Default */ + if (user_mode(regs)) + return 0; + else + // Kernel is built with -mregparm=3. + return 3; + } else + return (regparm & _STP_REGPARM_MASK); } #endif /* __i386__ */ #ifdef __x86_64__ -// I count 32 different names (not the same 32 as i386), but add a fudge factor. -static struct _stp_register_desc x86_64_registers[32+8]; -static struct _stp_register_table x86_64_register_table = { - .registers = x86_64_registers, - .nr_slots = ARRAY_SIZE(x86_64_registers) -}; - -/* NB: Redefining ADD_PT_REG here. ADD2NAMES and such change accordingly. */ -#undef ADD_PT_REG -#define ADD_PT_REG(name, member) \ - _stp_add_register(name, &x86_64_register_table, \ - sizeof(unsigned long), offsetof(struct pt_regs, member)) - -#define ADD_NREG(nm) ADD_PT_REG(#nm, nm) - #ifdef STAPCONF_X86_UNIREGS -#define ADD_RREG(nm) ADD2NAMES(#nm, "r" #nm, nm) +#define EREG(nm, regs) ((regs)->nm) +#define RREG(nm, regs) ((regs)->nm) #else -#define ADD_RREG(nm) ADD2NAMES(#nm, "r" #nm, r##nm) +#define EREG(nm, regs) ((regs)->r##nm) +#define RREG(nm, regs) ((regs)->r##nm) #endif -static void _stp_populate_register_table(void) +static long _stp_get_sp(struct pt_regs *regs) { - /* Same order as in struct pt_regs */ - ADD_NREG(r15); - ADD_NREG(r14); - ADD_NREG(r13); - ADD_NREG(r12); - ADD_RREG(bp); - ADD_RREG(bx); - ADD_NREG(r11); - ADD_NREG(r10); - ADD_NREG(r9); - ADD_NREG(r8); - ADD_RREG(ax); - ADD_RREG(cx); - ADD_RREG(dx); - ADD_RREG(si); - ADD_RREG(di); -#ifdef STAPCONF_X86_UNIREGS - ADD2NAMES("orig_ax", "orig_rax", orig_ax); -#else - ADD2NAMES("orig_ax", "orig_rax", orig_rax); -#endif - ADD_RREG(ip); - ADD_NREG(cs); - ADD_FLAGS_REG(); - ADD_RREG(sp); - ADD_NREG(ss); - - _stp_populate_i386_register_table(); + return RREG(sp, regs); } static int _stp_probing_32bit_app(struct pt_regs *regs) @@ -704,54 +447,26 @@ static int _stp_probing_32bit_app(struct pt_regs *regs) } /* Ensure that the upper 32 bits of val are a sign-extension of the lower 32. */ -static long _stp_sign_extend32(long val) +static int64_t __stp_sign_extend32(int64_t val) { int32_t *val_ptr32 = (int32_t*) &val; return *val_ptr32; } -/* - * Get the value of the 64-bit register with the specified name. "rax", - * "ax", and "eax" all get you regs->[r]ax. Sets *reg32=1 if the name - * designates a 32-bit register (e.g., "eax"), 0 otherwise. - */ -static unsigned long -_stp_get_reg64_by_name(const char *name, struct pt_regs *regs, int *reg32) +static int _stp_get_regparm(int regparm, struct pt_regs *regs) { - size_t offset = 0; - unsigned long value; - BUG_ON(!name); - if (!regs) { - _stp_error("Register values not available in this context.\n"); - return 0; - } - if (_stp_find_register(name, &x86_64_register_table, NULL, &offset)) { - if (reg32) - *reg32 = 0; - (void) memcpy(&value, ((char*)regs) + offset, sizeof(value)); - return value; - } - if (reg32) - *reg32 = 1; - return _stp_get_reg32_by_name(name, regs); + if (regparm == 0) { + /* Default */ + if (_stp_probing_32bit_app(regs)) + return 0; + else + return 6; + } else + return (regparm & _STP_REGPARM_MASK); } -#endif /* __x86_64__ */ - -/* Function arguments */ - -#define _STP_REGPARM 0x8000 -#define _STP_REGPARM_MASK ((_STP_REGPARM) - 1) +#endif /* __x86_64__ */ #if defined(__i386__) || defined(__x86_64__) -static long _stp_get_sp(struct pt_regs *regs) -{ -#ifdef __i386__ - if (!user_mode(regs)) - return (long) &EREG(sp, regs); -#endif - return EREG(sp, regs); -} - /* * Use this for i386 kernel and apps, and for 32-bit apps running on x86_64. * Does arch-specific work for fetching function arg #argnum (1 = first arg). @@ -792,21 +507,6 @@ static int _stp_get_arg32_by_number(int n, int nr_regargs, } #endif /* __i386__ || __x86_64__ */ -#ifdef __i386__ -static int _stp_get_regparm(int regparm, struct pt_regs *regs) -{ - if (regparm == 0) { - /* Default */ - if (user_mode(regs)) - return 0; - else - // Kernel is built with -mregparm=3. - return 3; - } else - return (regparm & _STP_REGPARM_MASK); -} -#endif - #ifdef __x86_64__ /* See _stp_get_arg32_by_number(). */ static int _stp_get_arg64_by_number(int n, int nr_regargs, @@ -835,18 +535,6 @@ static int _stp_get_arg64_by_number(int n, int nr_regargs, return 0; } } - -static int _stp_get_regparm(int regparm, struct pt_regs *regs) -{ - if (regparm == 0) { - /* Default */ - if (_stp_probing_32bit_app(regs)) - return 0; - else - return 6; - } else - return (regparm & _STP_REGPARM_MASK); -} #endif /* __x86_64__ */ /** @} */ diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 6d79c98a..2c27e4a3 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -231,43 +231,16 @@ __stp_utrace_attach(struct task_struct *tsk, return rc; } -static u32 -__stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine, - struct task_struct *parent, - unsigned long clone_flags, - struct task_struct *child) -{ - struct utrace_attached_engine *child_engine; - struct mm_struct *mm; - - if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) - return UTRACE_ACTION_RESUME; - - // On clone, attach to the child. - (void) __stp_utrace_attach(child, engine->ops, 0, - __STP_UTRACE_TASK_FINDER_EVENTS); - return UTRACE_ACTION_RESUME; -} - -static u32 -__stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine, - struct task_struct *tsk, - const struct linux_binprm *bprm, - struct pt_regs *regs) +static inline void +__stp_utrace_attach_match_filename(struct task_struct *tsk, + const char * const filename) { size_t filelen; struct list_head *tgt_node; struct stap_task_finder_target *tgt; int found_node = 0; - if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) - return UTRACE_ACTION_RESUME; - - // On exec, check bprm - if (bprm->filename == NULL) - return UTRACE_ACTION_RESUME; - - filelen = strlen(bprm->filename); + filelen = strlen(filename); list_for_each(tgt_node, &__stp_task_finder_list) { tgt = list_entry(tgt_node, struct stap_task_finder_target, list); @@ -275,7 +248,7 @@ __stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine, // here, since they are handled at startup. if (tgt != NULL && tgt->pathlen > 0 && tgt->pathlen == filelen - && strcmp(tgt->pathname, bprm->filename) == 0) { + && strcmp(tgt->pathname, filename) == 0) { found_node = 1; break; } @@ -309,6 +282,79 @@ __stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine, cb_tgt->engine_attached = 1; } } +} + +static u32 +__stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +{ + int rc; + struct mm_struct *mm; + char *mmpath_buf; + char *mmpath; + + if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) + return UTRACE_ACTION_RESUME; + + // On clone, attach to the child. + rc = __stp_utrace_attach(child, engine->ops, 0, + __STP_UTRACE_TASK_FINDER_EVENTS); + if (rc != 0 && rc != EPERM) + return UTRACE_ACTION_RESUME; + + /* Grab the path associated with this task. */ + mm = get_task_mm(child); + if (! mm) { + /* If the thread doesn't have a mm_struct, it is + * a kernel thread which we need to skip. */ + return UTRACE_ACTION_RESUME; + } + + // Allocate space for a path + mmpath_buf = _stp_kmalloc(PATH_MAX); + if (mmpath_buf == NULL) { + _stp_error("Unable to allocate space for path"); + return UTRACE_ACTION_RESUME; + } + + // Grab the path associated with the new task + mmpath = __stp_get_mm_path(mm, mmpath_buf, PATH_MAX); + mmput(mm); /* We're done with mm */ + if (IS_ERR(mmpath)) { + rc = -PTR_ERR(mmpath); + _stp_error("Unable to get path (error %d) for pid %d", + rc, (int)child->pid); + } + else { + __stp_utrace_attach_match_filename(child, mmpath); + } + + _stp_kfree(mmpath_buf); + return UTRACE_ACTION_RESUME; +} + +static u32 +__stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine, + struct task_struct *tsk, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + size_t filelen; + struct list_head *tgt_node; + struct stap_task_finder_target *tgt; + int found_node = 0; + + if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) + return UTRACE_ACTION_RESUME; + + // On exec, check bprm + if (bprm->filename == NULL) + return UTRACE_ACTION_RESUME; + + __stp_utrace_attach_match_filename(tsk, bprm->filename); + return UTRACE_ACTION_RESUME; } diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c index dcaa1bc3..4ffcf72e 100644 --- a/runtime/vsprintf.c +++ b/runtime/vsprintf.c @@ -248,6 +248,11 @@ int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) ++str; } } +#ifdef __ia64__ + if ((str + precision - 1) <= end) + memcpy(str, &num, precision); //to prevent unaligned access + str += precision; +#else switch(precision) { case 1: if(str <= end) @@ -256,21 +261,22 @@ int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) break; case 2: if((str + 1) <= end) - memcpy(str, &num, 2); + *(int16_t *)str = (int16_t)num; str+=2; break; case 4: if((str + 3) <= end) - memcpy(str, &num, 4); + *(int32_t *)str = num; str+=4; break; default: // "%.8b" by default case 8: if((str + 7) <= end) - memcpy(str, &num, 8); + *(int64_t *)str = num; str+=8; break; } +#endif while (len < field_width--) { if (str <= end) *str = '\0'; @@ -167,6 +167,7 @@ a specific process. Instead of running a probe script, just list all available probe points matching the given pattern. The pattern may include wildcards and aliases. +.TP .B \-\-kelf For names and addresses of functions to probe, consult the symbol tables in the kernel and modules. diff --git a/tapset/ChangeLog b/tapset/ChangeLog index cf41c9cb..70d75b83 100644 --- a/tapset/ChangeLog +++ b/tapset/ChangeLog @@ -1,3 +1,9 @@ +2008-05-08 Ananth N Mavinakayanahalli <ananth@in.ibm.com> + + PR 5231 + * ioblock.stp (ioblock.end): Set bytes_done depending on kernel + version. + 2008-04-29 Frank Ch. Eigler <fche@elastic.org> PR 6466 diff --git a/tapset/errno.stp b/tapset/errno.stp index 550e5d4f..2523d846 100644 --- a/tapset/errno.stp +++ b/tapset/errno.stp @@ -351,33 +351,45 @@ function errno_str:string (err:long) %{ /* pure */ strlcpy (THIS->__retvalue, errlist[e], MAXSTRINGLEN); %} -/* for syscall tapset. set returnp = 1 for decimal, 2 for hex */ -function returnstr:string (returnp:long) %{ /* pure */ - long ret; - - /* XXX: unfortunate duplication with return.stp:retval() */ - - if (CONTEXT->regs) { +%{ +static long _stp_returnval(struct pt_regs *regs) { + if (regs) { #if defined (STAPCONF_X86_UNIREGS) && (defined (__x86_64__) || defined (__i386__)) - ret = CONTEXT->regs->ax; + return regs->ax; #elif defined (__i386__) - ret = CONTEXT->regs->eax; + return regs->eax; #elif defined (__x86_64__) - ret = CONTEXT->regs->rax; + // TODO: Handle -m32 apps. + return regs->rax; #elif defined (__powerpc64__) - ret = CONTEXT->regs->gpr[3]; + return regs->gpr[3]; #elif defined (__ia64__) - ret = CONTEXT->regs->r8; + return regs->r8; #elif defined (__sparc64__) - ret = CONTEXT->regs->u_regs[UREG_RETPC]; + return regs->u_regs[UREG_RETPC]; #elif defined (__s390x__) - ret = CONTEXT->regs->gprs[2]; + return regs->gprs[2]; #elif defined (__arm__) - ret = CONTEXT->regs->ARM_r0; + return regs->ARM_r0; #else - goto no_ret; + _stp_error("returnval() not defined for this architecture"); + return 0; #endif + } else { + _stp_error("returnval() not defined in this context"); + return 0; + } +} +%} + +function returnval:long () %{ /* pure */ + THIS->__retvalue = _stp_returnval(CONTEXT->regs); +%} +/* for syscall tapset. set returnp = 1 for decimal, 2 for hex */ +function returnstr:string (returnp:long) %{ /* pure */ + if (CONTEXT->regs) { + long ret = _stp_returnval(CONTEXT->regs); if (ret < 0 && ret > -Maxerrno && errlist[-ret]) snprintf (THIS->__retvalue, MAXSTRINGLEN, "%ld (%s)", ret, errlist[-ret]); else if (THIS->returnp == 2) diff --git a/tapset/i686/registers.stp b/tapset/i686/registers.stp index 85aa7a7f..db532f7a 100644 --- a/tapset/i686/registers.stp +++ b/tapset/i686/registers.stp @@ -1,9 +1,70 @@ -/* Return the named register value as a signed value. */ -function register:long (name:string) %{ /* pure */ - THIS->__retvalue = (int64_t) - _stp_get_reg32_by_name(THIS->name, CONTEXT->regs); +global _reg_offsets, _stp_regs_registered + +function _stp_register_regs() { + /* Same order as pt_regs */ + _reg_offsets["ebx"] = 0 _reg_offsets["bx"] = 0 + _reg_offsets["ecx"] = 4 _reg_offsets["cx"] = 4 + _reg_offsets["edx"] = 8 _reg_offsets["dx"] = 8 + _reg_offsets["esi"] = 12 _reg_offsets["si"] = 12 + _reg_offsets["edi"] = 16 _reg_offsets["di"] = 16 + _reg_offsets["ebp"] = 20 _reg_offsets["bp"] = 20 + _reg_offsets["eax"] = 24 _reg_offsets["ax"] = 24 + _reg_offsets["xds"] = 28 _reg_offsets["ds"] = 28 + _reg_offsets["xes"] = 32 _reg_offsets["es"] = 32 + _reg_offsets["xfs"] = 36 _reg_offsets["fs"] = 36 + _reg_offsets["orig_eax"] = 40 _reg_offsets["orig_ax"] = 40 + _reg_offsets["eip"] = 44 _reg_offsets["ip"] = 44 + _reg_offsets["xcs"] = 48 _reg_offsets["cs"] = 48 + _reg_offsets["eflags"] = 52 _reg_offsets["flags"] = 52 + _reg_offsets["esp"] = 56 _reg_offsets["sp"] = 56 sp_offset = 56 + _reg_offsets["xss"] = 60 _reg_offsets["ss"] = 60 ss_offset = 60 + + _stp_regs_registered = 1 +} + +function _stp_get_register_by_offset:long (offset:long) %{ + long value; + memcpy(&value, ((char *)CONTEXT->regs) + THIS->offset, sizeof(value)); + THIS->__retvalue = value; +%} + +function _stp_probing_kernel:long () %{ + THIS->__retvalue = !user_mode(CONTEXT->regs); +%} + +/* + * esp and ss aren't saved on a breakpoint in kernel mode, so + * the pre-trap stack pointer is ®s->sp. + */ +function _stp_kernel_sp:long (sp_offset:long) %{ + THIS->__retvalue = ((long) CONTEXT->regs) + THIS->sp_offset; +%} + +/* Assume ss register hasn't changed since we took the trap. */ +function _stp_kernel_ss:long () %{ + unsigned short ss; + asm volatile("movw %%ss, %0" : : "m" (ss)); + THIS->__retvalue = ss; %} +/* Return the named register value as a signed value. */ +function register:long (name:string) { + if (!_stp_regs_registered) + _stp_register_regs() + offset = _reg_offsets[name] + if (offset == 0 && !(name in _reg_offsets)) { + error("Unknown register: " . name) + return 0 + } + if (_stp_probing_kernel()) { + if (offset == sp_offset) + return _stp_kernel_sp(sp_offset) + else if (offset == ss_offset) + return _stp_kernel_ss() + } + return _stp_get_register_by_offset(offset) +} + /* * Return the named register value as an unsigned value. Specifically, * don't sign-extend the register value when promoting it to 64 bits. diff --git a/tapset/ioblock.stp b/tapset/ioblock.stp index 94781c04..14ce3f6b 100644 --- a/tapset/ioblock.stp +++ b/tapset/ioblock.stp @@ -167,7 +167,7 @@ probe ioblock.end = kernel.function("bio_endio") devname = __bio_devname($bio) ino = __bio_ino($bio) - bytes_done = $bytes_done + bytes_done = %( kernel_vr < "2.6.24" %? $bytes_done %: $bio->bi_size %) error = $error sector = $bio->bi_sector diff --git a/tapset/nd_syscalls.stp b/tapset/nd_syscalls.stp index eb5efda0..5697cd21 100644 --- a/tapset/nd_syscalls.stp +++ b/tapset/nd_syscalls.stp @@ -8,6 +8,15 @@ // Public License (GPL); either version 2, or (at your option) any // later version. +/* + * nd_syscalls.stp is a copy of syscalls.stp, modified to refer to + * function arguments by number rather than name, so that this tapset + * can be used even when the probed kernel lacks debugging information. + * + * So far, the names-to-numbers conversion covers only syscall.a* + * through syscall.c*, plus a few others. + */ + /* Each syscall returns the calls parameters. In addition, the following * variables are set: @@ -88,16 +97,27 @@ probe nd_syscall.acct.return = kernel.function("sys_acct").return ? { # probe nd_syscall.add_key = kernel.function("sys_add_key") ? { name = "add_key" - type_uaddr = $_type - description_auddr = $_description - payload_uaddr = $_payload - plen = $plen - ringid = $ringid + // type_uaddr = $_type + // description_auddr = $_description + // payload_uaddr = $_payload + // plen = $plen + // ringid = $ringid + // argstr = sprintf("%s, %s, %s, %d, %d", + // user_string_quoted($_type), + // user_string_quoted($_description), + // text_strn(user_string($_payload),syscall_string_trunc,1), + // $plen, $ringid) + asmlinkage() + type_uaddr = pointer_arg(1) + description_uaddr = pointer_arg(2) + payload_uaddr = pointer_arg(3) + plen = ulong_arg(4) + ringid = int_arg(5) argstr = sprintf("%s, %s, %s, %d, %d", - user_string_quoted($_type), - user_string_quoted($_description), - text_strn(user_string($_payload),syscall_string_trunc,1), - $plen, $ringid) + user_string_quoted(type_uaddr), + user_string_quoted(description_uaddr), + text_strn(user_string(payload_uaddr),syscall_string_trunc,1), + plen, ringid) } probe nd_syscall.add_key.return = kernel.function("sys_add_key").return ? { name = "add_key" @@ -122,16 +142,21 @@ probe nd_syscall.adjtimex = kernel.function("sys_adjtimex") { * buf_time_tv_usec = __uget_timex_m($txc_p,10) * buf_tick = __uget_timex_m($txc_p,11) */ - argstr = sprintf("%p", $txc_p) + // argstr = sprintf("%p", $txc_p) + asmlinkage() + argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.adjtimex.return = kernel.function("sys_adjtimex").return { name = "adjtimex" - retstr = _adjtimex_return_str($return) + // retstr = _adjtimex_return_str($return) + retstr = _adjtimex_return_str(returnval()) } # long compat_sys_adjtimex(struct compat_timex __user *utp) probe nd_syscall.compat_adjtimex = kernel.function("compat_sys_adjtimex") ? { name = "compat_adjtimex" - argstr = sprintf("%p", $utp) + // argstr = sprintf("%p", $utp) + asmlinkage() + argstr = sprintf("%p", pointer_arg(1)) } probe nd_syscall.compat_adjtimex.return = kernel.function("compat_sys_adjtimex").return ? { name = "compat_adjtimex" @@ -147,8 +172,11 @@ probe nd_syscall.alarm = kernel.function("sys32_alarm") ? { name = "alarm" - seconds = $seconds - argstr = sprint($seconds) + // seconds = $seconds + // argstr = sprint($seconds) + asmlinkage() + seconds = uint_arg(1) + argstr = sprint(seconds) } probe nd_syscall.alarm.return = kernel.function("sys_alarm").return ?, @@ -162,12 +190,19 @@ probe nd_syscall.alarm.return = # long sys_bdflush(int func,long data) probe nd_syscall.bdflush = kernel.function("sys_bdflush") ? { name = "bdflush" - func = $func - data = $data - if (($func>=2)&&($func%2==0)) - data_str = sprintf("%p", $data) + // func = $func + // data = $data + // if (($func>=2)&&($func%2==0)) + // data_str = sprintf("%p", $data) + // else + // data_str = sprintf("%d", $data) + asmlinkage() + func = int_arg(1) + data = long_arg(2) + if ((func>=2)&&(func%2==0)) + data_str = sprintf("%p", data) else - data_str = sprintf("%d", $data) + data_str = sprintf("%d", data) argstr = sprintf("%d, %s",func, data_str) } probe nd_syscall.bdflush.return = kernel.function("sys_bdflush").return ? { @@ -179,10 +214,15 @@ probe nd_syscall.bdflush.return = kernel.function("sys_bdflush").return ? { # long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) probe nd_syscall.bind = kernel.function("sys_bind") ? { name = "bind" - sockfd = $fd - my_addr_uaddr = $umyaddr - addrlen = $addrlen - argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr,$addrlen),$addrlen) + // sockfd = $fd + // my_addr_uaddr = $umyaddr + // addrlen = $addrlen + // argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr,$addrlen),$addrlen) + asmlinkage() + sockfd = int_arg(1) + my_addr_uaddr = pointer_arg(2) + addrlen = int_arg(3) + argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(my_addr_uaddr,addrlen),addrlen) } probe nd_syscall.bind.return = kernel.function("sys_bind").return ? { name = "bind" @@ -196,7 +236,9 @@ probe nd_syscall.brk = kernel.function("ia64_brk") ? { name = "brk" - brk = $brk + // brk = $brk + asmlinkage() + brk = ulong_arg(1) argstr = sprintf("%p", brk) } probe nd_syscall.brk.return = @@ -222,9 +264,13 @@ probe nd_syscall.brk.return = # long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) probe nd_syscall.capget = kernel.function("sys_capget") { name = "capget" - header_uaddr = $header - data_uaddr = $dataptr - argstr = sprintf("%p, %p", $header, $dataptr) + // header_uaddr = $header + // data_uaddr = $dataptr + // argstr = sprintf("%p, %p", $header, $dataptr) + asmlinkage() + header_uaddr = pointer_arg(1) + data_uaddr = pointer_arg(2) + argstr = sprintf("%p, %p", header_uaddr, data_uaddr) } probe nd_syscall.capget.return = kernel.function("sys_capget").return { name = "capget" @@ -245,9 +291,13 @@ probe nd_syscall.capget.return = kernel.function("sys_capget").return { # long sys_capset(cap_user_header_t header, const cap_user_data_t data) probe nd_syscall.capset = kernel.function("sys_capset") { name = "capset" - header_uaddr = $header - data_uaddr = $data - argstr = sprintf("%p, %p", $header, $data) + // header_uaddr = $header + // data_uaddr = $data + // argstr = sprintf("%p, %p", $header, $data) + asmlinkage() + header_uaddr = pointer_arg(1) + data_uaddr = pointer_arg(2) + argstr = sprintf("%p, %p", header_uaddr, data_uaddr) } probe nd_syscall.capset.return = kernel.function("sys_capset").return { name = "capset" @@ -258,8 +308,11 @@ probe nd_syscall.capset.return = kernel.function("sys_capset").return { # long sys_chdir(const char __user * filename) probe nd_syscall.chdir = kernel.function("sys_chdir") { name = "chdir" - path = user_string($filename) - argstr = user_string_quoted($filename) + // path = user_string($filename) + // argstr = user_string_quoted($filename) + asmlinkage() + path = user_string(pointer_arg(1)) + argstr = user_string_quoted(pointer_arg(1)) } probe nd_syscall.chdir.return = kernel.function("sys_chdir").return { name = "chdir" @@ -270,9 +323,13 @@ probe nd_syscall.chdir.return = kernel.function("sys_chdir").return { # long sys_chmod(const char __user * filename, mode_t mode) probe nd_syscall.chmod = kernel.function("sys_chmod") { name = "chmod" - path = user_string($filename) - mode = $mode - argstr = sprintf("%s, %#o", user_string_quoted($filename), mode) + // path = user_string($filename) + // mode = $mode + // argstr = sprintf("%s, %#o", user_string_quoted($filename), mode) + asmlinkage() + path = user_string(pointer_arg(1)) + mode = uint_arg(2) + argstr = sprintf("%s, %#o", user_string_quoted(pointer_arg(1)), mode) } probe nd_syscall.chmod.return = kernel.function("sys_chmod").return { name = "chmod" @@ -283,10 +340,15 @@ probe nd_syscall.chmod.return = kernel.function("sys_chmod").return { # long sys_chown(const char __user * filename, uid_t user, gid_t group) probe nd_syscall.chown = kernel.function("sys_chown") { name = "chown" - path = user_string($filename) - owner = __int32($user) - group = __int32($group) - argstr = sprintf("%s, %d, %d",user_string_quoted($filename), owner, group) + // path = user_string($filename) + // owner = __int32($user) + // group = __int32($group) + // argstr = sprintf("%s, %d, %d",user_string_quoted($filename), owner, group) + asmlinkage() + path = user_string(pointer_arg(1)) + owner = __int32(uint_arg(2)) + group = __int32(uint_arg(3)) + argstr = sprintf("%s, %d, %d",user_string_quoted(pointer_arg(1)), owner, group) } probe nd_syscall.chown.return = kernel.function("sys_chown").return { name = "chown" @@ -298,10 +360,15 @@ probe nd_syscall.chown.return = kernel.function("sys_chown").return { # probe nd_syscall.chown16 = kernel.function("sys_chown16") ? { name = "chown16" - path = user_string($filename) - owner = __short($user) - group = __short($group) - argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) + // path = user_string($filename) + // owner = __short($user) + // group = __short($group) + // argstr = sprintf("%s, %d, %d", user_string_quoted($filename), owner, group) + asmlinkage() + path = user_string(pointer_arg(1)) + owner = __short(uint_arg(2)) + group = __short(uint_arg(3)) + argstr = sprintf("%s, %d, %d", user_string_quoted(pointer_arg(1)), owner, group) } probe nd_syscall.chown16.return = kernel.function("sys_chown16").return ? { name = "chown16" @@ -312,8 +379,11 @@ probe nd_syscall.chown16.return = kernel.function("sys_chown16").return ? { # long sys_chroot(const char __user * filename) probe nd_syscall.chroot = kernel.function("sys_chroot") { name = "chroot" - path = user_string($filename) - argstr = user_string_quoted($filename) + // path = user_string($filename) + // argstr = user_string_quoted($filename) + asmlinkage() + path = user_string(pointer_arg(1)) + argstr = user_string_quoted(pointer_arg(1)) } probe nd_syscall.chroot.return = kernel.function("sys_chroot").return { name = "chroot" @@ -329,10 +399,15 @@ probe nd_syscall.clock_getres = kernel.function("compat_clock_getres") ? { name = "clock_getres" - clk_id = $which_clock - clk_id_str = _get_wc_str($which_clock) - res_uaddr = $tp - argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) + // clk_id = $which_clock + // clk_id_str = _get_wc_str($which_clock) + // res_uaddr = $tp + // argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) + asmlinkage() + clk_id = int_arg(1) + clk_id_str = _get_wc_str(clk_id) + res_uaddr = pointer_arg(2) + argstr = sprintf("%s, %p", clk_id_str, res_uaddr) } probe nd_syscall.clock_getres.return = kernel.function("sys_clock_getres").return, @@ -349,9 +424,13 @@ probe nd_syscall.clock_gettime = kernel.function("sys_clock_gettime") { name = "clock_gettime" - clk_id = $which_clock - clk_id_str = _get_wc_str($which_clock) - argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) + // clk_id = $which_clock + // clk_id_str = _get_wc_str($which_clock) + // argstr = sprintf("%s, %p", _get_wc_str($which_clock), $tp) + asmlinkage() + clk_id = int_arg(1) + clk_id_str = _get_wc_str(clk_id) + argstr = sprintf("%s, %p", clk_id_str, pointer_arg(2)) } probe nd_syscall.clock_gettime.return = kernel.function("sys_clock_gettime").return { @@ -367,12 +446,20 @@ probe nd_syscall.clock_gettime.return = kernel.function("sys_clock_gettime").ret # probe nd_syscall.clock_nanosleep = kernel.function("sys_clock_nanosleep") { name = "clock_nanosleep" - if ($flags == 1) + // if ($flags == 1) + // flag_str = "TIMER_ABSTIME" + // else + // flag_str = sprintf("0x%x", $flags) + // argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, + // _struct_timespec_u($rqtp,1), $rmtp) + asmlinkage() + flags = int_arg(2) + if (flags == 1) flag_str = "TIMER_ABSTIME" else - flag_str = sprintf("0x%x", $flags) - argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, - _struct_timespec_u($rqtp,1), $rmtp) + flag_str = sprintf("0x%x", flags) + argstr = sprintf("%s, %s, %s, %p", _get_wc_str(int_arg(1)), flag_str, + _struct_timespec_u(pointer_arg(3),1), pointer_arg(4)) } probe nd_syscall.clock_nanosleep.return = kernel.function("sys_clock_nanosleep").return { name = "clock_nanosleep" @@ -389,12 +476,21 @@ probe nd_syscall.compat_clock_nanosleep = kernel.function("compat_sys_clock_nanosleep") ? { name = "compat_clock_nanosleep" - if ($flags == 1) + // if ($flags == 1) + // flag_str = "TIMER_ABSTIME" + // else + // flag_str = sprintf("0x%x", $flags) + // argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, + // _struct_compat_timespec_u($rqtp,1), $rmtp) + asmlinkage() + flags = int_arg(2) + if (flags == 1) flag_str = "TIMER_ABSTIME" else - flag_str = sprintf("0x%x", $flags) - argstr = sprintf("%s, %s, %s, %p", _get_wc_str($which_clock), flag_str, - _struct_compat_timespec_u($rqtp,1), $rmtp) + flag_str = sprintf("0x%x", flags) + argstr = sprintf("%s, %s, %s, %p", _get_wc_str(int_arg(1)), flag_str, + _struct_compat_timespec_u(pointer_arg(3),1), + pointer_arg(4)) } probe nd_syscall.compat_clock_nanosleep.return = kernel.function("compat_clock_nanosleep").return ?, @@ -410,10 +506,15 @@ probe nd_syscall.compat_clock_nanosleep.return = # probe nd_syscall.clock_settime = kernel.function("sys_clock_settime") { name = "clock_settime" - clk_id = $which_clock - clk_id_str = _get_wc_str($which_clock) - tp_uaddr = $tp - argstr = sprintf("%s, %s", clk_id_str, _struct_timespec_u($tp,1)) + // clk_id = $which_clock + // clk_id_str = _get_wc_str($which_clock) + // tp_uaddr = $tp + // argstr = sprintf("%s, %s", clk_id_str, _struct_timespec_u($tp,1)) + asmlinkage() + clk_id = int_arg(1) + clk_id_str = _get_wc_str(clk_id) + tp_uaddr = pointer_arg(2) + argstr = sprintf("%s, %s", clk_id_str, _struct_timespec_u(tp_uaddr,1)) } probe nd_syscall.clock_settime.return = kernel.function("sys_clock_settime").return { name = "clock_settime" @@ -437,10 +538,15 @@ probe nd_syscall.close.return = kernel.function("sys_close").return { # long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) probe nd_syscall.connect = kernel.function("sys_connect") ? { name = "connect" - sockfd = $fd - serv_addr_uaddr = $uservaddr - addrlen = $addrlen - argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($uservaddr,$addrlen),$addrlen) + // sockfd = $fd + // serv_addr_uaddr = $uservaddr + // addrlen = $addrlen + // argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($uservaddr,$addrlen),$addrlen) + asmlinkage() + sockfd = int_arg(1) + serv_addr_uaddr = pointer_arg(2) + addrlen = int_arg(3) + argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(serv_addr_uaddr,addrlen),addrlen) } probe nd_syscall.connect.return = kernel.function("sys_connect").return ? { name = "connect" @@ -452,9 +558,12 @@ probe nd_syscall.connect.return = kernel.function("sys_connect").return ? { probe nd_syscall.creat = kernel.function("sys_creat") ? { name = "creat" - mode = $mode - pathname = user_string($pathname) - argstr = sprintf("%s, %#o", user_string_quoted($pathname), $mode) + // mode = $mode + // pathname = user_string($pathname) + // argstr = sprintf("%s, %#o", user_string_quoted($pathname), $mode) + mode = int_arg(2) + pathname = user_string(pointer_arg(1)) + argstr = sprintf("%s, %#o", user_string_quoted(pointer_arg(1)), mode) } probe nd_syscall.creat.return = kernel.function("sys_creat").return ? { @@ -1128,18 +1237,32 @@ probe nd_syscall.ftruncate64.return = kernel.function("sys_ftruncate64").return # probe nd_syscall.futex = kernel.function("sys_futex") ? { name = "futex" - futex_uaddr = $uaddr - op = $op - val = $val - utime_uaddr = $utime - uaddr2_uaddr = $uaddr2 - val3 = $val3 + // futex_uaddr = $uaddr + // op = $op + // val = $val + // utime_uaddr = $utime + // uaddr2_uaddr = $uaddr2 + // val3 = $val3 + // if (op == 0) + // argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), + // $val, _struct_timespec_u($utime,1)) + // else + // argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), + // $val) + asmlinkage() + futex_uaddr = pointer_arg(1) + op = int_arg(2) + val = u32_arg(3) + utime_uaddr = pointer_arg(4) + uaddr2_uaddr = pointer_arg(5) + val3 = u32_arg(6) if (op == 0) - argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), - $val, _struct_timespec_u($utime,1)) + argstr = sprintf("%p, %s, %d, %s", futex_uaddr, + _futex_op_str(op), val, + _struct_timespec_u(utime_uaddr,1)) else - argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), - $val) + argstr = sprintf("%p, %s, %d", futex_uaddr, + _futex_op_str(op), val) } probe nd_syscall.futex.return = kernel.function("sys_futex").return ? { name = "futex" @@ -1147,18 +1270,32 @@ probe nd_syscall.futex.return = kernel.function("sys_futex").return ? { } probe nd_syscall.compat_futex = kernel.function("compat_sys_futex") ? { name = "futex" - futex_uaddr = $uaddr - op = $op - val = $val - utime_uaddr = $utime - uaddr2_uaddr = $uaddr2 - val3 = $val3 + // futex_uaddr = $uaddr + // op = $op + // val = $val + // utime_uaddr = $utime + // uaddr2_uaddr = $uaddr2 + // val3 = $val3 + // if (op == 0) + // argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), + // $val, _struct_compat_timespec_u($utime,1)) + // else + // argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), + // $val) + asmlinkage() + futex_uaddr = pointer_arg(1) + op = int_arg(2) + val = u32_arg(3) + utime_uaddr = pointer_arg(4) + uaddr2_uaddr = pointer_arg(5) + val3 = u32_arg(6) if (op == 0) - argstr = sprintf("%p, %s, %d, %s", $uaddr, _futex_op_str($op), - $val, _struct_compat_timespec_u($utime,1)) + argstr = sprintf("%p, %s, %d, %s", futex_uaddr, + _futex_op_str(op), val, + _struct_compat_timespec_u(utime_uaddr,1)) else - argstr = sprintf("%p, %s, %d", $uaddr, _futex_op_str($op), - $val) + argstr = sprintf("%p, %s, %d", futex_uaddr, + _futex_op_str(op), val) } probe nd_syscall.compat_futex.return = kernel.function("compat_sys_futex").return ? { name = "futex" @@ -1542,17 +1679,29 @@ probe nd_syscall.getrlimit.return = kernel.function("sys_getrlimit").return, # long sys_getrusage(int who, struct rusage __user *ru) probe nd_syscall.getrusage = kernel.function("sys_getrusage") { name = "getrusage" - who = $who - if($who==-2) + // who = $who + // if($who==-2) + // { + // # RUSAGE_BOTH is not valid argument for sys_getrusage + // who_str = sprintf("UNKNOWN VALUE: %d", $who) + // } + // else + // { + // who_str = _rusage_who_str($who) + // } + // usage_uaddr = $ru + asmlinkage() + who = int_arg(1) + if(who==-2) { # RUSAGE_BOTH is not valid argument for sys_getrusage - who_str = sprintf("UNKNOWN VALUE: %d", $who) + who_str = sprintf("UNKNOWN VALUE: %d", who) } else { - who_str = _rusage_who_str($who) + who_str = _rusage_who_str(who) } - usage_uaddr = $ru + usage_uaddr = pointer_arg(2) argstr = sprintf("%s, %p", who_str, usage_uaddr) } probe nd_syscall.getrusage.return = kernel.function("sys_getrusage").return { @@ -2561,16 +2710,28 @@ probe nd_syscall.mq_open = kernel.function("compat_sys_mq_open") ? { name = "mq_open" - name_uaddr = $u_name - filename = user_string($u_name) - mode = $mode - u_attr_uaddr = $u_attr - oflag = $oflag + // name_uaddr = $u_name + // filename = user_string($u_name) + // mode = $mode + // u_attr_uaddr = $u_attr + // oflag = $oflag + // if (oflag & 64) + // argstr = sprintf("%s, %s, %#o, %p", user_string_quoted($u_name), + // _sys_open_flag_str($oflag), $mode, $u_attr) + // else + // argstr = sprintf("%s, %s", user_string_quoted($u_name), _sys_open_flag_str($oflag)) + asmlinkage() + name_uaddr = pointer_arg(1) + filename = user_string(name_uaddr) + mode = uint_arg(3) + u_attr_uaddr = pointer_arg(4) + oflag = int_arg(2) if (oflag & 64) - argstr = sprintf("%s, %s, %#o, %p", user_string_quoted($u_name), - _sys_open_flag_str($oflag), $mode, $u_attr) + argstr = sprintf("%s, %s, %#o, %p", + user_string_quoted(name_uaddr), + _sys_open_flag_str(oflag), mode, u_attr_uaddr) else - argstr = sprintf("%s, %s", user_string_quoted($u_name), _sys_open_flag_str($oflag)) + argstr = sprintf("%s, %s", user_string_quoted(name_uaddr), _sys_open_flag_str(oflag)) } probe nd_syscall.mq_open.return = kernel.function("sys_mq_open").return ?, diff --git a/tapset/x86_64/registers.stp b/tapset/x86_64/registers.stp index 45acddd1..a5aba55a 100644 --- a/tapset/x86_64/registers.stp +++ b/tapset/x86_64/registers.stp @@ -1,18 +1,93 @@ -/* Return the named register value as a signed value. */ -function register:long (name:string) %{ /* pure */ - int reg32 = 0; - THIS->__retvalue = (int64_t) _stp_get_reg64_by_name(THIS->name, - CONTEXT->regs, ®32); - if (reg32) - THIS->__retvalue = _stp_sign_extend32(THIS->__retvalue); +global _reg_offsets, _r32_offsets, _stp_regs_registered + +function _stp_register_regs() { + /* Same order as pt_regs */ + _reg_offsets["r15"] = 0 + _reg_offsets["r14"] = 8 + _reg_offsets["r13"] = 16 + _reg_offsets["r12"] = 24 + _reg_offsets["rbp"] = 32 _reg_offsets["bp"] = 32 + _reg_offsets["rbx"] = 40 _reg_offsets["bx"] = 40 + _reg_offsets["r11"] = 48 + _reg_offsets["r10"] = 56 + _reg_offsets["r9"] = 64 + _reg_offsets["r8"] = 72 + _reg_offsets["rax"] = 80 _reg_offsets["ax"] = 80 + _reg_offsets["rcx"] = 88 _reg_offsets["cx"] = 88 + _reg_offsets["rdx"] = 96 _reg_offsets["dx"] = 96 + _reg_offsets["rsi"] = 104 _reg_offsets["si"] = 104 + _reg_offsets["rdi"] = 112 _reg_offsets["di"] = 112 + _reg_offsets["orig_rax"] = 120 _reg_offsets["orig_ax"] = 120 + _reg_offsets["rip"] = 128 _reg_offsets["ip"] = 128 + _reg_offsets["xcs"] = 136 _reg_offsets["cs"] = 136 + _reg_offsets["eflags"] = 144 _reg_offsets["flags"] = 144 + _reg_offsets["rsp"] = 152 _reg_offsets["sp"] = 152 + _reg_offsets["xss"] = 160 _reg_offsets["ss"] = 160 + + _r32_offsets["ebp"] = 32 + _r32_offsets["ebx"] = 40 + _r32_offsets["eax"] = 80 + _r32_offsets["ecx"] = 88 + _r32_offsets["edx"] = 96 + _r32_offsets["esi"] = 104 + _r32_offsets["edi"] = 112 + _r32_offsets["orig_eax"] = 120 + _r32_offsets["eip"] = 128 + _r32_offsets["esp"] = 152 + + _stp_regs_registered = 1 +} + +function _stp_get_register_by_offset:long (offset:long) %{ + long value; + memcpy(&value, ((char *)CONTEXT->regs) + THIS->offset, sizeof(value)); + THIS->__retvalue = value; %} -/* Return the named register value as an unsigned value. */ -function u_register:long (name:string) %{ - THIS->__retvalue = (int64_t) _stp_get_reg64_by_name(THIS->name, - CONTEXT->regs, NULL); +/* + * _stp_sign_extend32() is callable from a script function. + * __stp_sign_extend32() (in regs.c) is callable from a C function. + */ +function _stp_sign_extend32:long (value:long) %{ + THIS->__retvalue = __stp_sign_extend32(THIS->value); %} +function _stp_register:long (name:string, sign_extend:long) { + reg32 = 0 + if (!_stp_regs_registered) + _stp_register_regs() + offset = _reg_offsets[name] + if (offset == 0 && !(name in _reg_offsets)) { + offset = _r32_offsets[name] + if (offset == 0 && !(name in _r32_offsets)) { + error("Unknown register: " . name) + return 0 + } + reg32 = 1 + } + value = _stp_get_register_by_offset(offset) + if (reg32) { + if (sign_extend) + value = _stp_sign_extend32(value) + else + value &= 0xffffffff + } + return value +} + +/* Return the named register value as a signed value. */ +function register:long (name:string) { + return _stp_register(name, 1) +} + +/* + * Return the named register value as an unsigned value. Specifically, + * don't sign-extend the register value when promoting it to 64 bits. + */ +function u_register:long (name:string) { + return _stp_register(name, 0) +} + /* * Return the value of function arg #argnum (1=first arg). * If truncate=1, mask off the top 32 bits. @@ -68,7 +143,7 @@ function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) %{ } if (THIS->truncate || argsz == sizeof(int)) { if (THIS->sign_extend) - THIS->__retvalue = (int64_t) _stp_sign_extend32(val); + THIS->__retvalue = (int64_t) __stp_sign_extend32(val); else /* High bits may be garbage. */ THIS->__retvalue = (int64_t) (val & 0xffffffff); diff --git a/testsuite/parseko/twentyfive.stp b/testsuite/parseko/twentyfive.stp new file mode 100644 index 00000000..bebc72f8 --- /dev/null +++ b/testsuite/parseko/twentyfive.stp @@ -0,0 +1,3 @@ +#! stap -p1 + +global a,;b diff --git a/testsuite/parseko/twentyfour.stp b/testsuite/parseko/twentyfour.stp new file mode 100644 index 00000000..41ea076d --- /dev/null +++ b/testsuite/parseko/twentyfour.stp @@ -0,0 +1,3 @@ +#! stap -p1 + +global a;,b diff --git a/testsuite/systemtap.base/global_vars.exp b/testsuite/systemtap.base/global_vars.exp new file mode 100644 index 00000000..059ebf8d --- /dev/null +++ b/testsuite/systemtap.base/global_vars.exp @@ -0,0 +1,5 @@ +# Check that global variables terminated with a ; work fine + +set test "global_vars" + +stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string diff --git a/testsuite/systemtap.base/global_vars.stp b/testsuite/systemtap.base/global_vars.stp new file mode 100644 index 00000000..737e2556 --- /dev/null +++ b/testsuite/systemtap.base/global_vars.stp @@ -0,0 +1,57 @@ +/* + * global_vars.stp + * + * Check that global variables with a ; termination work fine + */ + +probe begin { println("systemtap starting probe") } +probe end { println("systemtap ending probe") } + +global a; +global c, d; +global g = 42; +global e[1], f; +global gstr = "foobar"; + +global gstr_saved; +probe begin(-9223372036854775808) { + c = g + d = c + g + a = d + f = c + e[0] = "a"; + gstr_saved = gstr +} + +probe end { + if (c == 42) + println("systemtap test success") + else + printf("systemtap test failure - c:%d != 42\n", c) + + if (d == (c + g)) + println("systemtap test success") + else + printf("systemtap test failure - d:%d != %d\n", d, (c+g)) + + if (a == d) + println("systemtap test success") + else + printf("systemtap test failure - a:%d != %d\n", a, d) + + if (f == c) + println("systemtap test success") + else + printf("systemtap test failure - f:%d != %d\n", f, c) + + if (e[0] == "a") + println("systemtap test success") + else + printf("systemtap test failure - e:%s != a\n", e[0]) + + if (gstr_saved == "foobar") + println("systemtap test success") + else + printf("systemtap test failure - gstr_saved:%s != foobar\n", gstr_saved) +} + diff --git a/testsuite/systemtap.examples/ChangeLog b/testsuite/systemtap.examples/ChangeLog index ad46276c..8d8c2ca1 100644 --- a/testsuite/systemtap.examples/ChangeLog +++ b/testsuite/systemtap.examples/ChangeLog @@ -1,3 +1,24 @@ +2008-05-08 William Cohen <wcohen@redhat.com> + + * iotime.meta: New. + +2008-05-08 William Cohen <wcohen@redhat.com> + + * sleeptime.meta, wait4time.meta: New. + +2008-05-08 Mark Wielaard <mwielaard@redhat.com> + + * futexes.meta (test_check,test_installcheck): Change futex.stp to + futexes.stp. + +2008-05-07 William Cohen <wcohen@redhat.com> + + * futexes.meta, nettop.meta, pf2.meta: New. + +2008-05-07 William Cohen <wcohen@redhat.com> + + * pf2.stp: Clean up output. + 2008-05-01 William Cohen <wcohen@redhat.com> * helloworld.meta: New file. diff --git a/testsuite/systemtap.examples/futexes.meta b/testsuite/systemtap.examples/futexes.meta new file mode 100644 index 00000000..0a34b2d8 --- /dev/null +++ b/testsuite/systemtap.examples/futexes.meta @@ -0,0 +1,13 @@ +title: System-Wide Futex Contention +name: futex.stp +version: 1.0 +author: anonymous +keywords: syscall locking futex +subsystem: locking +status: production +exit: user-controlled +output: sorted-list on-exit +scope: system-wide +description: The script watches the futex syscall on the system. On exit the futexes address, the number of contentions, and the average time for each contention on the futex are printed from lowest pid number to highest. +test_check: stap -p4 futexes.stp +test_installcheck: stap futexes.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/iotime.meta b/testsuite/systemtap.examples/iotime.meta new file mode 100644 index 00000000..f656ff85 --- /dev/null +++ b/testsuite/systemtap.examples/iotime.meta @@ -0,0 +1,13 @@ +title: Trace Time Spent in Read and Write for Files +name: iotime.stp +version: 1.0 +author: Daniel Berrange and Will Cohen +keywords: syscall read write time io +subsystem: syscall +status: production +exit: user-controlled +output: trace +scope: system-wide +description: The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls. +test_check: stap -p4 iotime.stp +test_installcheck: stap iotime.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/nettop.meta b/testsuite/systemtap.examples/nettop.meta new file mode 100644 index 00000000..61d1c153 --- /dev/null +++ b/testsuite/systemtap.examples/nettop.meta @@ -0,0 +1,13 @@ +title: Periodic Listing of Processes Using Network Interfaces +name: nettop.stp +version: 1.0 +author: anonymous +keywords: network traffic per-process +subsystem: network +status: production +exit: user-controlled +output: timed +scope: system-wide +description: Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval. +test_check: stap -p4 nettop.stp +test_installcheck: stap nettop.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/pf2.meta b/testsuite/systemtap.examples/pf2.meta new file mode 100644 index 00000000..d0a534bd --- /dev/null +++ b/testsuite/systemtap.examples/pf2.meta @@ -0,0 +1,13 @@ +title: Profile kernel functions +name: pf2.stp +version: 1.0 +author: anonymous +keywords: profiling +subsystem: kernel +status: production +exit: user-controlled +output: sorted-list +scope: system-wide +description: The pf2.stp script sets up time-based sampling. Every five seconds it prints out a sorted list with the top ten kernel functions with samples. +test_check: stap -p4 pf2.stp +test_installcheck: stap pf2.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/pf2.stp b/testsuite/systemtap.examples/pf2.stp index 96fdb7e7..a804c3ff 100755 --- a/testsuite/systemtap.examples/pf2.stp +++ b/testsuite/systemtap.examples/pf2.stp @@ -6,10 +6,10 @@ probe timer.profile { fn = probefunc () if (fn != "") profile[fn] <<< 1 } -probe timer.ms(4000) { +probe timer.ms(5000) { printf ("\n--- %d samples recorded:\n", @count(pcount)) foreach (f in profile- limit 10) { - printf ("%s\t%d\n", f, @count(profile[f])) + printf ("%-30s\t%6d\n", f, @count(profile[f])) } delete profile delete pcount diff --git a/testsuite/systemtap.examples/sig_by_pid.meta b/testsuite/systemtap.examples/sig_by_pid.meta new file mode 100644 index 00000000..03b02fba --- /dev/null +++ b/testsuite/systemtap.examples/sig_by_pid.meta @@ -0,0 +1,13 @@ +title: Signal Counts by Process ID +name: sig_by_pid.stp +version: 1.0 +author: IBM +keywords: signals +subsystem: signals +status: experimental +exit: user-controlled +output: sorted-list on-exit +scope: system-wide +description: Print signal counts by process ID in descending order. +test_check: stap -p4 sig_by_pid.stp +test_installcheck: stap sig_by_pid.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/sig_by_proc.meta b/testsuite/systemtap.examples/sig_by_proc.meta new file mode 100644 index 00000000..eea42be4 --- /dev/null +++ b/testsuite/systemtap.examples/sig_by_proc.meta @@ -0,0 +1,13 @@ +title: Signal Counts by Process Name +name: sig_by_proc.stp +version: 1.0 +author: IBM +keywords: signals +subsystem: signals +status: experimental +exit: user-controlled +output: sorted-list on-exit +scope: system-wide +description: Print signal counts by process name in descending order. +test_check: stap -p4 sig_by_proc.stp +test_installcheck: stap sig_by_proc.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/sigmon.meta b/testsuite/systemtap.examples/sigmon.meta new file mode 100644 index 00000000..18834997 --- /dev/null +++ b/testsuite/systemtap.examples/sigmon.meta @@ -0,0 +1,14 @@ +title: System-Wide Count of Syscalls by PID +name: syscalls_by_pid.stp +version: 1.0 +author: IBM +keywords: signals +subsystem: signals +status: experimental +exit: user-controlled +output: trace +scope: pid +description: The script watches for a particular signal sent to a specific process. When that signal is sent to the specified process, the script prints out the PID and executable of the process sending the signal, the PID and executable name of the process receiving the signal, and the signal number and name. +arg_1: The name of the signal to look for on selected process. +test_check: stap -p4 sigmon.stp SIGKILL +test_installcheck: stap sigmon.stp -c "sleep 1" SIGKILL diff --git a/testsuite/systemtap.examples/sleeptime.meta b/testsuite/systemtap.examples/sleeptime.meta new file mode 100644 index 00000000..d6c59345 --- /dev/null +++ b/testsuite/systemtap.examples/sleeptime.meta @@ -0,0 +1,13 @@ +title: Trace Time Spent in nanosleep Syscalls +name: sleeptime.stp +version: 1.0 +author: Daniel Berrange and Will Cohen +keywords: syscall sleep +subsystem: syscall +status: production +exit: user-controlled +output: trace +scope: system-wide +description: The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "nanosleep:" key, and the duration of the sleep in microseconds. +test_check: stap -p4 sleeptime.stp +test_installcheck: stap sleeptime.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/socket-trace.meta b/testsuite/systemtap.examples/socket-trace.meta new file mode 100644 index 00000000..0b26f2fe --- /dev/null +++ b/testsuite/systemtap.examples/socket-trace.meta @@ -0,0 +1,13 @@ +title: Trace Functions called in Network Socket Code +name: socket-trace.stp +version: 1.0 +author: anonymous +keywords: network socket +subsystem: network +status: production +exit: user-controlled +output: trace +scope: system-wide +description: The script instrument each of the functions inn the Linux kernel's net/socket.c file. The script prints out trace. The first element of a line is time delta in microseconds from the previous entry. This is followed by the command name and the PID. The "->" and "<-" indicates function entry and function exit, respectively. The last element of the line is the function name. +test_check: stap -p4 socket-trace.stp +test_installcheck: stap socket-trace.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/syscalls_by_pid.meta b/testsuite/systemtap.examples/syscalls_by_pid.meta new file mode 100644 index 00000000..590652b3 --- /dev/null +++ b/testsuite/systemtap.examples/syscalls_by_pid.meta @@ -0,0 +1,13 @@ +title: System-Wide Count of Syscalls by PID +name: syscalls_by_pid.stp +version: 1.0 +author: anonymous +keywords: syscall +subsystem: syscall +status: production +exit: user-controlled +output: sorted-list on-exit +scope: system-wide +description: The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each PID ordered from greatest to least number of syscalls. +test_check: stap -p4 syscalls_by_pid.stp +test_installcheck: stap syscalls_by_pid.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/syscalls_by_proc.meta b/testsuite/systemtap.examples/syscalls_by_proc.meta new file mode 100644 index 00000000..79aa3e87 --- /dev/null +++ b/testsuite/systemtap.examples/syscalls_by_proc.meta @@ -0,0 +1,13 @@ +title: System-Wide Count of Syscalls by Executable +name: syscalls_by_proc.stp +version: 1.0 +author: anonymous +keywords: syscall +subsystem: syscall +status: production +exit: user-controlled +output: sorted-list on-exit +scope: system-wide +description: The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greates to least number of syscalls. +test_check: stap -p4 syscalls_by_proc.stp +test_installcheck: stap syscalls_by_proc.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/wait4time.meta b/testsuite/systemtap.examples/wait4time.meta new file mode 100644 index 00000000..a939d466 --- /dev/null +++ b/testsuite/systemtap.examples/wait4time.meta @@ -0,0 +1,13 @@ +title: Trace Time Spent in wait4 Syscalls +name: wait4time.stp +version: 1.0 +author: Daniel Berrange and Will Cohen +keywords: syscall wait4 +subsystem: syscall +status: production +exit: user-controlled +output: trace +scope: system-wide +description: The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1". +test_check: stap -p4 wait4time.stp +test_installcheck: stap wait4time.stp -c "sleep 1" |