//===-- AddressResolverName.cpp ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Core/AddressResolverName.h" // Project includes #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/lldb-private-log.h" using namespace lldb; using namespace lldb_private; AddressResolverName::AddressResolverName ( const char *func_name, AddressResolver::MatchType type ) : AddressResolver (), m_func_name (func_name), m_class_name (NULL), m_regex (), m_match_type (type) { if (m_match_type == AddressResolver::Regexp) { if (!m_regex.Compile (m_func_name.AsCString())) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString()); } } } AddressResolverName::AddressResolverName ( RegularExpression &func_regex ) : AddressResolver (), m_func_name (NULL), m_class_name (NULL), m_regex (func_regex), m_match_type (AddressResolver::Regexp) { } AddressResolverName::AddressResolverName ( const char *class_name, const char *method, AddressResolver::MatchType type ) : AddressResolver (), m_func_name (method), m_class_name (class_name), m_regex (), m_match_type (type) { } AddressResolverName::~AddressResolverName () { } // FIXME: Right now we look at the module level, and call the module's "FindFunctions". // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. Searcher::CallbackReturn AddressResolverName::SearchCallback ( SearchFilter &filter, SymbolContext &context, Address *addr, bool containing ) { SymbolContextList func_list; SymbolContextList sym_list; bool skip_prologue = true; uint32_t i; SymbolContext sc; Address func_addr; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); if (m_class_name) { if (log) log->Warning ("Class/method function specification not supported yet.\n"); return Searcher::eCallbackReturnStop; } const bool include_symbols = false; const bool include_inlines = true; const bool append = false; switch (m_match_type) { case AddressResolver::Exact: if (context.module_sp) { context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list); context.module_sp->FindFunctions (m_func_name, NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, func_list); } break; case AddressResolver::Regexp: if (context.module_sp) { context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, func_list); } break; case AddressResolver::Glob: if (log) log->Warning ("glob is not supported yet."); break; } // Remove any duplicates between the funcion list and the symbol list if (func_list.GetSize()) { for (i = 0; i < func_list.GetSize(); i++) { if (func_list.GetContextAtIndex(i, sc) == false) continue; if (sc.function == NULL) continue; uint32_t j = 0; while (j < sym_list.GetSize()) { SymbolContext symbol_sc; if (sym_list.GetContextAtIndex(j, symbol_sc)) { if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) { if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) { sym_list.RemoveContextAtIndex(j); continue; // Don't increment j } } } j++; } } for (i = 0; i < func_list.GetSize(); i++) { if (func_list.GetContextAtIndex(i, sc)) { if (sc.function) { func_addr = sc.function->GetAddressRange().GetBaseAddress(); addr_t byte_size = sc.function->GetAddressRange().GetByteSize(); if (skip_prologue) { const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); if (prologue_byte_size) { func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size); byte_size -= prologue_byte_size; } } if (filter.AddressPasses (func_addr)) { AddressRange new_range (func_addr, byte_size); m_address_ranges.push_back (new_range); } } } } } for (i = 0; i < sym_list.GetSize(); i++) { if (sym_list.GetContextAtIndex(i, sc)) { if (sc.symbol && sc.symbol->ValueIsAddress()) { func_addr = sc.symbol->GetAddress(); addr_t byte_size = sc.symbol->GetByteSize(); if (skip_prologue) { const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); if (prologue_byte_size) { func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size); byte_size -= prologue_byte_size; } } if (filter.AddressPasses (func_addr)) { AddressRange new_range (func_addr, byte_size); m_address_ranges.push_back (new_range); } } } } return Searcher::eCallbackReturnContinue; } Searcher::Depth AddressResolverName::GetDepth() { return Searcher::eDepthModule; } void AddressResolverName::GetDescription (Stream *s) { s->PutCString("Address by function name: "); if (m_match_type == AddressResolver::Regexp) s->Printf("'%s' (regular expression)", m_regex.GetText()); else s->Printf("'%s'", m_func_name.AsCString()); }