summaryrefslogtreecommitdiff
path: root/usr/src/lib/libctf/common/ctf_dwarf.c
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@fingolfin.org>2020-01-11 10:14:11 +0000
committerRobert Mustacchi <rm@fingolfin.org>2020-02-13 05:12:47 +0000
commit3df9f0641f28754051d5e82c6457527cf4af1258 (patch)
tree2004e72ac7bda03ce0df401c40c8e051d1c47f76 /usr/src/lib/libctf/common/ctf_dwarf.c
parent6d9e11ccb59a5d4ea2127e1791163333c4337a08 (diff)
downloadillumos-joyent-3df9f0641f28754051d5e82c6457527cf4af1258.tar.gz
12227 libctf incorrectly handles clang anonymous unions
Reviewed by: John Levon <john.levon@joyent.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/lib/libctf/common/ctf_dwarf.c')
-rw-r--r--usr/src/lib/libctf/common/ctf_dwarf.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/usr/src/lib/libctf/common/ctf_dwarf.c b/usr/src/lib/libctf/common/ctf_dwarf.c
index 1aa0f2e5e1..529195d296 100644
--- a/usr/src/lib/libctf/common/ctf_dwarf.c
+++ b/usr/src/lib/libctf/common/ctf_dwarf.c
@@ -1238,7 +1238,7 @@ ctf_dwarf_fixup_sou(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t base, boolean_t add)
return (ret);
if (tag != DW_TAG_member)
- continue;
+ goto next;
if ((ret = ctf_dwarf_refdie(cup, memb, DW_AT_type, &tdie)) != 0)
return (ret);
@@ -1373,12 +1373,39 @@ ctf_dwarf_create_sou(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp,
return (ret);
/*
- * Members are in children. However, gcc also allows empty ones.
+ * The children of a structure or union are generally members. However,
+ * some compilers actually insert structs and unions there and not as a
+ * top-level die. Therefore, to make sure we honor our pass 1 contract
+ * of having all the base types, but not members, we need to walk this
+ * for instances of a DW_TAG_union_type.
*/
if ((ret = ctf_dwarf_child(cup, die, &child)) != 0)
return (ret);
- if (child == NULL)
- return (0);
+
+ while (child != NULL) {
+ Dwarf_Half tag;
+ Dwarf_Die sib;
+
+ if ((ret = ctf_dwarf_tag(cup, child, &tag)) != 0)
+ return (ret);
+
+ switch (tag) {
+ case DW_TAG_union_type:
+ case DW_TAG_structure_type:
+ ret = ctf_dwarf_convert_type(cup, child, NULL,
+ CTF_ADD_NONROOT);
+ if (ret != 0) {
+ return (ret);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if ((ret = ctf_dwarf_sib(cup, child, &sib)) != 0)
+ return (ret);
+ child = sib;
+ }
return (0);
}