]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Breakpoint/BreakpointResolver.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Breakpoint / BreakpointResolver.cpp
1 //===-- BreakpointResolver.cpp ----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Breakpoint/BreakpointResolver.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Address.h"
17 #include "lldb/Breakpoint/Breakpoint.h"
18 #include "lldb/Breakpoint/BreakpointLocation.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/ModuleList.h"
21 #include "lldb/Core/SearchFilter.h"
22 #include "lldb/Core/Stream.h"
23 #include "lldb/Core/StreamString.h"
24 #include "lldb/Symbol/SymbolContext.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/Function.h"
28
29 using namespace lldb_private;
30 using namespace lldb;
31
32 //----------------------------------------------------------------------
33 // BreakpointResolver:
34 //----------------------------------------------------------------------
35 BreakpointResolver::BreakpointResolver (Breakpoint *bkpt, const unsigned char resolverTy, lldb::addr_t offset) :
36     m_breakpoint (bkpt),
37     m_offset(offset),
38     SubclassID (resolverTy)
39 {
40 }
41
42 BreakpointResolver::~BreakpointResolver ()
43 {
44
45 }
46
47 void
48 BreakpointResolver::SetBreakpoint (Breakpoint *bkpt)
49 {
50     m_breakpoint = bkpt;
51 }
52
53 void
54 BreakpointResolver::ResolveBreakpointInModules (SearchFilter &filter, ModuleList &modules)
55 {
56     filter.SearchInModuleList(*this, modules);
57 }
58
59 void
60 BreakpointResolver::ResolveBreakpoint (SearchFilter &filter)
61 {
62     filter.Search (*this);
63 }
64
65 void
66 BreakpointResolver::SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident)
67 {
68     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
69
70     while (sc_list.GetSize() > 0)
71     {
72         SymbolContextList tmp_sc_list;
73         unsigned current_idx = 0;
74         SymbolContext sc;
75         bool first_entry = true;
76         
77         FileSpec match_file_spec;
78         FileSpec match_original_file_spec;
79         uint32_t closest_line_number = UINT32_MAX;
80
81         // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
82         while (current_idx < sc_list.GetSize())
83         {
84             bool matches;
85             
86             sc_list.GetContextAtIndex (current_idx, sc);
87             if (first_entry)
88             {
89                 match_file_spec = sc.line_entry.file;
90                 match_original_file_spec = sc.line_entry.original_file;
91                 matches = true;
92                 first_entry = false;
93             }
94             else
95                 matches = ((sc.line_entry.file == match_file_spec) ||
96                            (sc.line_entry.original_file == match_original_file_spec));
97             
98             if (matches)
99             {
100                 tmp_sc_list.Append (sc);
101                 sc_list.RemoveContextAtIndex(current_idx);
102                 
103                 // ResolveSymbolContext will always return a number that is >= the line number you pass in.
104                 // So the smaller line number is always better.
105                 if (sc.line_entry.line < closest_line_number)
106                     closest_line_number = sc.line_entry.line;
107             }
108             else
109                 current_idx++;
110         }
111             
112         // Okay, we've found the closest line number match, now throw away all the others:
113         
114         current_idx = 0;
115         while (current_idx < tmp_sc_list.GetSize())
116         {
117             if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
118             {
119                 if (sc.line_entry.line != closest_line_number)
120                     tmp_sc_list.RemoveContextAtIndex(current_idx);
121                 else
122                     current_idx++;
123             }
124         }
125         
126         // Next go through and see if there are line table entries that are contiguous, and if so keep only the
127         // first of the contiguous range:
128         
129         current_idx = 0;
130         std::map<Block *, lldb::addr_t> blocks_with_breakpoints;
131         
132         while (current_idx < tmp_sc_list.GetSize())
133         {
134             if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
135             {
136                 if (blocks_with_breakpoints.find (sc.block) != blocks_with_breakpoints.end())
137                     tmp_sc_list.RemoveContextAtIndex(current_idx);
138                 else
139                 {
140                     blocks_with_breakpoints.insert (std::pair<Block *, lldb::addr_t>(sc.block, sc.line_entry.range.GetBaseAddress().GetFileAddress()));
141                     current_idx++;
142                 }
143             }
144         }
145         
146         // and make breakpoints out of the closest line number match.
147         
148         uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
149         
150         for (uint32_t i = 0; i < tmp_sc_list_size; i++)
151         {
152             if (tmp_sc_list.GetContextAtIndex(i, sc))
153             {
154                 Address line_start = sc.line_entry.range.GetBaseAddress();
155                 if (line_start.IsValid())
156                 {
157                     if (filter.AddressPasses(line_start))
158                     {
159                         // If the line number is before the prologue end, move it there...
160                         bool skipped_prologue = false;
161                         if (skip_prologue)
162                         {
163                             if (sc.function)
164                             {
165                                 Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
166                                 if (prologue_addr.IsValid() && (line_start == prologue_addr))
167                                 {
168                                     const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
169                                     if (prologue_byte_size)
170                                     {
171                                         prologue_addr.Slide(prologue_byte_size);
172                  
173                                         if (filter.AddressPasses(prologue_addr))
174                                         {
175                                             skipped_prologue = true;
176                                             line_start = prologue_addr;
177                                         }
178                                     }
179                                 }
180                             }
181                         }
182                     
183                         BreakpointLocationSP bp_loc_sp (AddLocation(line_start));
184                         if (log && bp_loc_sp && !m_breakpoint->IsInternal())
185                         {
186                             StreamString s;
187                             bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
188                             log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData());
189                         }
190                     }
191                     else if (log)
192                     {
193                         log->Printf ("Breakpoint %s at file address 0x%" PRIx64 " didn't pass the filter.\n",
194                                      log_ident ? log_ident : "",
195                                      line_start.GetFileAddress());
196                     }
197                 }
198                 else
199                 {
200                     if (log)
201                         log->Printf ("error: Unable to set breakpoint %s at file address 0x%" PRIx64 "\n",
202                                      log_ident ? log_ident : "",
203                                      line_start.GetFileAddress());
204                 }
205             }
206         }
207     }
208 }
209
210 BreakpointLocationSP
211 BreakpointResolver::AddLocation(Address loc_addr, bool *new_location)
212 {
213     loc_addr.Slide(m_offset);
214     return m_breakpoint->AddLocation(loc_addr, new_location);
215 }
216     
217
218 void
219 BreakpointResolver::SetOffset (lldb::addr_t offset)
220 {
221     // There may already be an offset, so we are actually adjusting location addresses by the difference.
222     // lldb::addr_t slide = offset - m_offset;
223     // FIXME: We should go fix up all the already set locations for the new slide.
224
225     m_offset = offset;
226 }
227