Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 223880
b: refs/heads/master
c: 6d8e40a
h: refs/heads/master
v: v3
  • Loading branch information
Masami Hiramatsu authored and Ingo Molnar committed Dec 6, 2010
1 parent dca78b2 commit 12a6d9d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 48 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: e4b546a3643fbfc510d5ef7db538e4d3ab00effb
refs/heads/master: 6d8e40a85ef72a0514ebd00748eb18cab432b200
93 changes: 46 additions & 47 deletions trunk/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,10 @@ static inline int kprobe_aggrprobe(struct kprobe *p)
/*
* Keep all fields in the kprobe consistent
*/
static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
static inline void copy_kprobe(struct kprobe *ap, struct kprobe *p)
{
memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
memcpy(&p->opcode, &ap->opcode, sizeof(kprobe_opcode_t));
memcpy(&p->ainsn, &ap->ainsn, sizeof(struct arch_specific_insn));
}

#ifdef CONFIG_OPTPROBES
Expand Down Expand Up @@ -671,28 +671,28 @@ int proc_kprobes_optimization_handler(struct ctl_table *table, int write,

static void __kprobes __arm_kprobe(struct kprobe *p)
{
struct kprobe *old_p;
struct kprobe *_p;

/* Check collision with other optimized kprobes */
old_p = get_optimized_kprobe((unsigned long)p->addr);
if (unlikely(old_p))
unoptimize_kprobe(old_p); /* Fallback to unoptimized kprobe */
_p = get_optimized_kprobe((unsigned long)p->addr);
if (unlikely(_p))
unoptimize_kprobe(_p); /* Fallback to unoptimized kprobe */

arch_arm_kprobe(p);
optimize_kprobe(p); /* Try to optimize (add kprobe to a list) */
}

static void __kprobes __disarm_kprobe(struct kprobe *p)
{
struct kprobe *old_p;
struct kprobe *_p;

unoptimize_kprobe(p); /* Try to unoptimize */
arch_disarm_kprobe(p);

/* If another kprobe was blocked, optimize it. */
old_p = get_optimized_kprobe((unsigned long)p->addr);
if (unlikely(old_p))
optimize_kprobe(old_p);
_p = get_optimized_kprobe((unsigned long)p->addr);
if (unlikely(_p))
optimize_kprobe(_p);
}

#else /* !CONFIG_OPTPROBES */
Expand Down Expand Up @@ -993,18 +993,18 @@ static void __kprobes init_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
* This is the second or subsequent kprobe at the address - handle
* the intricacies
*/
static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
static int __kprobes register_aggr_kprobe(struct kprobe *orig_p,
struct kprobe *p)
{
int ret = 0;
struct kprobe *ap = old_p;
struct kprobe *ap = orig_p;

if (!kprobe_aggrprobe(old_p)) {
/* If old_p is not an aggr_kprobe, create new aggr_kprobe. */
ap = alloc_aggr_kprobe(old_p);
if (!kprobe_aggrprobe(orig_p)) {
/* If orig_p is not an aggr_kprobe, create new aggr_kprobe. */
ap = alloc_aggr_kprobe(orig_p);
if (!ap)
return -ENOMEM;
init_aggr_kprobe(ap, old_p);
init_aggr_kprobe(ap, orig_p);
}

if (kprobe_gone(ap)) {
Expand Down Expand Up @@ -1098,34 +1098,33 @@ static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
/* Check passed kprobe is valid and return kprobe in kprobe_table. */
static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
{
struct kprobe *old_p, *list_p;
struct kprobe *ap, *list_p;

old_p = get_kprobe(p->addr);
if (unlikely(!old_p))
ap = get_kprobe(p->addr);
if (unlikely(!ap))
return NULL;

if (p != old_p) {
list_for_each_entry_rcu(list_p, &old_p->list, list)
if (p != ap) {
list_for_each_entry_rcu(list_p, &ap->list, list)
if (list_p == p)
/* kprobe p is a valid probe */
goto valid;
return NULL;
}
valid:
return old_p;
return ap;
}

/* Return error if the kprobe is being re-registered */
static inline int check_kprobe_rereg(struct kprobe *p)
{
int ret = 0;
struct kprobe *old_p;

mutex_lock(&kprobe_mutex);
old_p = __get_valid_kprobe(p);
if (old_p)
if (__get_valid_kprobe(p))
ret = -EINVAL;
mutex_unlock(&kprobe_mutex);

return ret;
}

Expand Down Expand Up @@ -1234,43 +1233,43 @@ EXPORT_SYMBOL_GPL(register_kprobe);
*/
static int __kprobes __unregister_kprobe_top(struct kprobe *p)
{
struct kprobe *old_p, *list_p;
struct kprobe *ap, *list_p;

old_p = __get_valid_kprobe(p);
if (old_p == NULL)
ap = __get_valid_kprobe(p);
if (ap == NULL)
return -EINVAL;

if (old_p == p ||
(kprobe_aggrprobe(old_p) &&
list_is_singular(&old_p->list))) {
if (ap == p ||
(kprobe_aggrprobe(ap) &&
list_is_singular(&ap->list))) {
/*
* Only probe on the hash list. Disarm only if kprobes are
* enabled and not gone - otherwise, the breakpoint would
* already have been removed. We save on flushing icache.
*/
if (!kprobes_all_disarmed && !kprobe_disabled(old_p))
disarm_kprobe(old_p);
hlist_del_rcu(&old_p->hlist);
if (!kprobes_all_disarmed && !kprobe_disabled(ap))
disarm_kprobe(ap);
hlist_del_rcu(&ap->hlist);
} else {
if (p->break_handler && !kprobe_gone(p))
old_p->break_handler = NULL;
ap->break_handler = NULL;
if (p->post_handler && !kprobe_gone(p)) {
list_for_each_entry_rcu(list_p, &old_p->list, list) {
list_for_each_entry_rcu(list_p, &ap->list, list) {
if ((list_p != p) && (list_p->post_handler))
goto noclean;
}
old_p->post_handler = NULL;
ap->post_handler = NULL;
}
noclean:
list_del_rcu(&p->list);
if (!kprobe_disabled(old_p)) {
try_to_disable_aggr_kprobe(old_p);
if (!kprobe_disabled(ap)) {
try_to_disable_aggr_kprobe(ap);
if (!kprobes_all_disarmed) {
if (kprobe_disabled(old_p))
disarm_kprobe(old_p);
if (kprobe_disabled(ap))
disarm_kprobe(ap);
else
/* Try to optimize this probe again */
optimize_kprobe(old_p);
optimize_kprobe(ap);
}
}
}
Expand All @@ -1279,16 +1278,16 @@ static int __kprobes __unregister_kprobe_top(struct kprobe *p)

static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)
{
struct kprobe *old_p;
struct kprobe *ap;

if (list_empty(&p->list))
arch_remove_kprobe(p);
else if (list_is_singular(&p->list)) {
/* "p" is the last child of an aggr_kprobe */
old_p = list_entry(p->list.next, struct kprobe, list);
ap = list_entry(p->list.next, struct kprobe, list);
list_del(&p->list);
arch_remove_kprobe(old_p);
free_aggr_kprobe(old_p);
arch_remove_kprobe(ap);
free_aggr_kprobe(ap);
}
}

Expand Down

0 comments on commit 12a6d9d

Please sign in to comment.