Files
clang-p2996/lldb/source/Symbol/LineTable.cpp
Greg Clayton 0c5cd90d63 Added function name types to allow us to set breakpoints by name more
intelligently. The four name types we currently have are:

eFunctionNameTypeFull       = (1 << 1), // The function name.
                                        // For C this is the same as just the name of the function
                                        // For C++ this is the demangled version of the mangled name.
                                        // For ObjC this is the full function signature with the + or
                                        // - and the square brackets and the class and selector
eFunctionNameTypeBase       = (1 << 2), // The function name only, no namespaces or arguments and no class 
                                        // methods or selectors will be searched.
eFunctionNameTypeMethod     = (1 << 3), // Find function by method name (C++) with no namespace or arguments
eFunctionNameTypeSelector   = (1 << 4)  // Find function by selector name (ObjC) names


this allows much more flexibility when setting breakoints:

(lldb) breakpoint set --name main --basename
(lldb) breakpoint set --name main --fullname
(lldb) breakpoint set --name main --method
(lldb) breakpoint set --name main --selector

The default:

(lldb) breakpoint set --name main

will inspect the name "main" and look for any parens, or if the name starts
with "-[" or "+[" and if any are found then a full name search will happen.
Else a basename search will be the default.

Fixed some command option structures so not all options are required when they
shouldn't be.

Cleaned up the breakpoint output summary.

Made the "image lookup --address <addr>" output much more verbose so it shows
all the important symbol context results. Added a GetDescription method to 
many of the SymbolContext objects for the more verbose output.

llvm-svn: 107075
2010-06-28 21:30:43 +00:00

334 lines
11 KiB
C++

