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