Index: gdb/nacl-tdep.c |
diff --git a/gdb/nacl-tdep.c b/gdb/nacl-tdep.c |
index 53dc8f9f253bc94ca38354b33b667f8b8441cf6c..6ac49c75b7078453736102c85a2c855b0b71cf66 100644 |
--- a/gdb/nacl-tdep.c |
+++ b/gdb/nacl-tdep.c |
@@ -27,6 +27,9 @@ |
#include "solib-svr4.h" |
#include "frame.h" |
#include "osabi.h" |
+#include "disasm.h" |
+#include "breakpoint.h" |
+#include "target.h" |
static void |
nacl_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
@@ -99,6 +102,52 @@ amd64_nacl_fetch_link_map_offsets (void) |
return lmp; |
} |
+static CORE_ADDR |
+amd64_nacl_skip_rsp_sandboxing (CORE_ADDR addr) |
+{ |
+ gdb_byte buf[3]; |
+ if (target_read_memory (addr, buf, sizeof(buf)) == 0) |
+ { |
+ /* 4c 01 fc add %r15,%rsp */ |
+ if (buf[0] == 0x4c && buf[1] == 0x01 && buf[2] == 0xfc) |
+ { |
+ return addr + 3; |
+ } |
+ } |
+ return addr; |
+} |
+ |
+static CORE_ADDR |
+amd64_nacl_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR addr) |
+{ |
+ return amd64_nacl_skip_rsp_sandboxing (addr); |
+} |
+ |
+static int |
+amd64_nacl_software_single_step (struct frame_info *frame) |
+{ |
+ struct gdbarch *gdbarch; |
+ CORE_ADDR pc; |
+ CORE_ADDR bp_pc; |
+ |
+ gdbarch = get_frame_arch (frame); |
+ pc = get_frame_register_unsigned (frame, gdbarch_pc_regnum (gdbarch)); |
+ |
+ /* Check if next instruction is rsp sandboxing. If yes, assume current |
+ instruction is rsp modification. */ |
+ pc += gdb_insn_length (gdbarch, pc); |
+ bp_pc = amd64_nacl_skip_rsp_sandboxing (pc); |
+ if (bp_pc != pc) |
+ { |
+ insert_single_step_breakpoint (gdbarch, |
+ get_frame_address_space (frame), |
+ bp_pc); |
+ return 1; |
+ } |
+ |
+ return 0; |
+} |
+ |
static void |
amd64_nacl_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
{ |
@@ -130,6 +179,11 @@ amd64_nacl_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
set_gdbarch_addr_bits_remove (gdbarch, amd64_nacl_addr_bits_remove); |
set_gdbarch_unwind_pc (gdbarch, amd64_nacl_unwind_pc); |
set_gdbarch_unwind_sp (gdbarch, amd64_nacl_unwind_sp); |
+ |
+ /* Where to set breakpoints. */ |
+ set_gdbarch_adjust_breakpoint_address (gdbarch, |
+ amd64_nacl_adjust_breakpoint_address); |
+ set_gdbarch_software_single_step (gdbarch, amd64_nacl_software_single_step); |
} |
/* Provide a prototype to silence -Wmissing-prototypes. */ |