1254721Semaste//===-- BreakpointResolverFileLine.cpp --------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Breakpoint/BreakpointResolverFileLine.h" 11254721Semaste 12254721Semaste// C Includes 13254721Semaste// C++ Includes 14254721Semaste// Other libraries and framework includes 15254721Semaste// Project includes 16254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h" 17254721Semaste#include "lldb/Core/Log.h" 18254721Semaste#include "lldb/Core/Module.h" 19254721Semaste#include "lldb/Core/StreamString.h" 20254721Semaste#include "lldb/Symbol/CompileUnit.h" 21254721Semaste#include "lldb/Symbol/Function.h" 22254721Semaste#include "lldb/lldb-private-log.h" 23254721Semaste 24254721Semasteusing namespace lldb; 25254721Semasteusing namespace lldb_private; 26254721Semaste 27254721Semaste//---------------------------------------------------------------------- 28254721Semaste// BreakpointResolverFileLine: 29254721Semaste//---------------------------------------------------------------------- 30254721SemasteBreakpointResolverFileLine::BreakpointResolverFileLine 31254721Semaste( 32254721Semaste Breakpoint *bkpt, 33254721Semaste const FileSpec &file_spec, 34254721Semaste uint32_t line_no, 35254721Semaste bool check_inlines, 36254721Semaste bool skip_prologue 37254721Semaste) : 38254721Semaste BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver), 39254721Semaste m_file_spec (file_spec), 40254721Semaste m_line_number (line_no), 41254721Semaste m_inlines (check_inlines), 42254721Semaste m_skip_prologue(skip_prologue) 43254721Semaste{ 44254721Semaste} 45254721Semaste 46254721SemasteBreakpointResolverFileLine::~BreakpointResolverFileLine () 47254721Semaste{ 48254721Semaste} 49254721Semaste 50254721SemasteSearcher::CallbackReturn 51254721SemasteBreakpointResolverFileLine::SearchCallback 52254721Semaste( 53254721Semaste SearchFilter &filter, 54254721Semaste SymbolContext &context, 55254721Semaste Address *addr, 56254721Semaste bool containing 57254721Semaste) 58254721Semaste{ 59254721Semaste SymbolContextList sc_list; 60254721Semaste 61254721Semaste assert (m_breakpoint != NULL); 62254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 63254721Semaste 64254721Semaste // There is a tricky bit here. You can have two compilation units that #include the same file, and 65254721Semaste // 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 66254721Semaste // other it isn't. If we considered the CU's independently, then in the second inclusion, we'd move the breakpoint 67254721Semaste // to the next function that actually generated code in the header file. That would end up being confusing. 68254721Semaste // So instead, we do the CU iterations by hand here, then scan through the complete list of matches, and figure out 69254721Semaste // the closest line number match, and only set breakpoints on that match. 70254721Semaste 71254721Semaste // Note also that if file_spec only had a file name and not a directory, there may be many different file spec's in 72254721Semaste // the resultant list. The closest line match for one will not be right for some totally different file. 73254721Semaste // So we go through the match list and pull out the sets that have the same file spec in their line_entry 74254721Semaste // and treat each set separately. 75254721Semaste 76254721Semaste const size_t num_comp_units = context.module_sp->GetNumCompileUnits(); 77254721Semaste for (size_t i = 0; i < num_comp_units; i++) 78254721Semaste { 79254721Semaste CompUnitSP cu_sp (context.module_sp->GetCompileUnitAtIndex (i)); 80254721Semaste if (cu_sp) 81254721Semaste { 82254721Semaste if (filter.CompUnitPasses(*cu_sp)) 83254721Semaste cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list); 84254721Semaste } 85254721Semaste } 86254721Semaste 87254721Semaste while (sc_list.GetSize() > 0) 88254721Semaste { 89254721Semaste SymbolContextList tmp_sc_list; 90254721Semaste unsigned current_idx = 0; 91254721Semaste SymbolContext sc; 92254721Semaste bool first_entry = true; 93254721Semaste 94254721Semaste FileSpec match_file_spec; 95254721Semaste uint32_t closest_line_number = UINT32_MAX; 96254721Semaste 97254721Semaste // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list. 98254721Semaste while (current_idx < sc_list.GetSize()) 99254721Semaste { 100254721Semaste bool matches; 101254721Semaste 102254721Semaste sc_list.GetContextAtIndex (current_idx, sc); 103254721Semaste if (first_entry) 104254721Semaste { 105254721Semaste match_file_spec = sc.line_entry.file; 106254721Semaste matches = true; 107254721Semaste first_entry = false; 108254721Semaste } 109254721Semaste else 110254721Semaste matches = (sc.line_entry.file == match_file_spec); 111254721Semaste 112254721Semaste if (matches) 113254721Semaste { 114254721Semaste tmp_sc_list.Append (sc); 115254721Semaste sc_list.RemoveContextAtIndex(current_idx); 116254721Semaste 117254721Semaste // ResolveSymbolContext will always return a number that is >= the line number you pass in. 118254721Semaste // So the smaller line number is always better. 119254721Semaste if (sc.line_entry.line < closest_line_number) 120254721Semaste closest_line_number = sc.line_entry.line; 121254721Semaste } 122254721Semaste else 123254721Semaste current_idx++; 124254721Semaste } 125254721Semaste 126254721Semaste // Okay, we've found the closest line number match, now throw away all the others: 127254721Semaste 128254721Semaste current_idx = 0; 129254721Semaste while (current_idx < tmp_sc_list.GetSize()) 130254721Semaste { 131254721Semaste if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) 132254721Semaste { 133254721Semaste if (sc.line_entry.line != closest_line_number) 134254721Semaste tmp_sc_list.RemoveContextAtIndex(current_idx); 135254721Semaste else 136254721Semaste current_idx++; 137254721Semaste } 138254721Semaste } 139254721Semaste 140254721Semaste // Next go through and see if there are line table entries that are contiguous, and if so keep only the 141254721Semaste // first of the contiguous range: 142254721Semaste 143254721Semaste lldb::addr_t last_end_addr = LLDB_INVALID_ADDRESS; 144254721Semaste current_idx = 0; 145254721Semaste while (current_idx < tmp_sc_list.GetSize()) 146254721Semaste { 147254721Semaste if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) 148254721Semaste { 149254721Semaste lldb::addr_t start_file_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress(); 150254721Semaste lldb::addr_t end_file_addr = start_file_addr + sc.line_entry.range.GetByteSize(); 151254721Semaste 152254721Semaste if (start_file_addr == last_end_addr) 153254721Semaste tmp_sc_list.RemoveContextAtIndex(current_idx); 154254721Semaste else 155254721Semaste current_idx++; 156254721Semaste 157254721Semaste last_end_addr = end_file_addr; 158254721Semaste } 159254721Semaste } 160254721Semaste 161254721Semaste // and make breakpoints out of the closest line number match. 162254721Semaste 163254721Semaste uint32_t tmp_sc_list_size = tmp_sc_list.GetSize(); 164254721Semaste 165254721Semaste for (uint32_t i = 0; i < tmp_sc_list_size; i++) 166254721Semaste { 167254721Semaste if (tmp_sc_list.GetContextAtIndex(i, sc)) 168254721Semaste { 169254721Semaste Address line_start = sc.line_entry.range.GetBaseAddress(); 170254721Semaste if (line_start.IsValid()) 171254721Semaste { 172254721Semaste if (filter.AddressPasses(line_start)) 173254721Semaste { 174254721Semaste // If the line number is before the prologue end, move it there... 175254721Semaste bool skipped_prologue = false; 176254721Semaste if (m_skip_prologue) 177254721Semaste { 178254721Semaste if (sc.function) 179254721Semaste { 180254721Semaste Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress()); 181254721Semaste if (prologue_addr.IsValid() && (line_start == prologue_addr)) 182254721Semaste { 183254721Semaste const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 184254721Semaste if (prologue_byte_size) 185254721Semaste { 186254721Semaste prologue_addr.Slide(prologue_byte_size); 187254721Semaste 188254721Semaste if (filter.AddressPasses(prologue_addr)) 189254721Semaste { 190254721Semaste skipped_prologue = true; 191254721Semaste line_start = prologue_addr; 192254721Semaste } 193254721Semaste } 194254721Semaste } 195254721Semaste } 196254721Semaste } 197254721Semaste 198254721Semaste BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start)); 199254721Semaste if (log && bp_loc_sp && !m_breakpoint->IsInternal()) 200254721Semaste { 201254721Semaste StreamString s; 202254721Semaste bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); 203254721Semaste log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData()); 204254721Semaste } 205254721Semaste } 206254721Semaste else if (log) 207254721Semaste { 208254721Semaste log->Printf ("Breakpoint at file address 0x%" PRIx64 " for %s:%d didn't pass the filter.\n", 209254721Semaste line_start.GetFileAddress(), 210254721Semaste m_file_spec.GetFilename().AsCString("<Unknown>"), 211254721Semaste m_line_number); 212254721Semaste } 213254721Semaste } 214254721Semaste else 215254721Semaste { 216254721Semaste if (log) 217254721Semaste log->Printf ("error: Unable to set breakpoint at file address 0x%" PRIx64 " for %s:%d\n", 218254721Semaste line_start.GetFileAddress(), 219254721Semaste m_file_spec.GetFilename().AsCString("<Unknown>"), 220254721Semaste m_line_number); 221254721Semaste } 222254721Semaste } 223254721Semaste } 224254721Semaste } 225254721Semaste 226254721Semaste return Searcher::eCallbackReturnContinue; 227254721Semaste} 228254721Semaste 229254721SemasteSearcher::Depth 230254721SemasteBreakpointResolverFileLine::GetDepth() 231254721Semaste{ 232254721Semaste return Searcher::eDepthModule; 233254721Semaste} 234254721Semaste 235254721Semastevoid 236254721SemasteBreakpointResolverFileLine::GetDescription (Stream *s) 237254721Semaste{ 238254721Semaste s->Printf ("file = '%s', line = %u", m_file_spec.GetPath().c_str(), m_line_number); 239254721Semaste} 240254721Semaste 241254721Semastevoid 242254721SemasteBreakpointResolverFileLine::Dump (Stream *s) const 243254721Semaste{ 244254721Semaste 245254721Semaste} 246254721Semaste 247