summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Stubbs <andrew.stubbs@st.com>2006-03-31 10:36:18 +0000
committerAndrew Stubbs <andrew.stubbs@st.com>2006-03-31 10:36:18 +0000
commit3e3c6bfd41d9925260fba6cc04e6bbfe7ab0d4d0 (patch)
treec7f7747f4a765d4467caa8ec3d53a5e279536e2a
parentaa6be8b8574d4b14f26687d6930917ac02b66d63 (diff)
downloadgdb-3e3c6bfd41d9925260fba6cc04e6bbfe7ab0d4d0.tar.gz
2006-03-31 Andrew Stubbs <andrew.stubbs@st.com>
* value.h (struct internalvar): Add field 'endian'. * value.c (lookup_internalvar): Initialise endian. (value_of_internalvar): Flip the endian of built-in types if required. (set_internalvar): Set the endian. (show_convenience): Access the value through value_of_internalvar().
-rw-r--r--gdb/ChangeLog8
-rw-r--r--gdb/value.c39
-rw-r--r--gdb/value.h1
3 files changed, 47 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e581f704319..2409cacf4bc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-31 Andrew Stubbs <andrew.stubbs@st.com>
+
+ * value.h (struct internalvar): Add field 'endian'.
+ * value.c (lookup_internalvar): Initialise endian.
+ (value_of_internalvar): Flip the endian of built-in types if required.
+ (set_internalvar): Set the endian.
+ (show_convenience): Access the value through value_of_internalvar().
+
2006-03-30 Vladimir Prus <ghost@cs.msu.su>
* remote.c (watchpoint_to_Z_packet): Use values of Z_packet_type enum
diff --git a/gdb/value.c b/gdb/value.c
index 2e304854bfa..77b92f6db7d 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -755,6 +755,7 @@ lookup_internalvar (char *name)
var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
var->name = concat (name, (char *)NULL);
var->value = allocate_value (builtin_type_void);
+ var->endian = TARGET_BYTE_ORDER;
release_value (var->value);
var->next = internalvars;
internalvars = var;
@@ -765,12 +766,46 @@ struct value *
value_of_internalvar (struct internalvar *var)
{
struct value *val;
+ int i, j;
+ gdb_byte temp;
val = value_copy (var->value);
if (value_lazy (val))
value_fetch_lazy (val);
VALUE_LVAL (val) = lval_internalvar;
VALUE_INTERNALVAR (val) = var;
+
+ /* Values are always stored in the target's byte order. When connected to a
+ target this will most likely always be correct, so there's normally no
+ need to worry about it.
+
+ However, internal variables can be set up before the target endian is
+ known and so may become out of date. Fix it up before anybody sees.
+
+ Internal variables usually hold simple scalar values, and we can
+ correct those. More complex values (e.g. structures and floating
+ point types) are left alone, because they would be too complicated
+ to correct. */
+
+ if (var->endian != TARGET_BYTE_ORDER)
+ {
+ gdb_byte *array = value_contents_raw (val);
+ struct type *type = check_typedef (value_enclosing_type (val));
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_PTR:
+ /* Reverse the bytes. */
+ for (i = 0, j = TYPE_LENGTH (type) - 1; i < j; i++, j--)
+ {
+ temp = array[j];
+ array[j] = array[i];
+ array[i] = temp;
+ }
+ break;
+ }
+ }
+
return val;
}
@@ -809,6 +844,7 @@ set_internalvar (struct internalvar *var, struct value *val)
long. */
xfree (var->value);
var->value = newval;
+ var->endian = TARGET_BYTE_ORDER;
release_value (newval);
/* End code which must not call error(). */
}
@@ -877,7 +913,8 @@ show_convenience (char *ignore, int from_tty)
varseen = 1;
}
printf_filtered (("$%s = "), var->name);
- value_print (var->value, gdb_stdout, 0, Val_pretty_default);
+ value_print (value_of_internalvar (var), gdb_stdout,
+ 0, Val_pretty_default);
printf_filtered (("\n"));
}
if (!varseen)
diff --git a/gdb/value.h b/gdb/value.h
index e1972352270..a878ec4008d 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -245,6 +245,7 @@ struct internalvar
struct internalvar *next;
char *name;
struct value *value;
+ int endian;
};