This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[commit, s390] Fix GDB internal error after stack overflow in inferior call
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 25 Jun 2010 19:48:27 +0200 (CEST)
- Subject: [commit, s390] Fix GDB internal error after stack overflow in inferior call
Hello,
I'm seeing GDB internal errors on 31-bit s390 with the recently added
test that attempts an inferior call with $sp == 0. The underflow
during stack frame setup results in a SP value with high bit set
(i.e. outside the 31-bit address space range), which confuses GDB
later on.
To fix this, I've added a check for stack overflow in s390_push_dummy_call
and just throw an error in this case.
Tested on s390-ibm-linux. Committed to mainline.
Bye,
Ulrich
ChangeLog:
* s390-tdep.c (s390_push_dummy_call): Error on stack overflow
during inferior call stack frame setup.
Index: gdb/s390-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/s390-tdep.c,v
retrieving revision 1.188
diff -u -p -r1.188 s390-tdep.c
--- gdb/s390-tdep.c 4 Jan 2010 15:02:59 -0000 1.188
+++ gdb/s390-tdep.c 25 Jun 2010 17:43:25 -0000
@@ -2343,14 +2343,13 @@ s390_push_dummy_call (struct gdbarch *gd
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- ULONGEST orig_sp;
int i;
/* If the i'th argument is passed as a reference to a copy, then
copy_addr[i] is the address of the copy we made. */
CORE_ADDR *copy_addr = alloca (nargs * sizeof (CORE_ADDR));
- /* Build the reference-to-copy area. */
+ /* Reserve space for the reference-to-copy area. */
for (i = 0; i < nargs; i++)
{
struct value *arg = args[i];
@@ -2361,7 +2360,6 @@ s390_push_dummy_call (struct gdbarch *gd
{
sp -= length;
sp = align_down (sp, alignment_of (type));
- write_memory (sp, value_contents (arg), length);
copy_addr[i] = sp;
}
}
@@ -2376,13 +2374,26 @@ s390_push_dummy_call (struct gdbarch *gd
boundary. */
sp = align_down (sp, 8);
+ /* Allocate the standard frame areas: the register save area, the
+ word reserved for the compiler (which seems kind of meaningless),
+ and the back chain pointer. */
+ sp -= 16*word_size + 32;
+
+ /* Now we have the final SP value. Make sure we didn't underflow;
+ on 31-bit, this would result in addresses with the high bit set,
+ which causes confusion elsewhere. Note that if we error out
+ here, stack and registers remain untouched. */
+ if (gdbarch_addr_bits_remove (gdbarch, sp) != sp)
+ error (_("Stack overflow"));
+
+
/* Finally, place the actual parameters, working from SP towards
higher addresses. The code above is supposed to reserve enough
space for this. */
{
int fr = 0;
int gr = 2;
- CORE_ADDR starg = sp;
+ CORE_ADDR starg = sp + 16*word_size + 32;
/* A struct is returned using general register 2. */
if (struct_return)
@@ -2400,6 +2411,10 @@ s390_push_dummy_call (struct gdbarch *gd
if (s390_function_arg_pass_by_reference (type))
{
+ /* Actually copy the argument contents to the stack slot
+ that was reserved above. */
+ write_memory (copy_addr[i], value_contents (arg), length);
+
if (gr <= 6)
{
regcache_cooked_write_unsigned (regcache, S390_R0_REGNUM + gr,
@@ -2475,11 +2490,6 @@ s390_push_dummy_call (struct gdbarch *gd
}
}
- /* Allocate the standard frame areas: the register save area, the
- word reserved for the compiler (which seems kind of meaningless),
- and the back chain pointer. */
- sp -= 16*word_size + 32;
-
/* Store return address. */
regcache_cooked_write_unsigned (regcache, S390_RETADDR_REGNUM, bp_addr);
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com