1 //===-- BreakpointResolverAddress.cpp ---------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Breakpoint/BreakpointResolverAddress.h"
12 #include "lldb/Breakpoint/BreakpointLocation.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/Section.h"
15 #include "lldb/Target/Process.h"
16 #include "lldb/Target/Target.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/StreamString.h"
21 using namespace lldb_private
;
23 // BreakpointResolverAddress:
24 BreakpointResolverAddress::BreakpointResolverAddress(
25 Breakpoint
*bkpt
, const Address
&addr
, const FileSpec
&module_spec
)
26 : BreakpointResolver(bkpt
, BreakpointResolver::AddressResolver
),
27 m_addr(addr
), m_resolved_addr(LLDB_INVALID_ADDRESS
),
28 m_module_filespec(module_spec
) {}
30 BreakpointResolverAddress::BreakpointResolverAddress(Breakpoint
*bkpt
,
32 : BreakpointResolver(bkpt
, BreakpointResolver::AddressResolver
),
33 m_addr(addr
), m_resolved_addr(LLDB_INVALID_ADDRESS
), m_module_filespec() {
36 BreakpointResolverAddress::~BreakpointResolverAddress() {}
38 BreakpointResolver
*BreakpointResolverAddress::CreateFromStructuredData(
39 Breakpoint
*bkpt
, const StructuredData::Dictionary
&options_dict
,
41 llvm::StringRef module_name
;
42 lldb::addr_t addr_offset
;
43 FileSpec module_filespec
;
46 success
= options_dict
.GetValueForKeyAsInteger(
47 GetKey(OptionNames::AddressOffset
), addr_offset
);
49 error
.SetErrorString("BRFL::CFSD: Couldn't find address offset entry.");
52 Address
address(addr_offset
);
54 success
= options_dict
.HasKey(GetKey(OptionNames::ModuleName
));
56 success
= options_dict
.GetValueForKeyAsString(
57 GetKey(OptionNames::ModuleName
), module_name
);
59 error
.SetErrorString("BRA::CFSD: Couldn't read module name entry.");
62 module_filespec
.SetFile(module_name
, FileSpec::Style::native
);
64 return new BreakpointResolverAddress(bkpt
, address
, module_filespec
);
67 StructuredData::ObjectSP
68 BreakpointResolverAddress::SerializeToStructuredData() {
69 StructuredData::DictionarySP
options_dict_sp(
70 new StructuredData::Dictionary());
71 SectionSP section_sp
= m_addr
.GetSection();
73 ModuleSP module_sp
= section_sp
->GetModule();
74 ConstString module_name
;
76 module_name
.SetCString(module_name
.GetCString());
78 options_dict_sp
->AddStringItem(GetKey(OptionNames::ModuleName
),
79 module_name
.GetCString());
80 options_dict_sp
->AddIntegerItem(GetKey(OptionNames::AddressOffset
),
83 options_dict_sp
->AddIntegerItem(GetKey(OptionNames::AddressOffset
),
85 if (m_module_filespec
) {
86 options_dict_sp
->AddStringItem(GetKey(OptionNames::ModuleName
),
87 m_module_filespec
.GetPath());
91 return WrapOptionsDict(options_dict_sp
);
92 return StructuredData::ObjectSP();
95 void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter
&filter
) {
96 // If the address is not section relative, then we should not try to re-
97 // resolve it, it is just some random address and we wouldn't know what to do
98 // on reload. But if it is section relative, we need to re-resolve it since
99 // the section it's in may have shifted on re-run.
100 bool re_resolve
= false;
101 if (m_addr
.GetSection() || m_module_filespec
)
103 else if (m_breakpoint
->GetNumLocations() == 0)
107 BreakpointResolver::ResolveBreakpoint(filter
);
110 void BreakpointResolverAddress::ResolveBreakpointInModules(
111 SearchFilter
&filter
, ModuleList
&modules
) {
112 // See comment in ResolveBreakpoint.
113 bool re_resolve
= false;
114 if (m_addr
.GetSection())
116 else if (m_breakpoint
->GetNumLocations() == 0)
120 BreakpointResolver::ResolveBreakpointInModules(filter
, modules
);
123 Searcher::CallbackReturn
BreakpointResolverAddress::SearchCallback(
124 SearchFilter
&filter
, SymbolContext
&context
, Address
*addr
) {
125 assert(m_breakpoint
!= nullptr);
127 if (filter
.AddressPasses(m_addr
)) {
128 if (m_breakpoint
->GetNumLocations() == 0) {
129 // If the address is just an offset, and we're given a module, see if we
130 // can find the appropriate module loaded in the binary, and fix up
131 // m_addr to use that.
132 if (!m_addr
.IsSectionOffset() && m_module_filespec
) {
133 Target
&target
= m_breakpoint
->GetTarget();
134 ModuleSpec
module_spec(m_module_filespec
);
135 ModuleSP module_sp
= target
.GetImages().FindFirstModule(module_spec
);
138 if (module_sp
->ResolveFileAddress(m_addr
.GetOffset(), tmp_address
))
139 m_addr
= tmp_address
;
143 m_resolved_addr
= m_addr
.GetLoadAddress(&m_breakpoint
->GetTarget());
144 BreakpointLocationSP
bp_loc_sp(AddLocation(m_addr
));
145 if (bp_loc_sp
&& !m_breakpoint
->IsInternal()) {
147 bp_loc_sp
->GetDescription(&s
, lldb::eDescriptionLevelVerbose
);
149 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS
));
150 LLDB_LOGF(log
, "Added location: %s\n", s
.GetData());
153 BreakpointLocationSP loc_sp
= m_breakpoint
->GetLocationAtIndex(0);
154 lldb::addr_t cur_load_location
=
155 m_addr
.GetLoadAddress(&m_breakpoint
->GetTarget());
156 if (cur_load_location
!= m_resolved_addr
) {
157 m_resolved_addr
= cur_load_location
;
158 loc_sp
->ClearBreakpointSite();
159 loc_sp
->ResolveBreakpointSite();
163 return Searcher::eCallbackReturnStop
;
166 lldb::SearchDepth
BreakpointResolverAddress::GetDepth() {
167 return lldb::eSearchDepthTarget
;
170 void BreakpointResolverAddress::GetDescription(Stream
*s
) {
171 s
->PutCString("address = ");
172 m_addr
.Dump(s
, m_breakpoint
->GetTarget().GetProcessSP().get(),
173 Address::DumpStyleModuleWithFileAddress
,
174 Address::DumpStyleLoadAddress
);
177 void BreakpointResolverAddress::Dump(Stream
*s
) const {}
179 lldb::BreakpointResolverSP
180 BreakpointResolverAddress::CopyForBreakpoint(Breakpoint
&breakpoint
) {
181 lldb::BreakpointResolverSP
ret_sp(
182 new BreakpointResolverAddress(&breakpoint
, m_addr
));