Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 7503
b: refs/heads/master
c: d0aaff9
h: refs/heads/master
i:
  7501: 4bc5724
  7499: 3371567
  7495: 313317d
  7487: 269c217
v: v3
  • Loading branch information
Prasanna S Panchamukhi authored and Linus Torvalds committed Sep 7, 2005
1 parent b6ebeb3 commit 63e34dc
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 30 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: 505db03639db34ca2c64fe7ee27190d324281f2c
refs/heads/master: d0aaff9796c3310326d10da44fc0faed352a1d29
1 change: 1 addition & 0 deletions trunk/include/asm-generic/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ extern char _sextratext[] __attribute__((weak));
extern char _eextratext[] __attribute__((weak));
extern char _end[];
extern char __per_cpu_start[], __per_cpu_end[];
extern char __kprobes_text_start[], __kprobes_text_end[];

#endif /* _ASM_GENERIC_SECTIONS_H_ */
6 changes: 6 additions & 0 deletions trunk/include/asm-generic/vmlinux.lds.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,9 @@
VMLINUX_SYMBOL(__lock_text_start) = .; \
*(.spinlock.text) \
VMLINUX_SYMBOL(__lock_text_end) = .;

#define KPROBES_TEXT \
ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__kprobes_text_start) = .; \
*(.kprobes.text) \
VMLINUX_SYMBOL(__kprobes_text_end) = .;
3 changes: 3 additions & 0 deletions trunk/include/linux/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
#define KPROBE_REENTER 0x00000004
#define KPROBE_HIT_SSDONE 0x00000008

/* Attach to insert probes on any functions which should be ignored*/
#define __kprobes __attribute__((__section__(".kprobes.text")))

struct kprobe;
struct pt_regs;
struct kretprobe;
Expand Down
7 changes: 7 additions & 0 deletions trunk/include/linux/linkage.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
ALIGN; \
name:

#define KPROBE_ENTRY(name) \
.section .kprobes.text, "ax"; \
.globl name; \
ALIGN; \
name:


#endif

#define NORET_TYPE /**/
Expand Down
72 changes: 43 additions & 29 deletions trunk/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleloader.h>
#include <asm-generic/sections.h>
#include <asm/cacheflush.h>
#include <asm/errno.h>
#include <asm/kdebug.h>
Expand Down Expand Up @@ -72,7 +73,7 @@ static struct hlist_head kprobe_insn_pages;
* get_insn_slot() - Find a slot on an executable page for an instruction.
* We allocate an executable page if there's no room on existing ones.
*/
kprobe_opcode_t *get_insn_slot(void)
kprobe_opcode_t __kprobes *get_insn_slot(void)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
Expand Down Expand Up @@ -117,7 +118,7 @@ kprobe_opcode_t *get_insn_slot(void)
return kip->insns;
}

void free_insn_slot(kprobe_opcode_t *slot)
void __kprobes free_insn_slot(kprobe_opcode_t *slot)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
Expand Down Expand Up @@ -152,20 +153,20 @@ void free_insn_slot(kprobe_opcode_t *slot)
}

/* Locks kprobe: irqs must be disabled */
void lock_kprobes(void)
void __kprobes lock_kprobes(void)
{
spin_lock(&kprobe_lock);
kprobe_cpu = smp_processor_id();
}

void unlock_kprobes(void)
void __kprobes unlock_kprobes(void)
{
kprobe_cpu = NR_CPUS;
spin_unlock(&kprobe_lock);
}

/* You have to be holding the kprobe_lock */
struct kprobe *get_kprobe(void *addr)
struct kprobe __kprobes *get_kprobe(void *addr)
{
struct hlist_head *head;
struct hlist_node *node;
Expand All @@ -183,7 +184,7 @@ struct kprobe *get_kprobe(void *addr)
* Aggregate handlers for multiple kprobes support - these handlers
* take care of invoking the individual kprobe handlers on p->list
*/
static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp;

Expand All @@ -198,8 +199,8 @@ static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}

static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
unsigned long flags)
static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
unsigned long flags)
{
struct kprobe *kp;

Expand All @@ -213,8 +214,8 @@ static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
return;
}

