| //===-- Symbol.h ------------------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLDB_SYMBOL_SYMBOL_H |
| #define LLDB_SYMBOL_SYMBOL_H |
| |
| #include "lldb/Core/AddressRange.h" |
| #include "lldb/Core/Mangled.h" |
| #include "lldb/Symbol/SymbolContextScope.h" |
| #include "lldb/Utility/UserID.h" |
| #include "lldb/lldb-private.h" |
| |
| namespace lldb_private { |
| |
| class Symbol : public SymbolContextScope { |
| public: |
| // ObjectFile readers can classify their symbol table entries and searches |
| // can be made on specific types where the symbol values will have |
| // drastically different meanings and sorting requirements. |
| Symbol(); |
| |
| Symbol(uint32_t symID, llvm::StringRef name, lldb::SymbolType type, |
| bool external, bool is_debug, bool is_trampoline, bool is_artificial, |
| const lldb::SectionSP §ion_sp, lldb::addr_t value, |
| lldb::addr_t size, bool size_is_valid, |
| bool contains_linker_annotations, uint32_t flags); |
| |
| Symbol(uint32_t symID, const Mangled &mangled, lldb::SymbolType type, |
| bool external, bool is_debug, bool is_trampoline, bool is_artificial, |
| const AddressRange &range, bool size_is_valid, |
| bool contains_linker_annotations, uint32_t flags); |
| |
| Symbol(const Symbol &rhs); |
| |
| const Symbol &operator=(const Symbol &rhs); |
| |
| void Clear(); |
| |
| bool Compare(ConstString name, lldb::SymbolType type) const; |
| |
| void Dump(Stream *s, Target *target, uint32_t index, |
| Mangled::NamePreference name_preference = |
| Mangled::ePreferDemangled) const; |
| |
| bool ValueIsAddress() const; |
| |
| // The GetAddressRef() accessor functions should only be called if you |
| // previously call ValueIsAddress() otherwise you might get an reference to |
| // an Address object that contains an constant integer value in |
| // m_addr_range.m_base_addr.m_offset which could be incorrectly used to |
| // represent an absolute address since it has no section. |
| Address &GetAddressRef() { return m_addr_range.GetBaseAddress(); } |
| |
| const Address &GetAddressRef() const { return m_addr_range.GetBaseAddress(); } |
| |
| // Makes sure the symbol's value is an address and returns the file address. |
| // Returns LLDB_INVALID_ADDRESS if the symbol's value isn't an address. |
| lldb::addr_t GetFileAddress() const; |
| |
| // Makes sure the symbol's value is an address and gets the load address |
| // using \a target if it is. Returns LLDB_INVALID_ADDRESS if the symbol's |
| // value isn't an address or if the section isn't loaded in \a target. |
| lldb::addr_t GetLoadAddress(Target *target) const; |
| |
| // Access the address value. Do NOT hand out the AddressRange as an object as |
| // the byte size of the address range may not be filled in and it should be |
| // accessed via GetByteSize(). |
| Address GetAddress() const { |
| // Make sure the our value is an address before we hand a copy out. We use |
| // the Address inside m_addr_range to contain the value for symbols that |
| // are not address based symbols so we are using it for more than just |
| // addresses. For example undefined symbols on MacOSX have a nlist.n_value |
| // of 0 (zero) and this will get placed into |
| // m_addr_range.m_base_addr.m_offset and it will have no section. So in the |
| // GetAddress() accessor, we need to hand out an invalid address if the |
| // symbol's value isn't an address. |
| if (ValueIsAddress()) |
| return m_addr_range.GetBaseAddress(); |
| else |
| return Address(); |
| } |
| |
| // When a symbol's value isn't an address, we need to access the raw value. |
| // This function will ensure this symbol's value isn't an address and return |
| // the integer value if this checks out, otherwise it will return |
| // "fail_value" if the symbol is an address value. |
| uint64_t GetIntegerValue(uint64_t fail_value = 0) const { |
| if (ValueIsAddress()) { |
| // This symbol's value is an address. Use Symbol::GetAddress() to get the |
| // address. |
| return fail_value; |
| } else { |
| // The value is stored in the base address' offset |
| return m_addr_range.GetBaseAddress().GetOffset(); |
| } |
| } |
| |
| lldb::addr_t ResolveCallableAddress(Target &target) const; |
| |
| ConstString GetName() const; |
| |
| ConstString GetNameNoArguments() const; |
| |
| ConstString GetDisplayName() const; |
| |
| uint32_t GetID() const { return m_uid; } |
| |
| lldb::LanguageType GetLanguage() const { |
| // TODO: See if there is a way to determine the language for a symbol |
| // somehow, for now just return our best guess |
| return m_mangled.GuessLanguage(); |
| } |
| |
| void SetID(uint32_t uid) { m_uid = uid; } |
| |
| Mangled &GetMangled() { return m_mangled; } |
| |
| const Mangled &GetMangled() const { return m_mangled; } |
| |
| ConstString GetReExportedSymbolName() const; |
| |
| FileSpec GetReExportedSymbolSharedLibrary() const; |
| |
| void SetReExportedSymbolName(ConstString name); |
| |
| bool SetReExportedSymbolSharedLibrary(const FileSpec &fspec); |
| |
| Symbol *ResolveReExportedSymbol(Target &target) const; |
| |
| uint32_t GetSiblingIndex() const; |
| |
| lldb::SymbolType GetType() const { return (lldb::SymbolType)m_type; } |
| |
| void SetType(lldb::SymbolType type) { m_type = (lldb::SymbolType)type; } |
| |
| const char *GetTypeAsString() const; |
| |
| uint32_t GetFlags() const { return m_flags; } |
| |
| void SetFlags(uint32_t flags) { m_flags = flags; } |
| |
| void GetDescription(Stream *s, lldb::DescriptionLevel level, |
| Target *target) const; |
| |
| bool IsSynthetic() const { return m_is_synthetic; } |
| |
| void SetIsSynthetic(bool b) { m_is_synthetic = b; } |
| |
| bool GetSizeIsSynthesized() const { return m_size_is_synthesized; } |
| |
| void SetSizeIsSynthesized(bool b) { m_size_is_synthesized = b; } |
| |
| bool IsDebug() const { return m_is_debug; } |
| |
| void SetDebug(bool b) { m_is_debug = b; } |
| |
| bool IsExternal() const { return m_is_external; } |
| |
| void SetExternal(bool b) { m_is_external = b; } |
| |
| bool IsTrampoline() const; |
| |
| bool IsIndirect() const; |
| |
| bool IsWeak() const { return m_is_weak; } |
| |
| void SetIsWeak (bool b) { m_is_weak = b; } |
| |
| bool GetByteSizeIsValid() const { return m_size_is_valid; } |
| |
| lldb::addr_t GetByteSize() const; |
| |
| void SetByteSize(lldb::addr_t size) { |
| m_size_is_valid = size > 0; |
| m_addr_range.SetByteSize(size); |
| } |
| |
| bool GetSizeIsSibling() const { return m_size_is_sibling; } |
| |
| void SetSizeIsSibling(bool b) { m_size_is_sibling = b; } |
| |
| // If m_type is "Code" or "Function" then this will return the prologue size |
| // in bytes, else it will return zero. |
| uint32_t GetPrologueByteSize(); |
| |
| bool GetDemangledNameIsSynthesized() const { |
| return m_demangled_is_synthesized; |
| } |
| |
| void SetDemangledNameIsSynthesized(bool b) { m_demangled_is_synthesized = b; } |
| |
| bool ContainsLinkerAnnotations() const { |
| return m_contains_linker_annotations; |
| } |
| void SetContainsLinkerAnnotations(bool b) { |
| m_contains_linker_annotations = b; |
| } |
| /// \copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) |
| /// |
| /// \see SymbolContextScope |
| void CalculateSymbolContext(SymbolContext *sc) override; |
| |
| lldb::ModuleSP CalculateSymbolContextModule() override; |
| |
| Symbol *CalculateSymbolContextSymbol() override; |
| |
| /// \copydoc SymbolContextScope::DumpSymbolContext(Stream*) |
| /// |
| /// \see SymbolContextScope |
| void DumpSymbolContext(Stream *s) override; |
| |
| lldb::DisassemblerSP GetInstructions(const ExecutionContext &exe_ctx, |
| const char *flavor, |
| bool prefer_file_cache); |
| |
| bool GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor, |
| bool prefer_file_cache, Stream &strm); |
| |
| bool ContainsFileAddress(lldb::addr_t file_addr) const; |
| |
| protected: |
| // This is the internal guts of ResolveReExportedSymbol, it assumes |
| // reexport_name is not null, and that module_spec is valid. We track the |
| // modules we've already seen to make sure we don't get caught in a cycle. |
| |
| Symbol *ResolveReExportedSymbolInModuleSpec( |
| Target &target, ConstString &reexport_name, |
| lldb_private::ModuleSpec &module_spec, |
| lldb_private::ModuleList &seen_modules) const; |
| |
| uint32_t m_uid; // User ID (usually the original symbol table index) |
| uint16_t m_type_data; // data specific to m_type |
| uint16_t m_type_data_resolved : 1, // True if the data in m_type_data has |
| // already been calculated |
| m_is_synthetic : 1, // non-zero if this symbol is not actually in the |
| // symbol table, but synthesized from other info in |
| // the object file. |
| m_is_debug : 1, // non-zero if this symbol is debug information in a |
| // symbol |
| m_is_external : 1, // non-zero if this symbol is globally visible |
| m_size_is_sibling : 1, // m_size contains the index of this symbol's |
| // sibling |
| m_size_is_synthesized : 1, // non-zero if this symbol's size was |
| // calculated using a delta between this |
| // symbol and the next |
| m_size_is_valid : 1, |
| m_demangled_is_synthesized : 1, // The demangled name was created should |
| // not be used for expressions or other |
| // lookups |
| m_contains_linker_annotations : 1, // The symbol name contains linker |
| // annotations, which are optional when |
| // doing name lookups |
| m_is_weak : 1, |
| m_type : 6; // Values from the lldb::SymbolType enum. |
| Mangled m_mangled; // uniqued symbol name/mangled name pair |
| AddressRange m_addr_range; // Contains the value, or the section offset |
| // address when the value is an address in a |
| // section, and the size (if any) |
| uint32_t m_flags; // A copy of the flags from the original symbol table, the |
| // ObjectFile plug-in can interpret these |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // LLDB_SYMBOL_SYMBOL_H |