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