| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/developer/debug/zxdb/symbols/collection.h" |
| |
| #include "src/developer/debug/zxdb/symbols/compile_unit.h" |
| #include "src/developer/debug/zxdb/symbols/data_member.h" |
| #include "src/developer/debug/zxdb/symbols/symbol_utils.h" |
| #include "src/lib/fxl/strings/string_printf.h" |
| |
| namespace zxdb { |
| |
| Collection::Collection(DwarfTag tag, std::string name) : Type(tag) { |
| set_assigned_name(std::move(name)); |
| } |
| |
| Collection::~Collection() = default; |
| |
| const char* Collection::CallingConventionToString(CallingConvention cc) { |
| switch (cc) { |
| case kNormalCall: |
| return "DW_CC_normal"; |
| case kPassByReference: |
| return "DW_CC_pass_by_reference"; |
| case kPassByValue: |
| return "DW_CC_pass_by_value"; |
| } |
| return "<invalid>"; |
| } |
| |
| const Collection* Collection::AsCollection() const { return this; } |
| |
| Collection::SpecialType Collection::GetSpecialType() const { |
| if (!special_type_) |
| special_type_ = ComputeSpecialType(); |
| return *special_type_; |
| } |
| |
| const char* Collection::GetKindString() const { |
| switch (tag()) { |
| case DwarfTag::kStructureType: |
| return "struct"; |
| case DwarfTag::kClassType: |
| return "class"; |
| case DwarfTag::kUnionType: |
| return "union"; |
| default: |
| return "unknown"; |
| } |
| } |
| |
| Identifier Collection::ComputeIdentifier() const { |
| Identifier result = GetSymbolScopePrefix(this); |
| |
| if (auto& assigned_name = GetAssignedName(); !assigned_name.empty()) { |
| result.AppendComponent(IdentifierComponent(assigned_name)); |
| } else { |
| // Provide a name for anonymous structs. |
| result.AppendComponent(IdentifierComponent(fxl::StringPrintf("(anon %s)", GetKindString()))); |
| } |
| return result; |
| } |
| |
| Collection::SpecialType Collection::ComputeSpecialType() const { |
| // All the special types use "structure" as their tag. |
| if (tag() != DwarfTag::kStructureType) |
| return kNotSpecial; |
| |
| // As of this writing the language is slower to check because it involves |
| // decoding the CompileUnit which is not normally otherwise needed. As a |
| // result we try to check that last. |
| |
| if (variant_part_) { |
| // Having a variant part and no members currently means we consider it a |
| // Rust enum. This may need to be enhanced for fxbug.dev/6466 (support Rust |
| // generators). |
| // |
| // No other special types have variants. |
| if (data_members_.empty() && GetLanguage() == DwarfLang::kRust) |
| return kRustEnum; |
| return kNotSpecial; |
| } |
| |
| // Everything below requires at least one member. |
| if (data_members_.empty()) |
| return kNotSpecial; |
| |
| // Here we're checking for the two types of Rust tuples, regular tuples and |
| // tuple structs. Prefer to decode the first data member (it's very likely to |
| // be needed later no matter what) before the language. |
| // |
| // Tuples have members labeled starting counting from 0 with two leading |
| // underscores: __0, __1, __2, etc. With this heuristic we assume they're |
| // encoded in order in the symbols and that __0 will be first. Currently |
| // we check only the first one but this could be more precise (if slower) |
| // by checking to make sure all members are such numbers in sequential order. |
| const DataMember* first_member = data_members_[0].Get()->As<DataMember>(); |
| if (!first_member) |
| return kNotSpecial; |
| |
| if (first_member->GetAssignedName() != "__0") |
| return kNotSpecial; |
| |
| // Now that we're pretty sure this looks like some kind of Rust tuple, double |
| // check the language. |
| if (GetLanguage() != DwarfLang::kRust) |
| return kNotSpecial; |
| |
| // Either type of Rust tuple. Regular types are assigned names like |
| // "(i32, i32)" while struct tuples have regular names. Use the assigned name |
| // and not the full name because we don't want any namespace qualifications. |
| const std::string& assigned_name = GetAssignedName(); |
| if (assigned_name.size() > 2 && assigned_name[0] == '(' && assigned_name.back() == ')') |
| return kRustTuple; |
| return kRustTupleStruct; |
| } |
| |
| } // namespace zxdb |