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/Section.h"
21 #include "lldb/Core/StreamString.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 
28 //----------------------------------------------------------------------
29 // BreakpointResolverAddress:
30 //----------------------------------------------------------------------
31 BreakpointResolverAddress::BreakpointResolverAddress(
32     Breakpoint *bkpt, const Address &addr, const FileSpec &module_spec)
33     : BreakpointResolver(bkpt, BreakpointResolver::AddressResolver),
34       m_addr(addr), m_resolved_addr(LLDB_INVALID_ADDRESS),
35       m_module_filespec(module_spec) {}
36 
37 BreakpointResolverAddress::BreakpointResolverAddress(Breakpoint *bkpt,
38                                                      const Address &addr)
39     : BreakpointResolver(bkpt, BreakpointResolver::AddressResolver),
40       m_addr(addr), m_resolved_addr(LLDB_INVALID_ADDRESS), m_module_filespec() {
41 }
42 
43 BreakpointResolverAddress::~BreakpointResolverAddress() {}
44 
45 BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData(
46     Breakpoint *bkpt, StructuredData::Dictionary &options_dict, Error &error) {
47   std::string module_name;
48   lldb::addr_t addr_offset;
49   FileSpec module_filespec;
50   bool success;
51 
52   success = options_dict.GetValueForKeyAsInteger(
53       GetKey(OptionNames::AddressOffset), addr_offset);
54   if (!success) {
55     error.SetErrorString("BRFL::CFSD: Couldn't find address offset entry.");
56     return nullptr;
57   }
58   Address address(addr_offset);
59 
60   success = options_dict.HasKey(GetKey(OptionNames::ModuleName));
61   if (success) {
62     success = options_dict.GetValueForKeyAsString(
63         GetKey(OptionNames::ModuleName), module_name);
64     if (!success) {
65       error.SetErrorString("BRA::CFSD: Couldn't read module name entry.");
66       return nullptr;
67     }
68     module_filespec.SetFile(module_name.c_str(), false);
69   }
70   return new BreakpointResolverAddress(bkpt, address, module_filespec);
71 }
72 
73 StructuredData::ObjectSP
74 BreakpointResolverAddress::SerializeToStructuredData() {
75   StructuredData::DictionarySP options_dict_sp(
76       new StructuredData::Dictionary());
77   SectionSP section_sp = m_addr.GetSection();
78   if (section_sp) {
79     ModuleSP module_sp = section_sp->GetModule();
80     ConstString module_name;
81     if (module_sp)
82       module_name.SetCString(module_name.GetCString());
83 
84     options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName),
85                                    module_name.GetCString());
86     options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset),
87                                     m_addr.GetOffset());
88   } else {
89     options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset),
90                                     m_addr.GetOffset());
91     if (m_module_filespec) {
92       options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName),
93                                      m_module_filespec.GetPath());
94     }
95   }
96 
97   return WrapOptionsDict(options_dict_sp);
98   return StructuredData::ObjectSP();
99 }
100 
101 void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter &filter) {
102   // If the address is not section relative, then we should not try to
103   // re-resolve it, it is just some
104   // random address and we wouldn't know what to do on reload.  But if it is
105   // section relative, we need to
106   // re-resolve it since the section it's in may have shifted on re-run.
107   bool re_resolve = false;
108   if (m_addr.GetSection() || m_module_filespec)
109     re_resolve = true;
110   else if (m_breakpoint->GetNumLocations() == 0)
111     re_resolve = true;
112 
113   if (re_resolve)
114     BreakpointResolver::ResolveBreakpoint(filter);
115 }
116 
117 void BreakpointResolverAddress::ResolveBreakpointInModules(
118     SearchFilter &filter, ModuleList &modules) {
119   // See comment in ResolveBreakpoint.
120   bool re_resolve = false;
121   if (m_addr.GetSection())
122     re_resolve = true;
123   else if (m_breakpoint->GetNumLocations() == 0)
124     re_resolve = true;
125 
126   if (re_resolve)
127     BreakpointResolver::ResolveBreakpointInModules(filter, modules);
128 }
129 
130 Searcher::CallbackReturn
131 BreakpointResolverAddress::SearchCallback(SearchFilter &filter,
132                                           SymbolContext &context, Address *addr,
133                                           bool containing) {
134   assert(m_breakpoint != NULL);
135 
136   if (filter.AddressPasses(m_addr)) {
137     if (m_breakpoint->GetNumLocations() == 0) {
138       // If the address is just an offset, and we're given a module, see if we
139       // can find the appropriate module
140       // loaded in the binary, and fix up m_addr to use that.
141       if (!m_addr.IsSectionOffset() && m_module_filespec) {
142         Target &target = m_breakpoint->GetTarget();
143         ModuleSpec module_spec(m_module_filespec);
144         ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec);
145         if (module_sp) {
146           Address tmp_address;
147           if (module_sp->ResolveFileAddress(m_addr.GetOffset(), tmp_address))
148             m_addr = tmp_address;
149         }
150       }
151 
152       m_resolved_addr = m_addr.GetLoadAddress(&m_breakpoint->GetTarget());
153       BreakpointLocationSP bp_loc_sp(AddLocation(m_addr));
154       if (bp_loc_sp && !m_breakpoint->IsInternal()) {
155         StreamString s;
156         bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
157         Log *log(
158             lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
159         if (log)
160           log->Printf("Added location: %s\n", s.GetData());
161       }
162     } else {
163       BreakpointLocationSP loc_sp = m_breakpoint->GetLocationAtIndex(0);
164       lldb::addr_t cur_load_location =
165           m_addr.GetLoadAddress(&m_breakpoint->GetTarget());
166       if (cur_load_location != m_resolved_addr) {
167         m_resolved_addr = cur_load_location;
168         loc_sp->ClearBreakpointSite();
169         loc_sp->ResolveBreakpointSite();
170       }
171     }
172   }
173   return Searcher::eCallbackReturnStop;
174 }
175 
176 Searcher::Depth BreakpointResolverAddress::GetDepth() {
177   return Searcher::eDepthTarget;
178 }
179 
180 void BreakpointResolverAddress::GetDescription(Stream *s) {
181   s->PutCString("address = ");
182   m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(),
183               Address::DumpStyleModuleWithFileAddress,
184               Address::DumpStyleLoadAddress);
185 }
186 
187 void BreakpointResolverAddress::Dump(Stream *s) const {}
188 
189 lldb::BreakpointResolverSP
190 BreakpointResolverAddress::CopyForBreakpoint(Breakpoint &breakpoint) {
191   lldb::BreakpointResolverSP ret_sp(
192       new BreakpointResolverAddress(&breakpoint, m_addr));
193   return ret_sp;
194 }
195