diff --git a/dtrace.in b/dtrace.in index 168bfb1..21d313c 100755 --- a/dtrace.in +++ b/dtrace.in @@ -17,9 +17,17 @@ from subprocess import call from tempfile import mkstemp class provider: + semaphores_def = "\n" + # is the type a basic scalar type? + def basic_type(self, arg): + basic_types = [ "int","int*","long","long*","short","short int","unsigned long","char","char*","float","double" ] + split_arg = arg.rsplit(None,1) + return (split_arg[0].strip() in basic_types) & (arg.find("[") == -1) def typedef_append(self, typedefs,this_probe,arg,c): if (add_typedefs): split_arg = arg.rsplit(None,1) + if (self.basic_type(arg)): + return typedefs type_name = " %s_arg%d" % (this_probe.replace("__","_"),c) if (len(split_arg) > 1): typedefs += ("typedef " + arg.replace(" " + split_arg[1].split("[")[0].lstrip("*"),type_name).strip() + "; ") @@ -28,11 +36,17 @@ class provider: typedefs += ("typedef " + arg.strip() + type_name + "; ") typedefs += (type_name + type_name + "_v;\n") return typedefs + def semaphore_def_append(self, this_probe): + self.semaphores_def += "__extension__ long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe) + def semaphore_def_write(self, file): + file.write(self.semaphores_def) def generate(self, provider, header, add_typedefs): have_provider = False self.f = open(provider) self.h = open(header,mode='w') self.h.write("/* Generated by the Systemtap dtrace wrapper */\n") + if (build_source): + self.h.write("\n#define STAP_HAS_SEMAPHORES 1\n\n") self.h.write("\n#include \n\n") in_comment = False typedefs = "" @@ -64,6 +78,7 @@ class provider: arg = "" i = 0 c = 0 + self.semaphore_def_append (this_probe) while (i < len(args)): if (args[i:i+1] == ","): args_string = ('%s %s,' % (args_string, arg.strip())) @@ -91,7 +106,8 @@ class provider: stap_str = stap_str + ",arg%s" % (i); i += 1 self.h.write ('/* %s (%s) */\n' % (this_probe_canon,args_string)) - self.h.write ('#define %s_ENABLED() 1\n' % this_probe_canon) + self.h.write ('#define %s_ENABLED() %s_semaphore\n' % (this_probe_canon,this_probe)) + self.h.write ("__extension__ extern long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe)) self.h.write (define_str + ") \\\n") self.h.write (stap_str + ")\n\n") elif (line.find("}") != -1 and have_provider): @@ -176,9 +192,17 @@ if (build_header): elif (build_source): (basename,ext) = os.path.splitext(s_filename) basename = os.path.basename(basename) + + # create for semaphore_def_write + providers = provider() + (d,fn) = mkstemp(suffix=".h",prefix=basename) + providers.generate(s_filename, fn, add_typedefs) + os.remove(fn) + (d,fn) = mkstemp(suffix=".c",prefix=basename) f = open(fn,mode='w') f.write("static __dtrace () {}\n") + providers.semaphore_def_write(f) f.close() call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", os.path.basename(filename) + ".o"], shell=False) os.remove(fn) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index f179c2a..6f3aaab 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -252,21 +252,31 @@ extern long int syscall (long int __sysno, ...) __THROW; # define STAP_GUARD 0x33425250 # endif +#ifdef STAP_HAS_SEMAPHORES +#define STAP_SEMAPHORE(probe) \ + if ( probe ## _semaphore ) +#else +#define STAP_SEMAPHORE(probe) ; +#endif + #include #define STAP_PROBE_(probe) \ +STAP_SEMAPHORE(probe) \ do { \ - STAP_PROBE_DATA(probe,STAP_SYSCALL,0); \ + STAP_PROBE_DATA(probe,STAP_GUARD,0); \ syscall (STAP_SYSCALL, #probe, STAP_GUARD); \ } while (0) #define STAP_PROBE1_(probe,label,parm1) \ +STAP_SEMAPHORE(probe) \ do { \ STAP_PROBE_DATA(probe,STAP_GUARD,1); \ syscall (STAP_SYSCALL, #probe, STAP_GUARD, (size_t)parm1); \ } while (0) #define STAP_PROBE2_(probe,label,parm1,parm2) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8)));} \ @@ -276,16 +286,18 @@ do { \ } while (0) #define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ size_t arg3 __attribute__((aligned(8)));} \ stap_probe3_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3}; \ STAP_PROBE_DATA(probe,STAP_GUARD,3); \ - syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe3_args); \ + syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe3_args); \ } while (0) #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -293,10 +305,11 @@ do { \ size_t arg4 __attribute__((aligned(8)));} \ stap_probe4_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3, (size_t)parm4}; \ STAP_PROBE_DATA(probe,STAP_GUARD,4); \ - syscall (STAP_SYSCALL, #probe, STAP_GUARD,&stap_probe4_args); \ + syscall (STAP_SYSCALL, #probe, STAP_GUARD,&stap_probe4_args); \ } while (0) #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -310,6 +323,7 @@ do { \ } while (0) #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -324,6 +338,7 @@ do { \ } while (0) #define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -339,6 +354,7 @@ do { \ } while (0) #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -355,6 +371,7 @@ do { \ } while (0) #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -372,6 +389,7 @@ do { \ } while (0) #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -385,7 +403,7 @@ do { \ size_t arg10 __attribute__((aligned(8)));} \ stap_probe10_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3, (size_t)parm4, \ (size_t)parm5, (size_t)parm6, (size_t)parm7, (size_t)parm8, (size_t)parm9, (size_t)parm10}; \ - STAP_PROBE_DATA(probe,STAP_GUARD,10); \ + STAP_PROBE_DATA(probe,STAP_GUARD,10); \ syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe10_args); \ } while (0) diff --git a/session.h b/session.h index ea91442..861f012 100644 --- a/session.h +++ b/session.h @@ -221,6 +221,10 @@ struct systemtap_session void print_error_source (std::ostream&, std::string&, const token* tok); void print_warning (const std::string& w, const token* tok = 0); + + // Location of semaphores to activate sdt probes + std::map sdt_semaphore_addr; + // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (elaborate.cxx) // and/or main.cxx(main). diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index a07e08b..20bd4de 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -716,6 +716,15 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, break; } s.op->line() << " .engine_attached=0,"; + map::iterator its; + for (its = s.sdt_semaphore_addr.begin(); + its != s.sdt_semaphore_addr.end(); + its++) + { + if (p == ((struct utrace_derived_probe*)(its->second))) + s.op->line() << " .sdt_sem_address=(unsigned long)0x" << hex << its->first << dec << "ULL,"; + } + s.op->line() << " .tsk=0,"; s.op->line() << " },"; } @@ -750,6 +759,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "struct utrace_engine_ops ops;"; s.op->newline() << "unsigned long events;"; s.op->newline() << "int engine_attached;"; + s.op->newline() << "struct task_struct *tsk;"; + s.op->newline() << "unsigned long sdt_sem_address;"; s.op->newline(-1) << "};"; @@ -872,6 +883,15 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "break;"; s.op->indent(-1); s.op->newline(-1) << "}"; + + s.op->newline() << "{"; + s.op->newline(1) << "size_t sdt_semaphore;"; + s.op->newline() << "p->tsk = tsk;"; + s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore += 1;"; + s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; // Since this engine could be attached to multiple threads, don't @@ -1045,6 +1065,26 @@ utrace_derived_probe_group::emit_module_exit (systemtap_session& s) s.op->newline() << "stap_utrace_detach_ops(&p->ops);"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; + + int sem_idx = 0; + if (! s.sdt_semaphore_addr.empty()) + for (p_b_path_iterator it = probes_by_path.begin(); + it != probes_by_path.end(); it++) + { + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "size_t sdt_semaphore;"; + s.op->newline() << "for (i=0; inewline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];"; + + s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore -= 1;"; + s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; + sem_idx += it->second.size() - 1; + } } diff --git a/tapsets.cxx b/tapsets.cxx index f91d15d..2b59b89 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -3350,6 +3350,7 @@ private: probe * base_probe; probe_point * base_loc; + literal_map_t const & params; vector & results; string mark_name; @@ -3365,6 +3366,7 @@ private: bool get_next_probe(); void convert_probe(probe *base); + void record_semaphore(vector & results); void convert_location(probe *base, probe_point *location); }; @@ -3373,7 +3375,7 @@ sdt_query::sdt_query(probe * base_probe, probe_point * base_loc, dwflpp & dw, literal_map_t const & params, vector & results): base_query(dw, params), base_probe(base_probe), - base_loc(base_loc), results(results) + base_loc(base_loc), params(params), results(results) { assert(get_string_param(params, TOK_MARK, mark_name)); } @@ -3415,7 +3417,11 @@ sdt_query::handle_query_module() unsigned i = results.size(); if (probe_type == kprobe_type || probe_type == utrace_type) - derive_probes(sess, new_base, results); + { + derive_probes(sess, new_base, results); + record_semaphore(results); + } + else { literal_map_t params; @@ -3428,6 +3434,7 @@ sdt_query::handle_query_module() dwarf_query q(new_base, new_location, dw, params, results); q.has_mark = true; // enables mid-statement probing dw.iterate_over_modules(&query_module, &q); + record_semaphore(results); } if (sess.listing_mode) @@ -3559,6 +3566,28 @@ sdt_query::get_next_probe() void +sdt_query::record_semaphore (vector & results) +{ + int sym_count = dwfl_module_getsymtab(dw.module); + assert (sym_count >= 0); + for (int i = 0; i < sym_count; i++) + { + GElf_Sym sym; + GElf_Word shndxp; + char *sym_str = (char*)dwfl_module_getsym (dw.module, i, &sym, &shndxp); + if (strcmp(sym_str, string(probe_name + "_semaphore").c_str()) == 0) + { + string process_name; + derived_probe_builder::get_param(params, TOK_PROCESS, process_name); + for (unsigned int i = 0; i < results.size(); ++i) + sess.sdt_semaphore_addr.insert(make_pair(sym.st_value, results[i])); + break; + } + } +} + + +void sdt_query::convert_probe (probe *base) { block *b = new block; @@ -3709,7 +3738,6 @@ sdt_query::convert_location (probe *base, probe_point *location) base->locations.push_back(location); } - void dwarf_builder::build(systemtap_session & sess, probe * base, @@ -4423,6 +4451,8 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "const char *pathname;"; s.op->newline() << "const char *pp;"; s.op->newline() << "void (*ph) (struct context*);"; + s.op->newline() << "unsigned long sdt_sem_address;"; + s.op->newline() << "struct task_struct *tsk;"; s.op->newline() << "unsigned return_p:1;"; s.op->newline(-1) << "} stap_uprobe_specs [] = {"; s.op->indent(1); @@ -4442,7 +4472,16 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->line() << " .address=(unsigned long)0x" << hex << p->address << dec << "ULL,"; s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ","; s.op->line() << " .ph=&" << p->name << ","; - if (p->return_p) s.op->line() << " .return_p=1,"; + map::iterator its; + for (its = s.sdt_semaphore_addr.begin(); + its != s.sdt_semaphore_addr.end(); + its++) + { + if (p->module == ((struct uprobe_derived_probe*)(its->second))->module + && p->address == ((struct uprobe_derived_probe*)(its->second))->address) + s.op->line() << " .sdt_sem_address=(unsigned long)0x" << hex << its->first << dec << "ULL,"; + } + if (p->return_p) s.op->line() << " .return_p=1,"; s.op->line() << " },"; } s.op->newline(-1) << "};"; @@ -4626,6 +4665,16 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; + //---------- + s.op->newline() << "{"; + s.op->newline(1) << "size_t sdt_semaphore;"; + s.op->newline() << "sups->tsk = tsk;"; + s.op->newline() << "__access_process_vm (tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore += 1;"; + s.op->newline() << "__access_process_vm (tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + //---------- + s.op->newline() << "return 0;"; // XXX: or rc? s.op->newline(-1) << "}"; s.op->assert_0_indent(); @@ -4730,6 +4779,16 @@ uprobe_derived_probe_group::emit_module_exit (systemtap_session& s) s.op->newline() << "struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];"; s.op->newline() << "if (sup->spec_index < 0) continue;"; // free slot + //---------- + s.op->newline() << "{"; + s.op->newline(1) << "size_t sdt_semaphore;"; + s.op->newline() << "__access_process_vm (sups->tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore -= 1;"; + s.op->newline() << "__access_process_vm (sups->tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + //---------- + + s.op->newline() << "if (sups->return_p) {"; s.op->newline(1) << "#ifdef DEBUG_UPROBES"; s.op->newline() << "printk (KERN_INFO \"-uretprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);"; diff --git a/translate.cxx b/translate.cxx index 4a6a10b..3cc4fee 100644 --- a/translate.cxx +++ b/translate.cxx @@ -5177,6 +5177,8 @@ translate_pass (systemtap_session& s) s.op->newline() << "#include "; // s.op->newline() << "#include "; s.op->newline() << "#include \"loc2c-runtime.h\" "; + if (! s.sdt_semaphore_addr.empty()) + s.op->newline() << "#include \"access_process_vm.h\" "; // XXX: old 2.6 kernel hack s.op->newline() << "#ifndef read_trylock";