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