This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfc] Fix word-size detection in PowerPC Linux native target


Hello,

the ppc-linux-nat.c:ppc_linux_read_description routine carefully attempts
to detect whether the current inferior is a 32-bit or 64-bit process.

However, before it does so, the code has already make implicit assumptions
on the wordsize:

  if (ppc_linux_get_hwcap () & PPC_FEATURE_ARCH_2_05)
    isa205 = 1;

as the ppc_linux_get_hwcap routine calls target_auxv_search, which uses
the target wordsize as the size of auxillary vector entries ...


Now, in most scenarios, this doesn't matter, because at that point the
currently active architecture will be used, which will usually already
have the correct wordsize, as it was determined from the exec file.

However, there are some scenarios where determining the wordsize
actually matters (e.g. because the exec file cannot be determined).
In those cases, the attempts in ppc_linux_read_description would be
somewhat futile ...


The following patch overrides the target's to_auxv_parse callback
as well, so that it can use the same mechanism currently used in
ppc_linux_read_description in order to find the size of auxillary
vector entries.  This fixed the problem above.

Tested on powerpc64-linux (64-bit / 32-bit).

Any comment?  If there are objections, I'm planning to commit
this in a couple of days ...

Bye,
Ulrich 


ChangeLog:

	* ppc-linux-nat.c (ppc_linux_target_wordsize): New function.
	(ppc_linux_auxv_parse): New function.
	(ppc_linux_read_description): Use ppc_linux_target_wordsize.
	(_initialize_ppc_linux_nat): Install ppc_linux_auxv_parse.

Index: src/gdb/ppc-linux-nat.c
===================================================================
--- src.orig/gdb/ppc-linux-nat.c
+++ src/gdb/ppc-linux-nat.c
@@ -1238,6 +1238,51 @@ fill_fpregset (const struct regcache *re
 			fpregsetp, sizeof (*fpregsetp));
 }
 
+static int
+ppc_linux_target_wordsize (void)
+{
+  int wordsize = 4;
+
+  /* Check for 64-bit inferior process.  This is the case when the host is
+     64-bit, and in addition the top bit of the MSR register is set.  */
+#ifdef __powerpc64__
+  long msr;
+
+  int tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid);
+
+  errno = 0;
+  msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
+  if (errno == 0 && msr < 0)
+    wordsize = 8;
+#endif
+
+  return wordsize;
+}
+
+static int
+ppc_linux_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+                      gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  int sizeof_auxv_field = ppc_linux_target_wordsize ();
+  gdb_byte *ptr = *readptr;
+
+  if (endptr == ptr)
+    return 0;
+
+  if (endptr - ptr < sizeof_auxv_field * 2)
+    return -1;
+
+  *typep = extract_unsigned_integer (ptr, sizeof_auxv_field);
+  ptr += sizeof_auxv_field;
+  *valp = extract_unsigned_integer (ptr, sizeof_auxv_field);
+  ptr += sizeof_auxv_field;
+
+  *readptr = ptr;
+  return 1;
+}
+
 static const struct target_desc *
 ppc_linux_read_description (struct target_ops *ops)
 {
@@ -1291,24 +1336,15 @@ ppc_linux_read_description (struct targe
   if (ppc_linux_get_hwcap () & PPC_FEATURE_ARCH_2_05)
     isa205 = 1;
 
-  /* Check for 64-bit inferior process.  This is the case when the host is
-     64-bit, and in addition the top bit of the MSR register is set.  */
-#ifdef __powerpc64__
-  {
-    long msr;
-    errno = 0;
-    msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
-    if (errno == 0 && msr < 0)
-      {
-	if (vsx)
-	  return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
-	else if (altivec)
-	  return isa205? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
-
-	return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
-      }
-  }
-#endif
+  if (ppc_linux_target_wordsize () == 8)
+    {
+      if (vsx)
+	return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
+      else if (altivec)
+	return isa205? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
+
+      return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
+    }
 
   if (vsx)
     return isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
@@ -1342,6 +1378,7 @@ _initialize_ppc_linux_nat (void)
   t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
 
   t->to_read_description = ppc_linux_read_description;
+  t->to_auxv_parse = ppc_linux_auxv_parse;
 
   /* Register the target.  */
   linux_nat_add_target (t);
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]