|
@@ -1489,38 +1489,47 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Run handler and ask thread to singlestep.
|
|
|
- * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
|
|
|
- */
|
|
|
-static void handle_swbp(struct pt_regs *regs)
|
|
|
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr)
|
|
|
{
|
|
|
+ struct mm_struct *mm = current->mm;
|
|
|
+ struct uprobe *uprobe = NULL;
|
|
|
struct vm_area_struct *vma;
|
|
|
- struct uprobe_task *utask;
|
|
|
- struct uprobe *uprobe;
|
|
|
- struct mm_struct *mm;
|
|
|
- unsigned long bp_vaddr;
|
|
|
|
|
|
- uprobe = NULL;
|
|
|
- bp_vaddr = uprobe_get_swbp_addr(regs);
|
|
|
- mm = current->mm;
|
|
|
down_read(&mm->mmap_sem);
|
|
|
vma = find_vma(mm, bp_vaddr);
|
|
|
|
|
|
- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) {
|
|
|
- struct inode *inode;
|
|
|
- loff_t offset;
|
|
|
+ if (vma && vma->vm_start <= bp_vaddr) {
|
|
|
+ if (valid_vma(vma, false)) {
|
|
|
+ struct inode *inode;
|
|
|
+ loff_t offset;
|
|
|
|
|
|
- inode = vma->vm_file->f_mapping->host;
|
|
|
- offset = bp_vaddr - vma->vm_start;
|
|
|
- offset += (vma->vm_pgoff << PAGE_SHIFT);
|
|
|
- uprobe = find_uprobe(inode, offset);
|
|
|
+ inode = vma->vm_file->f_mapping->host;
|
|
|
+ offset = bp_vaddr - vma->vm_start;
|
|
|
+ offset += (vma->vm_pgoff << PAGE_SHIFT);
|
|
|
+ uprobe = find_uprobe(inode, offset);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
|
|
|
current->uprobe_srcu_id = -1;
|
|
|
up_read(&mm->mmap_sem);
|
|
|
|
|
|
+ return uprobe;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Run handler and ask thread to singlestep.
|
|
|
+ * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
|
|
|
+ */
|
|
|
+static void handle_swbp(struct pt_regs *regs)
|
|
|
+{
|
|
|
+ struct uprobe_task *utask;
|
|
|
+ struct uprobe *uprobe;
|
|
|
+ unsigned long bp_vaddr;
|
|
|
+
|
|
|
+ bp_vaddr = uprobe_get_swbp_addr(regs);
|
|
|
+ uprobe = find_active_uprobe(bp_vaddr);
|
|
|
+
|
|
|
if (!uprobe) {
|
|
|
/* No matching uprobe; signal SIGTRAP. */
|
|
|
send_sig(SIGTRAP, current, 0);
|