| // 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. |
| |
| #pragma once |
| |
| #include <string> |
| #include <vector> |
| |
| #include "garnet/bin/zxdb/symbols/lazy_symbol.h" |
| #include "lib/fxl/memory/ref_counted.h" |
| |
| namespace zxdb { |
| |
| class ArrayType; |
| class BaseType; |
| class CodeBlock; |
| class Collection; |
| class DataMember; |
| class Enumeration; |
| class Function; |
| class FunctionType; |
| class InheritedFrom; |
| class MemberPtr; |
| class ModifiedType; |
| class Namespace; |
| class Type; |
| class Value; |
| class Variable; |
| |
| // Represents the type of a variable. This is a deserialized version of the |
| // various DWARF DIE entries that define types. It is normally generated from |
| // a LazySymbol from a DIE reference. |
| class Symbol : public fxl::RefCountedThreadSafe<Symbol> { |
| public: |
| // Not a DWARF tag, this is used to indicate "not present." |
| static constexpr int kTagNone = 0x00; |
| |
| // Type modifier for arrays ("foo[]") of an underlying type. May have a |
| // SubrangeType child that indicates the size of the array. |
| static constexpr int kTagArrayType = 0x01; |
| |
| // C++ class definition. |
| static constexpr int kTagClassType = 0x02; |
| |
| // "Alternate entry point" to a function. Seems to be not generated. |
| static constexpr int kTagEntryPoint = 0x03; |
| |
| // C/C++ "enum" declaration. May have children of kTagEnumerator. |
| static constexpr int kTagEnumerationType = 0x04; |
| |
| // Normal function parameter, seen as a child of a "subprogram." It will |
| // normally have at least a name and a type. |
| static constexpr int kTagFormalParameter = 0x05; |
| |
| // Generated for "using" statements that bring a type into a namespace. |
| // Converted into a TypeModifier class. |
| static constexpr int kTagImportedDeclaration = 0x08; |
| |
| // Label (as used for "goto"). Probably don't need to handle. |
| static constexpr int kTagLabel = 0x0a; |
| |
| // A lexical block will typically have children of kTagVariable for |
| // everything declared in it. It will also often have ranges associated with |
| // it. |
| static constexpr int kTagLexicalBlock = 0x0b; |
| |
| // Class member data. |
| static constexpr int kTagMember = 0x0d; |
| |
| // Type modifier that indicates a pointer to an underlying type. |
| static constexpr int kTagPointerType = 0x0f; |
| |
| // Type modifier that indicates a reference to an underlying type. |
| static constexpr int kTagReferenceType = 0x10; |
| |
| static constexpr int kTagCompileUnit = 0x11; |
| |
| // Not used in C/C++ (they don't have a true primitive string type). |
| static constexpr int kTagStringType = 0x12; |
| |
| // C/C++ struct declaration. |
| static constexpr int kTagStructureType = 0x13; |
| |
| // Type for a C/C++ pointer to member function. See kTagPtrToMemberType. |
| static constexpr int kTagSubroutineType = 0x15; |
| |
| // Typedef that provides a different name for an underlying type. Converted |
| // into a TypeModifier class. |
| static constexpr int kTagTypedef = 0x16; |
| |
| static constexpr int kTagUnionType = 0x17; |
| |
| // Indicates a C/C++ parameter of "...". |
| static constexpr int kTagUnspecifiedParameters = 0x18; |
| |
| static constexpr int kTagVariant = 0x19; |
| |
| // Common block and common inclusion are used by Fortran. Can ignore. |
| static constexpr int kTagCommonBlock = 0x1a; |
| static constexpr int kTagCommonInclusion = 0x1b; |
| |
| // A member of a class or struct that indicates a type it inherits from. |
| static constexpr int kTagInheritance = 0x1c; |
| |
| // Child of a subroutine indicating a section of code that's from another |
| // subroutine that's been inlined. |
| static constexpr int kTagInlinedSubroutine = 0x1d; |
| |
| static constexpr int kTagModule = 0x1e; |
| |
| // C++ Foo::* type. See kTagSubroutineType. |
| static constexpr int kTagPtrToMemberType = 0x1f; |
| |
| // Used by Pascal. Can ignore. |
| static constexpr int kTagSetType = 0x20; |
| |
| // In C++ this can be generated as the child of an array entry with a "type" |
| // of "__ARRAY_SIZE_TYPE__" and a "count" indicating the size of the array. |
| static constexpr int kTagSubrangeType = 0x21; |
| |
| // Pascal and Modula-2 "with" statement. Can ignore. |
| static constexpr int kTagWithStmt = 0x22; |
| |
| // C++ "public", "private", "protected". Seems to not be generated. |
| static constexpr int kTagAccessDeclaration = 0x23; |
| |
| // Declaration of a built-in compiler base type like an "int". |
| static constexpr int kTagBaseType = 0x24; |
| |
| static constexpr int kTagCatchBlock = 0x25; |
| |
| // Type modifier that adds "const". |
| static constexpr int kTagConstType = 0x26; |
| |
| // Named constant. |
| static constexpr int kTagConstant = 0x27; |
| |
| // Member of an enumeration. Will be a child of an EnumerationType entry. |
| static constexpr int kTagEnumerator = 0x28; |
| |
| static constexpr int kTagFileType = 0x29; |
| |
| // C++ "friend" declaration. Seems to not be generated. |
| static constexpr int kTagFriend = 0x2a; |
| |
| // Namelists are used in Fortran 90. Can ignore. |
| static constexpr int kTagNamelist = 0x2b; |
| static constexpr int kTagNamelistItem = 0x2c; |
| |
| // Packed types are used only by Pascal and ADA. Can ignore. |
| static constexpr int kTagPackedType = 0x2d; |
| |
| // A function. Represented by a zxdb::Function object. |
| static constexpr int kTagSubprogram = 0x2e; |
| static constexpr int kTagTemplateTypeParameter = 0x2f; |
| static constexpr int kTagTemplateValueParameter = 0x30; |
| static constexpr int kTagThrownType = 0x31; |
| static constexpr int kTagTryBlock = 0x32; |
| static constexpr int kTagVariantPart = 0x33; |
| |
| // Local variable declaration. It will normally have a name, type, |
| // declaration location, and location. |
| static constexpr int kTagVariable = 0x34; |
| |
| // Type modifier that indicates adding "volatile" to an underlying type. |
| static constexpr int kTagVolatileType = 0x35; |
| static constexpr int kTagDwarfProcedure = 0x36; |
| |
| // Type modifier that indicates a C99 "restrict" qualifier on an underlying |
| // type. |
| static constexpr int kTagRestrictType = 0x37; |
| |
| // Java interface. Can ignore. |
| static constexpr int kTagInterfaceType = 0x38; |
| |
| // C++ namespace. The declarations inside this will be the contents of the |
| // namespace. This will be around declarations but not necessarily the |
| // function implementations. |
| static constexpr int kTagNamespace = 0x39; |
| |
| // Seems to be generated for "using namespace" statements. |
| static constexpr int kTagImportedModule = 0x3a; |
| |
| // Used in our toolchain for "decltype(nullptr)". |
| static constexpr int kTagUnspecifiedType = 0x3b; |
| |
| static constexpr int kTagPartialUnit = 0x3c; |
| static constexpr int kTagImportedUnit = 0x3d; |
| |
| // "If" statement. Seems to not be generated by our toolchain. |
| static constexpr int kTagCondition = 0x3f; |
| |
| // Used by the "UPC" language. Can ignore. |
| static constexpr int kTagSharedType = 0x40; |
| |
| // Seems to not be generated by our toolchain. |
| static constexpr int kTagTypeUnit = 0x41; |
| |
| // Type modifier that indicates an rvalue reference to an underlying type. |
| static constexpr int kTagRvalueReferenceType = 0x42; |
| static constexpr int kTagTemplateAlias = 0x43; |
| |
| // User-defined range. |
| static constexpr int kTagLoUser = 0x4080; |
| static constexpr int kTagHiUser = 0xffff; |
| |
| // One of kTag* constants above, or something totally different (depending |
| // on what's in the symbol file). |
| int tag() const { return tag_; } |
| |
| // The parent symbol. This could be many things. For inlined subroutines |
| // or lexical blocks, it could be an inlined subroutine, a lexical block, |
| // or a function. For a function it could be a class, namespace, or |
| // the top-level compilation unit. |
| // |
| // In the case of function implementations with separate definitions, the |
| // decoder will set the parent symbol to be the parent scope around |
| // the definition, which is how one will discover classes and namespaces |
| // that the function is in. This is what callers normally want, but it means |
| // that the parent symbol isn't necessarily the physical parent of the |
| // DIE that generated this symbol. |
| const LazySymbol& parent() const { return parent_; } |
| void set_parent(const LazySymbol& e) { parent_ = e; } |
| |
| // Returns the name associated with this symbol. This name comes from the |
| // corresponding record in the DWARF format (hence "assigned"). It will NOT |
| // include namespace and struct qualifiers. Anything without a name assigned |
| // on the particular DWARF record name will return an empty string, even if |
| // that thing logically has a name that can be computed (as for |
| // ModifiedType). |
| // |
| // This default implementation returns a reference to an empty string. |
| // Derived classes will override as needed. |
| // |
| // Most callers will want to use GetFullName(). |
| virtual const std::string& GetAssignedName() const; |
| |
| // Returns the fully-qualified user-visible name for this symbol. This will |
| // include all namespace and struct qualifications. |
| // |
| // This implements caching. Derived classes override ComputeFullName() to |
| // control how the full name is presented. |
| const std::string& GetFullName() const; |
| |
| // Manual RTTI. |
| virtual const ArrayType* AsArrayType() const; |
| virtual const BaseType* AsBaseType() const; |
| virtual const CodeBlock* AsCodeBlock() const; |
| virtual const DataMember* AsDataMember() const; |
| virtual const Enumeration* AsEnumeration() const; |
| virtual const Function* AsFunction() const; |
| virtual const FunctionType* AsFunctionType() const; |
| virtual const InheritedFrom* AsInheritedFrom() const; |
| virtual const MemberPtr* AsMemberPtr() const; |
| virtual const ModifiedType* AsModifiedType() const; |
| virtual const Namespace* AsNamespace() const; |
| virtual const Collection* AsCollection() const; |
| virtual const Type* AsType() const; |
| virtual const Value* AsValue() const; |
| virtual const Variable* AsVariable() const; |
| |
| // Non-const manual RTTI wrappers. |
| ArrayType* AsArrayType() { |
| return const_cast<ArrayType*>( |
| const_cast<const Symbol*>(this)->AsArrayType()); |
| } |
| BaseType* AsBaseType() { |
| return const_cast<BaseType*>(const_cast<const Symbol*>(this)->AsBaseType()); |
| } |
| CodeBlock* AsCodeBlock() { |
| return const_cast<CodeBlock*>( |
| const_cast<const Symbol*>(this)->AsCodeBlock()); |
| } |
| DataMember* AsDataMember() { |
| return const_cast<DataMember*>( |
| const_cast<const Symbol*>(this)->AsDataMember()); |
| } |
| Enumeration* AsEnumeration() { |
| return const_cast<Enumeration*>( |
| const_cast<const Symbol*>(this)->AsEnumeration()); |
| } |
| Function* AsFunction() { |
| return const_cast<Function*>(const_cast<const Symbol*>(this)->AsFunction()); |
| } |
| FunctionType* AsFunctionType() { |
| return const_cast<FunctionType*>( |
| const_cast<const Symbol*>(this)->AsFunctionType()); |
| } |
| InheritedFrom* AsInheritedFrom() { |
| return const_cast<InheritedFrom*>( |
| const_cast<const Symbol*>(this)->AsInheritedFrom()); |
| } |
| MemberPtr* AsMemberPtr() { |
| return const_cast<MemberPtr*>( |
| const_cast<const Symbol*>(this)->AsMemberPtr()); |
| } |
| ModifiedType* AsModifiedType() { |
| return const_cast<ModifiedType*>( |
| const_cast<const Symbol*>(this)->AsModifiedType()); |
| } |
| Namespace* AsNamespace() { |
| return const_cast<Namespace*>( |
| const_cast<const Symbol*>(this)->AsNamespace()); |
| } |
| Collection* AsCollection() { |
| return const_cast<Collection*>( |
| const_cast<const Symbol*>(this)->AsCollection()); |
| } |
| Type* AsType() { |
| return const_cast<Type*>(const_cast<const Symbol*>(this)->AsType()); |
| } |
| Value* AsValue() { |
| return const_cast<Value*>(const_cast<const Symbol*>(this)->AsValue()); |
| } |
| Variable* AsVariable() { |
| return const_cast<Variable*>(const_cast<const Symbol*>(this)->AsVariable()); |
| } |
| |
| protected: |
| FRIEND_REF_COUNTED_THREAD_SAFE(Symbol); |
| FRIEND_MAKE_REF_COUNTED(Symbol); |
| |
| // Construct via fxl::MakeRefCounted. |
| Symbol(); |
| explicit Symbol(int tag); |
| virtual ~Symbol(); |
| |
| // Computes the full name. Used by GetFullName() which adds a caching layer. |
| // Derived classes should override this to control how the name is presented. |
| // This implementation returns the scope prefix (namespaces, structs) + |
| // assigned name. |
| virtual std::string ComputeFullName() const; |
| |
| private: |
| int tag_ = kTagNone; |
| |
| LazySymbol parent_; |
| |
| // Lazily computed full symbol name. |
| // TODO(brettw) use std::optional when we can use C++17. |
| mutable bool computed_full_name_ = false; |
| mutable std::string full_name_; |
| }; |
| |
| } // namespace zxdb |