This is the mail archive of the 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]

[PATCH] [sparc] inferior SEGV while calling Ada subprogram

This is one of these issues that makes you wonder how we managed
to miss it after all these years...  But it's probably just because
our users simply never call subprograms that take an array as one
of the parameters - it's just the AdaCore testsuite that does :).

The problem can be reproduced on sparc-solaris using gdb.ada/arrayparam.exp:

   (gdb) print call_me ("bonjour")
   Program received signal SIGSEGV, Segmentation fault.
   0x000190d0 in pck.call_me (str=...) at /[...]/gdb.ada/arrayparam/pck.adb:18
   18         procedure Call_Me (Str : String) is
   The program being debugged was signaled while in a function called from GDB.

The SEGV is due to an unaligned access.  This is because Ada arrays
can take several forms, and the one that is used in this case is
a reference to a structure containing 2 pointers: One pointer to
the array of characters, and one pointer to another structure containing
the bounds. We call them `fat pointers'.

During the function call setup, there is some special code for Ada
inside value_arg_coerce that converts a C-type array into Ada arrays:

  /* Perform any Ada-specific coercion first.  */
  if (current_language->la_language == language_ada)
    arg = ada_convert_actual (arg, type, gdbarch, sp);

What this function does is allocating some memory on the stack
in order to store the array contents, the bounds, and the descriptor.
We start with the bounds, followed by the array, followed by the
descriptor. And in between each piece, we re-align the stack.

That's when I realized that sparc-tdep and sparc64-tdep do not
provide a routine that re-aligns the stack pointer.  So, with
the array above (7 bytes), once the array was allocated on stack,
the new stack-pointer value was badly misaligned. As a result,
the array descriptors gets allocated at a mis-aligned address,
and trying to load the addresses inside that descriptor triggered


        * sparc-tdep.c (sparc32_frame_align): New function.
        (sparc32_gdbarch_init): Set the frame_align gdbarch method.
        * sparc64-tdep.c (sparc64_frame_align): New function.
        (sparc64_gdbarch_init): Set the frame_align gdbarch method.

This fixes gdb.ada/arrayparam.exp. It also runs clean on AdaCore's
testsuite (Python-based), for sparc-solaris and sparc64-solaris.
However, as said previously, I am barred from running the testsuite
on any Solaris machine until further notice (it looks like one of
the testcases causes the machine to crash pretty badly - and I haven't
be able to get a window where it's OK to investigate that).

I don't see how this could hurt, though.

OK to commit?

 gdb/sparc-tdep.c   |   10 ++++++++++
 gdb/sparc64-tdep.c |   10 ++++++++++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 29a12cf..a35db79 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -398,6 +398,15 @@ sparc32_pseudo_register_write (struct gdbarch *gdbarch,
+/* Implement the frame_align gdbarch method.  */
+static CORE_ADDR
+sparc32_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
+  /* The ABI requires double-word alignment.  */
+  return address & ~0x7;
 static CORE_ADDR
 sparc32_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
 			 CORE_ADDR funcaddr,
@@ -1407,6 +1416,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_fp0_regnum (gdbarch, SPARC_F0_REGNUM); /* %f0 */
   /* Call dummy code.  */
+  set_gdbarch_frame_align (gdbarch, sparc32_frame_align);
   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
   set_gdbarch_push_dummy_code (gdbarch, sparc32_push_dummy_code);
   set_gdbarch_push_dummy_call (gdbarch, sparc32_push_dummy_call);
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index 3cd6109..978501a 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -937,6 +937,15 @@ sparc64_store_arguments (struct regcache *regcache, int nargs,
   return sp;
+/* Implement the frame_align gdbarch method.  */
+static CORE_ADDR
+sparc64_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
+  /* The ABI requires 16-byte alignment.  */
+  return address & ~0xf;
 static CORE_ADDR
 sparc64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 			 struct regcache *regcache, CORE_ADDR bp_addr,
@@ -1136,6 +1145,7 @@ sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_pc_regnum (gdbarch, SPARC64_PC_REGNUM); /* %pc */
   /* Call dummy code.  */
+  set_gdbarch_frame_align (gdbarch, sparc64_frame_align);
   set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
   set_gdbarch_push_dummy_code (gdbarch, NULL);
   set_gdbarch_push_dummy_call (gdbarch, sparc64_push_dummy_call);

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