1dda28197Spatrick //===-- BreakpointResolverAddress.cpp -------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Breakpoint/BreakpointResolverAddress.h"
10061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
11061da546Spatrick #include "lldb/Core/Module.h"
12061da546Spatrick #include "lldb/Core/Section.h"
13061da546Spatrick #include "lldb/Target/Process.h"
14061da546Spatrick #include "lldb/Target/Target.h"
15*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
16061da546Spatrick #include "lldb/Utility/StreamString.h"
17061da546Spatrick
18061da546Spatrick using namespace lldb;
19061da546Spatrick using namespace lldb_private;
20061da546Spatrick
21061da546Spatrick // BreakpointResolverAddress:
BreakpointResolverAddress(const BreakpointSP & bkpt,const Address & addr,const FileSpec & module_spec)22061da546Spatrick BreakpointResolverAddress::BreakpointResolverAddress(
23dda28197Spatrick const BreakpointSP &bkpt, const Address &addr, const FileSpec &module_spec)
24061da546Spatrick : BreakpointResolver(bkpt, BreakpointResolver::AddressResolver),
25061da546Spatrick m_addr(addr), m_resolved_addr(LLDB_INVALID_ADDRESS),
26061da546Spatrick m_module_filespec(module_spec) {}
27061da546Spatrick
BreakpointResolverAddress(const BreakpointSP & bkpt,const Address & addr)28dda28197Spatrick BreakpointResolverAddress::BreakpointResolverAddress(const BreakpointSP &bkpt,
29061da546Spatrick const Address &addr)
30061da546Spatrick : BreakpointResolver(bkpt, BreakpointResolver::AddressResolver),
31*f6aab3d8Srobert m_addr(addr), m_resolved_addr(LLDB_INVALID_ADDRESS) {}
32061da546Spatrick
CreateFromStructuredData(const BreakpointSP & bkpt,const StructuredData::Dictionary & options_dict,Status & error)33061da546Spatrick BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData(
34dda28197Spatrick const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict,
35061da546Spatrick Status &error) {
36061da546Spatrick llvm::StringRef module_name;
37061da546Spatrick lldb::addr_t addr_offset;
38061da546Spatrick FileSpec module_filespec;
39061da546Spatrick bool success;
40061da546Spatrick
41061da546Spatrick success = options_dict.GetValueForKeyAsInteger(
42061da546Spatrick GetKey(OptionNames::AddressOffset), addr_offset);
43061da546Spatrick if (!success) {
44061da546Spatrick error.SetErrorString("BRFL::CFSD: Couldn't find address offset entry.");
45061da546Spatrick return nullptr;
46061da546Spatrick }
47061da546Spatrick Address address(addr_offset);
48061da546Spatrick
49061da546Spatrick success = options_dict.HasKey(GetKey(OptionNames::ModuleName));
50061da546Spatrick if (success) {
51061da546Spatrick success = options_dict.GetValueForKeyAsString(
52061da546Spatrick GetKey(OptionNames::ModuleName), module_name);
53061da546Spatrick if (!success) {
54061da546Spatrick error.SetErrorString("BRA::CFSD: Couldn't read module name entry.");
55061da546Spatrick return nullptr;
56061da546Spatrick }
57061da546Spatrick module_filespec.SetFile(module_name, FileSpec::Style::native);
58061da546Spatrick }
59061da546Spatrick return new BreakpointResolverAddress(bkpt, address, module_filespec);
60061da546Spatrick }
61061da546Spatrick
62061da546Spatrick StructuredData::ObjectSP
SerializeToStructuredData()63061da546Spatrick BreakpointResolverAddress::SerializeToStructuredData() {
64061da546Spatrick StructuredData::DictionarySP options_dict_sp(
65061da546Spatrick new StructuredData::Dictionary());
66061da546Spatrick SectionSP section_sp = m_addr.GetSection();
67061da546Spatrick if (section_sp) {
68061da546Spatrick ModuleSP module_sp = section_sp->GetModule();
69061da546Spatrick ConstString module_name;
70061da546Spatrick if (module_sp)
71061da546Spatrick module_name.SetCString(module_name.GetCString());
72061da546Spatrick
73061da546Spatrick options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName),
74061da546Spatrick module_name.GetCString());
75061da546Spatrick options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset),
76061da546Spatrick m_addr.GetOffset());
77061da546Spatrick } else {
78061da546Spatrick options_dict_sp->AddIntegerItem(GetKey(OptionNames::AddressOffset),
79061da546Spatrick m_addr.GetOffset());
80061da546Spatrick if (m_module_filespec) {
81061da546Spatrick options_dict_sp->AddStringItem(GetKey(OptionNames::ModuleName),
82061da546Spatrick m_module_filespec.GetPath());
83061da546Spatrick }
84061da546Spatrick }
85061da546Spatrick
86061da546Spatrick return WrapOptionsDict(options_dict_sp);
87061da546Spatrick }
88061da546Spatrick
ResolveBreakpoint(SearchFilter & filter)89061da546Spatrick void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter &filter) {
90061da546Spatrick // If the address is not section relative, then we should not try to re-
91061da546Spatrick // resolve it, it is just some random address and we wouldn't know what to do
92061da546Spatrick // on reload. But if it is section relative, we need to re-resolve it since
93061da546Spatrick // the section it's in may have shifted on re-run.
94061da546Spatrick bool re_resolve = false;
95061da546Spatrick if (m_addr.GetSection() || m_module_filespec)
96061da546Spatrick re_resolve = true;
97dda28197Spatrick else if (GetBreakpoint()->GetNumLocations() == 0)
98061da546Spatrick re_resolve = true;
99061da546Spatrick
100061da546Spatrick if (re_resolve)
101061da546Spatrick BreakpointResolver::ResolveBreakpoint(filter);
102061da546Spatrick }
103061da546Spatrick
ResolveBreakpointInModules(SearchFilter & filter,ModuleList & modules)104061da546Spatrick void BreakpointResolverAddress::ResolveBreakpointInModules(
105061da546Spatrick SearchFilter &filter, ModuleList &modules) {
106061da546Spatrick // See comment in ResolveBreakpoint.
107061da546Spatrick bool re_resolve = false;
108061da546Spatrick if (m_addr.GetSection())
109061da546Spatrick re_resolve = true;
110dda28197Spatrick else if (GetBreakpoint()->GetNumLocations() == 0)
111061da546Spatrick re_resolve = true;
112061da546Spatrick
113061da546Spatrick if (re_resolve)
114061da546Spatrick BreakpointResolver::ResolveBreakpointInModules(filter, modules);
115061da546Spatrick }
116061da546Spatrick
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr)117061da546Spatrick Searcher::CallbackReturn BreakpointResolverAddress::SearchCallback(
118061da546Spatrick SearchFilter &filter, SymbolContext &context, Address *addr) {
119dda28197Spatrick BreakpointSP breakpoint_sp = GetBreakpoint();
120dda28197Spatrick Breakpoint &breakpoint = *breakpoint_sp;
121061da546Spatrick
122061da546Spatrick if (filter.AddressPasses(m_addr)) {
123dda28197Spatrick if (breakpoint.GetNumLocations() == 0) {
124061da546Spatrick // If the address is just an offset, and we're given a module, see if we
125061da546Spatrick // can find the appropriate module loaded in the binary, and fix up
126061da546Spatrick // m_addr to use that.
127061da546Spatrick if (!m_addr.IsSectionOffset() && m_module_filespec) {
128dda28197Spatrick Target &target = breakpoint.GetTarget();
129061da546Spatrick ModuleSpec module_spec(m_module_filespec);
130061da546Spatrick ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec);
131061da546Spatrick if (module_sp) {
132061da546Spatrick Address tmp_address;
133061da546Spatrick if (module_sp->ResolveFileAddress(m_addr.GetOffset(), tmp_address))
134061da546Spatrick m_addr = tmp_address;
135061da546Spatrick }
136061da546Spatrick }
137061da546Spatrick
138dda28197Spatrick m_resolved_addr = m_addr.GetLoadAddress(&breakpoint.GetTarget());
139061da546Spatrick BreakpointLocationSP bp_loc_sp(AddLocation(m_addr));
140dda28197Spatrick if (bp_loc_sp && !breakpoint.IsInternal()) {
141061da546Spatrick StreamString s;
142061da546Spatrick bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
143*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Breakpoints);
144061da546Spatrick LLDB_LOGF(log, "Added location: %s\n", s.GetData());
145061da546Spatrick }
146061da546Spatrick } else {
147dda28197Spatrick BreakpointLocationSP loc_sp = breakpoint.GetLocationAtIndex(0);
148061da546Spatrick lldb::addr_t cur_load_location =
149dda28197Spatrick m_addr.GetLoadAddress(&breakpoint.GetTarget());
150061da546Spatrick if (cur_load_location != m_resolved_addr) {
151061da546Spatrick m_resolved_addr = cur_load_location;
152061da546Spatrick loc_sp->ClearBreakpointSite();
153061da546Spatrick loc_sp->ResolveBreakpointSite();
154061da546Spatrick }
155061da546Spatrick }
156061da546Spatrick }
157061da546Spatrick return Searcher::eCallbackReturnStop;
158061da546Spatrick }
159061da546Spatrick
GetDepth()160061da546Spatrick lldb::SearchDepth BreakpointResolverAddress::GetDepth() {
161061da546Spatrick return lldb::eSearchDepthTarget;
162061da546Spatrick }
163061da546Spatrick
GetDescription(Stream * s)164061da546Spatrick void BreakpointResolverAddress::GetDescription(Stream *s) {
165061da546Spatrick s->PutCString("address = ");
166dda28197Spatrick m_addr.Dump(s, GetBreakpoint()->GetTarget().GetProcessSP().get(),
167061da546Spatrick Address::DumpStyleModuleWithFileAddress,
168061da546Spatrick Address::DumpStyleLoadAddress);
169061da546Spatrick }
170061da546Spatrick
Dump(Stream * s) const171061da546Spatrick void BreakpointResolverAddress::Dump(Stream *s) const {}
172061da546Spatrick
173061da546Spatrick lldb::BreakpointResolverSP
CopyForBreakpoint(BreakpointSP & breakpoint)174dda28197Spatrick BreakpointResolverAddress::CopyForBreakpoint(BreakpointSP &breakpoint) {
175061da546Spatrick lldb::BreakpointResolverSP ret_sp(
176dda28197Spatrick new BreakpointResolverAddress(breakpoint, m_addr));
177061da546Spatrick return ret_sp;
178061da546Spatrick }
179