Skip to content

Commit

Permalink
Merge branch 'signal-trigger'
Browse files Browse the repository at this point in the history
Add signal trigger to control tracing behavior using signals.  Currently
trace-on, trace-off and finish triggers are supported only.

Closed: #340

Signed-off-by: Namhyung Kim <namhyung@gmail.com>
  • Loading branch information
namhyung committed Jan 16, 2019
2 parents c71b4e9 + 770faff commit fa2abec
Show file tree
Hide file tree
Showing 25 changed files with 528 additions and 114 deletions.
9 changes: 1 addition & 8 deletions arch/aarch64/mcount.S
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,9 @@ ENTRY(mcount_return)

add x0, sp, #16
bl mcount_exit

cmp x0, #0
b.eq 1f
mov x16, x0
b 2f

1: /* if finish trigger fired, use restored address */
ldr x16, [sp, #40]

2: /* restore return values */
/* restore return values */
ldr d0, [sp], #16
ldp x0, x8, [sp], #16
/* restore frame pointer */
Expand Down
9 changes: 1 addition & 8 deletions arch/aarch64/plthook.S
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,9 @@ ENTRY(plthook_return)

add x0, sp, #16
bl plthook_exit

cmp x0, #0
b.eq 1f
mov x16, x0
b 2f

1: /* if finish trigger fired, use restored address */
ldr x16, [sp, #40]

2: /* restore return values */
/* restore return values */
ldr d0, [sp], #16
ldp x0, x8, [sp], #16
/* restore frame pointer */
Expand Down
6 changes: 0 additions & 6 deletions arch/arm/mcount.S
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,7 @@ ENTRY(mcount_return)
#if HAVE_ARM_HARDFP
vpop {d0}
#endif

/* if finish trigger fired, return address already updated */
cmp r0, #0
beq 1f

/* update return address (pc) in the stack */
str r0, [sp, #12]
1:
pop {r0-r1, lr, pc}
END(mcount_return)
6 changes: 0 additions & 6 deletions arch/arm/plthook.S
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,7 @@ ENTRY(plthook_return)
#ifdef HAVE_ARM_HARDFP
vpop {d0}
#endif

/* if finish trigger fired, return address already updated */
cmp r0, #0
beq 1f

/* update return address (pc) in the stack */
str r0, [sp, #12]
1:
pop {r0-r1, lr, pc}
END(plthook_return)
2 changes: 2 additions & 0 deletions arch/i386/mcount-arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ unsigned long * mcount_arch_parent_location(struct symtabs *symtabs,
#define ARCH_PLT0_SIZE 16
#define ARCH_PLTHOOK_ADDR_OFFSET 6

#define ARCH_CAN_RESTORE_PLTHOOK 1

#endif /* __MCOUNT_ARCH_H__ */
5 changes: 1 addition & 4 deletions arch/i386/mcount.S
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,8 @@ ENTRY(mcount_return)

/* returns original parent address */
call mcount_exit

test %eax, %eax
jz 1f
movl %eax, 12(%esp)
1:

movl 4(%esp), %eax
movl 8(%esp), %edx
add $12, %esp
Expand Down
5 changes: 1 addition & 4 deletions arch/i386/plthook.S
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,8 @@ ENTRY(plthook_return)
movl %eax, 0(%esp)

call plthook_exit

test %eax, %eax
jz 1f
movl %eax, 12(%esp)
1:

movl 4(%esp), %eax
movl 8(%esp), %edx
add $12, %esp
Expand Down
1 change: 1 addition & 0 deletions arch/x86_64/mcount-arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ struct mcount_arch_context {
#define ARCH_PLTHOOK_ADDR_OFFSET 6

#define ARCH_SUPPORT_AUTO_RECOVER 1
#define ARCH_CAN_RESTORE_PLTHOOK 1

#endif /* MCOUNT_ARCH_H */
5 changes: 1 addition & 4 deletions arch/x86_64/mcount.S
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,8 @@ ENTRY(mcount_return)

/* returns original parent address */
call mcount_exit
movq %rax, 40(%rsp)

test %rax, %rax
jz 1f
movq %rax, 40(%rsp)
1:
movq 0(%rsp), %rax
movq 8(%rsp), %rdx
movdqu 16(%rsp), %xmm0
Expand Down
5 changes: 1 addition & 4 deletions arch/x86_64/plthook.S
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,8 @@ ENTRY(plthook_return)
movq %rsp, %rdi

call plthook_exit
movq %rax, 40(%rsp)

test %rax, %rax
jz 1f
movq %rax, 40(%rsp)
1:
movq 0(%rsp), %rax
movq 8(%rsp), %rdx
movdqu 16(%rsp), %xmm0
Expand Down
8 changes: 4 additions & 4 deletions cmds/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -1096,17 +1096,17 @@ void process_uftrace_info(struct uftrace_data *handle, struct opts *opts,
if (info_mask & (1UL << EXIT_STATUS)) {
int status = info->exit_status;

if (WIFEXITED(status)) {
if (status == UFTRACE_EXIT_FINISHED) {
snprintf(buf, sizeof(buf), "terminated by finish trigger");
}
else if (WIFEXITED(status)) {
snprintf(buf, sizeof(buf), "exited with code: %d",
WEXITSTATUS(status));
}
else if (WIFSIGNALED(status)) {
snprintf(buf, sizeof(buf), "terminated by signal: %d",
WTERMSIG(status));
}
else if (status == UFTRACE_EXIT_FINISHED) {
snprintf(buf, sizeof(buf), "terminated by finish trigger");
}
else {
snprintf(buf, sizeof(buf), "unknown exit status: %d",
status);
Expand Down
14 changes: 12 additions & 2 deletions cmds/record.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static bool can_use_fast_libmcount(struct opts *opts)
getenv("UFTRACE_ARGUMENT") || getenv("UFTRACE_RETVAL") ||
getenv("UFTRACE_PATCH") || getenv("UFTRACE_SCRIPT") ||
getenv("UFTRACE_AUTO_ARGS") || getenv("UFTRACE_WATCH") ||
getenv("UFTRACE_CALLER"))
getenv("UFTRACE_CALLER") || getenv("UFTRACE_SIGNAL"))
return false;
return true;
}
Expand Down Expand Up @@ -306,6 +306,9 @@ static void setup_child_environ(struct opts *opts, int pfd,
if (opts->patt_type != PATT_REGEX)
setenv("UFTRACE_PATTERN", get_filter_pattern(opts->patt_type), 1);

if (opts->sig_trigger)
setenv("UFTRACE_SIGNAL", opts->sig_trigger, 1);

if (argc > 0) {
char *args = NULL;
int i;
Expand All @@ -317,6 +320,10 @@ static void setup_child_environ(struct opts *opts, int pfd,
free(args);
}

/*
* ----- end of option processing -----
*/

libpath = get_libmcount_path(opts);
if (libpath == NULL)
pr_err_ns("cannot found libmcount.so\n");
Expand Down Expand Up @@ -1748,7 +1755,7 @@ static int stop_tracing(struct writer_data *wd, struct opts *opts)
break;

if (finish_received) {
ret = UFTRACE_EXIT_FINISHED;
status = UFTRACE_EXIT_FINISHED;
break;
}

Expand Down Expand Up @@ -1888,6 +1895,9 @@ int do_main_loop(int pfd[2], int ready, struct opts *opts, int pid)
wd.pipefd = pfd[0];
close(pfd[1]);

if (opts->sig_trigger)
pr_out("uftrace: install signal handlers to task %d\n", pid);

setup_writers(&wd, opts);
start_tracing(&wd, opts, ready);
close(ready);
Expand Down
19 changes: 15 additions & 4 deletions doc/uftrace-live.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ OPTIONS
-W, \--watch=*POINT*
: Add watch point to display POINT if the value is changed. See *WATCH POINT*.

\--signal=*TRG*
: Set trigger on selected signals rather than functions. But there are
restrictions so only a few of trigger actions are support for signals.
The available actions are: traceon, traceoff, finish.
This option can be used more than once. See *TRIGGERS*.


FILTERS
=======
Expand Down Expand Up @@ -319,10 +325,9 @@ for details.

TRIGGERS
========
The uftrace tool supports triggering actions on selected function calls with or
without filters. Currently supported triggers are `depth` (for record and
replay) and `backtrace` (for replay only). The BNF for trigger specifications
is like below:
The uftrace tool supports triggering actions on selected function calls (with or
without filters) and/or signals. Currently supported triggers are listed below.
The BNF for trigger specifications is like below:

<trigger> := <symbol> "@" <actions>
<actions> := <action> | <action> "," <actions>
Expand Down Expand Up @@ -400,6 +405,12 @@ The 'filter' and 'notrace' triggers have same effect as -F/\--filter and

Triggers only work for user-level functions for now.

The trigger can be used for signals as well. This is done by signal trigger
with \--signal option. The syntax is similar to function trigger but only
"trace_on", "trace_off" and "finish" trigger actions are supported.

$ uftrace live --signal 'SIGUSR1@finish' ./some-daemon


ARGUMENTS
=========
Expand Down
21 changes: 16 additions & 5 deletions doc/uftrace-record.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ OPTIONS
-W, \--watch=*POINT*
: Add watch point to display POINT if the value is changed. See *WATCH POINT*.

\--signal=*TRG*
: Set trigger on selected signals rather than functions. But there are
restrictions so only a few of trigger actions are support for signals.
The available actions are: traceon, traceoff, finish.
This option can be used more than once. See *TRIGGERS*.


FILTERS
=======
Expand Down Expand Up @@ -325,8 +331,8 @@ example will show all user functions and the (kernel) page fault handler.

TRIGGERS
========
The uftrace tool supports triggering actions on selected function calls with or
without filters. Currently supported triggers are listed below.
The uftrace tool supports triggering actions on selected function calls (with or
without filters) and/or signals. Currently supported triggers are listed below.
The BNF for trigger specification is:

<trigger> := <symbol> "@" <actions>
Expand All @@ -335,9 +341,8 @@ The BNF for trigger specification is:
"time="<time_spec> | "read="<read_spec> | "finish" |
"filter" | "notrace" | "recover"
<time_spec> := <num> [ <time_unit> ]
<time_unit> := "ns" | "us" | "ms" | "s"
<read_spec> := "proc/statm" | "page-fault" | "pmu-cycle" | "pmu-cache" |
"pmu-branch"
<time_unit> := "ns" | "nsec" | "us" | "usec" | "ms" | "msec" | "s" | "sec" | "m" | "min"
<read_spec> := "proc/statm" | "page-fault" | "pmu-cycle" | "pmu-cache" | "pmu-branch"

The `depth` trigger is to change filter depth during execution of the function.
It can be used to apply different filter depths for different functions.
Expand Down Expand Up @@ -408,6 +413,12 @@ The 'filter' and 'notrace' triggers have same effect as `-F`/`--filter` and

Triggers only work for user-level functions for now.

The trigger can be used for signals as well. This is done by signal trigger
with \--signal option. The syntax is similar to function trigger but only
"trace_on", "trace_off" and "finish" trigger actions are supported.

$ uftrace record --signal 'SIGUSR1@finish' ./some-daemon


ARGUMENTS
=========
Expand Down
14 changes: 14 additions & 0 deletions libmcount/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@
#include "utils/filter.h"
#include "utils/compiler.h"

/* could be defined in mcount-arch.h */
#ifndef ARCH_SUPPORT_AUTO_RECOVER
# define ARCH_SUPPORT_AUTO_RECOVER 0
#endif

/* plt_hooker has return address to hook */
#ifndef ARCH_CAN_RESTORE_PLTHOOK
# define ARCH_CAN_RESTORE_PLTHOOK 0
#endif

enum filter_result {
FILTER_RSTACK = -1,
FILTER_OUT,
Expand Down Expand Up @@ -111,6 +121,7 @@ struct mcount_thread_data {
int record_idx;
bool recursion_marker;
bool in_exception;
bool dead;
unsigned long cygprof_dummy;
struct mcount_ret_stack *rstack;
void *argbuf;
Expand Down Expand Up @@ -144,6 +155,8 @@ static inline void mcount_restore_arch_context(struct mcount_arch_context *ctx)

extern TLS struct mcount_thread_data mtd;

void __mcount_guard_recursion(struct mcount_thread_data *mtdp);
void __mcount_unguard_recursion(struct mcount_thread_data *mtdp);
bool mcount_guard_recursion(struct mcount_thread_data *mtdp);
void mcount_unguard_recursion(struct mcount_thread_data *mtdp);

Expand Down Expand Up @@ -248,6 +261,7 @@ extern void mcount_rstack_reset_exception(struct mcount_thread_data *mtdp,
unsigned long frame_addr);
extern void mcount_auto_restore(struct mcount_thread_data *mtdp);
extern void mcount_auto_reset(struct mcount_thread_data *mtdp);
extern bool mcount_rstack_has_plthook(struct mcount_thread_data *mtdp);

extern void prepare_shmem_buffer(struct mcount_thread_data *mtdp);
extern void clear_shmem_buffer(struct mcount_thread_data *mtdp);
Expand Down
Loading

0 comments on commit fa2abec

Please sign in to comment.