Fix a typo in bunzip2..
[deliverable/binutils-gdb.git] / gdb / ppc-sysv-tdep.c
index 01438c159a288efdb2810f14eb3c7f81832abf42..7863aca197a99679171b97d7991245d8c58f8b4f 100644 (file)
@@ -1,7 +1,8 @@
 /* Target-dependent code for PowerPC systems using the SVR4 ABI
    for GDB, the GNU debugger.
 
-   Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2005 Free Software Foundation,
+   Inc.
 
    This file is part of GDB.
 
@@ -29,6 +30,8 @@
 #include "gdb_assert.h"
 #include "ppc-tdep.h"
 #include "target.h"
+#include "objfiles.h"
+#include "infcall.h"
 
 /* Pass the arguments in either registers, or in the stack. Using the
    ppc sysv ABI, the first eight words of the argument list (that might
@@ -42,7 +45,7 @@
    starting from r4. */
 
 CORE_ADDR
-ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                              struct regcache *regcache, CORE_ADDR bp_addr,
                              int nargs, struct value **args, CORE_ADDR sp,
                              int struct_return, CORE_ADDR struct_addr)
@@ -95,9 +98,9 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       for (argno = 0; argno < nargs; argno++)
        {
          struct value *arg = args[argno];
-         struct type *type = check_typedef (VALUE_TYPE (arg));
+         struct type *type = check_typedef (value_type (arg));
          int len = TYPE_LENGTH (type);
-         char *val = VALUE_CONTENTS (arg);
+         const bfd_byte *val = value_contents (arg);
 
          if (TYPE_CODE (type) == TYPE_CODE_FLT
              && ppc_floating_point_unit_p (current_gdbarch) && len <= 8)
@@ -113,9 +116,10 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                         the register's floating-point format.  */
                      char regval[MAX_REGISTER_SIZE];
                      struct type *regtype
-                       = register_type (gdbarch, FP0_REGNUM + freg);
+                       = register_type (gdbarch, tdep->ppc_fp0_regnum + freg);
                      convert_typed_floating (val, type, regval, regtype);
-                     regcache_cooked_write (regcache, FP0_REGNUM + freg,
+                     regcache_cooked_write (regcache,
+                                             tdep->ppc_fp0_regnum + freg,
                                             regval);
                    }
                  freg++;
@@ -138,7 +142,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                          memtype = builtin_type_ieee_double_little;
                          break;
                        default:
-                         internal_error (__FILE__, __LINE__, "bad switch");
+                         internal_error (__FILE__, __LINE__, _("bad switch"));
                        }
                      convert_typed_floating (val, type, memval, memtype);
                      write_memory (sp + argoffset, val, len);
@@ -337,8 +341,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
          /* Floats and doubles stored in "f1".  Convert the value to
             the required type.  */
          char regval[MAX_REGISTER_SIZE];
-         struct type *regtype = register_type (gdbarch, FP0_REGNUM + 1);
-         regcache_cooked_read (regcache, FP0_REGNUM + 1, regval);
+         struct type *regtype = register_type (gdbarch,
+                                                tdep->ppc_fp0_regnum + 1);
+         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
          convert_typed_floating (regval, regtype, readbuf, type);
        }
       if (writebuf)
@@ -346,9 +351,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
          /* Floats and doubles stored in "f1".  Convert the value to
             the register's "double" type.  */
          char regval[MAX_REGISTER_SIZE];
-         struct type *regtype = register_type (gdbarch, FP0_REGNUM);
+         struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
          convert_typed_floating (writebuf, type, regval, regtype);
-         regcache_cooked_write (regcache, FP0_REGNUM + 1, regval);
+         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -529,6 +534,47 @@ ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
                                   writebuf, 1);
 }
 
+/* The helper function for 64-bit SYSV push_dummy_call.  Converts the
+   function's code address back into the function's descriptor
+   address.
+
+   Find a value for the TOC register.  Every symbol should have both
+   ".FN" and "FN" in the minimal symbol table.  "FN" points at the
+   FN's descriptor, while ".FN" points at the entry point (which
+   matches FUNC_ADDR).  Need to reverse from FUNC_ADDR back to the
+   FN's descriptor address (while at the same time being careful to
+   find "FN" in the same object file as ".FN").  */
+
+static int
+convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
+{
+  struct obj_section *dot_fn_section;
+  struct minimal_symbol *dot_fn;
+  struct minimal_symbol *fn;
+  CORE_ADDR toc;
+  /* Find the minimal symbol that corresponds to CODE_ADDR (should
+     have a name of the form ".FN").  */
+  dot_fn = lookup_minimal_symbol_by_pc (code_addr);
+  if (dot_fn == NULL || SYMBOL_LINKAGE_NAME (dot_fn)[0] != '.')
+    return 0;
+  /* Get the section that contains CODE_ADDR.  Need this for the
+     "objfile" that it contains.  */
+  dot_fn_section = find_pc_section (code_addr);
+  if (dot_fn_section == NULL || dot_fn_section->objfile == NULL)
+    return 0;
+  /* Now find the corresponding "FN" (dropping ".") minimal symbol's
+     address.  Only look for the minimal symbol in ".FN"'s object file
+     - avoids problems when two object files (i.e., shared libraries)
+     contain a minimal symbol with the same name.  */
+  fn = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn) + 1, NULL,
+                             dot_fn_section->objfile);
+  if (fn == NULL)
+    return 0;
+  /* Found a descriptor.  */
+  (*desc_addr) = SYMBOL_VALUE_ADDRESS (fn);
+  return 1;
+}
+
 /* Pass the arguments in either registers, or in the stack. Using the
    ppc 64 bit SysV ABI.
 
@@ -537,11 +583,12 @@ ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
    greatly simplifies the logic. */
 
 CORE_ADDR
-ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                                struct regcache *regcache, CORE_ADDR bp_addr,
                                int nargs, struct value **args, CORE_ADDR sp,
                                int struct_return, CORE_ADDR struct_addr)
 {
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
   /* By this stage in the proceedings, SP has been decremented by "red
      zone size" + "struct return size".  Fetch the stack-pointer from
@@ -629,8 +676,8 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       for (argno = 0; argno < nargs; argno++)
        {
          struct value *arg = args[argno];
-         struct type *type = check_typedef (VALUE_TYPE (arg));
-         char *val = VALUE_CONTENTS (arg);
+         struct type *type = check_typedef (value_type (arg));
+         const bfd_byte *val = value_contents (arg);
          if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8)
            {
              /* Floats and Doubles go in f1 .. f13.  They also
@@ -642,10 +689,11 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                      && freg <= 13)
                    {
                      char regval[MAX_REGISTER_SIZE];
-                     struct type *regtype = register_type (gdbarch,
-                                                           FP0_REGNUM);
+                     struct type *regtype
+                        = register_type (gdbarch, tdep->ppc_fp0_regnum);
                      convert_typed_floating (val, type, regval, regtype);
-                     regcache_cooked_write (regcache, FP0_REGNUM + freg,
+                     regcache_cooked_write (regcache,
+                                             tdep->ppc_fp0_regnum + freg,
                                             regval);
                    }
                  if (greg <= 10)
@@ -697,15 +745,25 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                }
            }
          else if ((TYPE_CODE (type) == TYPE_CODE_INT
-                   || TYPE_CODE (type) == TYPE_CODE_ENUM)
+                   || TYPE_CODE (type) == TYPE_CODE_ENUM
+                   || TYPE_CODE (type) == TYPE_CODE_PTR)
                   && TYPE_LENGTH (type) <= 8)
            {
-             /* Scalars get sign[un]extended and go in gpr3 .. gpr10.
-                They can also end up in memory.  */
+             /* Scalars and Pointers get sign[un]extended and go in
+                gpr3 .. gpr10.  They can also end up in memory.  */
              if (write_pass)
                {
                  /* Sign extend the value, then store it unsigned.  */
                  ULONGEST word = unpack_long (type, val);
+                 /* Convert any function code addresses into
+                    descriptors.  */
+                 if (TYPE_CODE (type) == TYPE_CODE_PTR
+                     && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)
+                   {
+                     CORE_ADDR desc = word;
+                     convert_code_addr_to_desc_addr (word, &desc);
+                     word = desc;
+                   }
                  if (greg <= 10)
                    regcache_cooked_write_unsigned (regcache,
                                                    tdep->ppc_gp0_regnum +
@@ -758,6 +816,11 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                   value to memory.  Fortunately, doing this
                   simplifies the code.  */
                write_memory (gparam, val, TYPE_LENGTH (type));
+             if (write_pass)
+               /* WARNING: cagney/2004-06-20: It appears that GCC
+                  likes to put structures containing a single
+                  floating-point member in an FP register instead of
+                  general general purpose.  */
              /* Always consume parameter stack space.  */
              gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
            }
@@ -786,32 +849,18 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
      breakpoint.  */
   regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
 
-  /* Find a value for the TOC register.  Every symbol should have both
-     ".FN" and "FN" in the minimal symbol table.  "FN" points at the
-     FN's descriptor, while ".FN" points at the entry point (which
-     matches FUNC_ADDR).  Need to reverse from FUNC_ADDR back to the
-     FN's descriptor address.  */
+  /* Use the func_addr to find the descriptor, and use that to find
+     the TOC.  */
   {
-    /* Find the minimal symbol that corresponds to FUNC_ADDR (should
-       have the name ".FN").  */
-    struct minimal_symbol *dot_fn = lookup_minimal_symbol_by_pc (func_addr);
-    if (dot_fn != NULL && SYMBOL_LINKAGE_NAME (dot_fn)[0] == '.')
+    CORE_ADDR desc_addr;
+    if (convert_code_addr_to_desc_addr (func_addr, &desc_addr))
       {
-       /* Now find the corresponding "FN" (dropping ".") minimal
-          symbol's address.  */
-       struct minimal_symbol *fn =
-         lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn) + 1, NULL,
-                                NULL);
-       if (fn != NULL)
-         {
-           /* Got the address of that descriptor.  The TOC is the
-              second double word.  */
-           CORE_ADDR toc =
-             read_memory_unsigned_integer (SYMBOL_VALUE_ADDRESS (fn) +
-                                           tdep->wordsize, tdep->wordsize);
-           regcache_cooked_write_unsigned (regcache,
-                                           tdep->ppc_gp0_regnum + 2, toc);
-         }
+       /* The TOC is the second double word in the descriptor.  */
+       CORE_ADDR toc =
+         read_memory_unsigned_integer (desc_addr + tdep->wordsize,
+                                       tdep->wordsize);
+       regcache_cooked_write_unsigned (regcache,
+                                       tdep->ppc_gp0_regnum + 2, toc);
       }
   }
 
