[ARM] Read memory as unsigned integer
[deliverable/binutils-gdb.git] / gdb / arc-tdep.c
index 60a4e0442d4ec12e3f8c70c630eace1a4cf7558e..e7a7d53f6f79656464764f658bcaf86e3fbf124a 100644 (file)
@@ -557,6 +557,28 @@ arc_store_return_value (struct gdbarch *gdbarch, struct type *type,
     error (_("arc_store_return_value: type length too large."));
 }
 
+/* Implement the "get_longjmp_target" gdbarch method.  */
+
+static int
+arc_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+{
+  if (arc_debug)
+    debug_printf ("arc: get_longjmp_target\n");
+
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int pc_offset = tdep->jb_pc * ARC_REGISTER_SIZE;
+  gdb_byte buf[ARC_REGISTER_SIZE];
+  CORE_ADDR jb_addr = get_frame_register_unsigned (frame, ARC_FIRST_ARG_REGNUM);
+
+  if (target_read_memory (jb_addr + pc_offset, buf, ARC_REGISTER_SIZE))
+    return 0; /* Failed to read from memory.  */
+
+  *pc = extract_unsigned_integer (buf, ARC_REGISTER_SIZE,
+                                 gdbarch_byte_order (gdbarch));
+  return 1;
+}
+
 /* Implement the "return_value" gdbarch method.  */
 
 static enum return_value_convention
@@ -693,9 +715,7 @@ static const gdb_byte arc_brk_s_le[] = { 0xff, 0x7f };
 static const gdb_byte arc_brk_be[] = { 0x25, 0x6f, 0x00, 0x3f };
 static const gdb_byte arc_brk_le[] = { 0x6f, 0x25, 0x3f, 0x00 };
 
-/* Implement the "breakpoint_from_pc" gdbarch method.
-
-   For ARC ELF, breakpoint uses the 16-bit BRK_S instruction, which is 0x7fff
+/* For ARC ELF, breakpoint uses the 16-bit BRK_S instruction, which is 0x7fff
    (little endian) or 0xff7f (big endian).  We used to insert BRK_S even
    instead of 32-bit instructions, which works mostly ok, unless breakpoint is
    inserted into delay slot instruction.  In this case if branch is taken
@@ -712,15 +732,12 @@ static const gdb_byte arc_brk_le[] = { 0x6f, 0x25, 0x3f, 0x00 };
    NB: Baremetal GDB uses BRK[_S], while user-space GDB uses TRAP_S.  BRK[_S]
    is much better because it doesn't commit unlike TRAP_S, so it can be set in
    delay slots; however it cannot be used in user-mode, hence usage of TRAP_S
-   in GDB for user-space.
+   in GDB for user-space.  */
 
-   PCPTR is a pointer to the PC where we want to place a breakpoint.  LENPTR
-   is a number of bytes used by the breakpoint.  Returns the byte sequence of
-   a breakpoint instruction.  */
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
 
-static const gdb_byte *
-arc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-                       int *lenptr)
+static int
+arc_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   size_t length_with_limm = gdb_insn_length (gdbarch, *pcptr);
 
@@ -729,15 +746,26 @@ arc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
      bytes for 32-bit instructions.  */
   if ((length_with_limm == 4 || length_with_limm == 8)
       && !arc_mach_is_arc600 (gdbarch))
+    return sizeof (arc_brk_le);
+  else
+    return sizeof (arc_brk_s_le);
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  *size = kind;
+
+  if (kind == sizeof (arc_brk_le))
     {
-      *lenptr = sizeof (arc_brk_le);
       return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
              ? arc_brk_be
              : arc_brk_le);
     }
   else
     {
-      *lenptr = sizeof (arc_brk_s_le);
       return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
              ? arc_brk_s_be
              : arc_brk_s_le);
@@ -1159,7 +1187,11 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
     return NULL;
 
-  struct gdbarch *gdbarch = gdbarch_alloc (&info, NULL);
+  /* Allocate the ARC-private target-dependent information structure, and the
+     GDB target-independent information structure.  */
+  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+  tdep->jb_pc = -1; /* No longjmp support by default.  */
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
 
   /* Data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -1203,7 +1235,8 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_skip_prologue (gdbarch, arc_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, arc_breakpoint_from_pc);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch, arc_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch, arc_sw_breakpoint_from_kind);
 
   /* On ARC 600 BRK_S instruction advances PC, unlike other ARC cores.  */
   if (!arc_mach_is_arc600 (gdbarch))
@@ -1243,6 +1276,9 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      It can override functions set earlier.  */
   gdbarch_init_osabi (info, gdbarch);
 
+  if (tdep->jb_pc >= 0)
+    set_gdbarch_get_longjmp_target (gdbarch, arc_get_longjmp_target);
+
   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
 
   return gdbarch;
@@ -1253,7 +1289,9 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 static void
 arc_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  /* Empty for now.  */
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  fprintf_unfiltered (file, "arc_dump_tdep: jb_pc = %i\n", tdep->jb_pc);
 }
 
 /* Suppress warning from -Wmissing-prototypes.  */
This page took 0.025118 seconds and 4 git commands to generate.