예제 #1
0
size_t
ModuleList::FindFunctions(const RegularExpression &name,
                          bool include_symbols,
                          bool include_inlines,
                          bool append,
                          SymbolContextList& sc_list)
{
    const size_t initial_size = sc_list.GetSize();

    Mutex::Locker locker(m_modules_mutex);
    collection::const_iterator pos, end = m_modules.end();
    collection dylinker_modules;
    for (pos = m_modules.begin(); pos != end; ++pos)
    {
        if (!(*pos)->GetIsDynamicLinkEditor())
            (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list);
        else
            dylinker_modules.push_back(*pos);
    }
    bool keep_looking = KeepLookingInDylinker(sc_list, initial_size);

    if (keep_looking)
    {
        end = dylinker_modules.end();
        for (pos = dylinker_modules.begin() ; pos != end; pos++)
            (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list);
    }
    return sc_list.GetSize() - initial_size;
}
예제 #2
0
size_t
ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, 
                                             lldb::SymbolType symbol_type, 
                                             SymbolContextList &sc_list,
                                             bool append) const
{
    Mutex::Locker locker(m_modules_mutex);
    if (!append)
        sc_list.Clear();
    size_t initial_size = sc_list.GetSize();
    
    collection::const_iterator pos, end = m_modules.end();
    collection dylinker_modules;
    for (pos = m_modules.begin(); pos != end; ++pos)
    {
        if (!(*pos)->GetIsDynamicLinkEditor())
        (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
        else
            dylinker_modules.push_back (*pos);
    }

    bool keep_looking = KeepLookingInDylinker(sc_list, initial_size);

    if (keep_looking)
    {
        end = dylinker_modules.end();
        for (pos = dylinker_modules.begin(); pos != end; ++pos)
            (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
    }
    return sc_list.GetSize() - initial_size;
}
예제 #3
0
size_t
ModuleList::FindFunctionSymbols (const ConstString &name,
                                 uint32_t name_type_mask,
                                 SymbolContextList& sc_list)
{
    const size_t old_size = sc_list.GetSize();

    if (name_type_mask & eFunctionNameTypeAuto)
    {
        ConstString lookup_name;
        uint32_t lookup_name_type_mask = 0;
        bool match_name_after_lookup = false;
        Module::PrepareForFunctionNameLookup (name, name_type_mask,
                                              eLanguageTypeUnknown, // TODO: add support
                                              lookup_name,
                                              lookup_name_type_mask,
                                              match_name_after_lookup);
    
        Mutex::Locker locker(m_modules_mutex);
        collection::const_iterator pos, end = m_modules.end();
        for (pos = m_modules.begin(); pos != end; ++pos)
        {
            (*pos)->FindFunctionSymbols (lookup_name,
                                   lookup_name_type_mask,
                                   sc_list);
        }
        
        if (match_name_after_lookup)
        {
            SymbolContext sc;
            size_t i = old_size;
            while (i < sc_list.GetSize())
            {
                if (sc_list.GetContextAtIndex(i, sc))
                {
                    const char *func_name = sc.GetFunctionName().GetCString();
                    if (func_name != nullptr && strstr(func_name, name.GetCString()) == nullptr)
                    {
                        // Remove the current context
                        sc_list.RemoveContextAtIndex(i);
                        // Don't increment i and continue in the loop
                        continue;
                    }
                }
                ++i;
            }
        }
    }
    else
    {
        Mutex::Locker locker(m_modules_mutex);
        collection::const_iterator pos, end = m_modules.end();
        for (pos = m_modules.begin(); pos != end; ++pos)
        {
            (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list);
        }
    }

    return sc_list.GetSize() - old_size;
}
예제 #4
0
size_t
ModuleList::FindSymbolsWithNameAndType (const ConstString &name, 
                                        SymbolType symbol_type, 
                                        SymbolContextList &sc_list,
                                        bool append) const
{
    Mutex::Locker locker(m_modules_mutex);
    if (!append)
        sc_list.Clear();
    size_t initial_size = sc_list.GetSize();
    
    collection::const_iterator pos, end = m_modules.end();
    collection dylinker_modules;
    for (pos = m_modules.begin(); pos != end; ++pos)
    {
        if (!(*pos)->GetIsDynamicLinkEditor())
            (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
        else
            dylinker_modules.push_back (*pos);
    }

    // Lets see if we found anything but undefined symbols.  If so, then we'll also look in the dylinker.
    bool keep_looking = KeepLookingInDylinker(sc_list, initial_size);

    if (keep_looking)
    {
        end = dylinker_modules.end();
        for (pos = dylinker_modules.begin(); pos != end; ++pos)
            (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
    }

    return sc_list.GetSize() - initial_size;
}
예제 #5
0
파일: Module.cpp 프로젝트: eightcien/lldb
size_t
Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list)
{
    // No need to protect this call using m_mutex all other method calls are
    // already thread safe.


    Timer scoped_timer(__PRETTY_FUNCTION__,
                       "Module::FindSymbolsWithNameAndType (name = %s, type = %i)",
                       name.AsCString(),
                       symbol_type);
    const size_t initial_size = sc_list.GetSize();
    ObjectFile *objfile = GetObjectFile ();
    if (objfile)
    {
        Symtab *symtab = objfile->GetSymtab();
        if (symtab)
        {
            std::vector<uint32_t> symbol_indexes;
            symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes);
            SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list);
        }
    }
    return sc_list.GetSize() - initial_size;
}
예제 #6
0
static bool
KeepLookingInDylinker (SymbolContextList &sc_list, size_t start_idx)
{
    bool keep_looking = true;
    if (sc_list.GetSize() == start_idx)
    {
        return true;
    }

    SymbolContext sc;
    size_t num_symbols = sc_list.GetSize();
    for (size_t idx = start_idx; idx < num_symbols; idx++)
    {
        sc_list.GetContextAtIndex(idx, sc);
        if (sc.symbol && sc.symbol->GetType() != lldb::eSymbolTypeUndefined)
        {
            keep_looking = false;
            break;
        }
        // If we have a function it's not going to be an undefined symbol...
        if (sc.function)
        {
            keep_looking = false;
            break;
        }
    }
    return keep_looking;
}
예제 #7
0
size_t
ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, 
                                             lldb::SymbolType symbol_type, 
                                             SymbolContextList &sc_list,
                                             bool append) const
{
    Mutex::Locker locker(m_modules_mutex);
    if (!append)
        sc_list.Clear();
    size_t initial_size = sc_list.GetSize();
    
    collection::const_iterator pos, end = m_modules.end();
    for (pos = m_modules.begin(); pos != end; ++pos)
        (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
    return sc_list.GetSize() - initial_size;
}
예제 #8
0
size_t
ModuleList::FindSymbolsWithNameAndType (const ConstString &name, 
                                        SymbolType symbol_type, 
                                        SymbolContextList &sc_list,
                                        bool append) const
{
    Mutex::Locker locker(m_modules_mutex);
    if (!append)
        sc_list.Clear();
    size_t initial_size = sc_list.GetSize();
    
    collection::const_iterator pos, end = m_modules.end();
    for (pos = m_modules.begin(); pos != end; ++pos)
        (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
    return sc_list.GetSize() - initial_size;
}
예제 #9
0
size_t
Disassembler::Disassemble
(
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    SymbolContextList &sc_list,
    uint32_t num_mixed_context_lines,
    bool show_bytes,
    Stream &strm
)
{
    size_t success_count = 0;
    const size_t count = sc_list.GetSize();
    SymbolContext sc;
    AddressRange range;
    for (size_t i=0; i<count; ++i)
    {
        if (sc_list.GetContextAtIndex(i, sc) == false)
            break;
        if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
        {
            if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm))
            {
                ++success_count;
                strm.EOL();
            }
        }
    }
    return success_count;
}
예제 #10
0
uint32_t
Module::FindFunctions (const ConstString &name,
                       const ClangNamespaceDecl *namespace_decl,
                       uint32_t name_type_mask, 
                       bool include_symbols,
                       bool include_inlines,
                       bool append, 
                       SymbolContextList& sc_list)
{
    if (!append)
        sc_list.Clear();

    const uint32_t start_size = sc_list.GetSize();

    // Find all the functions (not symbols, but debug information functions...
    SymbolVendor *symbols = GetSymbolVendor ();
    if (symbols)
        symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);

    // Now check our symbol table for symbols that are code symbols if requested
    if (include_symbols)
    {
        ObjectFile *objfile = GetObjectFile();
        if (objfile)
        {
            Symtab *symtab = objfile->GetSymtab();
            if (symtab)
            {
                std::vector<uint32_t> symbol_indexes;
                symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes);
                const uint32_t num_matches = symbol_indexes.size();
                if (num_matches)
                {
                    const bool merge_symbol_into_function = true;
                    SymbolContext sc(this);
                    for (uint32_t i=0; i<num_matches; i++)
                    {
                        sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
                        sc_list.AppendIfUnique (sc, merge_symbol_into_function);
                    }
                }
            }
        }
    }
    return sc_list.GetSize() - start_size;
}
예제 #11
0
size_t
ModuleList::FindFunctions(const RegularExpression &name,
                          bool include_symbols,
                          bool include_inlines,
                          bool append,
                          SymbolContextList& sc_list)
{
    const size_t old_size = sc_list.GetSize();

    Mutex::Locker locker(m_modules_mutex);
    collection::const_iterator pos, end = m_modules.end();
    for (pos = m_modules.begin(); pos != end; ++pos)
    {
        (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list);
    }

    return sc_list.GetSize() - old_size;
}
예제 #12
0
 bool ContainsCompileUnit(const SymbolContextList &sc_list,
                          const FileSpec &spec) const {
     for (size_t i = 0; i < sc_list.GetSize(); ++i) {
         const SymbolContext &sc = sc_list[i];
         if (FileSpecMatchesAsBaseOrFull(*sc.comp_unit, spec))
             return true;
     }
     return false;
 }
