MIPS: Use NOKPROBE_SYMBOL() instead of __kprobes annotation
If define CONFIG_KPROBES, __kprobes annotation forces the whole function into the ".kprobes.text" section, NOKPROBE_SYMBOL() only stores the given function address in the "_kprobe_blacklist" section which is introduced to maintain kprobes blacklist. Modify the related code to use NOKPROBE_SYMBOL() to protect functions from kprobes instead of __kprobes annotation under arch/mips. No obvious functional change in this patch, some more work needs to be done to fix the kernel panic when execute the following testcase on mips: # cd tools/testing/selftests/ftrace # ./ftracetest test.d/kprobe/multiple_kprobes.tc Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
This commit is contained in:
Родитель
eab691b1a6
Коммит
f5e2d8186d
|
@ -44,10 +44,11 @@ static const union mips_instruction breakpoint2_insn = {
|
|||
DEFINE_PER_CPU(struct kprobe *, current_kprobe);
|
||||
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
|
||||
|
||||
static int __kprobes insn_has_delayslot(union mips_instruction insn)
|
||||
static int insn_has_delayslot(union mips_instruction insn)
|
||||
{
|
||||
return __insn_has_delay_slot(insn);
|
||||
}
|
||||
NOKPROBE_SYMBOL(insn_has_delayslot);
|
||||
|
||||
/*
|
||||
* insn_has_ll_or_sc function checks whether instruction is ll or sc
|
||||
|
@ -56,7 +57,7 @@ static int __kprobes insn_has_delayslot(union mips_instruction insn)
|
|||
* instructions; cannot do much about breakpoint in the middle of
|
||||
* ll/sc pair; it is upto user to avoid those places
|
||||
*/
|
||||
static int __kprobes insn_has_ll_or_sc(union mips_instruction insn)
|
||||
static int insn_has_ll_or_sc(union mips_instruction insn)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -72,8 +73,9 @@ static int __kprobes insn_has_ll_or_sc(union mips_instruction insn)
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
NOKPROBE_SYMBOL(insn_has_ll_or_sc);
|
||||
|
||||
int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
||||
int arch_prepare_kprobe(struct kprobe *p)
|
||||
{
|
||||
union mips_instruction insn;
|
||||
union mips_instruction prev_insn;
|
||||
|
@ -132,26 +134,30 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_prepare_kprobe);
|
||||
|
||||
void __kprobes arch_arm_kprobe(struct kprobe *p)
|
||||
void arch_arm_kprobe(struct kprobe *p)
|
||||
{
|
||||
*p->addr = breakpoint_insn;
|
||||
flush_insn_slot(p);
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_arm_kprobe);
|
||||
|
||||
void __kprobes arch_disarm_kprobe(struct kprobe *p)
|
||||
void arch_disarm_kprobe(struct kprobe *p)
|
||||
{
|
||||
*p->addr = p->opcode;
|
||||
flush_insn_slot(p);
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_disarm_kprobe);
|
||||
|
||||
void __kprobes arch_remove_kprobe(struct kprobe *p)
|
||||
void arch_remove_kprobe(struct kprobe *p)
|
||||
{
|
||||
if (p->ainsn.insn) {
|
||||
free_insn_slot(p->ainsn.insn, 0);
|
||||
p->ainsn.insn = NULL;
|
||||
}
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_remove_kprobe);
|
||||
|
||||
static void save_previous_kprobe(struct kprobe_ctlblk *kcb)
|
||||
{
|
||||
|
@ -257,7 +263,7 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
|
|||
* breakpoint trap. In case of branch instructions, the target
|
||||
* epc to be restored.
|
||||
*/
|
||||
static void __kprobes resume_execution(struct kprobe *p,
|
||||
static void resume_execution(struct kprobe *p,
|
||||
struct pt_regs *regs,
|
||||
struct kprobe_ctlblk *kcb)
|
||||
{
|
||||
|
@ -268,8 +274,9 @@ static void __kprobes resume_execution(struct kprobe *p,
|
|||
regs->cp0_epc = orig_epc + 4;
|
||||
}
|
||||
}
|
||||
NOKPROBE_SYMBOL(resume_execution);
|
||||
|
||||
static int __kprobes kprobe_handler(struct pt_regs *regs)
|
||||
static int kprobe_handler(struct pt_regs *regs)
|
||||
{
|
||||
struct kprobe *p;
|
||||
int ret = 0;
|
||||
|
@ -367,6 +374,7 @@ no_kprobe:
|
|||
return ret;
|
||||
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_handler);
|
||||
|
||||
static inline int post_kprobe_handler(struct pt_regs *regs)
|
||||
{
|
||||
|
@ -415,7 +423,7 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
|||
/*
|
||||
* Wrapper routine for handling exceptions.
|
||||
*/
|
||||
int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
|
||||
int kprobe_exceptions_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
|
||||
|
@ -446,6 +454,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_exceptions_notify);
|
||||
|
||||
/*
|
||||
* Function return probe trampoline:
|
||||
|
@ -469,7 +478,7 @@ static void __used kretprobe_trampoline_holder(void)
|
|||
|
||||
void __kretprobe_trampoline(void);
|
||||
|
||||
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||
void arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
ri->ret_addr = (kprobe_opcode_t *) regs->regs[31];
|
||||
|
@ -478,11 +487,12 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
|||
/* Replace the return addr with trampoline addr */
|
||||
regs->regs[31] = (unsigned long)__kretprobe_trampoline;
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_prepare_kretprobe);
|
||||
|
||||
/*
|
||||
* Called when the probe at kretprobe trampoline is hit
|
||||
*/
|
||||
static int __kprobes trampoline_probe_handler(struct kprobe *p,
|
||||
static int trampoline_probe_handler(struct kprobe *p,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
instruction_pointer(regs) = __kretprobe_trampoline_handler(regs, NULL);
|
||||
|
@ -493,14 +503,16 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
|
|||
*/
|
||||
return 1;
|
||||
}
|
||||
NOKPROBE_SYMBOL(trampoline_probe_handler);
|
||||
|
||||
int __kprobes arch_trampoline_kprobe(struct kprobe *p)
|
||||
int arch_trampoline_kprobe(struct kprobe *p)
|
||||
{
|
||||
if (p->addr == (kprobe_opcode_t *)__kretprobe_trampoline)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_trampoline_kprobe);
|
||||
|
||||
static struct kprobe trampoline_p = {
|
||||
.addr = (kprobe_opcode_t *)__kretprobe_trampoline,
|
||||
|
|
|
@ -35,7 +35,7 @@ int show_unhandled_signals = 1;
|
|||
* and the problem, and then passes it off to one of the appropriate
|
||||
* routines.
|
||||
*/
|
||||
static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
|
||||
static void __do_page_fault(struct pt_regs *regs, unsigned long write,
|
||||
unsigned long address)
|
||||
{
|
||||
struct vm_area_struct * vma = NULL;
|
||||
|
@ -322,8 +322,9 @@ vmalloc_fault:
|
|||
}
|
||||
#endif
|
||||
}
|
||||
NOKPROBE_SYMBOL(__do_page_fault);
|
||||
|
||||
asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
||||
asmlinkage void do_page_fault(struct pt_regs *regs,
|
||||
unsigned long write, unsigned long address)
|
||||
{
|
||||
enum ctx_state prev_state;
|
||||
|
@ -332,3 +333,4 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||
__do_page_fault(regs, write, address);
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_page_fault);
|
||||
|
|
Загрузка…
Ссылка в новой задаче