summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiva Chandra <sivachandra@chromium.org>2013-12-27 12:20:59 -0800
committerSiva Chandra <sivachandra@chromium.org>2014-01-13 17:35:56 -0800
commitb5b08fb4ffa53ec088f8ad865bee0fd6edb2906f (patch)
tree6235384f2a58a63987bc6d661390350c178730fa
parent13aaf454542c1028a033ac836d7a0d47c63a7029 (diff)
downloadbinutils-gdb-b5b08fb4ffa53ec088f8ad865bee0fd6edb2906f.tar.gz
Use bitpos and type to lookup a gdb.Field object when its name is 'None'.
PR python/15464 PR python/16113 * valops.c (value_struct_elt_bitpos): New function * py-type.c (convert_field): Set 'name' attribute of a gdb.Field object to 'None' if the field name is an empty string (""). * python/py-value.c (valpy_getitem): Use 'bitpos' and 'type' attribute to look for a field when 'name' is 'None'. (get_field_type): New function testsuite/ * gdb.python/py-type.c: Enhance test case. * gdb.python/py-value-cc.cc: Likewise * gdb.python/py-type.exp: Add new tests. * gdb.python/py-value-cc.exp: Likewise
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/python/py-type.c15
-rw-r--r--gdb/python/py-value.c80
-rw-r--r--gdb/testsuite/ChangeLog9
-rw-r--r--gdb/testsuite/gdb.python/py-type.c9
-rw-r--r--gdb/testsuite/gdb.python/py-type.exp9
-rw-r--r--gdb/testsuite/gdb.python/py-value-cc.cc23
-rw-r--r--gdb/testsuite/gdb.python/py-value-cc.exp20
-rw-r--r--gdb/valops.c45
-rw-r--r--gdb/value.h5
10 files changed, 208 insertions, 18 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index afcce17bf60..c4e1301a15c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2014-01-13 Siva Chandra Reddy <sivachandra@google.com>
+
+ PR python/15464
+ PR python/16113
+ * valops.c (value_struct_elt_bitpos): New function
+ * py-type.c (convert_field): Set 'name' attribute of a gdb.Field
+ object to 'None' if the field name is an empty string ("").
+ * python/py-value.c (valpy_getitem): Use 'bitpos' and 'type'
+ attribute to look for a field when 'name' is 'None'.
+ (get_field_type): New function
+
2014-01-13 Doug Evans <dje@google.com>
PR symtab/16426
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 16bb4421eed..c904d3af3fe 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -206,15 +206,22 @@ convert_field (struct type *type, int field)
Py_DECREF (arg);
}
+ arg = NULL;
if (TYPE_FIELD_NAME (type, field))
- arg = PyString_FromString (TYPE_FIELD_NAME (type, field));
- else
+ {
+ const char *field_name = TYPE_FIELD_NAME (type, field);
+ if (field_name[0] != '\0')
+ {
+ arg = PyString_FromString (TYPE_FIELD_NAME (type, field));
+ if (arg == NULL)
+ goto fail;
+ }
+ }
+ if (arg == NULL)
{
arg = Py_None;
Py_INCREF (arg);
}
- if (!arg)
- goto fail;
if (PyObject_SetAttrString (result, "name", arg) < 0)
goto failarg;
Py_DECREF (arg);
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 4ab782d83c3..65750a4aba4 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -563,6 +563,29 @@ get_field_flag (PyObject *field, const char *flag_name)
return flag_value;
}
+/* Return the "type" attribute of a gdb.Field object.
+ Returns NULL on error, with a Python exception set. */
+
+static struct type *
+get_field_type (PyObject *field)
+{
+ PyObject *ftype_obj = PyObject_GetAttrString (field, "type");
+ struct type *ftype;
+
+ if (ftype_obj == NULL)
+ return NULL;
+ ftype = type_object_to_type (ftype_obj);
+ Py_DECREF (ftype_obj);
+ if (ftype == NULL)
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("'type' attribute of gdb.Field object is not a "
+ "gdb.Type object."));
+ }
+
+ return ftype;
+}
+
/* Given string name or a gdb.Field object corresponding to an element inside
a structure, return its value object. Returns NULL on error, with a python
exception set. */
@@ -572,7 +595,8 @@ valpy_getitem (PyObject *self, PyObject *key)
{
value_object *self_value = (value_object *) self;
char *field = NULL;
- PyObject *base_class_type_object = NULL;
+ struct type *base_class_type = NULL, *field_type = NULL;
+ long bitpos = -1;
volatile struct gdb_exception except;
PyObject *result = NULL;
@@ -603,8 +627,8 @@ valpy_getitem (PyObject *self, PyObject *key)
return NULL;
else if (is_base_class > 0)
{
- base_class_type_object = PyObject_GetAttrString (key, "type");
- if (base_class_type_object == NULL)
+ base_class_type = get_field_type (key);
+ if (base_class_type == NULL)
return NULL;
}
else
@@ -614,10 +638,40 @@ valpy_getitem (PyObject *self, PyObject *key)
if (name_obj == NULL)
return NULL;
- field = python_string_to_host_string (name_obj);
- Py_DECREF (name_obj);
- if (field == NULL)
- return NULL;
+ if (name_obj != Py_None)
+ {
+ field = python_string_to_host_string (name_obj);
+ Py_DECREF (name_obj);
+ if (field == NULL)
+ return NULL;
+ }
+ else
+ {
+ PyObject *bitpos_obj;
+ int valid;
+
+ Py_DECREF (name_obj);
+
+ if (!PyObject_HasAttrString (key, "bitpos"))
+ {
+ PyErr_SetString (PyExc_AttributeError,
+ _("gdb.Field object has no name and no "
+ "'bitpos' attribute."));
+
+ return NULL;
+ }
+ bitpos_obj = PyObject_GetAttrString (key, "bitpos");
+ if (bitpos_obj == NULL)
+ return NULL;
+ valid = gdb_py_int_as_long (bitpos_obj, &bitpos);
+ Py_DECREF (bitpos_obj);
+ if (!valid)
+ return NULL;
+
+ field_type = get_field_type (key);
+ if (field_type == NULL)
+ return NULL;
+ }
}
}
@@ -629,14 +683,12 @@ valpy_getitem (PyObject *self, PyObject *key)
if (field)
res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
- else if (base_class_type_object != NULL)
+ else if (bitpos >= 0)
+ res_val = value_struct_elt_bitpos (&tmp, bitpos, field_type,
+ "struct/class/union");
+ else if (base_class_type != NULL)
{
- struct type *base_class_type, *val_type;
-
- base_class_type = type_object_to_type (base_class_type_object);
- Py_DECREF (base_class_type_object);
- if (base_class_type == NULL)
- error (_("Field type not an instance of gdb.Type."));
+ struct type *val_type;
val_type = check_typedef (value_type (tmp));
if (TYPE_CODE (val_type) == TYPE_CODE_PTR)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 904cca726a7..d2e011afe02 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2014-01-13 Siva Chandra Reddy <sivachandra@google.com>
+
+ PR python/15464
+ PR python/16113
+ * gdb.python/py-type.c: Enhance test case.
+ * gdb.python/py-value-cc.cc: Likewise
+ * gdb.python/py-type.exp: Add new tests.
+ * gdb.python/py-value-cc.exp: Likewise
+
2014-01-10 Andreas Arnez <arnez@linux.vnet.ibm.com>
Pedro Alves <palves@redhat.com>
diff --git a/gdb/testsuite/gdb.python/py-type.c b/gdb/testsuite/gdb.python/py-type.c
index 7cee383917c..697e29c2636 100644
--- a/gdb/testsuite/gdb.python/py-type.c
+++ b/gdb/testsuite/gdb.python/py-type.c
@@ -21,6 +21,12 @@ struct s
int b;
};
+struct SS
+{
+ union { int x; char y; };
+ union { int a; char b; };
+};
+
typedef struct s TS;
TS ts;
@@ -58,6 +64,7 @@ main ()
{
int ar[2] = {1,2};
struct s st;
+ struct SS ss;
#ifdef __cplusplus
C c;
c.c = 1;
@@ -72,6 +79,8 @@ main ()
st.b = 5;
e = v2;
+
+ ss.x = 100;
return 0; /* break to inspect struct and array. */
}
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index 93301d080d4..6b61f48f0a1 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -85,6 +85,15 @@ proc test_fields {lang} {
gdb_test "python print (fields\[0\].name)" "a" "Check structure field a name"
gdb_test "python print (fields\[1\].name)" "b" "Check structure field b name"
+ # Test that unamed fields have 'None' for name.
+ gdb_py_test_silent_cmd "python ss = gdb.parse_and_eval('ss')" "init ss" 1
+ gdb_py_test_silent_cmd "python ss_fields = ss.type.fields()" \
+ "get fields from ss.type" 1
+ gdb_test "python print len(ss_fields)" "2" "Check length of ss_fields"
+ gdb_test "python print ss_fields\[0\].name is None" "True" \
+ "Check ss_fields\[0\].name"
+ gdb_test "python print ss_fields\[1\].name is None" "True" \
+ "Check ss_fields\[1\].name"
# Regression test for
# http://sourceware.org/bugzilla/show_bug.cgi?id=12070.
gdb_test "python print ('type' in dir(fields\[0\]))" "True" \
diff --git a/gdb/testsuite/gdb.python/py-value-cc.cc b/gdb/testsuite/gdb.python/py-value-cc.cc
index 59f1decb5c9..ace957a1466 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.cc
+++ b/gdb/testsuite/gdb.python/py-value-cc.cc
@@ -30,8 +30,21 @@ class B : public A {
char a;
};
+struct X
+{
+ union { int x; char y; };
+ union { int a; char b; };
+};
+
+union UU
+{
+ union { int x; char y; };
+ union { int a; char b; };
+};
+
typedef B Btd;
typedef int *int_ptr;
+typedef X Xtd;
int
func (const A &a)
@@ -57,6 +70,16 @@ func (const A &a)
U u;
u.a = 99;
+ X x;
+ x.x = 101;
+ x.a = 102;
+
+ UU uu;
+ uu.x = 1000;
+
+ X *x_ptr = &x;
+ Xtd *xtd = &x;
+
return 0; /* Break here. */
}
diff --git a/gdb/testsuite/gdb.python/py-value-cc.exp b/gdb/testsuite/gdb.python/py-value-cc.exp
index 1faec5fa1a3..e6351f65418 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.exp
+++ b/gdb/testsuite/gdb.python/py-value-cc.exp
@@ -53,6 +53,14 @@ gdb_test_no_output "python b_ref = gdb.parse_and_eval('b_ref')" "init b_ref"
gdb_test_no_output "python b_td = gdb.parse_and_eval('b_td')" "init b_td"
gdb_test_no_output "python u = gdb.parse_and_eval('u')" "init u"
gdb_test_no_output "python u_fields = u.type.fields()" "init u_fields"
+gdb_test_no_output "python x = gdb.parse_and_eval('x')" "init x"
+gdb_test_no_output "python x_fields = x.type.fields()" "init x_fields"
+gdb_test_no_output "python uu = gdb.parse_and_eval('uu')" "init uu"
+gdb_test_no_output "python uu_fields = uu.type.fields()" "init uu_fields"
+gdb_test_no_output "python x_ptr = gdb.parse_and_eval('x_ptr')" "init x_ptr"
+gdb_test_no_output "python xtd = gdb.parse_and_eval('xtd')" "init xtd"
+
+gdb_test "python print(b\[b_fields\[1\]\])" "97 'a'" "b.a via field"
gdb_test "python print(b\[b_fields\[1\]\])" "97 'a'" "b.a via field"
gdb_test "python print(b\[b_fields\[0\]\].type)" "A" \
@@ -79,3 +87,15 @@ gdb_test "python print(b_td\[b_fields\[0\]\]\['a'\])" "100" \
gdb_test "python print(u\[u_fields\[0\]\])" "99.*" "u's first field via field"
gdb_test "python print(u\[u_fields\[1\]\])" "99.*" "u's second field via field"
+
+gdb_test "python print len(x_fields)" "2" "number for fields in u"
+gdb_test "python print x\[x_fields\[0\]\]\['x'\]" "101" "x.x via field"
+gdb_test "python print x\[x_fields\[1\]\]\['a'\]" "102" "x.a via field"
+gdb_test "python print x_ptr\[x_fields\[0\]\]\['x'\]" "101" "x_ptr->x via field"
+gdb_test "python print x_ptr\[x_fields\[1\]\]\['a'\]" "102" "x_ptr->a via field"
+gdb_test "python print xtd\[x_fields\[0\]\]\['x'\]" "101" "xtd->x via field"
+gdb_test "python print xtd\[x_fields\[1\]\]\['a'\]" "102" "xtd->a via field"
+
+gdb_test "python print len(uu_fields)" "2" "number of fields in uu"
+gdb_test "python print uu\[uu_fields\[0\]\]\['x'\]" "1000" "uu.x via field"
+gdb_test "python print uu\[uu_fields\[1\]\]\['a'\]" "1000" "uu.a via field"
diff --git a/gdb/valops.c b/gdb/valops.c
index 5382c4942b5..deb01cbad88 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2246,6 +2246,51 @@ value_struct_elt (struct value **argp, struct value **args,
return v;
}
+/* Given *ARGP, a value of type structure or union, or a pointer/reference
+ to a structure or union, extract and return its component (field) of
+ type FTYPE at the specified BITPOS.
+ Throw an exception on error. */
+
+struct value *
+value_struct_elt_bitpos (struct value **argp, int bitpos, struct type *ftype,
+ const char *err)
+{
+ struct type *t;
+ struct value *v;
+ int i;
+ int nbases;
+
+ *argp = coerce_array (*argp);
+
+ t = check_typedef (value_type (*argp));
+
+ while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+ {
+ *argp = value_ind (*argp);
+ if (TYPE_CODE (check_typedef (value_type (*argp))) != TYPE_CODE_FUNC)
+ *argp = coerce_array (*argp);
+ t = check_typedef (value_type (*argp));
+ }
+
+ if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error (_("Attempt to extract a component of a value that is not a %s."),
+ err);
+
+ for (i = TYPE_N_BASECLASSES (t); i < TYPE_NFIELDS (t); i++)
+ {
+ if (!field_is_static (&TYPE_FIELD (t, i))
+ && bitpos == TYPE_FIELD_BITPOS (t, i)
+ && types_equal (ftype, TYPE_FIELD_TYPE (t, i)))
+ return value_primitive_field (*argp, 0, i, t);
+ }
+
+ error (_("No field with matching bitpos and type."));
+
+ /* Never hit. */
+ return NULL;
+}
+
/* Search through the methods of an object (and its bases) to find a
specified method. Return the pointer to the fn_field list of
overloaded instances.
diff --git a/gdb/value.h b/gdb/value.h
index 5924b2f5b21..f8466690e0d 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -670,6 +670,11 @@ extern struct value *value_struct_elt (struct value **argp,
const char *name, int *static_memfuncp,
const char *err);
+extern struct value *value_struct_elt_bitpos (struct value **argp,
+ int bitpos,
+ struct type *field_type,
+ const char *err);
+
extern struct value *value_aggregate_elt (struct type *curtype,
char *name,
struct type *expect_type,