예제 #13
0
bool
lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs)
{
    const uint32_t size = lhs.GetSize();
    if (size != rhs.GetSize())
        return false;
    
    SymbolContext lhs_sc;
    SymbolContext rhs_sc;
    for (uint32_t i=0; i<size; ++i)
    {
        lhs.GetContextAtIndex(i, lhs_sc);
        rhs.GetContextAtIndex(i, rhs_sc);
        if (lhs_sc != rhs_sc)
            return false;
    }
    return true;
}
예제 #14
0
uint32_t
Module::FindFunctions (const RegularExpression& regex, 
                       bool include_symbols,
                       bool include_inlines,
                       bool append, 
                       SymbolContextList& sc_list)
{
    if (!append)
        sc_list.Clear();
    
    const uint32_t start_size = sc_list.GetSize();
    
    SymbolVendor *symbols = GetSymbolVendor ();
    if (symbols)
        symbols->FindFunctions(regex, include_inlines, append, sc_list);
    // Now check our symbol table for symbols that are code symbols if requested
    if (include_symbols)
    {
        ObjectFile *objfile = GetObjectFile();
        if (objfile)
        {
            Symtab *symtab = objfile->GetSymtab();
            if (symtab)
            {
                std::vector<uint32_t> symbol_indexes;
                symtab->AppendSymbolIndexesMatchingRegExAndType (regex, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes);
                const uint32_t num_matches = symbol_indexes.size();
                if (num_matches)
                {
                    const bool merge_symbol_into_function = true;
                    SymbolContext sc(this);
                    for (uint32_t i=0; i<num_matches; i++)
                    {
                        sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
                        sc_list.AppendIfUnique (sc, merge_symbol_into_function);
                    }
                }
            }
        }
    }
    return sc_list.GetSize() - start_size;
}
예제 #15
0
파일: Module.cpp 프로젝트: eightcien/lldb
uint32_t
Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
{
    Mutex::Locker locker (m_mutex);
    Timer scoped_timer(__PRETTY_FUNCTION__,
                       "Module::ResolveSymbolContextForFilePath (%s%s%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)",
                       file_spec.GetDirectory().AsCString(""),
                       file_spec.GetDirectory() ? "/" : "",
                       file_spec.GetFilename().AsCString(""),
                       line,
                       check_inlines ? "yes" : "no",
                       resolve_scope);

    const uint32_t initial_count = sc_list.GetSize();

    SymbolVendor *symbols = GetSymbolVendor  ();
    if (symbols)
        symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list);

    return sc_list.GetSize() - initial_count;
}
예제 #16
0
uint32_t
ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const
{
    Mutex::Locker locker(m_modules_mutex);
    collection::const_iterator pos, end = m_modules.end();
    for (pos = m_modules.begin(); pos != end; ++pos)
    {
        (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
    }

    return sc_list.GetSize();
}
예제 #17
0
파일: Module.cpp 프로젝트: markpeek/lldb
uint32_t
Module::FindCompileUnits (const FileSpec &path,
                          bool append,
                          SymbolContextList &sc_list)
{
    if (!append)
        sc_list.Clear();
    
    const uint32_t start_size = sc_list.GetSize();
    const uint32_t num_compile_units = GetNumCompileUnits();
    SymbolContext sc;
    sc.module_sp = this;
    const bool compare_directory = path.GetDirectory();
    for (uint32_t i=0; i<num_compile_units; ++i)
    {
        sc.comp_unit = GetCompileUnitAtIndex(i).get();
        if (FileSpec::Equal (*sc.comp_unit, path, compare_directory))
            sc_list.Append(sc);
    }
    return sc_list.GetSize() - start_size;
}
예제 #18
0
파일: Module.cpp 프로젝트: eightcien/lldb
size_t
Module::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, SymbolType symbol_type, SymbolContextList &sc_list)
{
    // No need to protect this call using m_mutex all other method calls are
    // already thread safe.

    Timer scoped_timer(__PRETTY_FUNCTION__,
                       "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)",
                       regex.GetText(),
                       symbol_type);
    const size_t initial_size = sc_list.GetSize();
    ObjectFile *objfile = GetObjectFile ();
    if (objfile)
    {
        Symtab *symtab = objfile->GetSymtab();
        if (symtab)
        {
            std::vector<uint32_t> symbol_indexes;
            symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes);
            SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list);
        }
    }
    return sc_list.GetSize() - initial_size;
}
예제 #19
0
size_t
ModuleList::FindCompileUnits (const FileSpec &path, 
                              bool append, 
                              SymbolContextList &sc_list) const
{
    if (!append)
        sc_list.Clear();
    
    Mutex::Locker locker(m_modules_mutex);
    collection::const_iterator pos, end = m_modules.end();
    for (pos = m_modules.begin(); pos != end; ++pos)
    {
        (*pos)->FindCompileUnits (path, true, sc_list);
    }
    
    return sc_list.GetSize();
}
예제 #20
0
size_t
Disassembler::Disassemble
(
    Debugger &debugger,
    const ArchSpec &arch,
    const char *plugin_name,
    const char *flavor,
    const ExecutionContext &exe_ctx,
    SymbolContextList &sc_list,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    size_t success_count = 0;
    const size_t count = sc_list.GetSize();
    SymbolContext sc;
    AddressRange range;
    const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
    const bool use_inline_block_range = true;
    for (size_t i=0; i<count; ++i)
    {
        if (sc_list.GetContextAtIndex(i, sc) == false)
            break;
        for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx)
        {
            if (Disassemble (debugger, 
                             arch, 
                             plugin_name,
                             flavor,
                             exe_ctx, 
                             range, 
                             num_instructions,
                             num_mixed_context_lines, 
                             options, 
                             strm))
            {
                ++success_count;
                strm.EOL();
            }
        }
    }
    return success_count;
}
예제 #21
0
uint32_t
ModuleList::FindFunctions (const ConstString &name, 
                           uint32_t name_type_mask, 
                           bool include_symbols,
                           bool append, 
                           SymbolContextList &sc_list)
{
    if (!append)
        sc_list.Clear();
    
    Mutex::Locker locker(m_modules_mutex);
    collection::const_iterator pos, end = m_modules.end();
    for (pos = m_modules.begin(); pos != end; ++pos)
    {
        (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, true, sc_list);
    }
    
    return sc_list.GetSize();
}
예제 #22
0
void
BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const
{
    if (match_name_after_lookup && name)
    {
        SymbolContext sc;
        size_t i = start_idx;
        while (i < sc_list.GetSize())
        {
            if (!sc_list.GetContextAtIndex(i, sc))
                break;
            ConstString full_name (sc.GetFunctionName());
            if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL)
            {
                sc_list.RemoveContextAtIndex(i);
            }
            else
            {
                ++i;
            }
        }
    }
}
예제 #23
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());
                }
            }
        }
    }
}
예제 #24
0
uint32_t
CompileUnit::ResolveSymbolContext
(
    const FileSpec& file_spec,
    uint32_t line,
    bool check_inlines,
    bool exact,
    uint32_t resolve_scope,
    SymbolContextList &sc_list
)
{
    // First find all of the file indexes that match our "file_spec". If 
    // "file_spec" has an empty directory, then only compare the basenames
    // when finding file indexes
    std::vector<uint32_t> file_indexes;
    bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, !file_spec.GetDirectory().IsEmpty());

    // If we are not looking for inlined functions and our file spec doesn't
    // match then we are done...
    if (file_spec_matches_cu_file_spec == false && check_inlines == false)
        return 0;

    uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true);
    while (file_idx != UINT32_MAX)
    {
        file_indexes.push_back (file_idx);
        file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true);
    }
    
    const size_t num_file_indexes = file_indexes.size();
    if (num_file_indexes == 0)
        return 0;

    const uint32_t prev_size = sc_list.GetSize();

    SymbolContext sc(GetModule());
    sc.comp_unit = this;


    if (line != 0)
    {
        LineTable *line_table = sc.comp_unit->GetLineTable();

        if (line_table != NULL)
        {
            uint32_t found_line;
            uint32_t line_idx;
            
            if (num_file_indexes == 1)
            {
                // We only have a single support file that matches, so use
                // the line table function that searches for a line entries
                // that match a single support file index
                LineEntry line_entry;
                line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &line_entry);

                // If "exact == true", then "found_line" will be the same
                // as "line". If "exact == false", the "found_line" will be the
                // closest line entry with a line number greater than "line" and 
                // we will use this for our subsequent line exact matches below.
                found_line = line_entry.line;

                while (line_idx != UINT32_MAX)
                {
                    // If they only asked for the line entry, then we're done, we can just copy that over.
                    // But if they wanted more than just the line number, fill it in.
                    if (resolve_scope == eSymbolContextLineEntry)
                    {
                        sc.line_entry = line_entry;
                    }
                    else
                    {
                        line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope);
                    }
                    
                    sc_list.Append(sc);
                    line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &line_entry);
                }
            }
            else
            {
                // We found multiple support files that match "file_spec" so use
                // the line table function that searches for a line entries
                // that match a multiple support file indexes.
                LineEntry line_entry;
                line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &line_entry);

                // If "exact == true", then "found_line" will be the same
                // as "line". If "exact == false", the "found_line" will be the
                // closest line entry with a line number greater than "line" and 
                // we will use this for our subsequent line exact matches below.
                found_line = line_entry.line;

                while (line_idx != UINT32_MAX)
                {
                    if (resolve_scope == eSymbolContextLineEntry)
                    {
                        sc.line_entry = line_entry;
                    }
                    else
                    {
                        line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope);
                    }
                    
                    sc_list.Append(sc);
                    line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &line_entry);
                }
            }
        }
    }
    else if (file_spec_matches_cu_file_spec && !check_inlines)
    {
        // only append the context if we aren't looking for inline call sites
        // by file and line and if the file spec matches that of the compile unit
        sc_list.Append(sc);
    }
    return sc_list.GetSize() - prev_size;
}
void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter,
                                            SymbolContextList &sc_list,
                                            bool skip_prologue,
                                            llvm::StringRef log_ident,
                                            uint32_t line, uint32_t column) {
  llvm::SmallVector<SymbolContext, 16> all_scs;
  for (uint32_t i = 0; i < sc_list.GetSize(); ++i)
    all_scs.push_back(sc_list[i]);

  while (all_scs.size()) {
    uint32_t closest_line = UINT32_MAX;

    // Move all the elements with a matching file spec to the end.
    auto &match = all_scs[0];
    auto worklist_begin = std::partition(
        all_scs.begin(), all_scs.end(), [&](const SymbolContext &sc) {
          if (sc.line_entry.file == match.line_entry.file ||
              sc.line_entry.original_file == match.line_entry.original_file) {
            // When a match is found, keep track of the smallest line number.
            closest_line = std::min(closest_line, sc.line_entry.line);
            return false;
          }
          return true;
        });

    // (worklist_begin, worklist_end) now contains all entries for one filespec.
    auto worklist_end = all_scs.end();

    if (column) {
      // If a column was requested, do a more precise match and only
      // return the first location that comes after or at the
      // requested location.
      SourceLoc requested(line, column);
      // First, filter out all entries left of the requested column.
      worklist_end = std::remove_if(
          worklist_begin, worklist_end,
          [&](const SymbolContext &sc) { return SourceLoc(sc) < requested; });
      // Sort the remaining entries by (line, column).
      llvm::sort(worklist_begin, worklist_end,
                 [](const SymbolContext &a, const SymbolContext &b) {
                   return SourceLoc(a) < SourceLoc(b);
                 });

      // Filter out all locations with a source location after the closest match.
      if (worklist_begin != worklist_end)
        worklist_end = std::remove_if(
            worklist_begin, worklist_end, [&](const SymbolContext &sc) {
              return SourceLoc(*worklist_begin) < SourceLoc(sc);
            });
    } else {
      // Remove all entries with a larger line number.
      // ResolveSymbolContext will always return a number that is >=
      // the line number you pass in. So the smaller line number is
      // always better.
      worklist_end = std::remove_if(worklist_begin, worklist_end,
                                    [&](const SymbolContext &sc) {
                                      return closest_line != sc.line_entry.line;
                                    });
    }

    // Sort by file address.
    llvm::sort(worklist_begin, worklist_end,
               [](const SymbolContext &a, const SymbolContext &b) {
                 return a.line_entry.range.GetBaseAddress().GetFileAddress() <
                        b.line_entry.range.GetBaseAddress().GetFileAddress();
               });

    // Go through and see if there are line table entries that are
    // contiguous, and if so keep only the first of the contiguous range.
    // We do this by picking the first location in each lexical block.
    llvm::SmallDenseSet<Block *, 8> blocks_with_breakpoints;
    for (auto first = worklist_begin; first != worklist_end; ++first) {
      assert(!blocks_with_breakpoints.count(first->block));
      blocks_with_breakpoints.insert(first->block);
      worklist_end =
          std::remove_if(std::next(first), worklist_end,
                         [&](const SymbolContext &sc) {
                           return blocks_with_breakpoints.count(sc.block);
                         });
    }

    // Make breakpoints out of the closest line number match.
    for (auto &sc : llvm::make_range(worklist_begin, worklist_end))
      AddLocation(filter, sc, skip_prologue, log_ident);

    // Remove all contexts processed by this iteration.
    all_scs.erase(worklist_begin, all_scs.end());
  }
}
예제 #26
0
size_t
ModuleList::FindFunctions (const ConstString &name, 
                           uint32_t name_type_mask, 
                           bool include_symbols,
                           bool include_inlines,
                           bool append, 
                           SymbolContextList &sc_list) const
{
    if (!append)
        sc_list.Clear();
    
    const size_t old_size = sc_list.GetSize();
    
    if (name_type_mask & eFunctionNameTypeAuto)
    {
        ConstString lookup_name;
        uint32_t lookup_name_type_mask = 0;
        bool match_name_after_lookup = false;
        Module::PrepareForFunctionNameLookup (name, name_type_mask,
                                              lookup_name,
                                              lookup_name_type_mask,
                                              match_name_after_lookup);
    
        Mutex::Locker locker(m_modules_mutex);
        collection::const_iterator pos, end = m_modules.end();
        for (pos = m_modules.begin(); pos != end; ++pos)
        {
            (*pos)->FindFunctions (lookup_name,
                                   NULL,
                                   lookup_name_type_mask,
                                   include_symbols,
                                   include_inlines,
                                   true,
                                   sc_list);
        }
        
        if (match_name_after_lookup)
        {
            SymbolContext sc;
            size_t i = old_size;
            while (i<sc_list.GetSize())
            {
                if (sc_list.GetContextAtIndex(i, sc))
                {
                    const char *func_name = sc.GetFunctionName().GetCString();
                    if (func_name && strstr (func_name, name.GetCString()) == NULL)
                    {
                        // Remove the current context
                        sc_list.RemoveContextAtIndex(i);
                        // Don't increment i and continue in the loop
                        continue;
                    }
                }
                ++i;
            }
        }

    }
    else
    {
        Mutex::Locker locker(m_modules_mutex);
        collection::const_iterator pos, end = m_modules.end();
        for (pos = m_modules.begin(); pos != end; ++pos)
        {
            (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
        }
    }
    return sc_list.GetSize() - old_size;
}