1 //===-- BreakpointResolverAddress.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/BreakpointResolverAddress.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 
17 #include "lldb/Breakpoint/BreakpointLocation.h"
18 #include "lldb/Core/Log.h"
19 #include "lldb/Core/Module.h"
20 #include "lldb/Core/StreamString.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/Target.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 //----------------------------------------------------------------------
28 // BreakpointResolverAddress:
29 //----------------------------------------------------------------------
30 BreakpointResolverAddress::BreakpointResolverAddress(
31     Breakpoint *bkpt, const Address &addr, const FileSpec &module_spec)
32     : BreakpointResolver(bkpt, BreakpointResolver::AddressResolver),
33       m_addr(addr), m_resolved_addr(LLDB_INVALID_ADDRESS),
34       m_module_filespec(module_spec) {}
35 
36 BreakpointResolverAddress::BreakpointResolverAddress(Breakpoint *bkpt,
37                                                      const Address &addr)
38     : BreakpointResolver(bkpt, BreakpointResolver::AddressResolver),
39       m_addr(addr), m_resolved_addr(LLDB_INVALID_ADDRESS), m_module_filespec() {
40 }
41 
42 BreakpointResolverAddress::~BreakpointResolverAddress() {}
43 
44 void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter &filter) {
45   // If the address is not section relative, then we should not try to
46   // re-resolve it, it is just some
47   // random address and we wouldn't know what to do on reload.  But if it is
48   // section relative, we need to
49   // re-resolve it since the section it's in may have shifted on re-run.
50   bool re_resolve = false;
51   if (m_addr.GetSection() || m_module_filespec)
52     re_resolve = true;
53   else if (m_breakpoint->GetNumLocations() == 0)
54     re_resolve = true;
55 
56   if (re_resolve)
57     BreakpointResolver::ResolveBreakpoint(filter);
58 }
59 
60 void BreakpointResolverAddress::ResolveBreakpointInModules(
61     SearchFilter &filter, ModuleList &modules) {
62   // See comment in ResolveBreakpoint.
63   bool re_resolve = false;
64   if (m_addr.GetSection())
65     re_resolve = true;
66   else if (m_breakpoint->GetNumLocations() == 0)
67     re_resolve = true;
68 
69   if (re_resolve)
70     BreakpointResolver::ResolveBreakpointInModules(filter, modules);
71 }
72 
73 Searcher::CallbackReturn
74 BreakpointResolverAddress::SearchCallback(SearchFilter &filter,
75                                           SymbolContext &context, Address *addr,
76                                           bool containing) {
77   assert(m_breakpoint != NULL);
78 
79   if (filter.AddressPasses(m_addr)) {
80     if (m_breakpoint->GetNumLocations() == 0) {
81       // If the address is just an offset, and we're given a module, see if we
82       // can find the appropriate module
83       // loaded in the binary, and fix up m_addr to use that.
84       if (!m_addr.IsSectionOffset() && m_module_filespec) {
85         Target &target = m_breakpoint->GetTarget();
86         ModuleSpec module_spec(m_module_filespec);
87         ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec);
88         if (module_sp) {
89           Address tmp_address;
90           if (module_sp->ResolveFileAddress(m_addr.GetOffset(), tmp_address))
91             m_addr = tmp_address;
92         }
93       }
94 
95       m_resolved_addr = m_addr.GetLoadAddress(&m_breakpoint->GetTarget());
96       BreakpointLocationSP bp_loc_sp(AddLocation(m_addr));
97       if (bp_loc_sp && !m_breakpoint->IsInternal()) {
98         StreamString s;
99         bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
100         Log *log(
101             lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
102         if (log)
103           log->Printf("Added location: %s\n", s.GetData());
104       }
105     } else {
106       BreakpointLocationSP loc_sp = m_breakpoint->GetLocationAtIndex(0);
107       lldb::addr_t cur_load_location =
108           m_addr.GetLoadAddress(&m_breakpoint->GetTarget());
109       if (cur_load_location != m_resolved_addr) {
110         m_resolved_addr = cur_load_location;
111         loc_sp->ClearBreakpointSite();
112         loc_sp->ResolveBreakpointSite();
113       }
114     }
115   }
116   return Searcher::eCallbackReturnStop;
117 }
118 
119 Searcher::Depth BreakpointResolverAddress::GetDepth() {
120   return Searcher::eDepthTarget;
121 }
122 
123 void BreakpointResolverAddress::GetDescription(Stream *s) {
124   s->PutCString("address = ");
125   m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(),
126               Address::DumpStyleModuleWithFileAddress,
127               Address::DumpStyleLoadAddress);
128 }
129 
130 void BreakpointResolverAddress::Dump(Stream *s) const {}
131 
132 lldb::BreakpointResolverSP
133 BreakpointResolverAddress::CopyForBreakpoint(Breakpoint &breakpoint) {
134   lldb::BreakpointResolverSP ret_sp(
135       new BreakpointResolverAddress(&breakpoint, m_addr));
136   return ret_sp;
137 }
138