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 LLDB_SYMBOL_SYMBOL_H |
10 | #define LLDB_SYMBOL_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 | |
18 | namespace lldb_private { |
19 | |
20 | class Symbol : public SymbolContextScope { |
21 | public: |
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 §ion_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 | |
226 | protected: |
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 // LLDB_SYMBOL_SYMBOL_H |
271 | |