Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 169854
b: refs/heads/master
c: 956ffd0
h: refs/heads/master
v: v3
  • Loading branch information
Tom Zanussi authored and Ingo Molnar committed Nov 28, 2009
1 parent 1160826 commit 0c5fe61
Show file tree
Hide file tree
Showing 20 changed files with 930 additions and 796 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e859cf8656043f158b4004ccc8cbbf1ba4f97177
refs/heads/master: 956ffd027bedc4106b901eb6a50f0a6c6de4113d
8 changes: 4 additions & 4 deletions trunk/arch/x86/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ extern const char *regs_query_register_name(unsigned int offset);
* @regs: pt_regs from which register value is gotten.
* @offset: offset number of the register.
*
* regs_get_register returns the value of a register. The @offset is the
* offset of the register in struct pt_regs address which specified by @regs.
* regs_get_register returns the value of a register whose offset from @regs
* is @offset. The @offset is the offset of the register in struct pt_regs.
* If @offset is bigger than MAX_REG_OFFSET, this returns 0.
*/
static inline unsigned long regs_get_register(struct pt_regs *regs,
Expand All @@ -244,7 +244,7 @@ static inline unsigned long regs_get_register(struct pt_regs *regs,
* @regs: pt_regs which contains kernel stack pointer.
* @addr: address which is checked.
*
* regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
* regs_within_kenel_stack() checks @addr is within the kernel stack page(s).
* If @addr is within the kernel stack, it returns true. If not, returns false.
*/
static inline int regs_within_kernel_stack(struct pt_regs *regs,
Expand All @@ -260,7 +260,7 @@ static inline int regs_within_kernel_stack(struct pt_regs *regs,
* @n: stack entry number.
*
* regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
* is specified by @regs. If the @n th entry is NOT in the kernel stack,
* is specifined by @regs. If the @n th entry is NOT in the kernel stack,
* this returns 0.
*/
static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
Expand Down
16 changes: 4 additions & 12 deletions trunk/arch/x86/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ static unsigned long ptrace_get_dr7(struct perf_event *bp[])

static struct perf_event *
ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
struct task_struct *tsk, int disabled)
struct task_struct *tsk)
{
int err;
int gen_len, gen_type;
Expand All @@ -616,7 +616,7 @@ ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
attr = bp->attr;
attr.bp_len = gen_len;
attr.bp_type = gen_type;
attr.disabled = disabled;
attr.disabled = 0;

return modify_user_hw_breakpoint(bp, &attr, bp->callback, tsk);
}
Expand Down Expand Up @@ -655,21 +655,13 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)
*/
if (!second_pass)
continue;

thread->ptrace_bps[i] = NULL;
bp = ptrace_modify_breakpoint(bp, len, type,
tsk, 1);
if (IS_ERR(bp)) {
rc = PTR_ERR(bp);
thread->ptrace_bps[i] = NULL;
break;
}
thread->ptrace_bps[i] = bp;
unregister_hw_breakpoint(bp);
}
continue;
}

bp = ptrace_modify_breakpoint(bp, len, type, tsk, 0);
bp = ptrace_modify_breakpoint(bp, len, type, tsk);

