summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2003-06-15 11:40:46 +0000
committerMark Kettenis <kettenis@gnu.org>2003-06-15 11:40:46 +0000
commitdcf6c1260613799bbea291b9366be14f18a6a8ca (patch)
tree212d7d2b6d3736157748bb4f952dd18cf51979f5 /gdb
parent168c4f1285d0794cddd3aa658fdc123cf69fec32 (diff)
downloadgdb-dcf6c1260613799bbea291b9366be14f18a6a8ca.tar.gz
* 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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/i386-tdep.c71
2 files changed, 54 insertions, 23 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c76c5245c90..bc4f971c605 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 350a93c812c..3b981806dc2 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;
+ }
}