···480 return 0;481}482483-/* architecture specific initialization */484-int arch_init_kprobes(void)000000000000485{0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000486 return 0;487}
···480 return 0;481}482483+/* Called with kretprobe_lock held. The value stored in the return484+ * address register is actually 2 instructions before where the485+ * callee will return to. Sequences usually look something like this486+ *487+ * call some_function <--- return register points here488+ * nop <--- call delay slot489+ * whatever <--- where callee returns to490+ *491+ * To keep trampoline_probe_handler logic simpler, we normalize the492+ * value kept in ri->ret_addr so we don't need to keep adjusting it493+ * back and forth.494+ */495+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,496+ struct pt_regs *regs)497{498+ ri->ret_addr = (kprobe_opcode_t *)(regs->u_regs[UREG_RETPC] + 8);499+500+ /* Replace the return addr with trampoline addr */501+ regs->u_regs[UREG_RETPC] =502+ ((unsigned long)kretprobe_trampoline) - 8;503+}504+505+/*506+ * Called when the probe at kretprobe trampoline is hit507+ */508+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)509+{510+ struct kretprobe_instance *ri = NULL;511+ struct hlist_head *head, empty_rp;512+ struct hlist_node *node, *tmp;513+ unsigned long flags, orig_ret_address = 0;514+ unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;515+516+ INIT_HLIST_HEAD(&empty_rp);517+ spin_lock_irqsave(&kretprobe_lock, flags);518+ head = kretprobe_inst_table_head(current);519+520+ /*521+ * It is possible to have multiple instances associated with a given522+ * task either because an multiple functions in the call path523+ * have a return probe installed on them, and/or more then one return524+ * return probe was registered for a target function.525+ *526+ * We can handle this because:527+ * - instances are always inserted at the head of the list528+ * - when multiple return probes are registered for the same529+ * function, the first instance's ret_addr will point to the530+ * real return address, and all the rest will point to531+ * kretprobe_trampoline532+ */533+ hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {534+ if (ri->task != current)535+ /* another task is sharing our hash bucket */536+ continue;537+538+ if (ri->rp && ri->rp->handler)539+ ri->rp->handler(ri, regs);540+541+ orig_ret_address = (unsigned long)ri->ret_addr;542+ recycle_rp_inst(ri, &empty_rp);543+544+ if (orig_ret_address != trampoline_address)545+ /*546+ * This is the real return address. Any other547+ * instances associated with this task are for548+ * other calls deeper on the call stack549+ */550+ break;551+ }552+553+ kretprobe_assert(ri, orig_ret_address, trampoline_address);554+ regs->tpc = orig_ret_address;555+ regs->tnpc = orig_ret_address + 4;556+557+ reset_current_kprobe();558+ spin_unlock_irqrestore(&kretprobe_lock, flags);559+ preempt_enable_no_resched();560+561+ hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {562+ hlist_del(&ri->hlist);563+ kfree(ri);564+ }565+ /*566+ * By returning a non-zero value, we are telling567+ * kprobe_handler() that we don't want the post_handler568+ * to run (and have re-enabled preemption)569+ */570+ return 1;571+}572+573+void kretprobe_trampoline_holder(void)574+{575+ asm volatile(".global kretprobe_trampoline\n"576+ "kretprobe_trampoline:\n"577+ "\tnop\n"578+ "\tnop\n");579+}580+static struct kprobe trampoline_p = {581+ .addr = (kprobe_opcode_t *) &kretprobe_trampoline,582+ .pre_handler = trampoline_probe_handler583+};584+585+int __init arch_init_kprobes(void)586+{587+ return register_kprobe(&trampoline_p);588+}589+590+int __kprobes arch_trampoline_kprobe(struct kprobe *p)591+{592+ if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline)593+ return 1;594+595 return 0;596}
+4
include/asm-sparc64/kprobes.h
···1415#define arch_remove_kprobe(p) do {} while (0)160017#define flush_insn_slot(p) \18do { flushi(&(p)->ainsn.insn[0]); \19 flushi(&(p)->ainsn.insn[1]); \20} while (0)002122/* Architecture specific copy of original instruction*/23struct arch_specific_insn {
···1415#define arch_remove_kprobe(p) do {} while (0)1617+#define ARCH_SUPPORTS_KRETPROBES18+19#define flush_insn_slot(p) \20do { flushi(&(p)->ainsn.insn[0]); \21 flushi(&(p)->ainsn.insn[1]); \22} while (0)23+24+void kretprobe_trampoline(void);2526/* Architecture specific copy of original instruction*/27struct arch_specific_insn {