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