diff options
Diffstat (limited to 'lldb/source/Core/AddressResolverName.cpp')
| -rw-r--r-- | lldb/source/Core/AddressResolverName.cpp | 198 | 
1 files changed, 198 insertions, 0 deletions
diff --git a/lldb/source/Core/AddressResolverName.cpp b/lldb/source/Core/AddressResolverName.cpp new file mode 100644 index 000000000000..6b9b7b2de723 --- /dev/null +++ b/lldb/source/Core/AddressResolverName.cpp @@ -0,0 +1,198 @@ +//===-- AddressResolverName.cpp ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/AddressResolverName.h" + +#include "lldb/Core/Address.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/Module.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" +#include "lldb/Utility/Stream.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" +#include "llvm/ADT/StringRef.h" + +#include <memory> +#include <string> +#include <vector> + +#include <stdint.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(nullptr), +      m_regex(), m_match_type(type) { +  if (m_match_type == AddressResolver::Regexp) { +    m_regex = RegularExpression(m_func_name.GetStringRef()); +    if (!m_regex.IsValid()) { +      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(nullptr), m_class_name(nullptr), +      m_regex(std::move(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() = default; + +// 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) { +  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; +  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, nullptr, +                                       eFunctionNameTypeAuto, include_symbols, +                                       include_inlines, 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, func_list); +    } +    break; + +  case AddressResolver::Glob: +    if (log) +      log->Warning("glob is not supported yet."); +    break; +  } + +  // Remove any duplicates between the function list and the symbol list +  if (func_list.GetSize()) { +    for (i = 0; i < func_list.GetSize(); i++) { +      if (!func_list.GetContextAtIndex(i, sc)) +        continue; + +      if (sc.function == nullptr) +        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->GetAddressRef()) { +              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->GetAddressRef(); +        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; +} + +lldb::SearchDepth AddressResolverName::GetDepth() { +  return lldb::eSearchDepthModule; +} + +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().str().c_str()); +  else +    s->Printf("'%s'", m_func_name.AsCString()); +}  | 
