summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dwarf-extract-struct.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/dwarf-extract-struct.c b/dwarf-extract-struct.c
index 141bb83..ba6f838 100644
--- a/dwarf-extract-struct.c
+++ b/dwarf-extract-struct.c
@@ -266,6 +266,18 @@ static int dwarf_get_offset(Dwarf_Debug dbg, Dwarf_Die die,
poffset, perr);
}
+static int dwarf_get_bitfield(Dwarf_Debug dbg, Dwarf_Die die,
+ int *pbit_size, int *pbit_offset, Dwarf_Error *perr) {
+ int rc;
+ rc = dwarf_get_attribute_value(dbg, die, DW_AT_bit_size,
+ pbit_size, perr);
+ if (rc) {
+ return rc;
+ }
+ return dwarf_get_attribute_value(dbg, die, DW_AT_bit_offset,
+ pbit_offset, perr);
+}
+
static int dwarf_get_size(Dwarf_Debug dbg, Dwarf_Die die,
int *psize, Dwarf_Error *perr) {
return dwarf_get_attribute_value(dbg, die, DW_AT_byte_size,
@@ -406,6 +418,7 @@ static void print_field(Dwarf_Debug dbg, Dwarf_Die die, const char *field_name,
char array_buf[128] = "";
char pointer_buf[128] = "";
int rc;
+ int bitfield_offset, bitfield_size = 0;
rc = dwarf_get_offset(dbg, die, &offset, &err);
if (rc == DW_DLV_NO_ENTRY) {
@@ -567,13 +580,41 @@ static void print_field(Dwarf_Debug dbg, Dwarf_Die die, const char *field_name,
}
}
- if (type_tag == DW_TAG_structure_type) {
+ if (type_tag == DW_TAG_base_type &&
+ dwarf_get_bitfield(dbg, die, &bitfield_size,
+ &bitfield_offset, &err) == DW_DLV_OK) {
+ int type_size;
+
+ rc = dwarf_get_size(dbg, die, &type_size, &err);
+ if (rc != DW_DLV_OK) {
+ fprintf(stderr,
+ "Could not get size for type for %s: %s\n",
+ field_name, dwarf_errmsg(err));
+ exit(7);
+ }
+
+ /* One subtlety of bitfields is that the order
+ * is reverse, e.g. the first bitfield will have
+ * an offset of type size - bitfield size
+ */
+ if (bitfield_size != type_size * 8 - bitfield_offset) {
+ snprintf(type_buf, 1024,
+ "%s bitfield_padding%d:%d\n\t\t\t%s %s",
+ type_name, padnum,
+ type_size * 8 - bitfield_offset - bitfield_size,
+ type_name, pointer_buf);
+ } else {
+ snprintf(type_buf, 1024, "%s %s", type_name,
+ pointer_buf);
+ }
+ snprintf(array_buf, 128, ":%d", bitfield_size);
+ } else if (type_tag == DW_TAG_structure_type) {
snprintf(type_buf, 1024, "struct %s %s",
type_name, pointer_buf);
} else if (type_tag == DW_TAG_base_type
|| type_tag == DW_TAG_typedef) {
snprintf(type_buf, 1024, "%s %s", type_name,
- pointer_buf);
+ pointer_buf);
} else if (type_tag == DW_TAG_pointer_type) {
snprintf(type_buf, 1024, "void %s", pointer_buf);
} else {