static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
int trapnr)
static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
int trapnr)
{
/*
* if we faulted "during" the execution of a user specified
Expand All @@ -227,7 +228,7 @@ static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
return 0;
}

static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp = curr_kprobe;
if (curr_kprobe && kp->break_handler) {
Expand All @@ -240,7 +241,7 @@ static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}

struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)
{
struct hlist_node *node;
struct kretprobe_instance *ri;
Expand All @@ -249,7 +250,8 @@ struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
return NULL;
}

static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe
*rp)
{
struct hlist_node *node;
struct kretprobe_instance *ri;
Expand All @@ -258,7 +260,7 @@ static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
return NULL;
}

void add_rp_inst(struct kretprobe_instance *ri)
void __kprobes add_rp_inst(struct kretprobe_instance *ri)
{
/*
* Remove rp inst off the free list -
Expand All @@ -276,7 +278,7 @@ void add_rp_inst(struct kretprobe_instance *ri)
hlist_add_head(&ri->uflist, &ri->rp->used_instances);
}

void recycle_rp_inst(struct kretprobe_instance *ri)
void __kprobes recycle_rp_inst(struct kretprobe_instance *ri)
{
/* remove rp inst off the rprobe_inst_table */
hlist_del(&ri->hlist);
Expand All @@ -291,7 +293,7 @@ void recycle_rp_inst(struct kretprobe_instance *ri)
kfree(ri);
}

struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
{
return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
}
Expand All @@ -302,7 +304,7 @@ struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
* instances associated with this task. These left over instances represent
* probed functions that have been called but will never return.
*/
void kprobe_flush_task(struct task_struct *tk)
void __kprobes kprobe_flush_task(struct task_struct *tk)
{
struct kretprobe_instance *ri;
struct hlist_head *head;
Expand All @@ -322,7 +324,8 @@ void kprobe_flush_task(struct task_struct *tk)
* This kprobe pre_handler is registered with every kretprobe. When probe
* hits it will set up the return probe.
*/
static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
static int __kprobes pre_handler_kretprobe(struct kprobe *p,
struct pt_regs *regs)
{
struct kretprobe *rp = container_of(p, struct kretprobe, kp);

Expand Down Expand Up @@ -353,7 +356,7 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
* Add the new probe to old_p->list. Fail if this is the
* second jprobe at the address - two jprobes can't coexist
*/
static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
{
struct kprobe *kp;

Expand Down Expand Up @@ -395,7 +398,8 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
* the intricacies
* TODO: Move kcalloc outside the spinlock
*/
static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p)
static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
struct kprobe *p)
{
int ret = 0;
struct kprobe *ap;
Expand Down Expand Up @@ -434,15 +438,25 @@ static inline void cleanup_aggr_kprobe(struct kprobe *old_p,
spin_unlock_irqrestore(&kprobe_lock, flags);
}

int register_kprobe(struct kprobe *p)
static int __kprobes in_kprobes_functions(unsigned long addr)
{
if (addr >= (unsigned long)__kprobes_text_start
&& addr < (unsigned long)__kprobes_text_end)
return -EINVAL;
return 0;
}

int __kprobes register_kprobe(struct kprobe *p)
{
int ret = 0;
unsigned long flags = 0;
struct kprobe *old_p;

if ((ret = arch_prepare_kprobe(p)) != 0) {
if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0)
return ret;
if ((ret = arch_prepare_kprobe(p)) != 0)
goto rm_kprobe;
}

spin_lock_irqsave(&kprobe_lock, flags);
old_p = get_kprobe(p->addr);
p->nmissed = 0;
Expand All @@ -466,7 +480,7 @@ int register_kprobe(struct kprobe *p)
return ret;
}

void unregister_kprobe(struct kprobe *p)
void __kprobes unregister_kprobe(struct kprobe *p)
{
unsigned long flags;
struct kprobe *old_p;
Expand All @@ -487,7 +501,7 @@ static struct notifier_block kprobe_exceptions_nb = {
.priority = 0x7fffffff /* we need to notified first */
};

int register_jprobe(struct jprobe *jp)
int __kprobes register_jprobe(struct jprobe *jp)
{
/* Todo: Verify probepoint is a function entry point */
jp->kp.pre_handler = setjmp_pre_handler;
Expand All @@ -496,14 +510,14 @@ int register_jprobe(struct jprobe *jp)
return register_kprobe(&jp->kp);
}

void unregister_jprobe(struct jprobe *jp)
void __kprobes unregister_jprobe(struct jprobe *jp)
{
unregister_kprobe(&jp->kp);
}

#ifdef ARCH_SUPPORTS_KRETPROBES

int register_kretprobe(struct kretprobe *rp)
int __kprobes register_kretprobe(struct kretprobe *rp)
{
int ret = 0;
struct kretprobe_instance *inst;
Expand Down Expand Up @@ -540,14 +554,14 @@ int register_kretprobe(struct kretprobe *rp)

#else /* ARCH_SUPPORTS_KRETPROBES */

int register_kretprobe(struct kretprobe *rp)
int __kprobes register_kretprobe(struct kretprobe *rp)
{
return -ENOSYS;
}

#endif /* ARCH_SUPPORTS_KRETPROBES */

void unregister_kretprobe(struct kretprobe *rp)
void __kprobes unregister_kretprobe(struct kretprobe *rp)
{
unsigned long flags;
struct kretprobe_instance *ri;
Expand Down

0 comments on commit 63e34dc

Please sign in to comment.