diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2010-06-25 17:47:29 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2010-06-25 17:47:29 +0000 |
commit | c0cc4c83bd3d981e727be0984987911edd47b98c (patch) | |
tree | bb5222b4e5c05865c5d35ac61fccc122e9978351 /gdb/s390-tdep.c | |
parent | f1d8ee66261af43a65975bac1f4528e9ee68c658 (diff) | |
download | gdb-c0cc4c83bd3d981e727be0984987911edd47b98c.zip gdb-c0cc4c83bd3d981e727be0984987911edd47b98c.tar.gz gdb-c0cc4c83bd3d981e727be0984987911edd47b98c.tar.bz2 |
* s390-tdep.c (s390_push_dummy_call): Error on stack overflow
during inferior call stack frame setup.
Diffstat (limited to 'gdb/s390-tdep.c')
-rw-r--r-- | gdb/s390-tdep.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index e7dc48d..daeed0d 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -2343,14 +2343,13 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function, 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 *gdbarch, struct value *function, { 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 *gdbarch, struct value *function, 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 *gdbarch, struct value *function, 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 *gdbarch, struct value *function, } } - /* 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); |