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