merge from gcc
[external/binutils.git] / gdb / rs6000-aix-tdep.c
index 43a3a0a..530c12e 100644 (file)
@@ -1,6 +1,6 @@
 /* Native support code for PPC AIX, for GDB the GNU debugger.
 
-   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    Free Software Foundation, Inc.
 
@@ -194,6 +194,7 @@ rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        int struct_return, CORE_ADDR struct_addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int ii;
   int len = 0;
   int argno;                   /* current argument number */
@@ -404,7 +405,7 @@ ran_out_of_registers_for_arguments:
   regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
 
   /* Set back chain properly.  */
-  store_unsigned_integer (tmp_buffer, wordsize, saved_sp);
+  store_unsigned_integer (tmp_buffer, wordsize, byte_order, saved_sp);
   write_memory (sp, tmp_buffer, wordsize);
 
   /* Point the inferior function call's return address at the dummy's
@@ -429,6 +430,7 @@ rs6000_return_value (struct gdbarch *gdbarch, struct type *func_type,
                     gdb_byte *readbuf, const gdb_byte *writebuf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte buf[8];
 
   /* The calling convention this function implements assumes the
@@ -500,7 +502,8 @@ rs6000_return_value (struct gdbarch *gdbarch, struct type *func_type,
          /* For reading we don't have to worry about sign extension.  */
          regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
                                         &regval);
-         store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval);
+         store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order,
+                                 regval);
        }
       if (writebuf)
        {
@@ -567,14 +570,27 @@ rs6000_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
                                   CORE_ADDR addr,
                                   struct target_ops *targ)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct obj_section *s;
 
   s = find_pc_section (addr);
-  if (s && s->the_bfd_section->flags & SEC_CODE)
-    return addr;
 
-  /* ADDR is in the data space, so it's a special function pointer. */
-  return read_memory_unsigned_integer (addr, gdbarch_tdep (gdbarch)->wordsize);
+  /* Normally, functions live inside a section that is executable.
+     So, if ADDR points to a non-executable section, then treat it
+     as a function descriptor and return the target address iff
+     the target address itself points to a section that is executable.  */
+  if (s && (s->the_bfd_section->flags & SEC_CODE) == 0)
+    {
+      CORE_ADDR pc =
+        read_memory_unsigned_integer (addr, tdep->wordsize, byte_order);
+      struct obj_section *pc_section = find_pc_section (pc);
+
+      if (pc_section && (pc_section->the_bfd_section->flags & SEC_CODE))
+        return pc;
+    }
+
+  return addr;
 }
 
 
@@ -584,7 +600,9 @@ static CORE_ADDR
 branch_dest (struct frame_info *frame, int opcode, int instr,
             CORE_ADDR pc, CORE_ADDR safety)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR dest;
   int immediate;
   int absolute;
@@ -624,7 +642,7 @@ branch_dest (struct frame_info *frame, int opcode, int instr,
          if (dest < AIX_TEXT_SEGMENT_BASE)
            dest = read_memory_unsigned_integer
                     (get_frame_base (frame) + SIG_FRAME_PC_OFFSET,
-                     tdep->wordsize);
+                     tdep->wordsize, byte_order);
        }
 
       else if (ext_op == 528)  /* br cond to count reg */
@@ -652,6 +670,9 @@ branch_dest (struct frame_info *frame, int opcode, int instr,
 static int
 rs6000_software_single_step (struct frame_info *frame)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct address_space *aspace = get_frame_address_space (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int ii, insn;
   CORE_ADDR loc;
   CORE_ADDR breaks[2];
@@ -659,7 +680,7 @@ rs6000_software_single_step (struct frame_info *frame)
 
   loc = get_frame_pc (frame);
 
-  insn = read_memory_integer (loc, 4);
+  insn = read_memory_integer (loc, 4, byte_order);
 
   if (ppc_deal_with_atomic_sequence (frame))
     return 1;
@@ -677,7 +698,7 @@ rs6000_software_single_step (struct frame_info *frame)
       /* ignore invalid breakpoint. */
       if (breaks[ii] == -1)
        continue;
-      insert_single_step_breakpoint (breaks[ii]);
+      insert_single_step_breakpoint (gdbarch, aspace, breaks[ii]);
     }
 
   errno = 0;                   /* FIXME, don't ignore errors! */
@@ -703,6 +724,13 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* RS6000/AIX does not support PT_STEP.  Has to be simulated.  */
   set_gdbarch_software_single_step (gdbarch, rs6000_software_single_step);
 
+  /* Displaced stepping is currently not supported in combination with
+     software single-stepping.  */
+  set_gdbarch_displaced_step_copy_insn (gdbarch, NULL);
+  set_gdbarch_displaced_step_fixup (gdbarch, NULL);
+  set_gdbarch_displaced_step_free_closure (gdbarch, NULL);
+  set_gdbarch_displaced_step_location (gdbarch, NULL);
+
   set_gdbarch_push_dummy_call (gdbarch, rs6000_push_dummy_call);
   set_gdbarch_return_value (gdbarch, rs6000_return_value);
   set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
@@ -731,6 +759,9 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
     set_gdbarch_frame_red_zone_size (gdbarch, 0);
 }
 
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_rs6000_aix_tdep;
+
 void
 _initialize_rs6000_aix_tdep (void)
 {