gollvm: enhance llvm-godumpspec handling of bitfields
Rework the code that detects bitfields in structures, which was
insufficiently flexible relative to recent changes in the DWARF
emitted by clang/gcc. In particular:
- handle both the legacy DW_AT_bit_offset and the more recent
DW_AT_data_bit_offset
- fall back on the underlying type ref to determine the byte size for
a field if DW_AT_byte_size is not present (the most recent version
of GCC has started to leave it out).
Change-Id: Ibad3f3d575c06babcdb760e2e5f5623e8b45e59b
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/290672
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Trust: Than McIntosh <thanm@google.com>
diff --git a/libgo/godumpspec/godumpspec.cpp b/libgo/godumpspec/godumpspec.cpp
index c802ac1..4abf442 100644
--- a/libgo/godumpspec/godumpspec.cpp
+++ b/libgo/godumpspec/godumpspec.cpp
@@ -772,20 +772,39 @@
return rval;
}
+// isBitField returns TRUE if a given member or field is a bitfield.
+//
+// Notes:
+// - some compilers emit DW_AT_bit_offset for bitfields and others use the
+// more recent DW_AT_data_bit_offset; we need to handle both.
+// - older versions of GCC emit DW_AT_byte_size for all fields; newer
+// versions leave this out (presumably assuming that the size can be
+// derived from the underlying type). Use the byte size attribute if
+// present, otherwise fall back on the type ref.
bool GoDumpHelper::isBitField(const DWARFDie &die)
{
auto bitSize = die.find(dwarf::DW_AT_bit_size);
if (!bitSize)
return false;
+ uint64_t tsz = 0;
auto byteSize = die.find(dwarf::DW_AT_byte_size);
- auto bitOffset = die.find(dwarf::DW_AT_bit_offset);
- assert(bitSize && bitOffset);
- auto byval = byteSize->getAsUnsignedConstant();
+ if (!byteSize) {
+ tsz = typeOfSize(die);
+ } else {
+ auto byval = byteSize->getAsUnsignedConstant();
+ assert(byval);
+ tsz = *byval;
+ }
+ auto bitOffset = die.find(dwarf::DW_AT_data_bit_offset);
+ if (!bitOffset) {
+ bitOffset = die.find(dwarf::DW_AT_bit_offset);
+ }
+ assert(bitOffset);
auto bsval = bitSize->getAsUnsignedConstant();
auto boval = bitOffset->getAsUnsignedConstant();
- assert(byval && bsval && boval);
+ assert(bsval && boval);
if (*boval % *bsval == 0 &&
- *bsval % *byval == 0 &&
+ *bsval % tsz == 0 &&
(*bsval == 8 || *bsval == 16 || *bsval == 32 || *bsval == 64))
return false;
return true;