/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Symbol/Symbol.h
Line | Count | Source (jump to first uncovered line) |
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/Core/Section.h" |
15 | | #include "lldb/Symbol/SymbolContextScope.h" |
16 | | #include "lldb/Utility/UserID.h" |
17 | | #include "lldb/lldb-private.h" |
18 | | #include "llvm/Support/JSON.h" |
19 | | |
20 | | namespace lldb_private { |
21 | | |
22 | | struct JSONSymbol { |
23 | | std::optional<uint64_t> address; |
24 | | std::optional<uint64_t> value; |
25 | | std::optional<uint64_t> size; |
26 | | std::optional<uint64_t> id; |
27 | | std::optional<lldb::SymbolType> type; |
28 | | std::string name; |
29 | | }; |
30 | | |
31 | | class Symbol : public SymbolContextScope { |
32 | | public: |
33 | | // ObjectFile readers can classify their symbol table entries and searches |
34 | | // can be made on specific types where the symbol values will have |
35 | | // drastically different meanings and sorting requirements. |
36 | | Symbol(); |
37 | | |
38 | | Symbol(uint32_t symID, llvm::StringRef name, lldb::SymbolType type, |
39 | | bool external, bool is_debug, bool is_trampoline, bool is_artificial, |
40 | | const lldb::SectionSP §ion_sp, lldb::addr_t value, |
41 | | lldb::addr_t size, bool size_is_valid, |
42 | | bool contains_linker_annotations, uint32_t flags); |
43 | | |
44 | | Symbol(uint32_t symID, const Mangled &mangled, lldb::SymbolType type, |
45 | | bool external, bool is_debug, bool is_trampoline, bool is_artificial, |
46 | | const AddressRange &range, bool size_is_valid, |
47 | | bool contains_linker_annotations, uint32_t flags); |
48 | | |
49 | | Symbol(const Symbol &rhs); |
50 | | |
51 | | const Symbol &operator=(const Symbol &rhs); |
52 | | |
53 | | static llvm::Expected<Symbol> FromJSON(const JSONSymbol &symbol, |
54 | | SectionList *section_list); |
55 | | |
56 | | void Clear(); |
57 | | |
58 | | bool Compare(ConstString name, lldb::SymbolType type) const; |
59 | | |
60 | | void Dump(Stream *s, Target *target, uint32_t index, |
61 | | Mangled::NamePreference name_preference = |
62 | | Mangled::ePreferDemangled) const; |
63 | | |
64 | | bool ValueIsAddress() const; |
65 | | |
66 | | // The GetAddressRef() accessor functions should only be called if you |
67 | | // previously call ValueIsAddress() otherwise you might get an reference to |
68 | | // an Address object that contains an constant integer value in |
69 | | // m_addr_range.m_base_addr.m_offset which could be incorrectly used to |
70 | | // represent an absolute address since it has no section. |
71 | 274M | Address &GetAddressRef() { return m_addr_range.GetBaseAddress(); } |
72 | | |
73 | 237M | const Address &GetAddressRef() const { return m_addr_range.GetBaseAddress(); } |
74 | | |
75 | | // Makes sure the symbol's value is an address and returns the file address. |
76 | | // Returns LLDB_INVALID_ADDRESS if the symbol's value isn't an address. |
77 | | lldb::addr_t GetFileAddress() const; |
78 | | |
79 | | // Makes sure the symbol's value is an address and gets the load address |
80 | | // using \a target if it is. Returns LLDB_INVALID_ADDRESS if the symbol's |
81 | | // value isn't an address or if the section isn't loaded in \a target. |
82 | | lldb::addr_t GetLoadAddress(Target *target) const; |
83 | | |
84 | | // Access the address value. Do NOT hand out the AddressRange as an object as |
85 | | // the byte size of the address range may not be filled in and it should be |
86 | | // accessed via GetByteSize(). |
87 | 110M | Address GetAddress() const { |
88 | | // Make sure the our value is an address before we hand a copy out. We use |
89 | | // the Address inside m_addr_range to contain the value for symbols that |
90 | | // are not address based symbols so we are using it for more than just |
91 | | // addresses. For example undefined symbols on MacOSX have a nlist.n_value |
92 | | // of 0 (zero) and this will get placed into |
93 | | // m_addr_range.m_base_addr.m_offset and it will have no section. So in the |
94 | | // GetAddress() accessor, we need to hand out an invalid address if the |
95 | | // symbol's value isn't an address. |
96 | 110M | if (ValueIsAddress()) |
97 | 110M | return m_addr_range.GetBaseAddress(); |
98 | 79 | else |
99 | 79 | return Address(); |
100 | 110M | } |
101 | | |
102 | | /// Get the raw value of the symbol from the symbol table. |
103 | | /// |
104 | | /// If the symbol's value is an address, return the file address, else return |
105 | | /// the raw value that is stored in the m_addr_range. If the base address has |
106 | | /// no section, then getting the file address will return the correct value |
107 | | /// as it will return the offset in the base address which is the value. |
108 | 6 | uint64_t GetRawValue() const { |
109 | 6 | return m_addr_range.GetBaseAddress().GetFileAddress(); |
110 | 6 | } |
111 | | |
112 | | // When a symbol's value isn't an address, we need to access the raw value. |
113 | | // This function will ensure this symbol's value isn't an address and return |
114 | | // the integer value if this checks out, otherwise it will return |
115 | | // "fail_value" if the symbol is an address value. |
116 | 1.34k | uint64_t GetIntegerValue(uint64_t fail_value = 0) const { |
117 | 1.34k | if (ValueIsAddress()) { |
118 | | // This symbol's value is an address. Use Symbol::GetAddress() to get the |
119 | | // address. |
120 | 0 | return fail_value; |
121 | 1.34k | } else { |
122 | | // The value is stored in the base address' offset |
123 | 1.34k | return m_addr_range.GetBaseAddress().GetOffset(); |
124 | 1.34k | } |
125 | 1.34k | } |
126 | | |
127 | | lldb::addr_t ResolveCallableAddress(Target &target) const; |
128 | | |
129 | | ConstString GetName() const; |
130 | | |
131 | | ConstString GetNameNoArguments() const; |
132 | | |
133 | | ConstString GetDisplayName() const; |
134 | | |
135 | 117M | uint32_t GetID() const { return m_uid; } |
136 | | |
137 | 53.0k | lldb::LanguageType GetLanguage() const { |
138 | | // TODO: See if there is a way to determine the language for a symbol |
139 | | // somehow, for now just return our best guess |
140 | 53.0k | return GetMangled().GuessLanguage(); |
141 | 53.0k | } |
142 | | |
143 | 135M | void SetID(uint32_t uid) { m_uid = uid; } |
144 | | |
145 | 282M | Mangled &GetMangled() { |
146 | 282M | SynthesizeNameIfNeeded(); |
147 | 282M | return m_mangled; |
148 | 282M | } |
149 | | |
150 | 4.01M | const Mangled &GetMangled() const { |
151 | 4.01M | SynthesizeNameIfNeeded(); |
152 | 4.01M | return m_mangled; |
153 | 4.01M | } |
154 | | |
155 | | ConstString GetReExportedSymbolName() const; |
156 | | |
157 | | FileSpec GetReExportedSymbolSharedLibrary() const; |
158 | | |
159 | | void SetReExportedSymbolName(ConstString name); |
160 | | |
161 | | bool SetReExportedSymbolSharedLibrary(const FileSpec &fspec); |
162 | | |
163 | | Symbol *ResolveReExportedSymbol(Target &target) const; |
164 | | |
165 | | uint32_t GetSiblingIndex() const; |
166 | | |
167 | 824M | lldb::SymbolType GetType() const { return (lldb::SymbolType)m_type; } |
168 | | |
169 | 147M | void SetType(lldb::SymbolType type) { m_type = (lldb::SymbolType)type; } |
170 | | |
171 | | const char *GetTypeAsString() const; |
172 | | |
173 | 1.34k | uint32_t GetFlags() const { return m_flags; } |
174 | | |
175 | 125M | void SetFlags(uint32_t flags) { m_flags = flags; } |
176 | | |
177 | | void GetDescription(Stream *s, lldb::DescriptionLevel level, |
178 | | Target *target) const; |
179 | | |
180 | 123M | bool IsSynthetic() const { return m_is_synthetic; } |
181 | | |
182 | | bool IsSyntheticWithAutoGeneratedName() const; |
183 | | |
184 | 9.96M | void SetIsSynthetic(bool b) { m_is_synthetic = b; } |
185 | | |
186 | 0 | bool GetSizeIsSynthesized() const { return m_size_is_synthesized; } |
187 | | |
188 | 35.4M | void SetSizeIsSynthesized(bool b) { m_size_is_synthesized = b; } |
189 | | |
190 | 169M | bool IsDebug() const { return m_is_debug; } |
191 | | |
192 | 126M | void SetDebug(bool b) { m_is_debug = b; } |
193 | | |
194 | 11.4M | bool IsExternal() const { return m_is_external; } |
195 | | |
196 | 137M | void SetExternal(bool b) { m_is_external = b; } |
197 | | |
198 | | bool IsTrampoline() const; |
199 | | |
200 | | bool IsIndirect() const; |
201 | | |
202 | 1.17M | bool IsWeak() const { return m_is_weak; } |
203 | | |
204 | 80.7k | void SetIsWeak(bool b) { m_is_weak = b; } |
205 | | |
206 | 297 | bool GetByteSizeIsValid() const { return m_size_is_valid; } |
207 | | |
208 | | lldb::addr_t GetByteSize() const; |
209 | | |
210 | 131M | void SetByteSize(lldb::addr_t size) { |
211 | 131M | m_size_is_valid = size > 0; |
212 | 131M | m_addr_range.SetByteSize(size); |
213 | 131M | } |
214 | | |
215 | 0 | bool GetSizeIsSibling() const { return m_size_is_sibling; } |
216 | | |
217 | 2.91k | void SetSizeIsSibling(bool b) { m_size_is_sibling = b; } |
218 | | |
219 | | // If m_type is "Code" or "Function" then this will return the prologue size |
220 | | // in bytes, else it will return zero. |
221 | | uint32_t GetPrologueByteSize(); |
222 | | |
223 | 451 | bool GetDemangledNameIsSynthesized() const { |
224 | 451 | return m_demangled_is_synthesized; |
225 | 451 | } |
226 | | |
227 | 2.64M | void SetDemangledNameIsSynthesized(bool b) { m_demangled_is_synthesized = b; } |
228 | | |
229 | 126M | bool ContainsLinkerAnnotations() const { |
230 | 126M | return m_contains_linker_annotations; |
231 | 126M | } |
232 | | void SetContainsLinkerAnnotations(bool b) { |
233 | | m_contains_linker_annotations = b; |
234 | | } |
235 | | /// \copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) |
236 | | /// |
237 | | /// \see SymbolContextScope |
238 | | void CalculateSymbolContext(SymbolContext *sc) override; |
239 | | |
240 | | lldb::ModuleSP CalculateSymbolContextModule() override; |
241 | | |
242 | | Symbol *CalculateSymbolContextSymbol() override; |
243 | | |
244 | | /// \copydoc SymbolContextScope::DumpSymbolContext(Stream*) |
245 | | /// |
246 | | /// \see SymbolContextScope |
247 | | void DumpSymbolContext(Stream *s) override; |
248 | | |
249 | | lldb::DisassemblerSP GetInstructions(const ExecutionContext &exe_ctx, |
250 | | const char *flavor, |
251 | | bool prefer_file_cache); |
252 | | |
253 | | bool GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor, |
254 | | bool prefer_file_cache, Stream &strm); |
255 | | |
256 | | bool ContainsFileAddress(lldb::addr_t file_addr) const; |
257 | | |
258 | 5.46M | static llvm::StringRef GetSyntheticSymbolPrefix() { |
259 | 5.46M | return "___lldb_unnamed_symbol"; |
260 | 5.46M | } |
261 | | |
262 | | /// Decode a serialized version of this object from data. |
263 | | /// |
264 | | /// \param data |
265 | | /// The decoder object that references the serialized data. |
266 | | /// |
267 | | /// \param offset_ptr |
268 | | /// A pointer that contains the offset from which the data will be decoded |
269 | | /// from that gets updated as data gets decoded. |
270 | | /// |
271 | | /// \param section_list |
272 | | /// A section list that allows lldb_private::Address objects to be filled |
273 | | /// in. The address information for symbols are serilized as file addresses |
274 | | /// and must be converted into Address objects with the right section and |
275 | | /// offset. |
276 | | /// |
277 | | /// \param strtab |
278 | | /// All strings in cache files are put into string tables for efficiency |
279 | | /// and cache file size reduction. Strings are stored as uint32_t string |
280 | | /// table offsets in the cache data. |
281 | | /// |
282 | | /// \return |
283 | | /// True if the symbol is successfully decoded, false otherwise. |
284 | | bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, |
285 | | const SectionList *section_list, const StringTableReader &strtab); |
286 | | |
287 | | /// Encode this object into a data encoder object. |
288 | | /// |
289 | | /// This allows this object to be serialized to disk. |
290 | | /// |
291 | | /// \param encoder |
292 | | /// A data encoder object that serialized bytes will be encoded into. |
293 | | /// |
294 | | /// \param strtab |
295 | | /// All strings in cache files are put into string tables for efficiency |
296 | | /// and cache file size reduction. Strings are stored as uint32_t string |
297 | | /// table offsets in the cache data. |
298 | | void Encode(DataEncoder &encoder, ConstStringTable &strtab) const; |
299 | | |
300 | | bool operator==(const Symbol &rhs) const; |
301 | | |
302 | | protected: |
303 | | // This is the internal guts of ResolveReExportedSymbol, it assumes |
304 | | // reexport_name is not null, and that module_spec is valid. We track the |
305 | | // modules we've already seen to make sure we don't get caught in a cycle. |
306 | | |
307 | | Symbol *ResolveReExportedSymbolInModuleSpec( |
308 | | Target &target, ConstString &reexport_name, |
309 | | lldb_private::ModuleSpec &module_spec, |
310 | | lldb_private::ModuleList &seen_modules) const; |
311 | | |
312 | | void SynthesizeNameIfNeeded() const; |
313 | | |
314 | | uint32_t m_uid = |
315 | | UINT32_MAX; // User ID (usually the original symbol table index) |
316 | | uint16_t m_type_data = 0; // data specific to m_type |
317 | | uint16_t m_type_data_resolved : 1, // True if the data in m_type_data has |
318 | | // already been calculated |
319 | | m_is_synthetic : 1, // non-zero if this symbol is not actually in the |
320 | | // symbol table, but synthesized from other info in |
321 | | // the object file. |
322 | | m_is_debug : 1, // non-zero if this symbol is debug information in a |
323 | | // symbol |
324 | | m_is_external : 1, // non-zero if this symbol is globally visible |
325 | | m_size_is_sibling : 1, // m_size contains the index of this symbol's |
326 | | // sibling |
327 | | m_size_is_synthesized : 1, // non-zero if this symbol's size was |
328 | | // calculated using a delta between this |
329 | | // symbol and the next |
330 | | m_size_is_valid : 1, |
331 | | m_demangled_is_synthesized : 1, // The demangled name was created should |
332 | | // not be used for expressions or other |
333 | | // lookups |
334 | | m_contains_linker_annotations : 1, // The symbol name contains linker |
335 | | // annotations, which are optional when |
336 | | // doing name lookups |
337 | | m_is_weak : 1, |
338 | | m_type : 6; // Values from the lldb::SymbolType enum. |
339 | | mutable Mangled m_mangled; // uniqued symbol name/mangled name pair |
340 | | AddressRange m_addr_range; // Contains the value, or the section offset |
341 | | // address when the value is an address in a |
342 | | // section, and the size (if any) |
343 | | uint32_t m_flags = 0; // A copy of the flags from the original symbol table, |
344 | | // the ObjectFile plug-in can interpret these |
345 | | }; |
346 | | |
347 | | } // namespace lldb_private |
348 | | |
349 | | namespace llvm { |
350 | | namespace json { |
351 | | |
352 | | bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol, |
353 | | llvm::json::Path path); |
354 | | |
355 | | bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type, |
356 | | llvm::json::Path path); |
357 | | |
358 | | } // namespace json |
359 | | } // namespace llvm |
360 | | |
361 | | #endif // LLDB_SYMBOL_SYMBOL_H |