Add a first pass at a "stop hook" mechanism. This allows you to add commands that get run every time the debugger stops, whether due to a breakpoint, the end of a step, interrupt, etc. You can also specify in which context you want the stop hook to run, for instance only on a particular thread, or only in a particular shared library, function, file, line range within a file.
Still need to add "in methods of a class" to the specifiers, and the ability to write the stop hooks in the Scripting language as well as in the Command Language.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@127457 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp
index 3a775b0..f595e53 100644
--- a/source/Symbol/SymbolContext.cpp
+++ b/source/Symbol/SymbolContext.cpp
@@ -433,25 +433,298 @@
return return_value;
}
-//SymbolContext
-//SymbolContext::CreateSymbolContextFromDescription (lldb::TargetSP &target_sp,
-// const char *module,
-// const char *comp_unit,
-// const char *function,
-// const char *block_spec
-// const char *line_number,
-// const char *symbol)
-//{
-// SymbolContext sc;
-// sc.target = target_sp;
-//
-// if (module != NULL && module[0] != '0')
-// {
-//
-// }
-//
-// return sc;
-//}
+//----------------------------------------------------------------------
+//
+// SymbolContextSpecifier
+//
+//----------------------------------------------------------------------
+
+bool
+SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type)
+{
+ bool return_value = true;
+ switch (type)
+ {
+ case eNothingSpecified:
+ Clear();
+ break;
+ case eLineStartSpecified:
+ m_start_line = line_no;
+ m_type |= eLineStartSpecified;
+ break;
+ case eLineEndSpecified:
+ m_end_line = line_no;
+ m_type |= eLineEndSpecified;
+ break;
+ default:
+ return_value = false;
+ break;
+ }
+ return return_value;
+}
+
+bool
+SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type)
+{
+ bool return_value = true;
+ switch (type)
+ {
+ case eNothingSpecified:
+ Clear();
+ break;
+ case eModuleSpecified:
+ {
+ // See if we can find the Module, if so stick it in the SymbolContext.
+ FileSpec module_spec(spec_string, true);
+ lldb::ModuleSP module_sp = m_target_sp->GetImages().FindFirstModuleForFileSpec (module_spec);
+ m_type |= eModuleSpecified;
+ if (module_sp)
+ m_module_sp = module_sp;
+ else
+ m_module_spec.assign (spec_string);
+ }
+ break;
+ case eFileSpecified:
+ // CompUnits can't necessarily be resolved here, since an inlined function might show up in
+ // a number of CompUnits. Instead we just convert to a FileSpec and store it away.
+ m_file_spec_ap.reset (new FileSpec (spec_string, true));
+ m_type |= eFileSpecified;
+ break;
+ case eLineStartSpecified:
+ m_start_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
+ if (return_value)
+ m_type |= eLineStartSpecified;
+ break;
+ case eLineEndSpecified:
+ m_end_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
+ if (return_value)
+ m_type |= eLineEndSpecified;
+ break;
+ case eFunctionSpecified:
+ m_function_spec.assign(spec_string);
+ m_type |= eFunctionSpecified;
+ break;
+ case eClassOrNamespaceSpecified:
+ Clear();
+ m_class_name.assign (spec_string);
+ m_type = eClassOrNamespaceSpecified;
+ break;
+ case eAddressRangeSpecified:
+ // Not specified yet...
+ break;
+ }
+
+ return return_value;
+}
+
+void
+SymbolContextSpecifier::Clear()
+{
+ m_module_spec.clear();
+ m_file_spec_ap.reset();
+ m_function_spec.clear();
+ m_class_name.clear();
+ m_start_line = 0;
+ m_end_line = 0;
+ m_address_range_ap.reset();
+
+ m_type = eNothingSpecified;
+}
+
+bool
+SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
+{
+ if (m_type == eNothingSpecified)
+ return true;
+
+ if (m_target_sp.get() != sc.target_sp.get())
+ return false;
+
+ if (m_type & eModuleSpecified)
+ {
+ if (sc.module_sp)
+ {
+ if (m_module_sp.get() != NULL)
+ {
+ if (m_module_sp.get() != sc.module_sp.get())
+ return false;
+ }
+ else
+ {
+ FileSpec module_file_spec (m_module_spec.c_str(), false);
+ if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false))
+ return false;
+ }
+ }
+ }
+ if (m_type & eFileSpecified)
+ {
+ if (m_file_spec_ap.get())
+ {
+ // If we don't have a block or a comp_unit, then we aren't going to match a source file.
+ if (sc.block == NULL && sc.comp_unit == NULL)
+ return false;
+
+ // Check if the block is present, and if so is it inlined:
+ bool was_inlined = false;
+ if (sc.block != NULL)
+ {
+ const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
+ if (inline_info != NULL)
+ {
+ was_inlined = true;
+ if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
+ return false;
+ }
+ }
+
+ // Next check the comp unit, but only if the SymbolContext was not inlined.
+ if (!was_inlined && sc.comp_unit != NULL)
+ {
+ if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
+ return false;
+ }
+ }
+ }
+ if (m_type & eLineStartSpecified
+ || m_type & eLineEndSpecified)
+ {
+ if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
+ return false;
+ }
+
+ if (m_type & eFunctionSpecified)
+ {
+ // First check the current block, and if it is inlined, get the inlined function name:
+ bool was_inlined = false;
+ ConstString func_name(m_function_spec.c_str());
+
+ if (sc.block != NULL)
+ {
+ const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
+ if (inline_info != NULL)
+ {
+ was_inlined = true;
+ const Mangled &name = inline_info->GetMangled();
+ if (!name.NameMatches (func_name))
+ return false;
+ }
+ }
+ // If it wasn't inlined, check the name in the function or symbol:
+ if (!was_inlined)
+ {
+ if (sc.function != NULL)
+ {
+ if (!sc.function->GetMangled().NameMatches(func_name))
+ return false;
+ }
+ else if (sc.symbol != NULL)
+ {
+ if (!sc.symbol->GetMangled().NameMatches(func_name))
+ return false;
+ }
+ }
+
+
+ }
+
+ return true;
+}
+
+bool
+SymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
+{
+ if (m_type & eAddressRangeSpecified)
+ {
+
+ }
+ else
+ {
+ Address match_address (addr, NULL);
+ SymbolContext sc;
+ m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
+ return SymbolContextMatches(sc);
+ }
+ return true;
+}
+
+void
+SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const
+{
+ char path_str[PATH_MAX + 1];
+
+ if (m_type == eNothingSpecified)
+ {
+ s->Printf ("Nothing specified.\n");
+ }
+
+ if (m_type == eModuleSpecified)
+ {
+ s->Indent();
+ if (m_module_sp)
+ {
+ m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX);
+ s->Printf ("Module: %s\n", path_str);
+ }
+ else
+ s->Printf ("Module: %s\n", m_module_spec.c_str());
+ }
+
+ if (m_type == eFileSpecified && m_file_spec_ap.get() != NULL)
+ {
+ m_file_spec_ap->GetPath (path_str, PATH_MAX);
+ s->Indent();
+ s->Printf ("File: %s", path_str);
+ if (m_type == eLineStartSpecified)
+ {
+ s->Printf (" from line %d", m_start_line);
+ if (m_type == eLineEndSpecified)
+ s->Printf ("to line %d", m_end_line);
+ else
+ s->Printf ("to end", m_end_line);
+ }
+ else if (m_type == eLineEndSpecified)
+ {
+ s->Printf (" from start to line %d", m_end_line);
+ }
+ s->Printf (".\n");
+ }
+
+ if (m_type == eLineStartSpecified)
+ {
+ s->Indent();
+ s->Printf ("From line %d", m_start_line);
+ if (m_type == eLineEndSpecified)
+ s->Printf ("to line %d", m_end_line);
+ else
+ s->Printf ("to end", m_end_line);
+ s->Printf (".\n");
+ }
+ else if (m_type == eLineEndSpecified)
+ {
+ s->Printf ("From start to line %d.\n", m_end_line);
+ }
+
+ if (m_type == eFunctionSpecified)
+ {
+ s->Indent();
+ s->Printf ("Function: %s.\n", m_function_spec.c_str());
+ }
+
+ if (m_type == eClassOrNamespaceSpecified)
+ {
+ s->Indent();
+ s->Printf ("Class name: %s.\n", m_class_name.c_str());
+ }
+
+ if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != NULL)
+ {
+ s->Indent();
+ s->PutCString ("Address range: ");
+ m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
+ s->PutCString ("\n");
+ }
+}
//----------------------------------------------------------------------
//