Searcher::CallbackReturn
BreakpointResolverAddress::SearchCallback
(
    SearchFilter &filter,
    SymbolContext &context,
    Address *addr,
    bool containing
)
{
    assert (m_breakpoint != NULL);

    if (filter.AddressPasses (m_addr))
    {
        BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr));
        if (bp_loc_sp && !m_breakpoint->IsInternal())
        {
            StreamString s;
            bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
            if (log)
                log->Printf ("Added location: %s\n", s.GetData());
        }
    }
    return Searcher::eCallbackReturnStop;
}
void BreakpointResolver::AddLocation(SearchFilter &filter,
                                     const SymbolContext &sc,
                                     bool skip_prologue,
                                     llvm::StringRef log_ident) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
  Address line_start = sc.line_entry.range.GetBaseAddress();
  if (!line_start.IsValid()) {
    if (log)
      log->Printf("error: Unable to set breakpoint %s at file address "
                  "0x%" PRIx64 "\n",
                  log_ident.str().c_str(), line_start.GetFileAddress());
    return;
  }

  if (!filter.AddressPasses(line_start)) {
    if (log)
      log->Printf("Breakpoint %s at file address 0x%" PRIx64
                  " didn't pass the filter.\n",
                  log_ident.str().c_str(), line_start.GetFileAddress());
  }

  // If the line number is before the prologue end, move it there...
  bool skipped_prologue = false;
  if (skip_prologue && sc.function) {
    Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
    if (prologue_addr.IsValid() && (line_start == prologue_addr)) {
      const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
      if (prologue_byte_size) {
        prologue_addr.Slide(prologue_byte_size);

        if (filter.AddressPasses(prologue_addr)) {
          skipped_prologue = true;
          line_start = prologue_addr;
        }
      }
    }
  }

  BreakpointLocationSP bp_loc_sp(AddLocation(line_start));
  if (log && bp_loc_sp && !m_breakpoint->IsInternal()) {
    StreamString s;
    bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
    log->Printf("Added location (skipped prologue: %s): %s \n",
                skipped_prologue ? "yes" : "no", s.GetData());
  }
}
Searcher::CallbackReturn
BreakpointResolverFileLine::SearchCallback
(
    SearchFilter &filter,
    SymbolContext &context,
    Address *addr,
    bool containing
)
{
    SymbolContextList sc_list;

    assert (m_breakpoint != NULL);
    
    // There is a tricky bit here.  You can have two compilation units that #include the same file, and
    // in one of them the function at m_line_number is used (and so code and a line entry for it is generated) but in the
    // other it isn't.  If we considered the CU's independently, then in the second inclusion, we'd move the breakpoint 
    // to the next function that actually generated code in the header file.  That would end up being confusing.
    // So instead, we do the CU iterations by hand here, then scan through the complete list of matches, and figure out 
    // the closest line number match, and only set breakpoints on that match.
    
    // Note also that if file_spec only had a file name and not a directory, there may be many different file spec's in
    // the resultant list.  The closest line match for one will not be right for some totally different file.
    // So we go through the match list and pull out the sets that have the same file spec in their line_entry
    // and treat each set separately.
    
    const size_t num_comp_units = context.module_sp->GetNumCompileUnits();
    for (size_t i = 0; i < num_comp_units; i++)
    {
        CompUnitSP cu_sp (context.module_sp->GetCompileUnitAtIndex (i));
        if (cu_sp)
        {
            if (filter.CompUnitPasses(*cu_sp))
                cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
        }
    }
    StreamString s;
    s.Printf ("for %s:%d ",
                        m_file_spec.GetFilename().AsCString("<Unknown>"),
                        m_line_number);

    SetSCMatchesByLine (filter, sc_list, m_skip_prologue, s.GetData());

    return Searcher::eCallbackReturnContinue;
}
Ejemplo n.º 4
0
Searcher::CallbackReturn
BreakpointResolverName::SearchCallback(SearchFilter &filter,
                                       SymbolContext &context, Address *addr,
                                       bool containing) {
  SymbolContextList func_list;
  // SymbolContextList sym_list;

  uint32_t i;
  bool new_location;
  Address break_addr;
  assert(m_breakpoint != nullptr);

  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;
  }
  bool filter_by_cu =
      (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
  bool filter_by_language = (m_language != eLanguageTypeUnknown);
  const bool include_symbols = !filter_by_cu;
  const bool include_inlines = true;
  const bool append = true;

  switch (m_match_type) {
  case Breakpoint::Exact:
    if (context.module_sp) {
      for (const auto &lookup : m_lookups) {
        const size_t start_func_idx = func_list.GetSize();
        context.module_sp->FindFunctions(
            lookup.GetLookupName(), nullptr, lookup.GetNameTypeMask(),
            include_symbols, include_inlines, append, func_list);

        const size_t end_func_idx = func_list.GetSize();

        if (start_func_idx < end_func_idx)
          lookup.Prune(func_list, start_func_idx);
      }
    }
    break;
  case Breakpoint::Regexp:
    if (context.module_sp) {
      context.module_sp->FindFunctions(
          m_regex,
          !filter_by_cu, // include symbols only if we aren't filtering by CU
          include_inlines, append, func_list);
    }
    break;
  case Breakpoint::Glob:
    if (log)
      log->Warning("glob is not supported yet.");
    break;
  }

  // If the filter specifies a Compilation Unit, remove the ones that don't
  // pass at this point.
  if (filter_by_cu || filter_by_language) {
    uint32_t num_functions = func_list.GetSize();

    for (size_t idx = 0; idx < num_functions; idx++) {
      bool remove_it = false;
      SymbolContext sc;
      func_list.GetContextAtIndex(idx, sc);
      if (filter_by_cu) {
        if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
          remove_it = true;
      }

      if (filter_by_language) {
        LanguageType sym_language = sc.GetLanguage();
        if ((Language::GetPrimaryLanguage(sym_language) !=
             Language::GetPrimaryLanguage(m_language)) &&
            (sym_language != eLanguageTypeUnknown)) {
          remove_it = true;
        }
      }

      if (remove_it) {
        func_list.RemoveContextAtIndex(idx);
        num_functions--;
        idx--;
      }
    }
  }

  // Remove any duplicates between the function list and the symbol list
  SymbolContext sc;
  if (func_list.GetSize()) {
    for (i = 0; i < func_list.GetSize(); i++) {
      if (func_list.GetContextAtIndex(i, sc)) {
        bool is_reexported = false;

        if (sc.block && sc.block->GetInlinedFunctionInfo()) {
          if (!sc.block->GetStartAddress(break_addr))
            break_addr.Clear();
        } else if (sc.function) {
          break_addr = sc.function->GetAddressRange().GetBaseAddress();
          if (m_skip_prologue && break_addr.IsValid()) {
            const uint32_t prologue_byte_size =
                sc.function->GetPrologueByteSize();
            if (prologue_byte_size)
              break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
          }
        } else if (sc.symbol) {
          if (sc.symbol->GetType() == eSymbolTypeReExported) {
            const Symbol *actual_symbol =
                sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget());
            if (actual_symbol) {
              is_reexported = true;
              break_addr = actual_symbol->GetAddress();
            }
          } else {
            break_addr = sc.symbol->GetAddress();
          }

          if (m_skip_prologue && break_addr.IsValid()) {
            const uint32_t prologue_byte_size =
                sc.symbol->GetPrologueByteSize();
            if (prologue_byte_size)
              break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
            else {
              const Architecture *arch =
                  m_breakpoint->GetTarget().GetArchitecturePlugin();
              if (arch)
                arch->AdjustBreakpointAddress(*sc.symbol, break_addr);
            }
          }
        }

        if (break_addr.IsValid()) {
          if (filter.AddressPasses(break_addr)) {
            BreakpointLocationSP bp_loc_sp(
                AddLocation(break_addr, &new_location));
            bp_loc_sp->SetIsReExported(is_reexported);
            if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) {
              if (log) {
                StreamString s;
                bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
                log->Printf("Added location: %s\n", s.GetData());
              }
            }
          }
        }
      }
    }
  }

  return Searcher::eCallbackReturnContinue;
}
Ejemplo n.º 5
0
void
BreakpointResolver::SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));

    while (sc_list.GetSize() > 0)
    {
        SymbolContextList tmp_sc_list;
        unsigned current_idx = 0;
        SymbolContext sc;
        bool first_entry = true;
        
        FileSpec match_file_spec;
        FileSpec match_original_file_spec;
        uint32_t closest_line_number = UINT32_MAX;

        // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
        while (current_idx < sc_list.GetSize())
        {
            bool matches;
            
            sc_list.GetContextAtIndex (current_idx, sc);
            if (first_entry)
            {
                match_file_spec = sc.line_entry.file;
                match_original_file_spec = sc.line_entry.original_file;
                matches = true;
                first_entry = false;
            }
            else
                matches = ((sc.line_entry.file == match_file_spec) ||
                           (sc.line_entry.original_file == match_original_file_spec));
            
            if (matches)
            {
                tmp_sc_list.Append (sc);
                sc_list.RemoveContextAtIndex(current_idx);
                
                // ResolveSymbolContext will always return a number that is >= the line number you pass in.
                // So the smaller line number is always better.
                if (sc.line_entry.line < closest_line_number)
                    closest_line_number = sc.line_entry.line;
            }
            else
                current_idx++;
        }
            
        // Okay, we've found the closest line number match, now throw away all the others:
        
        current_idx = 0;
        while (current_idx < tmp_sc_list.GetSize())
        {
            if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
            {
                if (sc.line_entry.line != closest_line_number)
                    tmp_sc_list.RemoveContextAtIndex(current_idx);
                else
                    current_idx++;
            }
        }
        
        // Next go through and see if there are line table entries that are contiguous, and if so keep only the
        // first of the contiguous range:
        
        current_idx = 0;
        std::map<Block *, lldb::addr_t> blocks_with_breakpoints;
        
        while (current_idx < tmp_sc_list.GetSize())
        {
            if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
            {
                if (blocks_with_breakpoints.find (sc.block) != blocks_with_breakpoints.end())
                    tmp_sc_list.RemoveContextAtIndex(current_idx);
                else
                {
                    blocks_with_breakpoints.insert (std::pair<Block *, lldb::addr_t>(sc.block, sc.line_entry.range.GetBaseAddress().GetFileAddress()));
                    current_idx++;
                }
            }
        }
        
        // and make breakpoints out of the closest line number match.
        
        uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
        
        for (uint32_t i = 0; i < tmp_sc_list_size; i++)
        {
            if (tmp_sc_list.GetContextAtIndex(i, sc))
            {
                Address line_start = sc.line_entry.range.GetBaseAddress();
                if (line_start.IsValid())
                {
                    if (filter.AddressPasses(line_start))
                    {
                        // If the line number is before the prologue end, move it there...
                        bool skipped_prologue = false;
                        if (skip_prologue)
                        {
                            if (sc.function)
                            {
                                Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
                                if (prologue_addr.IsValid() && (line_start == prologue_addr))
                                {
                                    const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
                                    if (prologue_byte_size)
                                    {
                                        prologue_addr.Slide(prologue_byte_size);
                 
                                        if (filter.AddressPasses(prologue_addr))
                                        {
                                            skipped_prologue = true;
                                            line_start = prologue_addr;
                                        }
                                    }
                                }
                            }
                        }
                    
                        BreakpointLocationSP bp_loc_sp (AddLocation(line_start));
                        if (log && bp_loc_sp && !m_breakpoint->IsInternal())
                        {
                            StreamString s;
                            bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
                            log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData());
                        }
                    }
                    else if (log)
                    {
                        log->Printf ("Breakpoint %s at file address 0x%" PRIx64 " didn't pass the filter.\n",
                                     log_ident ? log_ident : "",
                                     line_start.GetFileAddress());
                    }
                }
                else
                {
                    if (log)
                        log->Printf ("error: Unable to set breakpoint %s at file address 0x%" PRIx64 "\n",
                                     log_ident ? log_ident : "",
                                     line_start.GetFileAddress());
                }
            }
        }
    }
}
Ejemplo n.º 6
0
void
BreakpointResolver::ResolveBreakpoint (SearchFilter &filter)
{
    filter.Search (*this);
}
Ejemplo n.º 7
0
void
BreakpointResolver::ResolveBreakpointInModules (SearchFilter &filter, ModuleList &modules)
{
    filter.SearchInModuleList(*this, modules);
}
Ejemplo n.º 8
0
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;

    LogSP 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 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, 
                                              eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
                                              include_symbols,
                                              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,
                                              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->GetAddressRangePtr())
                    {
                        if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
                        {
                            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->GetAddressRangePtr())
            {
                func_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
                addr_t byte_size = sc.symbol->GetAddressRangePtr()->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::CallbackReturn
BreakpointResolverFileRegex::SearchCallback
(
    SearchFilter &filter,
    SymbolContext &context,
    Address *addr,
    bool containing
)
{

    assert (m_breakpoint != NULL);
    if (!context.target_sp)
        return eCallbackReturnContinue;
        
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));

    CompileUnit *cu = context.comp_unit;
    FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
    std::vector<uint32_t> line_matches;
    context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches); 
    uint32_t num_matches = line_matches.size();
    for (uint32_t i = 0; i < num_matches; i++)
    {
        uint32_t start_idx = 0;
        bool exact = false;
        while (1)
        {
            LineEntry line_entry;
        
            // Cycle through all the line entries that might match this one:
            start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, exact, &line_entry);
            if (start_idx == UINT32_MAX)
                break;
            exact = true;
            start_idx++;
            
            Address line_start = line_entry.range.GetBaseAddress();
            if (line_start.IsValid())
            {
                if (filter.AddressPasses(line_start))
                {
                    BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
                    if (log && bp_loc_sp && !m_breakpoint->IsInternal())
                    {
                        StreamString s;
                        bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
                        log->Printf ("Added location: %s\n", s.GetData());
                    }
                }
                else if (log)
                {
                    log->Printf ("Breakpoint at file address 0x%" PRIx64 " for %s:%d didn't pass filter.\n",
                                 line_start.GetFileAddress(),
                                 cu_file_spec.GetFilename().AsCString("<Unknown>"),
                                 line_matches[i]);
                }
            }
            else
            {
                if (log)
                    log->Printf ("error: Unable to set breakpoint at file address 0x%" PRIx64 " for %s:%d\n",
                                 line_start.GetFileAddress(),
                                 cu_file_spec.GetFilename().AsCString("<Unknown>"),
                                 line_matches[i]);
            }

        }
    }
    assert (m_breakpoint != NULL);        

    return Searcher::eCallbackReturnContinue;
}
Ejemplo n.º 10
0
void AddressResolver::ResolveAddress(SearchFilter &filter) {
  filter.Search(*this);
}
Ejemplo n.º 11
0
void AddressResolver::ResolveAddressInModules(SearchFilter &filter,
                                              ModuleList &modules) {
  filter.SearchInModuleList(*this, modules);
}