static int arm_linux_copy_svc (struct gdbarch *gdbarch, struct regcache *regs, struct displaced_step_closure *dsc) { CORE_ADDR return_to = 0; struct frame_info *frame; unsigned int svc_number = displaced_read_reg (regs, dsc, 7); int is_sigreturn = 0; int is_thumb; frame = get_current_frame (); is_sigreturn = arm_linux_sigreturn_return_addr(frame, svc_number, &return_to, &is_thumb); if (is_sigreturn) { struct symtab_and_line sal; if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: found " "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n", (unsigned long) get_frame_pc (frame)); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. " "Setting momentary breakpoint.\n", (unsigned long) return_to); gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL); sal = find_pc_line (return_to, 0); sal.pc = return_to; sal.section = find_pc_overlay (return_to); sal.explicit_pc = 1; frame = get_prev_frame (frame); if (frame) { inferior_thread ()->control.step_resume_breakpoint = set_momentary_breakpoint (gdbarch, sal, get_frame_id (frame), bp_step_resume); /* set_momentary_breakpoint invalidates FRAME. */ frame = NULL; /* We need to make sure we actually insert the momentary breakpoint set above. */ insert_breakpoints (); } else if (debug_displaced) fprintf_unfiltered (gdb_stderr, "displaced: couldn't find previous " "frame to set momentary breakpoint for " "sigreturn/rt_sigreturn\n"); } else if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn " "SVC call not in signal trampoline frame\n"); /* Preparation: If we detect sigreturn, set momentary breakpoint at resume location, else nothing. Insn: unmodified svc. Cleanup: if pc lands in scratch space, pc <- insn_addr + 4 else leave pc alone. */ dsc->cleanup = &arm_linux_cleanup_svc; /* Pretend we wrote to the PC, so cleanup doesn't set PC to the next instruction. */ dsc->wrote_to_pc = 1; return 0; }
static int arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to, struct regcache *regs, struct displaced_step_closure *dsc) { CORE_ADDR from = dsc->insn_addr; struct frame_info *frame; unsigned int svc_number = displaced_read_reg (regs, from, 7); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: copying Linux svc insn %.8lx\n", (unsigned long) insn); frame = get_current_frame (); /* Is this a sigreturn or rt_sigreturn syscall? Note: these are only useful for EABI. */ if (svc_number == 119 || svc_number == 173) { if (get_frame_type (frame) == SIGTRAMP_FRAME) { CORE_ADDR return_to; struct symtab_and_line sal; if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: found " "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n", (unsigned long) get_frame_pc (frame)); return_to = frame_unwind_caller_pc (frame); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. " "Setting momentary breakpoint.\n", (unsigned long) return_to); gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL); sal = find_pc_line (return_to, 0); sal.pc = return_to; sal.section = find_pc_overlay (return_to); sal.explicit_pc = 1; frame = get_prev_frame (frame); if (frame) { inferior_thread ()->step_resume_breakpoint = set_momentary_breakpoint (gdbarch, sal, get_frame_id (frame), bp_step_resume); /* We need to make sure we actually insert the momentary breakpoint set above. */ insert_breakpoints (); } else if (debug_displaced) fprintf_unfiltered (gdb_stderr, "displaced: couldn't find previous " "frame to set momentary breakpoint for " "sigreturn/rt_sigreturn\n"); } else if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn " "SVC call not in signal trampoline frame\n"); } /* Preparation: If we detect sigreturn, set momentary breakpoint at resume location, else nothing. Insn: unmodified svc. Cleanup: if pc lands in scratch space, pc <- insn_addr + 4 else leave pc alone. */ dsc->modinsn[0] = insn; dsc->cleanup = &arm_linux_cleanup_svc; /* Pretend we wrote to the PC, so cleanup doesn't set PC to the next instruction. */ dsc->wrote_to_pc = 1; return 0; }