//===-- LineTable.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/Address.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include <algorithm>
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// LineTable constructor
//----------------------------------------------------------------------
LineTable::LineTable(CompileUnit* comp_unit) :
m_comp_unit(comp_unit),
m_section_list(),
m_entries()
{
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
LineTable::~LineTable()
{
}
//void
//LineTable::AddLineEntry(const LineEntry& entry)
//{
// // Do a binary search for the correct entry and insert it
// m_line_entries.insert(std::upper_bound(m_line_entries.begin(), m_line_entries.end(), entry), entry);
//}
void
LineTable::AppendLineEntry
(
SectionSP& section_sp,
lldb::addr_t section_offset,
uint32_t line,
uint16_t column,
uint16_t file_idx,
bool is_start_of_statement,
bool is_start_of_basic_block,
bool is_prologue_end,
bool is_epilogue_begin,
bool is_terminal_entry
)
{
uint32_t sect_idx = m_section_list.AddUniqueSection (section_sp);
// Make sure we don't user more than 256 sections as that is all we have
// room for in the LineTable::Entry::m_sect_idx. If this assert fires,
// we will need to m_sect_idx have more bits...
assert((section_offset & 0xffffffffff000000ull) == 0);
Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
m_entries.push_back (entry);
}
void
LineTable::InsertLineEntry
(
SectionSP& section_sp,
lldb::addr_t section_offset,
uint32_t line,
uint16_t column,
uint16_t file_idx,
bool is_start_of_statement,
bool is_start_of_basic_block,
bool is_prologue_end,
bool is_epilogue_begin,
bool is_terminal_entry
)
{
SectionSP line_section_sp(section_sp);
const Section *linked_section = line_section_sp->GetLinkedSection();
if (linked_section)
{
section_offset += line_section_sp->GetLinkedOffset();
line_section_sp = linked_section->GetSharedPointer();
assert(line_section_sp.get());
}
uint32_t sect_idx = m_section_list.AddUniqueSection (line_section_sp);
// Make sure we don't user more than 256 sections as that is all we have
// room for in the LineTable::Entry::m_sect_idx. If this assert fires,
// we will need to m_sect_idx have more bits...
assert((section_offset & 0xffffffffff000000ull) == 0);
Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
entry_collection::iterator begin_pos = m_entries.begin();
entry_collection::iterator end_pos = m_entries.end();
LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp);
// Stream s(stdout);
// s << "\n\nBefore:\n";
// Dump (&s, Address::DumpStyleFileAddress);
m_entries.insert(pos, entry);
// s << "After:\n";
// Dump (&s, Address::DumpStyleFileAddress);
}
//----------------------------------------------------------------------
LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) :
m_line_table (line_table)
{
}
bool
LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const
{
if (a.sect_idx == b.sect_idx)
{
#define LT_COMPARE(a,b) if (a != b) return a < b
LT_COMPARE (a.sect_offset, b.sect_offset);
LT_COMPARE (a.line, b.line);
LT_COMPARE (a.column, b.column);
LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement);
LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block);
// b and a reversed on purpose below.
LT_COMPARE (b.is_prologue_end, a.is_prologue_end);
LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin);
// b and a reversed on purpose below.
LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry);
LT_COMPARE (a.file_idx, b.file_idx);
return false;
#undef LT_COMPARE
}
const Section *a_section = m_line_table->GetSectionForEntryIndex (a.sect_idx);
const Section *b_section = m_line_table->GetSectionForEntryIndex (b.sect_idx);
return Section::Compare(*a_section, *b_section) < 0;
}
Section *
LineTable::GetSectionForEntryIndex (uint32_t idx)
{
if (idx < m_section_list.GetSize())
return m_section_list.GetSectionAtIndex(idx).get();
return NULL;
}
uint32_t
LineTable::GetSize() const
{
return m_entries.size();
}
bool
LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry)
{
if (idx < m_entries.size())
{
ConvertEntryAtIndexToLineEntry (idx, line_entry);
return true;
}
line_entry.Clear();
return false;
}
bool
LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr)
{
if (index_ptr != NULL )
*index_ptr = UINT32_MAX;
bool success = false;
uint32_t sect_idx = m_section_list.FindSectionIndex (so_addr.GetSection());
if (sect_idx != UINT32_MAX)
{
Entry search_entry;
search_entry.sect_idx = sect_idx;
search_entry.sect_offset = so_addr.GetOffset();
entry_collection::const_iterator begin_pos = m_entries.begin();
entry_collection::const_iterator end_pos = m_entries.end();
entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan);
if (pos != end_pos)
{
if (pos != begin_pos)
{
if (pos->sect_offset != search_entry.sect_offset)
--pos;
else if (pos->sect_offset == search_entry.sect_offset)
{
while (pos != begin_pos)
{
entry_collection::const_iterator prev_pos = pos - 1;
if (prev_pos->sect_idx == search_entry.sect_idx &&
prev_pos->sect_offset == search_entry.sect_offset)
--pos;
else
break;
}
}
}
uint32_t match_idx = std::distance (begin_pos, pos);
success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
if (index_ptr != NULL && success)
*index_ptr = match_idx;
}
}
return success;
}
bool
LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry)
{
if (idx < m_entries.size())
{
const Entry& entry = m_entries[idx];
line_entry.range.GetBaseAddress().SetSection(m_section_list.GetSectionAtIndex (entry.sect_idx).get());
line_entry.range.GetBaseAddress().SetOffset(entry.sect_offset);
if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
{
const Entry& next_entry = m_entries[idx+1];
if (next_entry.sect_idx == entry.sect_idx)
{
line_entry.range.SetByteSize(next_entry.sect_offset - entry.sect_offset);
}
else
{
Address next_line_addr(m_section_list.GetSectionAtIndex (next_entry.sect_idx).get(), next_entry.sect_offset);
line_entry.range.SetByteSize(next_line_addr.GetFileAddress() - line_entry.range.GetBaseAddress().GetFileAddress());
}
}
else
line_entry.range.SetByteSize(0);
line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx);
line_entry.line = entry.line;
line_entry.column = entry.column;
line_entry.is_start_of_statement = entry.is_start_of_statement;
line_entry.is_start_of_basic_block = entry.is_start_of_basic_block;
line_entry.is_prologue_end = entry.is_prologue_end;
line_entry.is_epilogue_begin = entry.is_epilogue_begin;
line_entry.is_terminal_entry = entry.is_terminal_entry;
return true;
}
return false;
}
uint32_t
LineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr)
{
const size_t count = m_entries.size();
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 (m_entries[idx].file_idx != file_idx)
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;
}
void
LineTable::Dump (Stream *s, Process *process, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges)
{
const size_t count = m_entries.size();
LineEntry line_entry;
FileSpec prev_file;
for (size_t idx = 0; idx < count; ++idx)
{
ConvertEntryAtIndexToLineEntry (idx, line_entry);
line_entry.Dump (s, process, prev_file != line_entry.file, style, fallback_style, show_line_ranges);
s->EOL();
prev_file = line_entry.file;
}
}
void
LineTable::GetDescription (Stream *s, Process *process, DescriptionLevel level)
{
const size_t count = m_entries.size();
LineEntry line_entry;
for (size_t idx = 0; idx < count; ++idx)
{
ConvertEntryAtIndexToLineEntry (idx, line_entry);
line_entry.GetDescription (s, level, m_comp_unit, process, true);
s->EOL();
}
}