summaryrefslogtreecommitdiffstats
path: root/cddl
diff options
context:
space:
mode:
authorkaiw <kaiw@FreeBSD.org>2014-01-20 01:35:14 +0000
committerkaiw <kaiw@FreeBSD.org>2014-01-20 01:35:14 +0000
commitcb3a8568bd4e3f2bf20a1c342c6957d1a568a5df (patch)
tree0161ffedd29f7d6a703f7ef5caf630097481c8fc /cddl
parent9ccc946cdb76c29bc6ec126ee139bdc025baf0a3 (diff)
downloadFreeBSD-src-cb3a8568bd4e3f2bf20a1c342c6957d1a568a5df.zip
FreeBSD-src-cb3a8568bd4e3f2bf20a1c342c6957d1a568a5df.tar.gz
Clang 3.4 will sometimes emit DIE for struct/union member before
emitting the DIE for the type of that member. ctfconvert can not handle this properly and will calculate a wrong member bit offset. Same struct/union type from different .o file will be treated as different types when their member bit offsets are different, and gets added/merged multiple times. This will in turn cause many other structs/pointers/typedefs that refer to the duplicated struct/union gets added/merged multiple times and eventually causes numerous duplicated CTF types in the kernel.debug file. The simple workaround here is to make use of DW_AT_byte_size attribute of the member DIE to calculate the bits occupied by the member's type, without actually resolving the type.
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
index 8725f15..15060f3 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
@@ -938,7 +938,7 @@ static void
die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
int type, const char *typename)
{
- Dwarf_Unsigned sz, bitsz, bitoff, maxsz=0;
+ Dwarf_Unsigned sz, bysz, bitsz, bitoff, maxsz=0;
Dwarf_Die mem;
mlist_t *ml, **mlastp;
iidesc_t *ii;
@@ -1013,8 +1013,26 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
#if BYTE_ORDER == _BIG_ENDIAN
ml->ml_offset += bitoff;
#else
- ml->ml_offset += tdesc_bitsize(ml->ml_type) - bitoff -
- ml->ml_size;
+ /*
+ * Note that Clang 3.4 will sometimes generate
+ * member DIE before generating the DIE for the
+ * member's type. The code can not handle this
+ * properly so that tdesc_bitsize(ml->ml_type) will
+ * return 0 because ml->ml_type is unknown. As a
+ * result, a wrong member offset will be calculated.
+ * To workaround this, we can instead try to
+ * retrieve the value of DW_AT_byte_size attribute
+ * which stores the byte size of the space occupied
+ * by the type. If this attribute exists, its value
+ * should equal to tdesc_bitsize(ml->ml_type)/NBBY.
+ */
+ if (die_unsigned(dw, mem, DW_AT_byte_size, &bysz, 0) &&
+ bysz > 0)
+ ml->ml_offset += bysz * NBBY - bitoff -
+ ml->ml_size;
+ else
+ ml->ml_offset += tdesc_bitsize(ml->ml_type) -
+ bitoff - ml->ml_size;
#endif
}
OpenPOWER on IntegriCloud