From: Pierre-Marc Fournier Date: Tue, 27 Oct 2009 22:58:15 +0000 (-0400) Subject: Merge branch 'for-pierre-marc' of git://git.infradead.org/users/jblunck/ust X-Git-Tag: v0.1~71 X-Git-Url: https://git.lttng.org/?a=commitdiff_plain;h=aa08b4413291fabcbd1b1144377d37034ad361de;hp=fbca6b624335eef18c8d86194aeb101a720168f4;p=ust.git Merge branch 'for-pierre-marc' of git://git.infradead.org/users/jblunck/ust Fixed conflicts: include/ust/marker.h --- diff --git a/include/ust/marker.h b/include/ust/marker.h index 2b5a0c3..5c7d1b3 100644 --- a/include/ust/marker.h +++ b/include/ust/marker.h @@ -30,6 +30,7 @@ //ust// #include #include #include +#include "processor.h" //ust// struct module; //ust// struct task_struct; @@ -49,7 +50,7 @@ struct marker; * format string to recover the variable argument list. */ typedef void marker_probe_func(const struct marker *mdata, - void *probe_private, void *call_private, + void *probe_private, struct registers *regs, void *call_private, const char *fmt, va_list *args); struct marker_probe_closure { @@ -68,11 +69,12 @@ struct marker { /* Probe wrapper */ u16 channel_id; /* Numeric channel identifier, dynamic */ u16 event_id; /* Numeric event identifier, dynamic */ - void (*call)(const struct marker *mdata, void *call_private, ...); + void (*call)(const struct marker *mdata, void *call_private, struct registers *regs, ...); struct marker_probe_closure single; struct marker_probe_closure *multi; const char *tp_name; /* Optional tracepoint name */ void *tp_cb; /* Optional tracepoint callback */ + void *location; /* Address of marker in code */ } __attribute__((aligned(8))); #define CONFIG_MARKERS @@ -82,6 +84,7 @@ struct marker { static const char __mstrtab_##channel##_##name[] \ __attribute__((section("__markers_strings"))) \ = #channel "\0" #name "\0" format; \ + struct registers regs; \ static struct marker __mark_##channel##_##name \ __attribute__((section("__markers"), aligned(8))) = \ { __mstrtab_##channel##_##name, \ @@ -90,7 +93,15 @@ struct marker { sizeof(#name)], \ 0, 0, 0, 0, marker_probe_cb, \ { __mark_empty_function, NULL}, \ - NULL, tp_name_str, tp_cb } + NULL, tp_name_str, tp_cb, NULL }; \ + asm (".section __marker_addr,\"aw\",@progbits\n\t" \ + _ASM_PTR "%c[marker_struct], (1f)\n\t" \ + ".previous\n\t" \ + "1:\n\t" \ + :: [marker_struct] "i" (&__mark_##channel##_##name));\ + save_registers(®s) + + #define DEFINE_MARKER(channel, name, format) \ _DEFINE_MARKER(channel, name, NULL, NULL, format) @@ -116,13 +127,13 @@ struct marker { __mark_##channel##_##name.state))) \ (*__mark_##channel##_##name.call) \ (&__mark_##channel##_##name, \ - call_private, ## args); \ + call_private, ®s, ## args); \ } else { \ if (unlikely(_imv_read( \ __mark_##channel##_##name.state))) \ (*__mark_##channel##_##name.call) \ (&__mark_##channel##_##name, \ - call_private, ## args); \ + call_private, ®s, ## args); \ } \ } while (0) @@ -136,7 +147,7 @@ struct marker { DEFINE_MARKER_TP(channel, name, tp_name, tp_cb, format);\ __mark_check_format(format, ## args); \ (*__mark_##channel##_##name.call)(&__mark_##channel##_##name, \ - call_private, ## args); \ + call_private, ®s, ## args); \ } while (0) extern void marker_update_probe_range(struct marker *begin, @@ -230,7 +241,7 @@ static inline void __printf(1, 2) ___mark_check_format(const char *fmt, ...) extern marker_probe_func __mark_empty_function; extern void marker_probe_cb(const struct marker *mdata, - void *call_private, ...); + void *call_private, struct registers *regs, ...); /* * Connect a probe to a marker. @@ -286,23 +297,29 @@ extern int is_marker_enabled(const char *channel, const char *name); //ust// } //ust// #endif +struct marker_addr { + struct marker *marker; + void *addr; +}; struct lib { struct marker *markers_start; + struct marker_addr *markers_addr_start; int markers_count; struct list_head list; }; -extern int marker_register_lib(struct marker *markers_start, - int markers_count); - -#define MARKER_LIB \ -extern struct marker __start___markers[] __attribute__((visibility("hidden"))); \ -extern struct marker __stop___markers[] __attribute__((visibility("hidden"))); \ - \ -static void __attribute__((constructor)) __markers__init(void) \ -{ \ - marker_register_lib(__start___markers, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker));\ +extern int marker_register_lib(struct marker *markers_start, struct marker_addr *marker_addr_start, int markers_count); + +#define MARKER_LIB \ +extern struct marker __start___markers[] __attribute__((visibility("hidden"))); \ +extern struct marker __stop___markers[] __attribute__((visibility("hidden"))); \ +extern struct marker_addr __start___marker_addr[] __attribute__((visibility("hidden"))); \ +extern struct marker_addr __stop___marker_addr[] __attribute__((visibility("hidden"))); \ + \ +static void __attribute__((constructor)) __markers__init(void) \ +{ \ + marker_register_lib(__start___markers, __start___marker_addr, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker)); \ } extern void marker_set_new_marker_cb(void (*cb)(struct marker *)); diff --git a/libust/marker.c b/libust/marker.c index 8690d2b..b543b16 100644 --- a/libust/marker.c +++ b/libust/marker.c @@ -43,6 +43,8 @@ extern struct marker __start___markers[] __attribute__((visibility("hidden"))); extern struct marker __stop___markers[] __attribute__((visibility("hidden"))); +extern struct marker_addr __start___marker_addr[] __attribute__((visibility("hidden"))); +extern struct marker_addr __stop___marker_addr[] __attribute__((visibility("hidden"))); /* Set to 1 to enable marker debug output */ static const int marker_debug; @@ -87,7 +89,7 @@ struct marker_entry { char *format; char *name; /* Probe wrapper */ - void (*call)(const struct marker *mdata, void *call_private, ...); + void (*call)(const struct marker *mdata, void *call_private, struct registers *regs, ...); struct marker_probe_closure single; struct marker_probe_closure *multi; int refcount; /* Number of times armed. 0 if disarmed. */ @@ -123,7 +125,7 @@ static void marker_update_processes(void) * operations that modifies the execution flow of preemptible code. */ notrace void __mark_empty_function(const struct marker *mdata, - void *probe_private, void *call_private, const char *fmt, va_list *args) + void *probe_private, struct registers *regs, void *call_private, const char *fmt, va_list *args) { } //ust// EXPORT_SYMBOL_GPL(__mark_empty_function); @@ -139,7 +141,7 @@ notrace void __mark_empty_function(const struct marker *mdata, * rcu_dereference() for the pointer read. */ notrace void marker_probe_cb(const struct marker *mdata, - void *call_private, ...) + void *call_private, struct registers *regs, ...) { va_list args; char ptype; @@ -160,8 +162,8 @@ notrace void marker_probe_cb(const struct marker *mdata, /* Must read the ptr before private data. They are not data * dependant, so we put an explicit smp_rmb() here. */ smp_rmb(); - va_start(args, call_private); - func(mdata, mdata->single.probe_private, call_private, + va_start(args, regs); + func(mdata, mdata->single.probe_private, regs, call_private, mdata->format, &args); va_end(args); } else { @@ -181,9 +183,9 @@ notrace void marker_probe_cb(const struct marker *mdata, */ smp_read_barrier_depends(); for (i = 0; multi[i].func; i++) { - va_start(args, call_private); + va_start(args, regs); multi[i].func(mdata, multi[i].probe_private, - call_private, mdata->format, &args); + regs, call_private, mdata->format, &args); va_end(args); } } @@ -200,7 +202,7 @@ notrace void marker_probe_cb(const struct marker *mdata, * Should be connected to markers "MARK_NOARGS". */ static notrace void marker_probe_cb_noarg(const struct marker *mdata, - void *call_private, ...) + void *call_private, struct registers *regs, ...) { va_list args; /* not initialized */ char ptype; @@ -216,7 +218,7 @@ static notrace void marker_probe_cb_noarg(const struct marker *mdata, /* Must read the ptr before private data. They are not data * dependant, so we put an explicit smp_rmb() here. */ smp_rmb(); - func(mdata, mdata->single.probe_private, call_private, + func(mdata, mdata->single.probe_private, regs, call_private, mdata->format, &args); } else { struct marker_probe_closure *multi; @@ -235,7 +237,7 @@ static notrace void marker_probe_cb_noarg(const struct marker *mdata, */ smp_read_barrier_depends(); for (i = 0; multi[i].func; i++) - multi[i].func(mdata, multi[i].probe_private, + multi[i].func(mdata, multi[i].probe_private, regs, call_private, mdata->format, &args); } //ust// rcu_read_unlock_sched_notrace(); @@ -823,6 +825,7 @@ int marker_probe_register(const char *channel, const char *name, } mutex_unlock(&markers_mutex); + /* Activate marker if necessary */ marker_update_probes(); mutex_lock(&markers_mutex); @@ -1495,15 +1498,22 @@ static void new_markers(struct marker *start, struct marker *end) } } -int marker_register_lib(struct marker *markers_start, int markers_count) +int marker_register_lib(struct marker *markers_start, struct marker_addr *marker_addr_start, int markers_count) { struct lib *pl; + struct marker_addr *addr; pl = (struct lib *) malloc(sizeof(struct lib)); pl->markers_start = markers_start; + pl->markers_addr_start = marker_addr_start; pl->markers_count = markers_count; + lock_markers(); + for(addr = marker_addr_start; addr < marker_addr_start + markers_count; addr++) + addr->marker->location = addr->addr; + unlock_markers(); + /* FIXME: maybe protect this with its own mutex? */ lock_markers(); list_add(&pl->list, &libs); @@ -1532,8 +1542,8 @@ static int initialized = 0; void __attribute__((constructor)) init_markers(void) { if(!initialized) { - marker_register_lib(__start___markers, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker)); - DBG("markers_start: %p, markers_stop: %p\n", __start___markers, __stop___markers); + marker_register_lib(__start___markers, __start___marker_addr, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker)); + //DBG("markers_start: %p, markers_stop: %p\n", __start___markers, __stop___markers); initialized = 1; } } diff --git a/libust/processor.h b/libust/processor.h new file mode 100644 index 0000000..1eb5843 --- /dev/null +++ b/libust/processor.h @@ -0,0 +1,107 @@ +#ifndef UST_PROCESSOR_H +#define UST_PROCESSOR_H + +#include + +#ifdef X86_32 + +struct registers { + long eax; + long ebx; + long ecx; + long edx; + long ebp; + long esp; + long esi; + long edi; + int xds; + int xes; + int xfs; + int xgs; + long eip; + int xcs; + long eflags; + int xss; +}; + +static inline save_registers(struct registers *regs) +{ +} + +#define RELATIVE_ADDRESS(__rel_label__) __rel_label__ + +#define _ASM_PTR ".long " + +#else + +struct registers { + unsigned long rax; + unsigned long rbx; + unsigned long rcx; + unsigned long rdx; + unsigned long rbp; + unsigned long rsp; + unsigned long rsi; + unsigned long rdi; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + int cs; + int ss; +}; + +#define save_registers(regsptr) \ + asm ("movq %%rax,%c[rax_off](%[regs])\n\t" \ + "movq %%rbx,%c[rbx_off](%[regs])\n\t" \ + "movq %%rcx,%c[rcx_off](%[regs])\n\t" \ + "movq %%rdx,%c[rdx_off](%[regs])\n\t" \ + "movq %%rbp,%c[rbp_off](%[regs])\n\t" \ + "movq %%rsp,%c[rsp_off](%[regs])\n\t" \ + "movq %%rsi,%c[rsi_off](%[regs])\n\t" \ + "movq %%rdi,%c[rdi_off](%[regs])\n\t" \ + "movq %%r8,%c[r8_off](%[regs])\n\t" \ + "movq %%r9,%c[r9_off](%[regs])\n\t" \ + "movq %%r10,%c[r10_off](%[regs])\n\t" \ + "movq %%r11,%c[r11_off](%[regs])\n\t" \ + "movq %%r12,%c[r12_off](%[regs])\n\t" \ + "movq %%r13,%c[r13_off](%[regs])\n\t" \ + "movq %%r14,%c[r14_off](%[regs])\n\t" \ + "movq %%r15,%c[r15_off](%[regs])\n\t" \ + "movw %%cs,%c[cs_off](%[regs])\n\t" \ + "movw %%ss,%c[ss_off](%[regs])\n\t" \ + : \ + : [regs] "r" (regsptr), \ + [rax_off] "i" (offsetof(struct registers, rax)), \ + [rbx_off] "i" (offsetof(struct registers, rbx)), \ + [rcx_off] "i" (offsetof(struct registers, rcx)), \ + [rdx_off] "i" (offsetof(struct registers, rdx)), \ + [rbp_off] "i" (offsetof(struct registers, rbp)), \ + [rsp_off] "i" (offsetof(struct registers, rsp)), \ + [rsi_off] "i" (offsetof(struct registers, rsi)), \ + [rdi_off] "i" (offsetof(struct registers, rdi)), \ + [r8_off] "i" (offsetof(struct registers, r8)), \ + [r9_off] "i" (offsetof(struct registers, r9)), \ + [r10_off] "i" (offsetof(struct registers, r10)), \ + [r11_off] "i" (offsetof(struct registers, r11)), \ + [r12_off] "i" (offsetof(struct registers, r12)), \ + [r13_off] "i" (offsetof(struct registers, r13)), \ + [r14_off] "i" (offsetof(struct registers, r14)), \ + [r15_off] "i" (offsetof(struct registers, r15)), \ + [cs_off] "i" (offsetof(struct registers, cs)), \ + [ss_off] "i" (offsetof(struct registers, ss)) \ + ); + +/* Macro to insert the address of a relative jump in an assembly stub, + * in a relocatable way. On x86-64, this uses a special (%rip) notation. */ +#define RELATIVE_ADDRESS(__rel_label__) __rel_label__(%%rip) + +#define _ASM_PTR ".quad " + +#endif + +#endif /* UST_PROCESSOR_H */ diff --git a/libust/serialize.c b/libust/serialize.c index 99d4dce..beaf639 100644 --- a/libust/serialize.c +++ b/libust/serialize.c @@ -583,7 +583,8 @@ void ltt_write_event_data(struct rchan_buf *buf, size_t buf_offset, notrace void ltt_vtrace(const struct marker *mdata, void *probe_data, - void *call_data, const char *fmt, va_list *args) + struct registers *regs, void *call_data, + const char *fmt, va_list *args) { int largest_align, ret; struct ltt_active_marker *pdata; @@ -697,12 +698,13 @@ notrace void ltt_vtrace(const struct marker *mdata, void *probe_data, } notrace void ltt_trace(const struct marker *mdata, void *probe_data, - void *call_data, const char *fmt, ...) + struct registers *regs, void *call_data, + const char *fmt, ...) { va_list args; va_start(args, fmt); - ltt_vtrace(mdata, probe_data, call_data, fmt, &args); + ltt_vtrace(mdata, probe_data, regs, call_data, fmt, &args); va_end(args); } diff --git a/libust/tracectl.c b/libust/tracectl.c index 3d3bd48..e28b315 100644 --- a/libust/tracectl.c +++ b/libust/tracectl.c @@ -117,7 +117,7 @@ static void print_markers(FILE *fp) marker_iter_start(&iter); while(iter.marker) { - fprintf(fp, "marker: %s/%s %d \"%s\"\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format); + fprintf(fp, "marker: %s/%s %d \"%s\" %p\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format, iter.marker->location); marker_iter_next(&iter); } unlock_markers(); @@ -837,7 +837,7 @@ static void auto_probe_connect(struct marker *m) if(result && result != -EEXIST) ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result); - DBG("auto connected marker %s %s to probe default", m->channel, m->name); + DBG("auto connected marker %s (addr: %p) %s to probe default", m->channel, m, m->name); } diff --git a/libust/tracer.h b/libust/tracer.h index cb84dad..502cdcc 100644 --- a/libust/tracer.h +++ b/libust/tracer.h @@ -110,9 +110,9 @@ struct ltt_active_marker { struct marker; //ust// extern void ltt_vtrace(const struct marker *mdata, void *probe_data, - void *call_data, const char *fmt, va_list *args); + struct registers *regs, void *call_data, const char *fmt, va_list *args); extern void ltt_trace(const struct marker *mdata, void *probe_data, - void *call_data, const char *fmt, ...); + struct registers *regs, void *call_data, const char *fmt, ...); /* * Unique ID assigned to each registered probe. diff --git a/ustd/ustd.c b/ustd/ustd.c index 0026c3b..bfa6352 100644 --- a/ustd/ustd.c +++ b/ustd/ustd.c @@ -541,6 +541,24 @@ void sigterm_handler(int sig) terminate_req = 1; } +static int write_pidfile(const char *file_name, pid_t pid) +{ + FILE *pidfp; + + pidfp = fopen(file_name, "w+"); + if(!pidfp) { + PERROR("fopen (%s)", pidfile); + WARN("killing child process"); + return -1; + } + + fprintf(pidfp, "%d\n", pid); + + fclose(pidfp); + + return 0; +} + int start_ustd(int fd) { struct ustcomm_ustd ustd; @@ -585,6 +603,15 @@ int start_ustd(int fd) return 1; } + /* Write pidfile */ + if(pidfile) { + result = write_pidfile(pidfile, getpid()); + if(result == -1) { + ERR("failed to write pidfile"); + return 1; + } + } + /* Notify parent that we are successfully started. */ if(fd != -1) { /* write any one character */ @@ -673,26 +700,6 @@ int start_ustd_daemon() char buf; FILE *pidfp; - /* It's important to write the file *before* - * the parent ends, because the file may be - * read as soon as the parent ends. - */ - if(pidfile) { - pidfp = fopen(pidfile, "w+"); - if(!pidfp) { - PERROR("fopen (%s)", pidfile); - WARN("killing child process"); - result = kill(child_pid, SIGTERM); - if(result == -1) { - PERROR("kill"); - } - return -1; - } - - fprintf(pidfp, "%d\n", child_pid); - fclose(pidfp); - } - result = read(fd[0], &buf, 1); if(result == -1) { PERROR("read"); diff --git a/usttrace b/usttrace index fe8a5cd..52c378d 100755 --- a/usttrace +++ b/usttrace @@ -78,9 +78,9 @@ SOCKPATH="/tmp/ust-sock-$$" if [ "$arg_syswide_daemon" != "1" ]; then pidfilepath="/tmp/usttrace-$USER-$(date +%Y%m%d%H%M%S%N)-ustd-pid" - + mkfifo -m 0600 "$pidfilepath" # Start daemon - $USTD -d --pidfile "$pidfilepath" -s "$SOCKPATH" -o "$OUTDIR" >"$OUTDIR/ustd.log" 2>&1 & + $USTD --pidfile "$pidfilepath" -s "$SOCKPATH" -o "$OUTDIR" >"$OUTDIR/ustd.log" 2>&1 & USTDPID="$(<$pidfilepath)" export UST_DAEMON_SOCKET="$SOCKPATH" fi @@ -129,7 +129,7 @@ then kill -SIGTERM "$USTDPID" echo "Waiting for ustd to shutdown..." - wait "$USTDPID" + wait "$(USTDPID)" rm "$pidfilepath" fi