1 | //===-- SymbolFileSymtab.cpp ----------------------------------------------===// |
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 | #include "SymbolFileSymtab.h" |
10 | |
11 | #include "lldb/Core/Module.h" |
12 | #include "lldb/Core/PluginManager.h" |
13 | #include "lldb/Symbol/CompileUnit.h" |
14 | #include "lldb/Symbol/Function.h" |
15 | #include "lldb/Symbol/ObjectFile.h" |
16 | #include "lldb/Symbol/Symbol.h" |
17 | #include "lldb/Symbol/SymbolContext.h" |
18 | #include "lldb/Symbol/Symtab.h" |
19 | #include "lldb/Symbol/TypeList.h" |
20 | #include "lldb/Utility/RegularExpression.h" |
21 | #include "lldb/Utility/Timer.h" |
22 | |
23 | #include <memory> |
24 | #include <optional> |
25 | |
26 | using namespace lldb; |
27 | using namespace lldb_private; |
28 | |
29 | LLDB_PLUGIN_DEFINE(SymbolFileSymtab) |
30 | |
31 | char SymbolFileSymtab::ID; |
32 | |
33 | void SymbolFileSymtab::Initialize() { |
34 | PluginManager::RegisterPlugin(name: GetPluginNameStatic(), |
35 | description: GetPluginDescriptionStatic(), create_callback: CreateInstance); |
36 | } |
37 | |
38 | void SymbolFileSymtab::Terminate() { |
39 | PluginManager::UnregisterPlugin(create_callback: CreateInstance); |
40 | } |
41 | |
42 | llvm::StringRef SymbolFileSymtab::GetPluginDescriptionStatic() { |
43 | return "Reads debug symbols from an object file's symbol table." ; |
44 | } |
45 | |
46 | SymbolFile *SymbolFileSymtab::CreateInstance(ObjectFileSP objfile_sp) { |
47 | return new SymbolFileSymtab(std::move(objfile_sp)); |
48 | } |
49 | |
50 | void SymbolFileSymtab::GetTypes(SymbolContextScope *sc_scope, |
51 | TypeClass type_mask, |
52 | lldb_private::TypeList &type_list) {} |
53 | |
54 | SymbolFileSymtab::SymbolFileSymtab(ObjectFileSP objfile_sp) |
55 | : SymbolFileCommon(std::move(objfile_sp)), m_source_indexes(), |
56 | m_func_indexes(), m_code_indexes(), m_objc_class_name_to_index() {} |
57 | |
58 | uint32_t SymbolFileSymtab::CalculateAbilities() { |
59 | uint32_t abilities = 0; |
60 | if (m_objfile_sp) { |
61 | const Symtab *symtab = m_objfile_sp->GetSymtab(); |
62 | if (symtab) { |
63 | // The snippet of code below will get the indexes the module symbol table |
64 | // entries that are code, data, or function related (debug info), sort |
65 | // them by value (address) and dump the sorted symbols. |
66 | if (symtab->AppendSymbolIndexesWithType(symbol_type: eSymbolTypeSourceFile, |
67 | indexes&: m_source_indexes)) { |
68 | abilities |= CompileUnits; |
69 | } |
70 | |
71 | if (symtab->AppendSymbolIndexesWithType( |
72 | symbol_type: eSymbolTypeCode, symbol_debug_type: Symtab::eDebugYes, symbol_visibility: Symtab::eVisibilityAny, |
73 | matches&: m_func_indexes)) { |
74 | symtab->SortSymbolIndexesByValue(indexes&: m_func_indexes, remove_duplicates: true); |
75 | abilities |= Functions; |
76 | } |
77 | |
78 | if (symtab->AppendSymbolIndexesWithType(symbol_type: eSymbolTypeCode, symbol_debug_type: Symtab::eDebugNo, |
79 | symbol_visibility: Symtab::eVisibilityAny, |
80 | matches&: m_code_indexes)) { |
81 | symtab->SortSymbolIndexesByValue(indexes&: m_code_indexes, remove_duplicates: true); |
82 | abilities |= Functions; |
83 | } |
84 | |
85 | if (symtab->AppendSymbolIndexesWithType(symbol_type: eSymbolTypeData, |
86 | indexes&: m_data_indexes)) { |
87 | symtab->SortSymbolIndexesByValue(indexes&: m_data_indexes, remove_duplicates: true); |
88 | abilities |= GlobalVariables; |
89 | } |
90 | |
91 | lldb_private::Symtab::IndexCollection objc_class_indexes; |
92 | if (symtab->AppendSymbolIndexesWithType(symbol_type: eSymbolTypeObjCClass, |
93 | indexes&: objc_class_indexes)) { |
94 | symtab->AppendSymbolNamesToMap(indexes: objc_class_indexes, add_demangled: true, add_mangled: true, |
95 | name_to_index_map&: m_objc_class_name_to_index); |
96 | m_objc_class_name_to_index.Sort(); |
97 | } |
98 | } |
99 | } |
100 | return abilities; |
101 | } |
102 | |
103 | uint32_t SymbolFileSymtab::CalculateNumCompileUnits() { |
104 | // If we don't have any source file symbols we will just have one compile |
105 | // unit for the entire object file |
106 | if (m_source_indexes.empty()) |
107 | return 0; |
108 | |
109 | // If we have any source file symbols we will logically organize the object |
110 | // symbols using these. |
111 | return m_source_indexes.size(); |
112 | } |
113 | |
114 | CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) { |
115 | CompUnitSP cu_sp; |
116 | |
117 | // If we don't have any source file symbols we will just have one compile |
118 | // unit for the entire object file |
119 | if (idx < m_source_indexes.size()) { |
120 | const Symbol *cu_symbol = |
121 | m_objfile_sp->GetSymtab()->SymbolAtIndex(idx: m_source_indexes[idx]); |
122 | if (cu_symbol) |
123 | cu_sp = std::make_shared<CompileUnit>(args: m_objfile_sp->GetModule(), args: nullptr, |
124 | args: cu_symbol->GetName().AsCString(), args: 0, |
125 | args: eLanguageTypeUnknown, args: eLazyBoolNo); |
126 | } |
127 | return cu_sp; |
128 | } |
129 | |
130 | lldb::LanguageType SymbolFileSymtab::ParseLanguage(CompileUnit &comp_unit) { |
131 | return eLanguageTypeUnknown; |
132 | } |
133 | |
134 | size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) { |
135 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); |
136 | size_t num_added = 0; |
137 | // We must at least have a valid compile unit |
138 | const Symtab *symtab = m_objfile_sp->GetSymtab(); |
139 | const Symbol *curr_symbol = nullptr; |
140 | const Symbol *next_symbol = nullptr; |
141 | // const char *prefix = m_objfile_sp->SymbolPrefix(); |
142 | // if (prefix == NULL) |
143 | // prefix == ""; |
144 | // |
145 | // const uint32_t prefix_len = strlen(prefix); |
146 | |
147 | // If we don't have any source file symbols we will just have one compile |
148 | // unit for the entire object file |
149 | if (m_source_indexes.empty()) { |
150 | // The only time we will have a user ID of zero is when we don't have and |
151 | // source file symbols and we declare one compile unit for the entire |
152 | // object file |
153 | if (!m_func_indexes.empty()) { |
154 | } |
155 | |
156 | if (!m_code_indexes.empty()) { |
157 | // StreamFile s(stdout); |
158 | // symtab->Dump(&s, m_code_indexes); |
159 | |
160 | uint32_t idx = 0; // Index into the indexes |
161 | const uint32_t num_indexes = m_code_indexes.size(); |
162 | for (idx = 0; idx < num_indexes; ++idx) { |
163 | uint32_t symbol_idx = m_code_indexes[idx]; |
164 | curr_symbol = symtab->SymbolAtIndex(idx: symbol_idx); |
165 | if (curr_symbol) { |
166 | // Union of all ranges in the function DIE (if the function is |
167 | // discontiguous) |
168 | AddressRange func_range(curr_symbol->GetAddress(), 0); |
169 | if (func_range.GetBaseAddress().IsSectionOffset()) { |
170 | uint32_t symbol_size = curr_symbol->GetByteSize(); |
171 | if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling()) |
172 | func_range.SetByteSize(symbol_size); |
173 | else if (idx + 1 < num_indexes) { |
174 | next_symbol = symtab->SymbolAtIndex(idx: m_code_indexes[idx + 1]); |
175 | if (next_symbol) { |
176 | func_range.SetByteSize( |
177 | next_symbol->GetAddressRef().GetOffset() - |
178 | curr_symbol->GetAddressRef().GetOffset()); |
179 | } |
180 | } |
181 | |
182 | FunctionSP func_sp( |
183 | new Function(&comp_unit, |
184 | symbol_idx, // UserID is the DIE offset |
185 | LLDB_INVALID_UID, // We don't have any type info |
186 | // for this function |
187 | curr_symbol->GetMangled(), // Linker/mangled name |
188 | nullptr, // no return type for a code symbol... |
189 | func_range)); // first address range |
190 | |
191 | if (func_sp.get() != nullptr) { |
192 | comp_unit.AddFunction(function_sp&: func_sp); |
193 | ++num_added; |
194 | } |
195 | } |
196 | } |
197 | } |
198 | } |
199 | } else { |
200 | // We assume we |
201 | } |
202 | return num_added; |
203 | } |
204 | |
205 | size_t SymbolFileSymtab::ParseTypes(CompileUnit &comp_unit) { return 0; } |
206 | |
207 | bool SymbolFileSymtab::ParseLineTable(CompileUnit &comp_unit) { return false; } |
208 | |
209 | bool SymbolFileSymtab::ParseDebugMacros(CompileUnit &comp_unit) { |
210 | return false; |
211 | } |
212 | |
213 | bool SymbolFileSymtab::ParseSupportFiles(CompileUnit &comp_unit, |
214 | SupportFileList &support_files) { |
215 | return false; |
216 | } |
217 | |
218 | bool SymbolFileSymtab::ParseImportedModules( |
219 | const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { |
220 | return false; |
221 | } |
222 | |
223 | size_t SymbolFileSymtab::ParseBlocksRecursive(Function &func) { return 0; } |
224 | |
225 | size_t SymbolFileSymtab::ParseVariablesForContext(const SymbolContext &sc) { |
226 | return 0; |
227 | } |
228 | |
229 | Type *SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) { |
230 | return nullptr; |
231 | } |
232 | |
233 | std::optional<SymbolFile::ArrayInfo> |
234 | SymbolFileSymtab::GetDynamicArrayInfoForUID( |
235 | lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { |
236 | return std::nullopt; |
237 | } |
238 | |
239 | bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) { |
240 | return false; |
241 | } |
242 | |
243 | uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr, |
244 | SymbolContextItem resolve_scope, |
245 | SymbolContext &sc) { |
246 | std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); |
247 | if (m_objfile_sp->GetSymtab() == nullptr) |
248 | return 0; |
249 | |
250 | uint32_t resolved_flags = 0; |
251 | if (resolve_scope & eSymbolContextSymbol) { |
252 | sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress( |
253 | file_addr: so_addr.GetFileAddress()); |
254 | if (sc.symbol) |
255 | resolved_flags |= eSymbolContextSymbol; |
256 | } |
257 | return resolved_flags; |
258 | } |
259 | |