aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuliano Procida <gprocida@google.com>2024-05-14 17:00:46 +0100
committerGiuliano Procida <gprocida@google.com>2024-05-14 17:00:46 +0100
commit120708097f00900e4582becaae61bea313be1aaf (patch)
tree11fb9f7f0397a182b6218ec2ffd4d37621262996
parent6007ac729006c2bb7b38a31a816e30572f46f07d (diff)
parentf82154992367ecb47f469c071bec6b979277e3ef (diff)
downloadstg-main.tar.gz
Merge branch 'upstream-main' into 'main'HEADmastermain
* aosp/upstream-main: DWARF processor: handle DW_TAG_GNU_formal_parameter_pack DIEs rust: delegate DWARF processing for `variant_part` to variant DWARF processor rust: add DWARF processor for `Variant` node rust: add DWARF processor for `VariantMember` nodes Signed-off-by: Giuliano Procida <gprocida@google.com> Change-Id: I0d3cf9167a0c6edc43f4a8c60bb428d9ea602bab
-rw-r--r--dwarf_processor.cc111
-rw-r--r--test_cases/info_tests/variant/expected/negative_discriminant_rs.elf_stg75
-rw-r--r--test_cases/info_tests/variant/expected/simple_rs.elf_stg108
3 files changed, 280 insertions, 14 deletions
diff --git a/dwarf_processor.cc b/dwarf_processor.cc
index 9e84971..9955b82 100644
--- a/dwarf_processor.cc
+++ b/dwarf_processor.cc
@@ -496,6 +496,7 @@ class Processor {
std::vector<Id> base_classes;
std::vector<Id> members;
std::vector<Id> methods;
+ std::optional<VariantAndMembers> variant_and_members = std::nullopt;
for (auto& child : entry.GetChildren()) {
auto child_tag = child.GetTag();
@@ -550,7 +551,11 @@ class Processor {
// properly (resulting in no references to such DIEs).
break;
case DW_TAG_variant_part:
- // TODO: Add a DWARF processor to process variants.
+ if (full_name.empty()) {
+ Die() << "Variant name should not be empty: "
+ << EntryToString(entry);
+ }
+ variant_and_members = GetVariantAndMembers(child);
break;
default:
Die() << "Unexpected tag for child of struct/class/union: "
@@ -558,6 +563,17 @@ class Processor {
}
}
+ if (variant_and_members.has_value()) {
+ // Add a Variant node since this entry represents a variant rather than a
+ // struct or union.
+ const Id id =
+ AddProcessedNode<Variant>(entry, full_name, GetByteSize(entry),
+ variant_and_members->discriminant_type_id,
+ std::move(variant_and_members->members));
+ AddNamedTypeNode(id);
+ return;
+ }
+
if (entry.GetFlag(DW_AT_declaration) ||
!ShouldKeepDefinition(entry, type_name)) {
// Declaration may have partial information about members or method.
@@ -577,6 +593,37 @@ class Processor {
}
}
+ void ProcessVariantMember(Entry& entry) {
+ // TODO: Process signed discriminant values.
+ auto dw_discriminant_value =
+ entry.MaybeGetUnsignedConstant(DW_AT_discr_value);
+ auto discriminant_value =
+ dw_discriminant_value
+ ? std::optional(static_cast<int64_t>(*dw_discriminant_value))
+ : std::nullopt;
+
+ auto children = entry.GetChildren();
+ if (children.size() != 1) {
+ Die() << "Unexpected number of children for variant member: "
+ << EntryToString(entry);
+ }
+
+ auto child = children[0];
+ if (child.GetTag() != DW_TAG_member) {
+ Die() << "Unexpected tag for variant member child: "
+ << Hex(child.GetTag()) << ", " << EntryToString(child);
+ }
+ if (GetDataBitOffset(child, 0, is_little_endian_binary_) != 0) {
+ Die() << "Unexpected data member location for variant member: "
+ << EntryToString(child);
+ }
+
+ const std::string name = GetNameOrEmpty(child);
+ auto referred_type_id = GetReferredTypeId(GetReferredType(child));
+ AddProcessedNode<VariantMember>(entry, name, discriminant_value,
+ referred_type_id);
+ }
+
void ProcessMember(Entry& entry) {
const auto name = GetNameOrEmpty(entry);
auto referred_type = GetReferredType(entry);
@@ -726,6 +773,56 @@ class Processor {
}
}
+ struct VariantAndMembers {
+ Id discriminant_type_id;
+ std::vector<Id> members;
+ };
+
+ VariantAndMembers GetVariantAndMembers(Entry& entry) {
+ std::vector<Id> members;
+ std::optional<Id> discriminant_type_id = std::nullopt;
+ auto discriminant_entry = entry.MaybeGetReference(DW_AT_discr);
+ if (!discriminant_entry.has_value()) {
+ Die() << "Variant must have a discriminant: " << EntryToString(entry);
+ }
+
+ for (auto& child : entry.GetChildren()) {
+ auto child_tag = child.GetTag();
+ switch (child_tag) {
+ case DW_TAG_member: {
+ if (child.GetOffset() != discriminant_entry->GetOffset()) {
+ Die() << "Encountered unexpected member for variant: "
+ << EntryToString(entry);
+ }
+ discriminant_type_id = GetReferredTypeId(GetReferredType(child));
+ if (GetDataBitOffset(child, 0, is_little_endian_binary_) != 0) {
+ Die() << "Unexpected member location for variant discriminant: "
+ << EntryToString(child);
+ }
+ if (!child.GetFlag(DW_AT_artificial)) {
+ Die() << "Variant discriminant must be an artificial member: "
+ << EntryToString(child);
+ }
+ break;
+ }
+ case DW_TAG_variant:
+ members.push_back(GetIdForEntry(child));
+ ProcessVariantMember(child);
+ break;
+ default:
+ Die() << "Unexpected tag for child of variant: " << Hex(child_tag)
+ << ", " << EntryToString(child);
+ }
+ }
+
+ if (!discriminant_type_id.has_value()) {
+ Die() << "No discriminant member found for variant: "
+ << EntryToString(entry);
+ }
+ return VariantAndMembers{.discriminant_type_id = *discriminant_type_id,
+ .members = std::move(members)};
+ }
+
struct NameWithContext {
std::optional<Dwarf_Off> specification;
std::optional<std::string> unscoped_name;
@@ -901,10 +998,20 @@ class Processor {
case DW_TAG_template_value_parameter:
case DW_TAG_GNU_template_template_param:
case DW_TAG_GNU_template_parameter_pack:
- case DW_TAG_GNU_formal_parameter_pack:
// We just skip these as neither GCC nor Clang seem to use them
// properly (resulting in no references to such DIEs).
break;
+ case DW_TAG_GNU_formal_parameter_pack:
+ // https://wiki.dwarfstd.org/C++0x_Variadic_templates.md
+ //
+ // As per this (rejected) proposal, GCC includes parameters as
+ // children of this DIE.
+ for (auto& child2 : child.GetChildren()) {
+ if (child2.GetTag() == DW_TAG_formal_parameter) {
+ parameters.push_back(GetReferredTypeId(GetReferredType(child2)));
+ }
+ }
+ break;
default:
Die() << "Unexpected tag for child of function: " << Hex(child_tag)
<< ", " << EntryToString(child);
diff --git a/test_cases/info_tests/variant/expected/negative_discriminant_rs.elf_stg b/test_cases/info_tests/variant/expected/negative_discriminant_rs.elf_stg
index debfaf8..748f73e 100644
--- a/test_cases/info_tests/variant/expected/negative_discriminant_rs.elf_stg
+++ b/test_cases/info_tests/variant/expected/negative_discriminant_rs.elf_stg
@@ -6,28 +6,91 @@ primitive {
encoding: BOOLEAN
bytesize: 0x00000001
}
+primitive {
+ id: 0xd4bacb77
+ name: "u32"
+ encoding: UNSIGNED_INTEGER
+ bytesize: 0x00000004
+}
+primitive {
+ id: 0xedc43a15
+ name: "i64"
+ encoding: SIGNED_INTEGER
+ bytesize: 0x00000008
+}
+member {
+ id: 0x976dcda7
+ name: "__0"
+ type_id: 0xd4bacb77 # u32
+ offset: 64
+}
+variant_member {
+ id: 0x72c55dce
+ name: "MinusTwo"
+ discriminant_value: 65534
+ type_id: 0xc8fb9972
+}
+variant_member {
+ id: 0x528ee922
+ name: "MinusOne"
+ discriminant_value: 65535
+ type_id: 0xdfc84a58
+}
+variant_member {
+ id: 0x27839c0b
+ name: "Zero"
+ discriminant_value: 0
+ type_id: 0x5da8c8f1
+}
struct_union {
- id: 0x7a8d8645
+ id: 0xdfc84a58
kind: STRUCT
- name: "negative_discriminant::Foo"
+ name: "negative_discriminant::Foo::MinusOne"
definition {
bytesize: 16
}
}
+struct_union {
+ id: 0xc8fb9972
+ kind: STRUCT
+ name: "negative_discriminant::Foo::MinusTwo"
+ definition {
+ bytesize: 16
+ member_id: 0x976dcda7 # u32 __0
+ }
+}
+struct_union {
+ id: 0x5da8c8f1
+ kind: STRUCT
+ name: "negative_discriminant::Foo::Zero"
+ definition {
+ bytesize: 16
+ member_id: 0x976dcda7 # u32 __0
+ }
+}
+variant {
+ id: 0x29673df8
+ name: "negative_discriminant::Foo"
+ bytesize: 16
+ discriminant_type_id: 0xedc43a15
+ member_id: 0x72c55dce
+ member_id: 0x528ee922
+ member_id: 0x27839c0b
+}
function {
- id: 0xa0f30a2f
+ id: 0xb409a4c0
return_type_id: 0x62aebfd4 # bool
- parameter_id: 0x7a8d8645 # struct negative_discriminant::Foo
+ parameter_id: 0x29673df8 # variant negative_discriminant::Foo
}
elf_symbol {
id: 0x0f95dadc
name: "is_minus_one"
is_defined: true
symbol_type: FUNCTION
- type_id: 0xa0f30a2f # bool(struct negative_discriminant::Foo)
+ type_id: 0xb409a4c0 # bool(variant negative_discriminant::Foo)
full_name: "negative_discriminant::is_minus_one"
}
interface {
id: 0x84ea5130
- symbol_id: 0x0f95dadc # bool negative_discriminant::is_minus_one(struct negative_discriminant::Foo)
+ symbol_id: 0x0f95dadc # bool negative_discriminant::is_minus_one(variant negative_discriminant::Foo)
}
diff --git a/test_cases/info_tests/variant/expected/simple_rs.elf_stg b/test_cases/info_tests/variant/expected/simple_rs.elf_stg
index 4621cf8..0d051aa 100644
--- a/test_cases/info_tests/variant/expected/simple_rs.elf_stg
+++ b/test_cases/info_tests/variant/expected/simple_rs.elf_stg
@@ -1,33 +1,129 @@
version: 0x00000002
root_id: 0x84ea5130 # interface
primitive {
+ id: 0x2d2f93e0
+ name: "u8"
+ encoding: UNSIGNED_INTEGER
+ bytesize: 0x00000001
+}
+primitive {
+ id: 0x47ea5d8b
+ name: "i16"
+ encoding: SIGNED_INTEGER
+ bytesize: 0x00000002
+}
+primitive {
id: 0x62aebfd4
name: "bool"
encoding: BOOLEAN
bytesize: 0x00000001
}
+primitive {
+ id: 0xd4bacb77
+ name: "u32"
+ encoding: UNSIGNED_INTEGER
+ bytesize: 0x00000004
+}
+member {
+ id: 0x976dc47d
+ name: "__0"
+ type_id: 0xd4bacb77 # u32
+ offset: 32
+}
+member {
+ id: 0xdb2c3143
+ name: "__1"
+ type_id: 0xd4bacb77 # u32
+ offset: 64
+}
+member {
+ id: 0xa0f58f35
+ name: "x"
+ type_id: 0x47ea5d8b # i16
+ offset: 16
+}
+member {
+ id: 0xff34ede2
+ name: "y"
+ type_id: 0x47ea5d8b # i16
+ offset: 32
+}
+member {
+ id: 0x2172932a
+ name: "z"
+ type_id: 0x47ea5d8b # i16
+ offset: 48
+}
+variant_member {
+ id: 0xfc632c0e
+ name: "Unit"
+ discriminant_value: 0
+ type_id: 0x624786fb
+}
+variant_member {
+ id: 0xad130615
+ name: "TwoU32s"
+ discriminant_value: 1
+ type_id: 0x117f6853
+}
+variant_member {
+ id: 0xc48d72bf
+ name: "ThreeI16s"
+ discriminant_value: 2
+ type_id: 0x0e0db07a
+}
struct_union {
- id: 0x176387ba
+ id: 0x0e0db07a
kind: STRUCT
- name: "simple::Foo"
+ name: "simple::Foo::ThreeI16s"
+ definition {
+ bytesize: 12
+ member_id: 0xa0f58f35 # i16 x
+ member_id: 0xff34ede2 # i16 y
+ member_id: 0x2172932a # i16 z
+ }
+}
+struct_union {
+ id: 0x117f6853
+ kind: STRUCT
+ name: "simple::Foo::TwoU32s"
definition {
bytesize: 12
+ member_id: 0x976dc47d # u32 __0
+ member_id: 0xdb2c3143 # u32 __1
}
}
+struct_union {
+ id: 0x624786fb
+ kind: STRUCT
+ name: "simple::Foo::Unit"
+ definition {
+ bytesize: 12
+ }
+}
+variant {
+ id: 0x15514ee1
+ name: "simple::Foo"
+ bytesize: 12
+ discriminant_type_id: 0x2d2f93e0
+ member_id: 0xfc632c0e
+ member_id: 0xad130615
+ member_id: 0xc48d72bf
+}
function {
- id: 0xbb888a50
+ id: 0xbb043806
return_type_id: 0x62aebfd4 # bool
- parameter_id: 0x176387ba # struct simple::Foo
+ parameter_id: 0x15514ee1 # variant simple::Foo
}
elf_symbol {
id: 0x4e2f2fc8
name: "is_unit"
is_defined: true
symbol_type: FUNCTION
- type_id: 0xbb888a50 # bool(struct simple::Foo)
+ type_id: 0xbb043806 # bool(variant simple::Foo)
full_name: "simple::is_unit"
}
interface {
id: 0x84ea5130
- symbol_id: 0x4e2f2fc8 # bool simple::is_unit(struct simple::Foo)
+ symbol_id: 0x4e2f2fc8 # bool simple::is_unit(variant simple::Foo)
}