/* Incorrect bp, or we have a bug in bp API */
if (IS_ERR(bp)) {
Expand Down
77 changes: 63 additions & 14 deletions trunk/include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,37 @@ struct perf_event_attr;
#define __SC_TEST6(t6, a6, ...) __SC_TEST(t6); __SC_TEST5(__VA_ARGS__)

#ifdef CONFIG_EVENT_PROFILE
#define TRACE_SYS_ENTER_PROFILE(sname) \
static int prof_sysenter_enable_##sname(struct ftrace_event_call *unused) \
{ \
return reg_prof_syscall_enter("sys"#sname); \
} \
\
static void prof_sysenter_disable_##sname(struct ftrace_event_call *unused) \
{ \
unreg_prof_syscall_enter("sys"#sname); \
}

#define TRACE_SYS_EXIT_PROFILE(sname) \
static int prof_sysexit_enable_##sname(struct ftrace_event_call *unused) \
{ \
return reg_prof_syscall_exit("sys"#sname); \
} \
\
static void prof_sysexit_disable_##sname(struct ftrace_event_call *unused) \
{ \
unreg_prof_syscall_exit("sys"#sname); \
}

#define TRACE_SYS_ENTER_PROFILE_INIT(sname) \
.profile_count = ATOMIC_INIT(-1), \
.profile_enable = prof_sysenter_enable, \
.profile_disable = prof_sysenter_disable,
.profile_enable = prof_sysenter_enable_##sname, \
.profile_disable = prof_sysenter_disable_##sname,

#define TRACE_SYS_EXIT_PROFILE_INIT(sname) \
.profile_count = ATOMIC_INIT(-1), \
.profile_enable = prof_sysexit_enable, \
.profile_disable = prof_sysexit_disable,
.profile_enable = prof_sysexit_enable_##sname, \
.profile_disable = prof_sysexit_disable_##sname,
#else
#define TRACE_SYS_ENTER_PROFILE(sname)
#define TRACE_SYS_ENTER_PROFILE_INIT(sname)
Expand All @@ -132,46 +153,74 @@ struct perf_event_attr;
#define __SC_STR_TDECL6(t, a, ...) #t, __SC_STR_TDECL5(__VA_ARGS__)

#define SYSCALL_TRACE_ENTER_EVENT(sname) \
static const struct syscall_metadata __syscall_meta_##sname; \
static struct ftrace_event_call event_enter_##sname; \
static struct trace_event enter_syscall_print_##sname = { \
struct trace_event enter_syscall_print_##sname = { \
.trace = print_syscall_enter, \
}; \
static int init_enter_##sname(struct ftrace_event_call *call) \
{ \
int num, id; \
num = syscall_name_to_nr("sys"#sname); \
if (num < 0) \
return -ENOSYS; \
id = register_ftrace_event(&enter_syscall_print_##sname);\
if (!id) \
return -ENODEV; \
event_enter_##sname.id = id; \
set_syscall_enter_id(num, id); \
INIT_LIST_HEAD(&event_enter_##sname.fields); \
return 0; \
} \
TRACE_SYS_ENTER_PROFILE(sname); \
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
event_enter_##sname = { \
.name = "sys_enter"#sname, \
.system = "syscalls", \
.event = &enter_syscall_print_##sname, \
.raw_init = init_syscall_trace, \
.event = &event_syscall_enter, \
.raw_init = init_enter_##sname, \
.show_format = syscall_enter_format, \
.define_fields = syscall_enter_define_fields, \
.regfunc = reg_event_syscall_enter, \
.unregfunc = unreg_event_syscall_enter, \
.data = (void *)&__syscall_meta_##sname,\
.data = "sys"#sname, \
TRACE_SYS_ENTER_PROFILE_INIT(sname) \
}

#define SYSCALL_TRACE_EXIT_EVENT(sname) \
static const struct syscall_metadata __syscall_meta_##sname; \
static struct ftrace_event_call event_exit_##sname; \
static struct trace_event exit_syscall_print_##sname = { \
struct trace_event exit_syscall_print_##sname = { \
.trace = print_syscall_exit, \
}; \
static int init_exit_##sname(struct ftrace_event_call *call) \
{ \
int num, id; \
num = syscall_name_to_nr("sys"#sname); \
if (num < 0) \
return -ENOSYS; \
id = register_ftrace_event(&exit_syscall_print_##sname);\
if (!id) \
return -ENODEV; \
event_exit_##sname.id = id; \
set_syscall_exit_id(num, id); \
INIT_LIST_HEAD(&event_exit_##sname.fields); \
return 0; \
} \
TRACE_SYS_EXIT_PROFILE(sname); \
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
event_exit_##sname = { \
.name = "sys_exit"#sname, \
.system = "syscalls", \
.event = &exit_syscall_print_##sname, \
.raw_init = init_syscall_trace, \
.event = &event_syscall_exit, \
.raw_init = init_exit_##sname, \
.show_format = syscall_exit_format, \
.define_fields = syscall_exit_define_fields, \
.regfunc = reg_event_syscall_exit, \
.unregfunc = unreg_event_syscall_exit, \
.data = (void *)&__syscall_meta_##sname,\
.data = "sys"#sname, \
TRACE_SYS_EXIT_PROFILE_INIT(sname) \
}

Expand Down
20 changes: 13 additions & 7 deletions trunk/include/trace/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,33 @@
* A syscall entry in the ftrace syscalls array.
*
* @name: name of the syscall
* @syscall_nr: number of the syscall
* @nb_args: number of parameters it takes
* @types: list of types as strings
* @args: list of args as strings (args[i] matches types[i])
* @enter_id: associated ftrace enter event id
* @exit_id: associated ftrace exit event id
* @enter_event: associated syscall_enter trace event
* @exit_event: associated syscall_exit trace event
*/
struct syscall_metadata {
const char *name;
int syscall_nr;
int nb_args;
const char **types;
const char **args;
int enter_id;
int exit_id;

struct ftrace_event_call *enter_event;
struct ftrace_event_call *exit_event;
};

#ifdef CONFIG_FTRACE_SYSCALLS
extern unsigned long arch_syscall_addr(int nr);
extern int init_syscall_trace(struct ftrace_event_call *call);
extern int syscall_name_to_nr(char *name);
void set_syscall_enter_id(int num, int id);
void set_syscall_exit_id(int num, int id);
extern struct trace_event event_syscall_enter;
extern struct trace_event event_syscall_exit;

extern int syscall_enter_format(struct ftrace_event_call *call,
struct trace_seq *s);
Expand All @@ -50,10 +56,10 @@ enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags);
enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags);
#endif
#ifdef CONFIG_EVENT_PROFILE
int prof_sysenter_enable(struct ftrace_event_call *call);
void prof_sysenter_disable(struct ftrace_event_call *call);
int prof_sysexit_enable(struct ftrace_event_call *call);
void prof_sysexit_disable(struct ftrace_event_call *call);
int reg_prof_syscall_enter(char *name);
void unreg_prof_syscall_enter(char *name);
int reg_prof_syscall_exit(char *name);
void unreg_prof_syscall_exit(char *name);

#endif

Expand Down
4 changes: 1 addition & 3 deletions trunk/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -2210,7 +2210,6 @@ static void perf_mmap_data_free(struct perf_mmap_data *data)
perf_mmap_free_page((unsigned long)data->user_page);
for (i = 0; i < data->nr_pages; i++)
perf_mmap_free_page((unsigned long)data->data_pages[i]);
kfree(data);
}

#else
Expand Down Expand Up @@ -2251,7 +2250,6 @@ static void perf_mmap_data_free_work(struct work_struct *work)
perf_mmap_unmark_page(base + (i * PAGE_SIZE));

vfree(base);
kfree(data);
}

static void perf_mmap_data_free(struct perf_mmap_data *data)
Expand Down Expand Up @@ -2357,6 +2355,7 @@ static void perf_mmap_data_free_rcu(struct rcu_head *rcu_head)

data = container_of(rcu_head, struct perf_mmap_data, rcu_head);
perf_mmap_data_free(data);
kfree(data);
}

static void perf_mmap_data_release(struct perf_event *event)
Expand Down Expand Up @@ -4011,7 +4010,6 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
event->pmu->read(event);

data.addr = 0;
data.period = event->hw.last_period;
regs = get_irq_regs();
/*
* In case we exclude kernel IPs or are somehow not in interrupt
Expand Down
26 changes: 7 additions & 19 deletions trunk/kernel/trace/trace_kprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,8 +483,7 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
return ret;
}

/* Recursive argument parser */
static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
{
int ret = 0;
unsigned long param;
Expand Down Expand Up @@ -544,7 +543,7 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
if (!id)
return -ENOMEM;
id->offset = offset;
ret = __parse_probe_arg(arg, &id->orig, is_return);
ret = parse_probe_arg(arg, &id->orig, is_return);
if (ret)
kfree(id);
else {
Expand All @@ -561,16 +560,6 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
return ret;
}

/* String length checking wrapper */
static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
{
if (strlen(arg) > MAX_ARGSTR_LEN) {
pr_info("Argument is too long.: %s\n", arg);
return -ENOSPC;
}
return __parse_probe_arg(arg, ff, is_return);
}

/* Return 1 if name is reserved or already used by another argument */
static int conflict_field_name(const char *name,
struct probe_arg *args, int narg)
Expand Down Expand Up @@ -709,14 +698,13 @@ static int create_trace_probe(int argc, char **argv)
}

tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
if (!tp->args[i].name) {
pr_info("Failed to allocate argument%d name '%s'.\n",
i, argv[i]);
ret = -ENOMEM;
goto error;
}

/* Parse fetch argument */
if (strlen(arg) > MAX_ARGSTR_LEN) {
pr_info("Argument%d(%s) is too long.\n", i, arg);
ret = -ENOSPC;
goto error;
}
ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return);
if (ret) {
pr_info("Parse error at argument%d. (%d)\n", i, ret);
Expand Down
Loading

0 comments on commit 0c5fe61

Please sign in to comment.