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