summaryrefslogtreecommitdiffstats
path: root/source/Symbol/SymbolVendor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Symbol/SymbolVendor.cpp')
-rw-r--r--source/Symbol/SymbolVendor.cpp486
1 files changed, 486 insertions, 0 deletions
diff --git a/source/Symbol/SymbolVendor.cpp b/source/Symbol/SymbolVendor.cpp
new file mode 100644
index 0000000..b51ac5a
--- /dev/null
+++ b/source/Symbol/SymbolVendor.cpp
@@ -0,0 +1,486 @@
+//===-- SymbolVendor.mm -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/SymbolVendor.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// FindPlugin
+//
+// Platforms can register a callback to use when creating symbol
+// vendors to allow for complex debug information file setups, and to
+// also allow for finding separate debug information files.
+//----------------------------------------------------------------------
+SymbolVendor*
+SymbolVendor::FindPlugin (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm)
+{
+ std::unique_ptr<SymbolVendor> instance_ap;
+ SymbolVendorCreateInstance create_callback;
+
+ for (size_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ {
+ instance_ap.reset(create_callback(module_sp, feedback_strm));
+
+ if (instance_ap.get())
+ {
+ return instance_ap.release();
+ }
+ }
+ // The default implementation just tries to create debug information using the
+ // file representation for the module.
+ instance_ap.reset(new SymbolVendor(module_sp));
+ if (instance_ap.get())
+ {
+ ObjectFile *objfile = module_sp->GetObjectFile();
+ if (objfile)
+ instance_ap->AddSymbolFileRepresentation(objfile->shared_from_this());
+ }
+ return instance_ap.release();
+}
+
+//----------------------------------------------------------------------
+// SymbolVendor constructor
+//----------------------------------------------------------------------
+SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp) :
+ ModuleChild (module_sp),
+ m_type_list(),
+ m_compile_units(),
+ m_sym_file_ap()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SymbolVendor::~SymbolVendor()
+{
+}
+
+//----------------------------------------------------------------------
+// Add a represention given an object file.
+//----------------------------------------------------------------------
+void
+SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (objfile_sp)
+ {
+ m_objfile_sp = objfile_sp;
+ m_sym_file_ap.reset(SymbolFile::FindPlugin(objfile_sp.get()));
+ }
+ }
+}
+
+bool
+SymbolVendor::SetCompileUnitAtIndex (size_t idx, const CompUnitSP &cu_sp)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ const size_t num_compile_units = GetNumCompileUnits();
+ if (idx < num_compile_units)
+ {
+ // Fire off an assertion if this compile unit already exists for now.
+ // The partial parsing should take care of only setting the compile
+ // unit once, so if this assertion fails, we need to make sure that
+ // we don't have a race condition, or have a second parse of the same
+ // compile unit.
+ assert(m_compile_units[idx].get() == NULL);
+ m_compile_units[idx] = cu_sp;
+ return true;
+ }
+ else
+ {
+ // This should NOT happen, and if it does, we want to crash and know
+ // about it
+ assert (idx < num_compile_units);
+ }
+ }
+ return false;
+}
+
+size_t
+SymbolVendor::GetNumCompileUnits()
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_compile_units.empty())
+ {
+ if (m_sym_file_ap.get())
+ {
+ // Resize our array of compile unit shared pointers -- which will
+ // each remain NULL until someone asks for the actual compile unit
+ // information. When this happens, the symbol file will be asked
+ // to parse this compile unit information.
+ m_compile_units.resize(m_sym_file_ap->GetNumCompileUnits());
+ }
+ }
+ }
+ return m_compile_units.size();
+}
+
+lldb::LanguageType
+SymbolVendor::ParseCompileUnitLanguage (const SymbolContext& sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseCompileUnitLanguage(sc);
+ }
+ return eLanguageTypeUnknown;
+}
+
+
+size_t
+SymbolVendor::ParseCompileUnitFunctions (const SymbolContext &sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseCompileUnitFunctions(sc);
+ }
+ return 0;
+}
+
+bool
+SymbolVendor::ParseCompileUnitLineTable (const SymbolContext &sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseCompileUnitLineTable(sc);
+ }
+ return false;
+}
+
+bool
+SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files);
+ }
+ return false;
+}
+
+size_t
+SymbolVendor::ParseFunctionBlocks (const SymbolContext &sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseFunctionBlocks(sc);
+ }
+ return 0;
+}
+
+size_t
+SymbolVendor::ParseTypes (const SymbolContext &sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseTypes(sc);
+ }
+ return 0;
+}
+
+size_t
+SymbolVendor::ParseVariablesForContext (const SymbolContext& sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseVariablesForContext(sc);
+ }
+ return 0;
+}
+
+Type*
+SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ResolveTypeUID(type_uid);
+ }
+ return NULL;
+}
+
+
+uint32_t
+SymbolVendor::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc);
+ }
+ return 0;
+}
+
+uint32_t
+SymbolVendor::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list);
+ }
+ return 0;
+}
+
+size_t
+SymbolVendor::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, size_t max_matches, VariableList& variables)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->FindGlobalVariables(name, namespace_decl, append, max_matches, variables);
+ }
+ return 0;
+}
+
+size_t
+SymbolVendor::FindGlobalVariables (const RegularExpression& regex, bool append, size_t max_matches, VariableList& variables)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->FindGlobalVariables(regex, append, max_matches, variables);
+ }
+ return 0;
+}
+
+size_t
+SymbolVendor::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
+ }
+ return 0;
+}
+
+size_t
+SymbolVendor::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->FindFunctions(regex, include_inlines, append, sc_list);
+ }
+ return 0;
+}
+
+
+size_t
+SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, size_t max_matches, TypeList& types)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->FindTypes(sc, name, namespace_decl, append, max_matches, types);
+ }
+ if (!append)
+ types.Clear();
+ return 0;
+}
+
+size_t
+SymbolVendor::GetTypes (SymbolContextScope *sc_scope,
+ uint32_t type_mask,
+ lldb_private::TypeList &type_list)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->GetTypes (sc_scope, type_mask, type_list);
+ }
+ return 0;
+}
+
+ClangNamespaceDecl
+SymbolVendor::FindNamespace(const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *parent_namespace_decl)
+{
+ ClangNamespaceDecl namespace_decl;
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ namespace_decl = m_sym_file_ap->FindNamespace (sc, name, parent_namespace_decl);
+ }
+ return namespace_decl;
+}
+
+void
+SymbolVendor::Dump(Stream *s)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ bool show_context = false;
+
+ s->Printf("%p: ", this);
+ s->Indent();
+ s->PutCString("SymbolVendor");
+ if (m_sym_file_ap.get())
+ {
+ ObjectFile *objfile = m_sym_file_ap->GetObjectFile();
+ if (objfile)
+ {
+ const FileSpec &objfile_file_spec = objfile->GetFileSpec();
+ if (objfile_file_spec)
+ {
+ s->PutCString(" (");
+ objfile_file_spec.Dump(s);
+ s->PutChar(')');
+ }
+ }
+ }
+ s->EOL();
+ s->IndentMore();
+ m_type_list.Dump(s, show_context);
+
+ CompileUnitConstIter cu_pos, cu_end;
+ cu_end = m_compile_units.end();
+ for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos)
+ {
+ // We currently only dump the compile units that have been parsed
+ if (cu_pos->get())
+ (*cu_pos)->Dump(s, show_context);
+ }
+
+ s->IndentLess();
+ }
+}
+
+CompUnitSP
+SymbolVendor::GetCompileUnitAtIndex(size_t idx)
+{
+ CompUnitSP cu_sp;
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ const size_t num_compile_units = GetNumCompileUnits();
+ if (idx < num_compile_units)
+ {
+ cu_sp = m_compile_units[idx];
+ if (cu_sp.get() == NULL)
+ {
+ m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx);
+ cu_sp = m_compile_units[idx];
+ }
+ }
+ }
+ return cu_sp;
+}
+
+Symtab *
+SymbolVendor::GetSymtab ()
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ ObjectFile *objfile = module_sp->GetObjectFile();
+ if (objfile)
+ {
+ // Get symbol table from unified section list.
+ return objfile->GetSymtab ();
+ }
+ }
+ return NULL;
+}
+
+void
+SymbolVendor::ClearSymtab()
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ ObjectFile *objfile = module_sp->GetObjectFile();
+ if (objfile)
+ {
+ // Clear symbol table from unified section list.
+ objfile->ClearSymtab ();
+ }
+ }
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+SymbolVendor::GetPluginName()
+{
+ static ConstString g_name("vendor-default");
+ return g_name;
+}
+
+uint32_t
+SymbolVendor::GetPluginVersion()
+{
+ return 1;
+}
+
OpenPOWER on IntegriCloud