1*969795f1SJim Ingham //===-- BreakpointResolverFileRegex.cpp --------------------------*- C++ -*-===//
2*969795f1SJim Ingham //
3*969795f1SJim Ingham //                     The LLVM Compiler Infrastructure
4*969795f1SJim Ingham //
5*969795f1SJim Ingham // This file is distributed under the University of Illinois Open Source
6*969795f1SJim Ingham // License. See LICENSE.TXT for details.
7*969795f1SJim Ingham //
8*969795f1SJim Ingham //===----------------------------------------------------------------------===//
9*969795f1SJim Ingham 
10*969795f1SJim Ingham #include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
11*969795f1SJim Ingham 
12*969795f1SJim Ingham // C Includes
13*969795f1SJim Ingham // C++ Includes
14*969795f1SJim Ingham // Other libraries and framework includes
15*969795f1SJim Ingham // Project includes
16*969795f1SJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h"
17*969795f1SJim Ingham #include "lldb/Core/SourceManager.h"
18*969795f1SJim Ingham #include "lldb/Core/Log.h"
19*969795f1SJim Ingham #include "lldb/Core/StreamString.h"
20*969795f1SJim Ingham #include "lldb/Target/Target.h"
21*969795f1SJim Ingham #include "lldb/lldb-private-log.h"
22*969795f1SJim Ingham 
23*969795f1SJim Ingham using namespace lldb;
24*969795f1SJim Ingham using namespace lldb_private;
25*969795f1SJim Ingham 
26*969795f1SJim Ingham //----------------------------------------------------------------------
27*969795f1SJim Ingham // BreakpointResolverFileRegex:
28*969795f1SJim Ingham //----------------------------------------------------------------------
29*969795f1SJim Ingham BreakpointResolverFileRegex::BreakpointResolverFileRegex
30*969795f1SJim Ingham (
31*969795f1SJim Ingham     Breakpoint *bkpt,
32*969795f1SJim Ingham     const FileSpec &file_spec,
33*969795f1SJim Ingham     RegularExpression &regex
34*969795f1SJim Ingham ) :
35*969795f1SJim Ingham     BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
36*969795f1SJim Ingham     m_file_spec (file_spec),
37*969795f1SJim Ingham     m_regex (regex)
38*969795f1SJim Ingham {
39*969795f1SJim Ingham }
40*969795f1SJim Ingham 
41*969795f1SJim Ingham BreakpointResolverFileRegex::~BreakpointResolverFileRegex ()
42*969795f1SJim Ingham {
43*969795f1SJim Ingham }
44*969795f1SJim Ingham 
45*969795f1SJim Ingham Searcher::CallbackReturn
46*969795f1SJim Ingham BreakpointResolverFileRegex::SearchCallback
47*969795f1SJim Ingham (
48*969795f1SJim Ingham     SearchFilter &filter,
49*969795f1SJim Ingham     SymbolContext &context,
50*969795f1SJim Ingham     Address *addr,
51*969795f1SJim Ingham     bool containing
52*969795f1SJim Ingham )
53*969795f1SJim Ingham {
54*969795f1SJim Ingham 
55*969795f1SJim Ingham     assert (m_breakpoint != NULL);
56*969795f1SJim Ingham     if (!context.target_sp)
57*969795f1SJim Ingham         return eCallbackReturnContinue;
58*969795f1SJim Ingham 
59*969795f1SJim Ingham     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
60*969795f1SJim Ingham 
61*969795f1SJim Ingham     CompileUnit *cu = context.comp_unit;
62*969795f1SJim Ingham     FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
63*969795f1SJim Ingham     if (cu_file_spec == m_file_spec
64*969795f1SJim Ingham         || (!m_file_spec.GetDirectory() && cu_file_spec.GetFilename() == m_file_spec.GetFilename()))
65*969795f1SJim Ingham     {
66*969795f1SJim Ingham         std::vector<uint32_t> line_matches;
67*969795f1SJim Ingham         context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches);
68*969795f1SJim Ingham         uint32_t num_matches = line_matches.size();
69*969795f1SJim Ingham         for (int i = 0; i < num_matches; i++)
70*969795f1SJim Ingham         {
71*969795f1SJim Ingham             uint32_t start_idx = 0;
72*969795f1SJim Ingham             while (1)
73*969795f1SJim Ingham             {
74*969795f1SJim Ingham                 LineEntry line_entry;
75*969795f1SJim Ingham 
76*969795f1SJim Ingham                 // Cycle through all the line entries that might match this one:
77*969795f1SJim Ingham                 start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, &line_entry);
78*969795f1SJim Ingham                 if (start_idx == UINT32_MAX)
79*969795f1SJim Ingham                     break;
80*969795f1SJim Ingham                 start_idx++;
81*969795f1SJim Ingham 
82*969795f1SJim Ingham                 Address line_start = line_entry.range.GetBaseAddress();
83*969795f1SJim Ingham                 if (line_start.IsValid())
84*969795f1SJim Ingham                 {
85*969795f1SJim Ingham                     if (filter.AddressPasses(line_start))
86*969795f1SJim Ingham                     {
87*969795f1SJim Ingham                         BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
88*969795f1SJim Ingham                         if (log && bp_loc_sp && !m_breakpoint->IsInternal())
89*969795f1SJim Ingham                         {
90*969795f1SJim Ingham                             StreamString s;
91*969795f1SJim Ingham                             bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
92*969795f1SJim Ingham                             log->Printf ("Added location: %s\n", s.GetData());
93*969795f1SJim Ingham                         }
94*969795f1SJim Ingham                     }
95*969795f1SJim Ingham                     else if (log)
96*969795f1SJim Ingham                     {
97*969795f1SJim Ingham                         log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass filter.\n",
98*969795f1SJim Ingham                                      line_start.GetFileAddress(),
99*969795f1SJim Ingham                                      m_file_spec.GetFilename().AsCString("<Unknown>"),
100*969795f1SJim Ingham                                      line_matches[i]);
101*969795f1SJim Ingham                     }
102*969795f1SJim Ingham                 }
103*969795f1SJim Ingham                 else
104*969795f1SJim Ingham                 {
105*969795f1SJim Ingham                     if (log)
106*969795f1SJim Ingham                         log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
107*969795f1SJim Ingham                                      line_start.GetFileAddress(),
108*969795f1SJim Ingham                                      m_file_spec.GetFilename().AsCString("<Unknown>"),
109*969795f1SJim Ingham                                      line_matches[i]);
110*969795f1SJim Ingham                 }
111*969795f1SJim Ingham 
112*969795f1SJim Ingham             }
113*969795f1SJim Ingham         }
114*969795f1SJim Ingham         assert (m_breakpoint != NULL);
115*969795f1SJim Ingham         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
116*969795f1SJim Ingham 
117*969795f1SJim Ingham 
118*969795f1SJim Ingham     }
119*969795f1SJim Ingham     return Searcher::eCallbackReturnContinue;
120*969795f1SJim Ingham }
121*969795f1SJim Ingham 
122*969795f1SJim Ingham Searcher::Depth
123*969795f1SJim Ingham BreakpointResolverFileRegex::GetDepth()
124*969795f1SJim Ingham {
125*969795f1SJim Ingham     return Searcher::eDepthCompUnit;
126*969795f1SJim Ingham }
127*969795f1SJim Ingham 
128*969795f1SJim Ingham void
129*969795f1SJim Ingham BreakpointResolverFileRegex::GetDescription (Stream *s)
130*969795f1SJim Ingham {
131*969795f1SJim Ingham     s->Printf ("file ='%s', regular expression = \"%s\"", m_file_spec.GetFilename().AsCString(), m_regex.GetText());
132*969795f1SJim Ingham }
133*969795f1SJim Ingham 
134*969795f1SJim Ingham void
135*969795f1SJim Ingham BreakpointResolverFileRegex::Dump (Stream *s) const
136*969795f1SJim Ingham {
137*969795f1SJim Ingham 
138*969795f1SJim Ingham }
139*969795f1SJim Ingham 
140