diff options
author | Mark Kettenis <kettenis@gnu.org> | 2003-06-15 11:40:46 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2003-06-15 11:40:46 +0000 |
commit | de5b9bb93a97c218441ce891c4fa0dc0787f1626 (patch) | |
tree | 7fc2f977658335970cc2f76f01f0ba118b6031fb | |
parent | d532c08fb0172968305f4ebda8e128593e27dba0 (diff) | |
download | gdb-de5b9bb93a97c218441ce891c4fa0dc0787f1626.zip gdb-de5b9bb93a97c218441ce891c4fa0dc0787f1626.tar.gz gdb-de5b9bb93a97c218441ce891c4fa0dc0787f1626.tar.bz2 |
* i386-tdep.c (i386_next_regnum): Fix bounds checking.
(i386_convert_register_p, i386_register_to_value,
i386_register_from_value): Handle types longer than 8 bytes.
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/i386-tdep.c | 71 |
2 files changed, 54 insertions, 23 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c76c524..bc4f971 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,11 @@ 2003-06-15 Mark Kettenis <kettenis@gnu.org> + * i386-tdep.c (i386_next_regnum): Fix bounds checking. + (i386_convert_register_p, i386_register_to_value, + i386_register_from_value): Handle types longer than 8 bytes. + +2003-06-15 Mark Kettenis <kettenis@gnu.org> + * i386-tdep.c (i386_register_to_value, i386_value_to_register): Move floating-point code to new function in i387-tdep.c. * i387-tdep.c (i387_register_to_value, i387_value_to_register): diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 350a93c..3b98180 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -1357,7 +1357,7 @@ i386_next_regnum (int regnum) I386_EBP_REGNUM /* Slot for %edi. */ }; - if (regnum < sizeof (next_regnum) / sizeof (next_regnum[0])) + if (regnum >= 0 && regnum < sizeof (next_regnum) / sizeof (next_regnum[0])) return next_regnum[regnum]; return -1; @@ -1369,13 +1369,26 @@ i386_next_regnum (int regnum) static int i386_convert_register_p (int regnum, struct type *type) { + int len = TYPE_LENGTH (type); + /* Values may be spread across multiple registers. Most debugging formats aren't expressive enough to specify the locations, so some heuristics is involved. Right now we only handle types that - are exactly 8 bytes long as GCC doesn't seem to put any other - types into registers. */ - if (TYPE_LENGTH (type) == 8 && i386_next_regnum (regnum) != -1) - return 1; + have a length that is a multiple of the word size, since GCC + doesn't seem to put any other types into registers. */ + if (len > 4 && len % 4 == 0) + { + int last_regnum = regnum; + + while (len > 4) + { + last_regnum = i386_next_regnum (last_regnum); + len -= 4; + } + + if (last_regnum != -1) + return 1; + } return i386_fp_regnum_p (regnum); } @@ -1387,6 +1400,9 @@ static void i386_register_to_value (struct frame_info *frame, int regnum, struct type *type, void *to) { + int len = TYPE_LENGTH (type); + char *buf = to; + /* FIXME: kettenis/20030609: What should we do if REGNUM isn't available in FRAME (i.e. if it wasn't saved)? */ @@ -1396,17 +1412,20 @@ i386_register_to_value (struct frame_info *frame, int regnum, return; } - gdb_assert (TYPE_LENGTH (type) == 8); + /* Read a value spread accross multiple registers. */ + + gdb_assert (len > 4 && len % 4 == 0); - /* Read the first part. */ - gdb_assert (register_size (current_gdbarch, regnum) == 4); - frame_read_register (frame, regnum, (char *) to + 0); + while (len > 0) + { + gdb_assert (regnum != -1); + gdb_assert (register_size (current_gdbarch, regnum) == 4); - /* Read the second part. */ - regnum = i386_next_regnum (regnum); - gdb_assert (regnum != -1); - gdb_assert (register_size (current_gdbarch, regnum)); - frame_read_register (frame, regnum, (char *) to + 4); + frame_read_register (frame, regnum, buf); + regnum = i386_next_regnum (regnum); + len -= 4; + buf += 4; + } } /* Write the contents FROM of a value of type TYPE into register @@ -1416,23 +1435,29 @@ static void i386_value_to_register (struct frame_info *frame, int regnum, struct type *type, const void *from) { + int len = TYPE_LENGTH (type); + const char *buf = from; + if (i386_fp_regnum_p (regnum)) { i387_value_to_register (frame, regnum, type, from); return; } - gdb_assert (TYPE_LENGTH (type) == 8); + /* Write a value spread accross multiple registers. */ + + gdb_assert (len > 4 && len % 4 == 0); - /* Write the first part. */ - gdb_assert (register_size (current_gdbarch, regnum) == 4); - put_frame_register (frame, regnum, (const char *) from + 0); + while (len > 0) + { + gdb_assert (regnum != -1); + gdb_assert (register_size (current_gdbarch, regnum) == 4); - /* Write the second part. */ - regnum = i386_next_regnum (regnum); - gdb_assert (regnum != -1); - gdb_assert (register_size (current_gdbarch, regnum) == 4); - put_frame_register (frame, regnum, (const char *) from + 4); + put_frame_register (frame, regnum, buf); + regnum = i386_next_regnum (regnum); + len -= 4; + buf += 4; + } } |