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 ... 125 if (!m_addr.IsSectionOffset()) { 126 ModuleSP containing_module_sp = nullptr; 127 Target &target = breakpoint.GetTarget(); 128 if (m_module_filespec) { 129 // ... and we're given a module, see if we can find the 130 // appropriate module loaded in the binary, and fix up 131 // m_addr to use that. 132 ModuleSpec module_spec(m_module_filespec); 133 containing_module_sp = 134 target.GetImages().FindFirstModule(module_spec); 135 } else { 136 // ... and we're not given a module, see if the offset is 137 // somewhere in the executable module. If it is, then we'll 138 // fix up m_addr to use that. 139 containing_module_sp = target.GetExecutableModule(); 140 } 141 if (containing_module_sp) { 142 Address tmp_address; 143 if (containing_module_sp->ResolveFileAddress(m_addr.GetOffset(), 144 tmp_address)) 145 m_addr = tmp_address; 146 } 147 } 148 149 m_resolved_addr = m_addr.GetLoadAddress(&breakpoint.GetTarget()); 150 BreakpointLocationSP bp_loc_sp(AddLocation(m_addr)); 151 if (bp_loc_sp && !breakpoint.IsInternal()) { 152 StreamString s; 153 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 154 Log *log = GetLog(LLDBLog::Breakpoints); 155 LLDB_LOGF(log, "Added location: %s\n", s.GetData()); 156 } 157 } else { 158 BreakpointLocationSP loc_sp = breakpoint.GetLocationAtIndex(0); 159 lldb::addr_t cur_load_location = 160 m_addr.GetLoadAddress(&breakpoint.GetTarget()); 161 if (cur_load_location != m_resolved_addr) { 162 m_resolved_addr = cur_load_location; 163 loc_sp->ClearBreakpointSite(); 164 loc_sp->ResolveBreakpointSite(); 165 } 166 } 167 } 168 return Searcher::eCallbackReturnStop; 169 } 170 171 lldb::SearchDepth BreakpointResolverAddress::GetDepth() { 172 return lldb::eSearchDepthTarget; 173 } 174 175 void BreakpointResolverAddress::GetDescription(Stream *s) { 176 s->PutCString("address = "); 177 m_addr.Dump(s, GetBreakpoint()->GetTarget().GetProcessSP().get(), 178 Address::DumpStyleModuleWithFileAddress, 179 Address::DumpStyleLoadAddress); 180 } 181 182 void BreakpointResolverAddress::Dump(Stream *s) const {} 183 184 lldb::BreakpointResolverSP 185 BreakpointResolverAddress::CopyForBreakpoint(BreakpointSP &breakpoint) { 186 lldb::BreakpointResolverSP ret_sp( 187 new BreakpointResolverAddress(breakpoint, m_addr)); 188 return ret_sp; 189 } 190