aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2read.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2013-05-06 19:44:04 +0000
committerTom Tromey <tromey@redhat.com>2013-05-06 19:44:04 +0000
commitb6807d988a28dc2718bae1abba1f28779bc0c3c3 (patch)
treebb4adece022138ab739318623eec8dce672a03b8 /gdb/dwarf2read.c
parent3aef2284c6976e2b497d5e712cf0cedcc14bed58 (diff)
downloadgdb-b6807d988a28dc2718bae1abba1f28779bc0c3c3.zip
gdb-b6807d988a28dc2718bae1abba1f28779bc0c3c3.tar.gz
gdb-b6807d988a28dc2718bae1abba1f28779bc0c3c3.tar.bz2
* dwarf2loc.c (invalid_synthetic_pointer): Move earlier.
(indirect_pieced_value): Call dwarf2_fetch_constant_bytes if needed. * dwarf2loc.h (dwarf2_fetch_constant_bytes): Declare. * dwarf2read.c (write_constant_as_bytes) (dwarf2_fetch_constant_bytes): New functions. gdb/testsuite * gdb.dwarf2/implptrconst.c: New file. * gdb.dwarf2/implptrconst.exp: New file. * lib/dwarf.exp (Dwarf::_nz_quote): New proc. (Dwarf::_handle_DW_FORM): Handle DW_FORM_block1. (Dwarf::_location): Handle DW_OP_GNU_implicit_pointer.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r--gdb/dwarf2read.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 1154b11..2a5acf0 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -17765,6 +17765,150 @@ dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton);
}
+/* Write a constant of a given type as target-ordered bytes into
+ OBSTACK. */
+
+static const gdb_byte *
+write_constant_as_bytes (struct obstack *obstack,
+ enum bfd_endian byte_order,
+ struct type *type,
+ ULONGEST value,
+ LONGEST *len)
+{
+ gdb_byte *result;
+
+ *len = TYPE_LENGTH (type);
+ result = obstack_alloc (obstack, *len);
+ store_unsigned_integer (result, *len, byte_order, value);
+
+ return result;
+}
+
+/* If the DIE at OFFSET in PER_CU has a DW_AT_const_value, return a
+ pointer to the constant bytes and set LEN to the length of the
+ data. If memory is needed, allocate it on OBSTACK. If the DIE
+ does not have a DW_AT_const_value, return NULL. */
+
+const gdb_byte *
+dwarf2_fetch_constant_bytes (sect_offset offset,
+ struct dwarf2_per_cu_data *per_cu,
+ struct obstack *obstack,
+ LONGEST *len)
+{
+ struct dwarf2_cu *cu;
+ struct die_info *die;
+ struct attribute *attr;
+ const gdb_byte *result = NULL;
+ struct type *type;
+ LONGEST value;
+ enum bfd_endian byte_order;
+
+ dw2_setup (per_cu->objfile);
+
+ if (per_cu->cu == NULL)
+ load_cu (per_cu);
+ cu = per_cu->cu;
+
+ die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+ if (!die)
+ error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
+ offset.sect_off, per_cu->objfile->name);
+
+
+ attr = dwarf2_attr (die, DW_AT_const_value, cu);
+ if (attr == NULL)
+ return NULL;
+
+ byte_order = (bfd_big_endian (per_cu->objfile->obfd)
+ ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE);
+
+ switch (attr->form)
+ {
+ case DW_FORM_addr:
+ case DW_FORM_GNU_addr_index:
+ {
+ gdb_byte *tem;
+
+ *len = cu->header.addr_size;
+ tem = obstack_alloc (obstack, *len);
+ store_unsigned_integer (tem, *len, byte_order, DW_ADDR (attr));
+ result = tem;
+ }
+ break;
+ case DW_FORM_string:
+ case DW_FORM_strp:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_strp_alt:
+ /* DW_STRING is already allocated on the objfile obstack, point
+ directly to it. */
+ result = (const gdb_byte *) DW_STRING (attr);
+ *len = strlen (DW_STRING (attr));
+ break;
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ result = DW_BLOCK (attr)->data;
+ *len = DW_BLOCK (attr)->size;
+ break;
+
+ /* The DW_AT_const_value attributes are supposed to carry the
+ symbol's value "represented as it would be on the target
+ architecture." By the time we get here, it's already been
+ converted to host endianness, so we just need to sign- or
+ zero-extend it as appropriate. */
+ case DW_FORM_data1:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 8);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+ case DW_FORM_data2:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 16);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+ case DW_FORM_data4:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 32);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+ case DW_FORM_data8:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 64);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+
+ case DW_FORM_sdata:
+ type = die_type (die, cu);
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, DW_SND (attr), len);
+ break;
+
+ case DW_FORM_udata:
+ type = die_type (die, cu);
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, DW_UNSND (attr), len);
+ break;
+
+ default:
+ complaint (&symfile_complaints,
+ _("unsupported const value attribute form: '%s'"),
+ dwarf_form_name (attr->form));
+ break;
+ }
+
+ return result;
+}
+
/* Return the type of the DIE at DIE_OFFSET in the CU named by
PER_CU. */