forked from OSchip/llvm-project
Bug #: 8408441
Fixed an issue where LLDB would fail to set a breakpoint by file and line if the DWARF line table has multiple file entries in the support files for a source file. llvm-svn: 113721
This commit is contained in:
parent
26abd3e0c2
commit
fd26915742
|
@ -158,6 +158,13 @@ public:
|
|||
uint32_t
|
||||
FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr);
|
||||
|
||||
uint32_t
|
||||
FindLineEntryIndexByFileIndex (uint32_t start_idx,
|
||||
const std::vector<uint32_t> &file_indexes,
|
||||
uint32_t line,
|
||||
bool exact,
|
||||
LineEntry* line_entry_ptr);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the line entry from the line table at index \a idx.
|
||||
///
|
||||
|
|
|
@ -281,58 +281,88 @@ CompileUnit::ResolveSymbolContext
|
|||
SymbolContextList &sc_list
|
||||
)
|
||||
{
|
||||
const uint32_t prev_size = sc_list.GetSize();
|
||||
// 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::Compare(file_spec, this, !file_spec.GetDirectory().IsEmpty()) == 0;
|
||||
if (check_inlines || file_spec_matches_cu_file_spec)
|
||||
|
||||
// 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);
|
||||
while (file_idx != UINT32_MAX)
|
||||
{
|
||||
SymbolContext sc(GetModule());
|
||||
sc.comp_unit = this;
|
||||
file_indexes.push_back (file_idx);
|
||||
file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec);
|
||||
}
|
||||
|
||||
const size_t num_file_indexes = file_indexes.size();
|
||||
if (num_file_indexes == 0)
|
||||
return 0;
|
||||
|
||||
uint32_t file_idx = UINT32_MAX;
|
||||
const uint32_t prev_size = sc_list.GetSize();
|
||||
|
||||
// If we are looking for inline functions only and we don't
|
||||
// find it in the support files, we are done.
|
||||
SymbolContext sc(GetModule());
|
||||
sc.comp_unit = this;
|
||||
|
||||
if (check_inlines)
|
||||
|
||||
if (line != 0)
|
||||
{
|
||||
LineTable *line_table = sc.comp_unit->GetLineTable();
|
||||
|
||||
if (line_table != NULL)
|
||||
{
|
||||
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
|
||||
if (file_idx == UINT32_MAX)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 will have already looked up the file index if
|
||||
// we are searching for inline entries.
|
||||
if (!check_inlines)
|
||||
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
|
||||
// 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
|
||||
line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &sc.line_entry);
|
||||
|
||||
if (file_idx != UINT32_MAX)
|
||||
// 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 = sc.line_entry.line;
|
||||
|
||||
while (line_idx != UINT_MAX)
|
||||
{
|
||||
uint32_t found_line;
|
||||
sc_list.Append(sc);
|
||||
line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &sc.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.
|
||||
line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &sc.line_entry);
|
||||
|
||||
uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, exact, &sc.line_entry);
|
||||
found_line = sc.line_entry.line;
|
||||
// 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 = sc.line_entry.line;
|
||||
|
||||
while (line_idx != UINT_MAX)
|
||||
{
|
||||
sc_list.Append(sc);
|
||||
line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry);
|
||||
}
|
||||
while (line_idx != UINT_MAX)
|
||||
{
|
||||
sc_list.Append(sc);
|
||||
line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &sc.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);
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -280,6 +280,64 @@ LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
LineTable::FindLineEntryIndexByFileIndex
|
||||
(
|
||||
uint32_t start_idx,
|
||||
const std::vector<uint32_t> &file_indexes,
|
||||
uint32_t line,
|
||||
bool exact,
|
||||
LineEntry* line_entry_ptr
|
||||
)
|
||||
{
|
||||
|
||||
const size_t count = m_entries.size();
|
||||
std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin();
|
||||
std::vector<uint32_t>::const_iterator end_pos = file_indexes.end();
|
||||
size_t best_match = UINT_MAX;
|
||||
|
||||
for (size_t idx = start_idx; idx < count; ++idx)
|
||||
{
|
||||
// Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
|
||||
if (m_entries[idx].is_terminal_entry)
|
||||
continue;
|
||||
|
||||
if (find (begin_pos, end_pos, m_entries[idx].file_idx) == end_pos)
|
||||
continue;
|
||||
|
||||
// Exact match always wins. Otherwise try to find the closest line > the desired
|
||||
// line.
|
||||
// FIXME: Maybe want to find the line closest before and the line closest after and
|
||||
// if they're not in the same function, don't return a match.
|
||||
|
||||
if (m_entries[idx].line < line)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (m_entries[idx].line == line)
|
||||
{
|
||||
if (line_entry_ptr)
|
||||
ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr);
|
||||
return idx;
|
||||
}
|
||||
else if (!exact)
|
||||
{
|
||||
if (best_match == UINT32_MAX)
|
||||
best_match = idx;
|
||||
else if (m_entries[idx].line < m_entries[best_match].line)
|
||||
best_match = idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_match != UINT_MAX)
|
||||
{
|
||||
if (line_entry_ptr)
|
||||
ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr);
|
||||
return best_match;
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
LineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue