From b6e1c0277f4d6e1097b05c7d67f25221995bddb9 Mon Sep 17 00:00:00 2001
From: Andrew Cagney <cagney@redhat.com>
Date: Wed, 9 Feb 2005 16:51:43 +0000
Subject: [PATCH] 2005-02-09  Andrew Cagney  <cagney@gnu.org>

	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call)
	(convert_code_addr_to_desc_addr): Convert any function code
	address to the corresponding function's descriptor.
	(ppc64_sysv_abi_return_value): have TYPE_CODE_ENUM and
	TYPE_CODE_INT use the same code paths as TYPE_CODE_INT.  When
	writing, convert any function code address to the corresponding
	descriptor.
---
 gdb/ChangeLog       |  18 +++++--
 gdb/ppc-sysv-tdep.c | 111 ++++++++++++++++++++++++++++----------------
 2 files changed, 85 insertions(+), 44 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6aff8c87100..05064f24425 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,10 +1,13 @@
-2005-02-09  Corinna Vinschen  <vinschen@redhat.com>
-
-	* symmisc.c: Include gdb_stat.h.
-	(maintenance_print_msymbols): Use inode numbers to compare files.
-
 2005-02-09  Andrew Cagney  <cagney@gnu.org>
 
+	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call)
+	(convert_code_addr_to_desc_addr): Convert any function code
+	address to the corresponding function's descriptor.
+	(ppc64_sysv_abi_return_value): have TYPE_CODE_ENUM and
+	TYPE_CODE_INT use the same code paths as TYPE_CODE_INT.  When
+	writing, convert any function code address to the corresponding
+	descriptor.
+
 	* config/sh/linux.mt (TDEPFILES): Add symfile-mem.o.
 	* config/powerpc/linux.mt (TDEPFILES): Ditto.
 	* config/pa/linux.mt (TDEPFILES): Ditto.
@@ -14,6 +17,11 @@
 	* config/ia64/linux.mt (TDEPFILES): Ditto.
 	* config/arm/linux.mt (TDEPFILES): Ditto.
 
+2005-02-09  Corinna Vinschen  <vinschen@redhat.com>
+
+	* symmisc.c: Include gdb_stat.h.
+	(maintenance_print_msymbols): Use inode numbers to compare files.
+
 2005-02-08  Andrew Cagney  <cagney@gnu.org>
 
 	* value.h (METHOD_PTR_IS_VIRTUAL, METHOD_PTR_FROM_VOFFSET) 
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index 9d9d1f43dae..481b38ce353 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -534,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.
 
@@ -704,15 +745,25 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 		}
 	    }
 	  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 +
@@ -765,6 +816,11 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 		   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);
 	    }
@@ -793,43 +849,18 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      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 (while at the same time being careful to
-     find "FN" in the same object file as ".FN").  */
+  /* 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))
       {
-	/* Get the section that contains FUNC_ADR.  Need this for the
-           "objfile" that it contains.  */
-	struct obj_section *dot_fn_section = find_pc_section (func_addr);
-	if (dot_fn_section != NULL && dot_fn_section->objfile != NULL)
-	  {
-	    /* 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.  */
-	    struct minimal_symbol *fn =
-	      lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn) + 1, NULL,
-				     dot_fn_section->objfile);
-	    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);
       }
   }
 
@@ -876,7 +907,9 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *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)
-- 
GitLab