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/Module.h" 19 #include "lldb/Core/Section.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Utility/Log.h" 23 #include "lldb/Utility/StreamString.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, const StructuredData::Dictionary &options_dict, 47 Status &error) { 48 llvm::StringRef module_name; 49 lldb::addr_t addr_offset; 50 FileSpec module_filespec; 51 bool success; 52 53 success = options_dict.GetValueForKeyAsInteger( 54 GetKey(OptionNames::AddressOffset), addr_offset); 55 if (!success) { 56 error.SetErrorString("BRFL::CFSD: Couldn't find address offset entry."); 57 return nullptr; 58 } 59 Address address(addr_offset); 60 61 success = options_dict.HasKey(GetKey(OptionNames::ModuleName)); 62 if (success) { 63 success = options_dict.GetValueForKeyAsString( 64 GetKey(OptionNames::ModuleName), module_name); 65 if (!success) { 66 error.SetErrorString("BRA::CFSD: Couldn't read module name entry."); 67 return nullptr; 68 } 69 module_filespec.SetFile(module_name, false, FileSpec::Style::native); 70 } 71 return new BreakpointResolverAddress(bkpt, address, module_filespec); 72 } 73 74 StructuredData::ObjectSP 75 BreakpointResolverAddress::SerializeToStructuredData() { 76 StructuredData::DictionarySP options_dict_sp( 77 new StructuredData::Dictionary()); 78 SectionSP section_sp = m_addr.GetSection(); 79 if (section_sp) { 80 ModuleSP module_sp = section_sp->GetModule(); 81 ConstString module_name; 82 if (module_sp) 83 module_name.SetCString(module_name.GetCString()); 84 85 options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName), 86 module_name.GetCString()); 87 options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset), 88 m_addr.GetOffset()); 89 } else { 90 options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset), 91 m_addr.GetOffset()); 92 if (m_module_filespec) { 93 options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName), 94 m_module_filespec.GetPath()); 95 } 96 } 97 98 return WrapOptionsDict(options_dict_sp); 99 return StructuredData::ObjectSP(); 100 } 101 102 void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter &filter) { 103 // If the address is not section relative, then we should not try to re- 104 // resolve it, it is just some random address and we wouldn't know what to do 105 // on reload. But if it is section relative, we need to re-resolve it since 106 // 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 loaded in the binary, and fix up 140 // 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 lldb::SearchDepth BreakpointResolverAddress::GetDepth() { 177 return lldb::eSearchDepthTarget; 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