0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/highmem.h>
0014 #include <linux/uprobes.h>
0015 #include <linux/uaccess.h>
0016 #include <linux/sched.h> /* For struct task_struct */
0017 #include <linux/kdebug.h>
0018
0019 #include <asm/cacheflush.h>
0020
0021
0022
0023
0024
0025
0026 unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
0027 {
0028 return instruction_pointer(regs);
0029 }
0030
0031 static void copy_to_page(struct page *page, unsigned long vaddr,
0032 const void *src, int len)
0033 {
0034 void *kaddr = kmap_atomic(page);
0035
0036 memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
0037 kunmap_atomic(kaddr);
0038 }
0039
0040
0041
0042
0043
0044
0045
0046
0047 void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
0048 void *src, unsigned long len)
0049 {
0050 const u32 stp_insn = UPROBE_STP_INSN;
0051 u32 insn = *(u32 *) src;
0052
0053
0054
0055
0056
0057
0058
0059 u32 op = (insn >> 30) & 0x3;
0060 u32 op2 = (insn >> 22) & 0x7;
0061
0062 if (op == 0 &&
0063 (op2 == 1 || op2 == 2 || op2 == 3 || op2 == 5 || op2 == 6) &&
0064 (insn & ANNUL_BIT) == ANNUL_BIT)
0065 insn &= ~ANNUL_BIT;
0066
0067 copy_to_page(page, vaddr, &insn, len);
0068 copy_to_page(page, vaddr+len, &stp_insn, 4);
0069 }
0070
0071
0072
0073
0074
0075
0076 int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
0077 struct mm_struct *mm, unsigned long addr)
0078 {
0079
0080 return 0;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 static unsigned long relbranch_fixup(u32 insn, struct uprobe_task *utask,
0092 struct pt_regs *regs)
0093 {
0094
0095 if (regs->tnpc == regs->tpc + 0x4UL)
0096 return utask->autask.saved_tnpc + 0x4UL;
0097
0098
0099
0100
0101 if ((insn & 0xc0000000) == 0x40000000 ||
0102 (insn & 0xc1c00000) == 0x00400000 ||
0103 (insn & 0xc1c00000) == 0x00800000) {
0104 unsigned long real_pc = (unsigned long) utask->vaddr;
0105 unsigned long ixol_addr = utask->xol_vaddr;
0106
0107
0108
0109
0110
0111 return (real_pc + (regs->tnpc - ixol_addr));
0112 }
0113
0114
0115
0116
0117 return regs->tnpc;
0118 }
0119
0120
0121
0122
0123 static int retpc_fixup(struct pt_regs *regs, u32 insn,
0124 unsigned long real_pc)
0125 {
0126 unsigned long *slot = NULL;
0127 int rc = 0;
0128
0129
0130 if ((insn & 0xc0000000) == 0x40000000)
0131 slot = ®s->u_regs[UREG_I7];
0132
0133
0134 if ((insn & 0xc1f80000) == 0x81c00000) {
0135 unsigned long rd = ((insn >> 25) & 0x1f);
0136
0137 if (rd <= 15) {
0138 slot = ®s->u_regs[rd];
0139 } else {
0140 unsigned long fp = regs->u_regs[UREG_FP];
0141
0142 flushw_all();
0143
0144 rd -= 16;
0145 if (test_thread_64bit_stack(fp)) {
0146 unsigned long __user *uslot =
0147 (unsigned long __user *) (fp + STACK_BIAS) + rd;
0148 rc = __put_user(real_pc, uslot);
0149 } else {
0150 unsigned int __user *uslot = (unsigned int
0151 __user *) fp + rd;
0152 rc = __put_user((u32) real_pc, uslot);
0153 }
0154 }
0155 }
0156 if (slot != NULL)
0157 *slot = real_pc;
0158 return rc;
0159 }
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
0170 {
0171
0172
0173
0174 if (auprobe->ixol == (1 << 24)) {
0175 regs->tnpc += 4;
0176 regs->tpc += 4;
0177 return true;
0178 }
0179
0180 return false;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190 int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
0191 {
0192 struct uprobe_task *utask = current->utask;
0193 struct arch_uprobe_task *autask = ¤t->utask->autask;
0194
0195
0196
0197
0198 autask->saved_tpc = regs->tpc;
0199 autask->saved_tnpc = regs->tnpc;
0200
0201
0202
0203
0204 instruction_pointer_set(regs, utask->xol_vaddr);
0205
0206 return 0;
0207 }
0208
0209
0210
0211
0212
0213
0214
0215
0216 int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
0217 {
0218 struct uprobe_task *utask = current->utask;
0219 struct arch_uprobe_task *autask = &utask->autask;
0220 u32 insn = auprobe->ixol;
0221 int rc = 0;
0222
0223 if (utask->state == UTASK_SSTEP_ACK) {
0224 regs->tnpc = relbranch_fixup(insn, utask, regs);
0225 regs->tpc = autask->saved_tnpc;
0226 rc = retpc_fixup(regs, insn, (unsigned long) utask->vaddr);
0227 } else {
0228 regs->tnpc = utask->vaddr+4;
0229 regs->tpc = autask->saved_tnpc+4;
0230 }
0231 return rc;
0232 }
0233
0234
0235
0236
0237 asmlinkage void uprobe_trap(struct pt_regs *regs,
0238 unsigned long trap_level)
0239 {
0240 BUG_ON(trap_level != 0x173 && trap_level != 0x174);
0241
0242
0243
0244
0245 if (!user_mode(regs)) {
0246 local_irq_enable();
0247 bad_trap(regs, trap_level);
0248 return;
0249 }
0250
0251
0252
0253
0254 if (notify_die((trap_level == 0x173) ? DIE_BPT : DIE_SSTEP,
0255 (trap_level == 0x173) ? "bpt" : "sstep",
0256 regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP)
0257 bad_trap(regs, trap_level);
0258 }
0259
0260
0261
0262 int arch_uprobe_exception_notify(struct notifier_block *self,
0263 unsigned long val, void *data)
0264 {
0265 int ret = NOTIFY_DONE;
0266 struct die_args *args = (struct die_args *)data;
0267
0268
0269 if (args->regs && !user_mode(args->regs))
0270 return NOTIFY_DONE;
0271
0272 switch (val) {
0273 case DIE_BPT:
0274 if (uprobe_pre_sstep_notifier(args->regs))
0275 ret = NOTIFY_STOP;
0276 break;
0277
0278 case DIE_SSTEP:
0279 if (uprobe_post_sstep_notifier(args->regs))
0280 ret = NOTIFY_STOP;
0281
0282 default:
0283 break;
0284 }
0285
0286 return ret;
0287 }
0288
0289
0290
0291
0292
0293 void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
0294 {
0295 struct uprobe_task *utask = current->utask;
0296
0297 instruction_pointer_set(regs, utask->vaddr);
0298 }
0299
0300
0301
0302
0303
0304 bool arch_uprobe_xol_was_trapped(struct task_struct *t)
0305 {
0306 return false;
0307 }
0308
0309 unsigned long
0310 arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
0311 struct pt_regs *regs)
0312 {
0313 unsigned long orig_ret_vaddr = regs->u_regs[UREG_I7];
0314
0315 regs->u_regs[UREG_I7] = trampoline_vaddr-8;
0316
0317 return orig_ret_vaddr + 8;
0318 }