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