xref: /openbsd-src/gnu/llvm/lldb/source/Breakpoint/BreakpointResolverAddress.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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