130fdc8d8SChris Lattner //===-- BreakpointResolverFileLine.cpp --------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointResolverFileLine.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
1630fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
1730fdc8d8SChris Lattner #include "lldb/Core/Log.h"
1830fdc8d8SChris Lattner #include "lldb/Core/StreamString.h"
1930fdc8d8SChris Lattner #include "lldb/lldb-private-log.h"
2030fdc8d8SChris Lattner 
2130fdc8d8SChris Lattner using namespace lldb;
2230fdc8d8SChris Lattner using namespace lldb_private;
2330fdc8d8SChris Lattner 
2430fdc8d8SChris Lattner //----------------------------------------------------------------------
2530fdc8d8SChris Lattner // BreakpointResolverFileLine:
2630fdc8d8SChris Lattner //----------------------------------------------------------------------
2730fdc8d8SChris Lattner BreakpointResolverFileLine::BreakpointResolverFileLine
2830fdc8d8SChris Lattner (
2930fdc8d8SChris Lattner     Breakpoint *bkpt,
3030fdc8d8SChris Lattner     const FileSpec &file_spec,
3130fdc8d8SChris Lattner     uint32_t line_no,
3230fdc8d8SChris Lattner     bool check_inlines
3330fdc8d8SChris Lattner ) :
34b7234e40SJohnny Chen     BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
3530fdc8d8SChris Lattner     m_file_spec (file_spec),
3630fdc8d8SChris Lattner     m_line_number (line_no),
3730fdc8d8SChris Lattner     m_inlines (check_inlines)
3830fdc8d8SChris Lattner {
3930fdc8d8SChris Lattner }
4030fdc8d8SChris Lattner 
4130fdc8d8SChris Lattner BreakpointResolverFileLine::~BreakpointResolverFileLine ()
4230fdc8d8SChris Lattner {
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
4530fdc8d8SChris Lattner Searcher::CallbackReturn
4630fdc8d8SChris Lattner BreakpointResolverFileLine::SearchCallback
4730fdc8d8SChris Lattner (
4830fdc8d8SChris Lattner     SearchFilter &filter,
4930fdc8d8SChris Lattner     SymbolContext &context,
5030fdc8d8SChris Lattner     Address *addr,
5130fdc8d8SChris Lattner     bool containing
5230fdc8d8SChris Lattner )
5330fdc8d8SChris Lattner {
5430fdc8d8SChris Lattner     SymbolContextList sc_list;
5530fdc8d8SChris Lattner 
5630fdc8d8SChris Lattner     assert (m_breakpoint != NULL);
572d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
5830fdc8d8SChris Lattner 
59*bc2f9182SJim Ingham     // There is a tricky bit here.  You can have two compilation units that #include the same file, and
60*bc2f9182SJim Ingham     // 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
61*bc2f9182SJim Ingham     // other it isn't.  If we considered the CU's independently, then in the second inclusion, we'd move the breakpoint
62*bc2f9182SJim Ingham     // to the next function that actually generated code in the header file.  That would end up being confusing.
63*bc2f9182SJim Ingham     // So instead, we do the CU iterations by hand here, then scan through the complete list of matches, and figure out
64*bc2f9182SJim Ingham     // the closest line number match, and only set breakpoints on that match.
65*bc2f9182SJim Ingham 
66*bc2f9182SJim Ingham     // Note also that if file_spec only had a file name and not a directory, there may be many different file spec's in
67*bc2f9182SJim Ingham     // the resultant list.  The closest line match for one will not be right for some totally different file.
68*bc2f9182SJim Ingham     // So we go through the match list and pull out the sets that have the same file spec in their line_entry
69*bc2f9182SJim Ingham     // and treat each set separately.
70*bc2f9182SJim Ingham 
71*bc2f9182SJim Ingham     uint32_t num_comp_units = context.module_sp->GetNumCompileUnits();
72*bc2f9182SJim Ingham     for (uint32_t i = 0; i < num_comp_units; i++)
73*bc2f9182SJim Ingham     {
74*bc2f9182SJim Ingham         CompUnitSP cu_sp (context.module_sp->GetCompileUnitAtIndex (i));
75*bc2f9182SJim Ingham         if (filter.CompUnitPasses(*(cu_sp.get())))
76*bc2f9182SJim Ingham             cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
77*bc2f9182SJim Ingham     }
78*bc2f9182SJim Ingham 
79*bc2f9182SJim Ingham     while (sc_list.GetSize() > 0)
80*bc2f9182SJim Ingham     {
81*bc2f9182SJim Ingham         SymbolContextList tmp_sc_list;
82*bc2f9182SJim Ingham         int current_idx = 0;
83*bc2f9182SJim Ingham         SymbolContext sc;
84*bc2f9182SJim Ingham         bool first_entry = true;
85*bc2f9182SJim Ingham 
86*bc2f9182SJim Ingham         FileSpec match_file_spec;
87*bc2f9182SJim Ingham         uint32_t closest_line_number = UINT32_MAX;
88*bc2f9182SJim Ingham 
89*bc2f9182SJim Ingham         // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
90*bc2f9182SJim Ingham         while (current_idx < sc_list.GetSize())
91*bc2f9182SJim Ingham         {
92*bc2f9182SJim Ingham             bool matches;
93*bc2f9182SJim Ingham 
94*bc2f9182SJim Ingham             sc_list.GetContextAtIndex (current_idx, sc);
95*bc2f9182SJim Ingham             if (first_entry)
96*bc2f9182SJim Ingham             {
97*bc2f9182SJim Ingham                 match_file_spec = sc.line_entry.file;
98*bc2f9182SJim Ingham                 matches = true;
99*bc2f9182SJim Ingham                 first_entry = false;
100*bc2f9182SJim Ingham             }
101*bc2f9182SJim Ingham             else
102*bc2f9182SJim Ingham                 matches = (sc.line_entry.file == match_file_spec);
103*bc2f9182SJim Ingham 
104*bc2f9182SJim Ingham             if (matches)
105*bc2f9182SJim Ingham             {
106*bc2f9182SJim Ingham                 tmp_sc_list.Append (sc);
107*bc2f9182SJim Ingham                 sc_list.RemoveContextAtIndex(current_idx);
108*bc2f9182SJim Ingham 
109*bc2f9182SJim Ingham                 // ResolveSymbolContext will always return a number that is >= the line number you pass in.
110*bc2f9182SJim Ingham                 // So the smaller line number is always better.
111*bc2f9182SJim Ingham                 if (sc.line_entry.line < closest_line_number)
112*bc2f9182SJim Ingham                     closest_line_number = sc.line_entry.line;
113*bc2f9182SJim Ingham             }
114*bc2f9182SJim Ingham             else
115*bc2f9182SJim Ingham                 current_idx++;
116*bc2f9182SJim Ingham         }
117*bc2f9182SJim Ingham 
118*bc2f9182SJim Ingham         // Okay, we've found the closest line number match, now throw away all the others,
119*bc2f9182SJim Ingham         // and make breakpoints out of the closest line number match.
120*bc2f9182SJim Ingham 
121*bc2f9182SJim Ingham         uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
122*bc2f9182SJim Ingham 
123*bc2f9182SJim Ingham         for (uint32_t i = 0; i < tmp_sc_list_size; i++)
12430fdc8d8SChris Lattner         {
12530fdc8d8SChris Lattner             SymbolContext sc;
126*bc2f9182SJim Ingham             if (tmp_sc_list.GetContextAtIndex(i, sc))
127*bc2f9182SJim Ingham             {
128*bc2f9182SJim Ingham                 if (sc.line_entry.line == closest_line_number)
12930fdc8d8SChris Lattner                 {
13030fdc8d8SChris Lattner                     Address line_start = sc.line_entry.range.GetBaseAddress();
13130fdc8d8SChris Lattner                     if (line_start.IsValid())
13230fdc8d8SChris Lattner                     {
133969795f1SJim Ingham                         if (filter.AddressPasses(line_start))
134969795f1SJim Ingham                         {
13530fdc8d8SChris Lattner                             BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
13630fdc8d8SChris Lattner                             if (log && bp_loc_sp && !m_breakpoint->IsInternal())
13730fdc8d8SChris Lattner                             {
13830fdc8d8SChris Lattner                                 StreamString s;
13930fdc8d8SChris Lattner                                 bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
14030fdc8d8SChris Lattner                                 log->Printf ("Added location: %s\n", s.GetData());
14130fdc8d8SChris Lattner                             }
14230fdc8d8SChris Lattner                         }
143969795f1SJim Ingham                         else if (log)
144969795f1SJim Ingham                         {
145969795f1SJim Ingham                             log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass the filter.\n",
146969795f1SJim Ingham                                          line_start.GetFileAddress(),
147969795f1SJim Ingham                                          m_file_spec.GetFilename().AsCString("<Unknown>"),
148969795f1SJim Ingham                                          m_line_number);
149969795f1SJim Ingham                         }
150969795f1SJim Ingham                     }
15130fdc8d8SChris Lattner                     else
15230fdc8d8SChris Lattner                     {
15330fdc8d8SChris Lattner                         if (log)
15430fdc8d8SChris Lattner                             log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
15530fdc8d8SChris Lattner                                          line_start.GetFileAddress(),
15630fdc8d8SChris Lattner                                          m_file_spec.GetFilename().AsCString("<Unknown>"),
15730fdc8d8SChris Lattner                                          m_line_number);
15830fdc8d8SChris Lattner                     }
15930fdc8d8SChris Lattner                 }
16030fdc8d8SChris Lattner                 else
16130fdc8d8SChris Lattner                 {
16230fdc8d8SChris Lattner         #if 0
16330fdc8d8SChris Lattner                     s << "error: Breakpoint at '" << pos->c_str() << "' isn't resolved yet: \n";
16430fdc8d8SChris Lattner                     if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionNameOffset))
16530fdc8d8SChris Lattner                         s.EOL();
16630fdc8d8SChris Lattner                     if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionPointerOffset))
16730fdc8d8SChris Lattner                         s.EOL();
16830fdc8d8SChris Lattner                     if (sc.line_entry.address.Dump(&s, Address::DumpStyleFileAddress))
16930fdc8d8SChris Lattner                         s.EOL();
17030fdc8d8SChris Lattner                     if (sc.line_entry.address.Dump(&s, Address::DumpStyleLoadAddress))
17130fdc8d8SChris Lattner                         s.EOL();
17230fdc8d8SChris Lattner         #endif
17330fdc8d8SChris Lattner                 }
17430fdc8d8SChris Lattner             }
175*bc2f9182SJim Ingham         }
176*bc2f9182SJim Ingham     }
177*bc2f9182SJim Ingham 
17830fdc8d8SChris Lattner     return Searcher::eCallbackReturnContinue;
17930fdc8d8SChris Lattner }
18030fdc8d8SChris Lattner 
18130fdc8d8SChris Lattner Searcher::Depth
18230fdc8d8SChris Lattner BreakpointResolverFileLine::GetDepth()
18330fdc8d8SChris Lattner {
184*bc2f9182SJim Ingham     return Searcher::eDepthModule;
18530fdc8d8SChris Lattner }
18630fdc8d8SChris Lattner 
18730fdc8d8SChris Lattner void
18830fdc8d8SChris Lattner BreakpointResolverFileLine::GetDescription (Stream *s)
18930fdc8d8SChris Lattner {
1900c5cd90dSGreg Clayton     s->Printf ("file ='%s', line = %u", m_file_spec.GetFilename().AsCString(), m_line_number);
19130fdc8d8SChris Lattner }
19230fdc8d8SChris Lattner 
19330fdc8d8SChris Lattner void
19430fdc8d8SChris Lattner BreakpointResolverFileLine::Dump (Stream *s) const
19530fdc8d8SChris Lattner {
19630fdc8d8SChris Lattner 
19730fdc8d8SChris Lattner }
19830fdc8d8SChris Lattner 
199