Created
May 20, 2016 22:56
-
-
Save stffrdhrn/e7c1eab1394ab33b42ff25ff155f502c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/gdb/or1k-tdep.c b/gdb/or1k-tdep.c | |
index 8cfa440..1275b2a 100644 | |
--- a/gdb/or1k-tdep.c | |
+++ b/gdb/or1k-tdep.c | |
@@ -443,8 +443,13 @@ or1k_return_value (struct gdbarch *gdbarch, | |
is returned in memory. Large (2 word) scalars are returned in r11 and r12 | |
(this is a change from GCC 4.2.2, when they were apparently returned in | |
memory). */ | |
- if (((TYPE_CODE_STRUCT == rv_type) || (TYPE_CODE_UNION == rv_type)) && | |
- (rv_size > bpw)) | |
+ | |
+ // FIXME why is array handled like this? Nothing in the spec mentions it | |
+ // I cant figure it out from GCC code. But all tests pass if we do | |
+ // this way. | |
+ if ((TYPE_CODE_STRUCT == rv_type) || (TYPE_CODE_UNION == rv_type) || | |
+ ((TYPE_CODE_ARRAY == rv_type) && rv_size > bpw) || | |
+ (rv_size > 2*bpw)) | |
{ | |
if (readbuf) | |
{ | |
@@ -1228,6 +1233,7 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
unsigned int bpa = (gdbarch_tdep (gdbarch))->bytes_per_address; | |
unsigned int bpw = (gdbarch_tdep (gdbarch))->bytes_per_word; | |
+ struct type *func_type = value_type (function); | |
/* Return address */ | |
regcache_cooked_write_unsigned (regcache, OR1K_LR_REGNUM, bp_addr); | |
@@ -1237,9 +1243,9 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
/* Location for a returned structure. This is passed as a silent first | |
argument. */ | |
- | |
if (struct_return) | |
{ | |
+printf ("return struct in reg ptr"); | |
regcache_cooked_write_unsigned (regcache, OR1K_FIRST_ARG_REGNUM, | |
struct_addr); | |
argreg++; | |
@@ -1256,13 +1262,33 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
int len = arg_type->length; | |
enum type_code typecode = arg_type->main_type->code; | |
- /* Handle the different argument types. */ | |
- if((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)) | |
+ if (TYPE_VARARGS (func_type) && argnum >= TYPE_NFIELDS(func_type)) | |
+ { | |
+ break; /* end or regular args, varargs go to stack */ | |
+ } | |
+ | |
+ /* Extract the value, either a reference or the data */ | |
+ if ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode) || (len > bpw*2)) | |
{ | |
- /* The ABI passes all structures by reference, so get its address. */ | |
- store_unsigned_integer (valbuf, bpa, byte_order, value_address (arg)); | |
- len = bpa; | |
- val = valbuf; | |
+ CORE_ADDR valaddr = value_address (arg); | |
+ | |
+ /* if the arg is fabricated (i.e. 3*i, instead of i) valaddr is undefined */ | |
+ if (valaddr == 0) { | |
+ /* The argument needs to be copied into the target space */ | |
+ // FIXME This is a BIG hack now, we need to stuff the data somewhere, but down | |
+ // below we start storing stuff on the stack and the location is important. | |
+ // The location of this data isnt important. We need as way to put arbitrary | |
+ // data into the target memory. | |
+ valaddr = sp - 100 + stack_offset; | |
+ | |
+ write_memory (valaddr, value_contents(arg), len); | |
+ stack_offset += align_up (len, bpw); | |
+ } | |
+ | |
+ /* The ABI passes all structures by reference, so get its address. */ | |
+ store_unsigned_integer (valbuf, bpa, byte_order, valaddr); | |
+ len = bpa; | |
+ val = valbuf; | |
} | |
else | |
{ | |
@@ -1273,9 +1299,7 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
/* Stick the value in a register */ | |
if(len > bpw) | |
{ | |
- /* Big scalars use two registers, but need NOT be pair aligned. This | |
- code breaks if we can have quad-word scalars (e.g. long | |
- double). */ | |
+ /* Big scalars use two registers, but need NOT be pair aligned. */ | |
if (argreg <= (OR1K_LAST_ARG_REGNUM - 1)) | |
{ | |
@@ -1286,8 +1310,6 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
ULONGEST lo = regval & mask; | |
ULONGEST hi = regval >> bits_per_word; | |
- gdb_assert (len <= (bpw * 2)); | |
- | |
regcache_cooked_write_unsigned (regcache, argreg, hi); | |
regcache_cooked_write_unsigned (regcache, argreg + 1, lo); | |
argreg += 2; | |
@@ -1328,7 +1350,7 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
int len = arg_type->length; | |
enum type_code typecode = arg_type->main_type->code; | |
- if((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)) | |
+ if ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode) || (len > bpw*2)) | |
{ | |
/* Structures are passed as addresses */ | |
sp -= bpa; | |
@@ -1337,7 +1359,7 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
{ | |
/* Big scalars use more than one word. Code here allows for future | |
quad-word entities (e.g. long double) */ | |
- sp -= ((len + bpw - 1) / bpw) * bpw; | |
+ sp -= align_up(len, bpw); | |
} | |
} | |
@@ -1354,10 +1376,9 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
struct type *arg_type = check_typedef (value_type (arg)); | |
int len = arg_type->length; | |
enum type_code typecode = arg_type->main_type->code; | |
- | |
/* The EABI passes structures that do not fit in a register by | |
reference. In all other cases, pass the structure by value. */ | |
- if((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)) | |
+ if ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode) || (len > bpw*2)) | |
{ | |
store_unsigned_integer (valbuf, bpa, byte_order, value_address (arg)); | |
len = bpa; | |
@@ -1368,10 +1389,15 @@ or1k_push_dummy_call (struct gdbarch *gdbarch, | |
val = value_contents (arg); | |
} | |
- gdb_assert (len <= (bpw * 2)); | |
+ while (len > 0) | |
+ { | |
+ int partial_len = (len < bpw ? len : bpw); | |
- write_memory (sp + stack_offset, val, len); | |
- stack_offset += ((len + bpw - 1) / bpw) * bpw; | |
+ write_memory (sp + stack_offset, val, partial_len); | |
+ stack_offset += align_up (partial_len, bpw); | |
+ len -= partial_len; | |
+ val += partial_len; | |
+ } | |
} | |
/* Save the updated stack pointer */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment