1//===-- Symbol.h ------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef liblldb_Symbol_h_
10#define liblldb_Symbol_h_
11
12#include "lldb/Core/AddressRange.h"
13#include "lldb/Core/Mangled.h"
14#include "lldb/Symbol/SymbolContextScope.h"
15#include "lldb/Utility/UserID.h"
16#include "lldb/lldb-private.h"
17
18namespace lldb_private {
19
20class Symbol : public SymbolContextScope {
21public:
22  // ObjectFile readers can classify their symbol table entries and searches
23  // can be made on specific types where the symbol values will have
24  // drastically different meanings and sorting requirements.
25  Symbol();
26
27  Symbol(uint32_t symID, llvm::StringRef name, lldb::SymbolType type,
28         bool external, bool is_debug, bool is_trampoline, bool is_artificial,
29         const lldb::SectionSP &section_sp, lldb::addr_t value,
30         lldb::addr_t size, bool size_is_valid,
31         bool contains_linker_annotations, uint32_t flags);
32
33  Symbol(uint32_t symID, const Mangled &mangled, lldb::SymbolType type,
34         bool external, bool is_debug, bool is_trampoline, bool is_artificial,
35         const AddressRange &range, bool size_is_valid,
36         bool contains_linker_annotations, uint32_t flags);
37
38  Symbol(const Symbol &rhs);
39
40  const Symbol &operator=(const Symbol &rhs);
41
42  void Clear();
43
44  bool Compare(ConstString name, lldb::SymbolType type) const;
45
46  void Dump(Stream *s, Target *target, uint32_t index,
47            Mangled::NamePreference name_preference =
48                Mangled::ePreferDemangled) const;
49
50  bool ValueIsAddress() const;
51
52  // The GetAddressRef() accessor functions should only be called if you
53  // previously call ValueIsAddress() otherwise you might get an reference to
54  // an Address object that contains an constant integer value in
55  // m_addr_range.m_base_addr.m_offset which could be incorrectly used to
56  // represent an absolute address since it has no section.
57  Address &GetAddressRef() { return m_addr_range.GetBaseAddress(); }
58
59  const Address &GetAddressRef() const { return m_addr_range.GetBaseAddress(); }
60
61  // Makes sure the symbol's value is an address and returns the file address.
62  // Returns LLDB_INVALID_ADDRESS if the symbol's value isn't an address.
63  lldb::addr_t GetFileAddress() const;
64
65  // Makes sure the symbol's value is an address and gets the load address
66  // using \a target if it is. Returns LLDB_INVALID_ADDRESS if the symbol's
67  // value isn't an address or if the section isn't loaded in \a target.
68  lldb::addr_t GetLoadAddress(Target *target) const;
69
70  // Access the address value. Do NOT hand out the AddressRange as an object as
71  // the byte size of the address range may not be filled in and it should be
72  // accessed via GetByteSize().
73  Address GetAddress() const {
74    // Make sure the our value is an address before we hand a copy out. We use
75    // the Address inside m_addr_range to contain the value for symbols that
76    // are not address based symbols so we are using it for more than just
77    // addresses. For example undefined symbols on MacOSX have a nlist.n_value
78    // of 0 (zero) and this will get placed into
79    // m_addr_range.m_base_addr.m_offset and it will have no section. So in the
80    // GetAddress() accessor, we need to hand out an invalid address if the
81    // symbol's value isn't an address.
82    if (ValueIsAddress())
83      return m_addr_range.GetBaseAddress();
84    else
85      return Address();
86  }
87
88  // When a symbol's value isn't an address, we need to access the raw value.
89  // This function will ensure this symbol's value isn't an address and return
90  // the integer value if this checks out, otherwise it will return
91  // "fail_value" if the symbol is an address value.
92  uint64_t GetIntegerValue(uint64_t fail_value = 0) const {
93    if (ValueIsAddress()) {
94      // This symbol's value is an address. Use Symbol::GetAddress() to get the
95      // address.
96      return fail_value;
97    } else {
98      // The value is stored in the base address' offset
99      return m_addr_range.GetBaseAddress().GetOffset();
100    }
101  }
102
103  lldb::addr_t ResolveCallableAddress(Target &target) const;
104
105  ConstString GetName() const;
106
107  ConstString GetNameNoArguments() const;
108
109  ConstString GetDisplayName() const;
110
111  uint32_t GetID() const { return m_uid; }
112
113  lldb::LanguageType GetLanguage() const {
114    // TODO: See if there is a way to determine the language for a symbol
115    // somehow, for now just return our best guess
116    return m_mangled.GuessLanguage();
117  }
118
119  void SetID(uint32_t uid) { m_uid = uid; }
120
121  Mangled &GetMangled() { return m_mangled; }
122
123  const Mangled &GetMangled() const { return m_mangled; }
124
125  ConstString GetReExportedSymbolName() const;
126
127  FileSpec GetReExportedSymbolSharedLibrary() const;
128
129  void SetReExportedSymbolName(ConstString name);
130
131  bool SetReExportedSymbolSharedLibrary(const FileSpec &fspec);
132
133  Symbol *ResolveReExportedSymbol(Target &target) const;
134
135  uint32_t GetSiblingIndex() const;
136
137  lldb::SymbolType GetType() const { return (lldb::SymbolType)m_type; }
138
139  void SetType(lldb::SymbolType type) { m_type = (lldb::SymbolType)type; }
140
141  const char *GetTypeAsString() const;
142
143  uint32_t GetFlags() const { return m_flags; }
144
145  void SetFlags(uint32_t flags) { m_flags = flags; }
146
147  void GetDescription(Stream *s, lldb::DescriptionLevel level,
148                      Target *target) const;
149
150  bool IsSynthetic() const { return m_is_synthetic; }
151
152  void SetIsSynthetic(bool b) { m_is_synthetic = b; }
153
154  bool GetSizeIsSynthesized() const { return m_size_is_synthesized; }
155
156  void SetSizeIsSynthesized(bool b) { m_size_is_synthesized = b; }
157
158  bool IsDebug() const { return m_is_debug; }
159
160  void SetDebug(bool b) { m_is_debug = b; }
161
162  bool IsExternal() const { return m_is_external; }
163
164  void SetExternal(bool b) { m_is_external = b; }
165
166  bool IsTrampoline() const;
167
168  bool IsIndirect() const;
169
170  bool IsWeak() const { return m_is_weak; }
171
172  void SetIsWeak (bool b) { m_is_weak = b; }
173
174  bool GetByteSizeIsValid() const { return m_size_is_valid; }
175
176  lldb::addr_t GetByteSize() const;
177
178  void SetByteSize(lldb::addr_t size) {
179    m_size_is_valid = size > 0;
180    m_addr_range.SetByteSize(size);
181  }
182
183  bool GetSizeIsSibling() const { return m_size_is_sibling; }
184
185  void SetSizeIsSibling(bool b) { m_size_is_sibling = b; }
186
187  // If m_type is "Code" or "Function" then this will return the prologue size
188  // in bytes, else it will return zero.
189  uint32_t GetPrologueByteSize();
190
191  bool GetDemangledNameIsSynthesized() const {
192    return m_demangled_is_synthesized;
193  }
194
195  void SetDemangledNameIsSynthesized(bool b) { m_demangled_is_synthesized = b; }
196
197  bool ContainsLinkerAnnotations() const {
198    return m_contains_linker_annotations;
199  }
200  void SetContainsLinkerAnnotations(bool b) {
201    m_contains_linker_annotations = b;
202  }
203  /// \copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*)
204  ///
205  /// \see SymbolContextScope
206  void CalculateSymbolContext(SymbolContext *sc) override;
207
208  lldb::ModuleSP CalculateSymbolContextModule() override;
209
210  Symbol *CalculateSymbolContextSymbol() override;
211
212  /// \copydoc SymbolContextScope::DumpSymbolContext(Stream*)
213  ///
214  /// \see SymbolContextScope
215  void DumpSymbolContext(Stream *s) override;
216
217  lldb::DisassemblerSP GetInstructions(const ExecutionContext &exe_ctx,
218                                       const char *flavor,
219                                       bool prefer_file_cache);
220
221  bool GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor,
222                      bool prefer_file_cache, Stream &strm);
223
224  bool ContainsFileAddress(lldb::addr_t file_addr) const;
225
226protected:
227  // This is the internal guts of ResolveReExportedSymbol, it assumes
228  // reexport_name is not null, and that module_spec is valid.  We track the
229  // modules we've already seen to make sure we don't get caught in a cycle.
230
231  Symbol *ResolveReExportedSymbolInModuleSpec(
232      Target &target, ConstString &reexport_name,
233      lldb_private::ModuleSpec &module_spec,
234      lldb_private::ModuleList &seen_modules) const;
235
236  uint32_t m_uid;       // User ID (usually the original symbol table index)
237  uint16_t m_type_data; // data specific to m_type
238  uint16_t m_type_data_resolved : 1, // True if the data in m_type_data has
239                                     // already been calculated
240      m_is_synthetic : 1, // non-zero if this symbol is not actually in the
241                          // symbol table, but synthesized from other info in
242                          // the object file.
243      m_is_debug : 1,     // non-zero if this symbol is debug information in a
244                          // symbol
245      m_is_external : 1,  // non-zero if this symbol is globally visible
246      m_size_is_sibling : 1,     // m_size contains the index of this symbol's
247                                 // sibling
248      m_size_is_synthesized : 1, // non-zero if this symbol's size was
249                                 // calculated using a delta between this
250                                 // symbol and the next
251      m_size_is_valid : 1,
252      m_demangled_is_synthesized : 1, // The demangled name was created should
253                                      // not be used for expressions or other
254                                      // lookups
255      m_contains_linker_annotations : 1, // The symbol name contains linker
256                                         // annotations, which are optional when
257                                         // doing name lookups
258      m_is_weak : 1,
259      m_type : 6;            // Values from the lldb::SymbolType enum.
260  Mangled m_mangled;         // uniqued symbol name/mangled name pair
261  AddressRange m_addr_range; // Contains the value, or the section offset
262                             // address when the value is an address in a
263                             // section, and the size (if any)
264  uint32_t m_flags; // A copy of the flags from the original symbol table, the
265                    // ObjectFile plug-in can interpret these
266};
267
268} // namespace lldb_private
269
270#endif // liblldb_Symbol_h_
271