diff options
author | Dominique Martinet <asmadeus@codewreck.org> | 2018-08-23 14:35:09 +0900 |
---|---|---|
committer | Dominique Martinet <asmadeus@codewreck.org> | 2018-08-23 14:35:09 +0900 |
commit | 4921edf53d4dd38f1615401216d7deddae978ae1 (patch) | |
tree | 65d62f8141cbc3cb242da3cafff91f2868e45043 | |
parent | 93915e5d8eb3f0dc6faa4e7a691aceca6c1e861a (diff) |
-rw-r--r-- | dwarf-extract-struct.c | 45 |
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 { |