@@ -835,24 +884,32 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
                             const void *writebuf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* This function exists to support a calling convention that
+     requires floating-point registers.  It shouldn't be used on
+     processors that lack them.  */
+  gdb_assert (ppc_floating_point_unit_p (gdbarch));
+
   /* Floats and doubles in F1.  */
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT && TYPE_LENGTH (valtype) <= 8)
     {
       char regval[MAX_REGISTER_SIZE];
-      struct type *regtype = register_type (gdbarch, FP0_REGNUM);
+      struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
       if (writebuf != NULL)
        {
          convert_typed_floating (writebuf, valtype, regval, regtype);
-         regcache_cooked_write (regcache, FP0_REGNUM + 1, regval);
+         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
        }
       if (readbuf != NULL)
        {
-         regcache_cooked_read (regcache, FP0_REGNUM + 1, regval);
+         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
          convert_typed_floating (regval, regtype, readbuf, valtype);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
-  if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 8)
+  if ((TYPE_CODE (valtype) == TYPE_CODE_INT
+       || TYPE_CODE (valtype) == TYPE_CODE_ENUM)
+      && TYPE_LENGTH (valtype) <= 8)
     {
       /* Integers in r3.  */
       if (writebuf != NULL)
@@ -909,10 +966,10 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
          for (i = 0; i < TYPE_LENGTH (valtype) / 8; i++)
            {
              if (writebuf != NULL)
-               regcache_cooked_write (regcache, FP0_REGNUM + 1 + i,
+               regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i,
                                       (const bfd_byte *) writebuf + i * 8);
              if (readbuf != NULL)
-               regcache_cooked_read (regcache, FP0_REGNUM + 1 + i,
+               regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i,
                                      (bfd_byte *) readbuf + i * 8);
            }
        }
@@ -929,18 +986,21 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
            {
              char regval[MAX_REGISTER_SIZE];
              struct type *regtype =
-               register_type (current_gdbarch, FP0_REGNUM);
+               register_type (current_gdbarch, tdep->ppc_fp0_regnum);
              if (writebuf != NULL)
                {
                  convert_typed_floating ((const bfd_byte *) writebuf +
                                          i * (TYPE_LENGTH (valtype) / 2),
                                          valtype, regval, regtype);
-                 regcache_cooked_write (regcache, FP0_REGNUM + 1 + i,
+                 regcache_cooked_write (regcache,
+                                         tdep->ppc_fp0_regnum + 1 + i,
                                         regval);
                }
              if (readbuf != NULL)
                {
-                 regcache_cooked_read (regcache, FP0_REGNUM + 1 + i, regval);
+                 regcache_cooked_read (regcache,
+                                        tdep->ppc_fp0_regnum + 1 + i,
+                                        regval);
                  convert_typed_floating (regval, regtype,
                                          (bfd_byte *) readbuf +
                                          i * (TYPE_LENGTH (valtype) / 2),
@@ -959,10 +1019,10 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
          for (i = 0; i < 4; i++)
            {
              if (writebuf != NULL)
-               regcache_cooked_write (regcache, FP0_REGNUM + 1 + i,
+               regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i,
                                       (const bfd_byte *) writebuf + i * 8);
              if (readbuf != NULL)
-               regcache_cooked_read (regcache, FP0_REGNUM + 1 + i,
+               regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i,
                                      (bfd_byte *) readbuf + i * 8);
            }
        }
This page took 0.028318 seconds and 4 git commands to generate.