180814287SRaphael Isemann //===-- BreakpointResolver.cpp --------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointResolver.h"
1030fdc8d8SChris Lattner 
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
1305097246SAdrian Prantl // Have to include the other breakpoint resolver types here so the static
1405097246SAdrian Prantl // create from StructuredData can call them.
15e14dc268SJim Ingham #include "lldb/Breakpoint/BreakpointResolverAddress.h"
16e14dc268SJim Ingham #include "lldb/Breakpoint/BreakpointResolverFileLine.h"
17e14dc268SJim Ingham #include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
18e14dc268SJim Ingham #include "lldb/Breakpoint/BreakpointResolverName.h"
193815e702SJim Ingham #include "lldb/Breakpoint/BreakpointResolverScripted.h"
20b9c1b51eSKate Stone #include "lldb/Core/Address.h"
2130fdc8d8SChris Lattner #include "lldb/Core/ModuleList.h"
2230fdc8d8SChris Lattner #include "lldb/Core/SearchFilter.h"
23f642373cSJim Ingham #include "lldb/Symbol/CompileUnit.h"
24f642373cSJim Ingham #include "lldb/Symbol/Function.h"
25b9c1b51eSKate Stone #include "lldb/Symbol/SymbolContext.h"
26b9c1b51eSKate Stone #include "lldb/Target/Target.h"
27c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
286f9e6901SZachary Turner #include "lldb/Utility/Log.h"
29bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
30bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3130fdc8d8SChris Lattner 
3230fdc8d8SChris Lattner using namespace lldb_private;
33f642373cSJim Ingham using namespace lldb;
3430fdc8d8SChris Lattner 
3530fdc8d8SChris Lattner // BreakpointResolver:
36e14dc268SJim Ingham const char *BreakpointResolver::g_ty_to_name[] = {"FileAndLine", "Address",
37e14dc268SJim Ingham                                                   "SymbolName",  "SourceRegex",
3847b33dccSJim Ingham                                                   "Python",   "Exception",
3947b33dccSJim Ingham                                                   "Unknown"};
40e14dc268SJim Ingham 
4175f0f583SJim Ingham const char *BreakpointResolver::g_option_names[static_cast<uint32_t>(
4275f0f583SJim Ingham     BreakpointResolver::OptionNames::LastOptionName)] = {
43e14dc268SJim Ingham     "AddressOffset", "Exact",     "FileName",     "Inlines",     "Language",
44431b1584SAdrian Prantl     "LineNumber",    "Column",    "ModuleName",   "NameMask",    "Offset",
453815e702SJim Ingham     "PythonClass",   "Regex",     "ScriptArgs",   "SectionName", "SearchDepth",
463815e702SJim Ingham     "SkipPrologue",  "SymbolNames"};
47e14dc268SJim Ingham 
ResolverTyToName(enum ResolverTy type)48e14dc268SJim Ingham const char *BreakpointResolver::ResolverTyToName(enum ResolverTy type) {
49e14dc268SJim Ingham   if (type > LastKnownResolverType)
50e14dc268SJim Ingham     return g_ty_to_name[UnknownResolver];
51e14dc268SJim Ingham 
52e14dc268SJim Ingham   return g_ty_to_name[type];
53e14dc268SJim Ingham }
54e14dc268SJim Ingham 
55e14dc268SJim Ingham BreakpointResolver::ResolverTy
NameToResolverTy(llvm::StringRef name)562833321fSZachary Turner BreakpointResolver::NameToResolverTy(llvm::StringRef name) {
57e14dc268SJim Ingham   for (size_t i = 0; i < LastKnownResolverType; i++) {
582833321fSZachary Turner     if (name == g_ty_to_name[i])
59e14dc268SJim Ingham       return (ResolverTy)i;
60e14dc268SJim Ingham   }
61e14dc268SJim Ingham   return UnknownResolver;
62e14dc268SJim Ingham }
63e14dc268SJim Ingham 
BreakpointResolver(const BreakpointSP & bkpt,const unsigned char resolverTy,lldb::addr_t offset)646c17cc53STatyana Krasnukha BreakpointResolver::BreakpointResolver(const BreakpointSP &bkpt,
65b9c1b51eSKate Stone                                        const unsigned char resolverTy,
66b9c1b51eSKate Stone                                        lldb::addr_t offset)
67b9c1b51eSKate Stone     : m_breakpoint(bkpt), m_offset(offset), SubclassID(resolverTy) {}
6830fdc8d8SChris Lattner 
69fd2433e1SJonas Devlieghere BreakpointResolver::~BreakpointResolver() = default;
7030fdc8d8SChris Lattner 
CreateFromStructuredData(const StructuredData::Dictionary & resolver_dict,Status & error)71e14dc268SJim Ingham BreakpointResolverSP BreakpointResolver::CreateFromStructuredData(
7297206d57SZachary Turner     const StructuredData::Dictionary &resolver_dict, Status &error) {
73e14dc268SJim Ingham   BreakpointResolverSP result_sp;
74e14dc268SJim Ingham   if (!resolver_dict.IsValid()) {
75e14dc268SJim Ingham     error.SetErrorString("Can't deserialize from an invalid data object.");
76e14dc268SJim Ingham     return result_sp;
77e14dc268SJim Ingham   }
78e14dc268SJim Ingham 
792833321fSZachary Turner   llvm::StringRef subclass_name;
80e14dc268SJim Ingham 
81e14dc268SJim Ingham   bool success = resolver_dict.GetValueForKeyAsString(
82e14dc268SJim Ingham       GetSerializationSubclassKey(), subclass_name);
83e14dc268SJim Ingham 
84e14dc268SJim Ingham   if (!success) {
8589533764SJonas Devlieghere     error.SetErrorString("Resolver data missing subclass resolver key");
86e14dc268SJim Ingham     return result_sp;
87e14dc268SJim Ingham   }
88e14dc268SJim Ingham 
892833321fSZachary Turner   ResolverTy resolver_type = NameToResolverTy(subclass_name);
90e14dc268SJim Ingham   if (resolver_type == UnknownResolver) {
912833321fSZachary Turner     error.SetErrorStringWithFormatv("Unknown resolver type: {0}.",
922833321fSZachary Turner                                     subclass_name);
93e14dc268SJim Ingham     return result_sp;
94e14dc268SJim Ingham   }
95e14dc268SJim Ingham 
96e14dc268SJim Ingham   StructuredData::Dictionary *subclass_options = nullptr;
97e14dc268SJim Ingham   success = resolver_dict.GetValueForKeyAsDictionary(
98e14dc268SJim Ingham       GetSerializationSubclassOptionsKey(), subclass_options);
99e14dc268SJim Ingham   if (!success || !subclass_options || !subclass_options->IsValid()) {
100e14dc268SJim Ingham     error.SetErrorString("Resolver data missing subclass options key.");
101e14dc268SJim Ingham     return result_sp;
102e14dc268SJim Ingham   }
103e14dc268SJim Ingham 
104e14dc268SJim Ingham   lldb::addr_t offset;
105e14dc268SJim Ingham   success = subclass_options->GetValueForKeyAsInteger(
106e14dc268SJim Ingham       GetKey(OptionNames::Offset), offset);
107e14dc268SJim Ingham   if (!success) {
108e14dc268SJim Ingham     error.SetErrorString("Resolver data missing offset options key.");
109e14dc268SJim Ingham     return result_sp;
110e14dc268SJim Ingham   }
111e14dc268SJim Ingham 
112*6f1ce046SJonas Devlieghere   BreakpointResolver *resolver = nullptr;
113e14dc268SJim Ingham   switch (resolver_type) {
114e14dc268SJim Ingham   case FileLineResolver:
115e14dc268SJim Ingham     resolver = BreakpointResolverFileLine::CreateFromStructuredData(
116e14dc268SJim Ingham         nullptr, *subclass_options, error);
117e14dc268SJim Ingham     break;
118e14dc268SJim Ingham   case AddressResolver:
119e14dc268SJim Ingham     resolver = BreakpointResolverAddress::CreateFromStructuredData(
120e14dc268SJim Ingham         nullptr, *subclass_options, error);
121e14dc268SJim Ingham     break;
122e14dc268SJim Ingham   case NameResolver:
123e14dc268SJim Ingham     resolver = BreakpointResolverName::CreateFromStructuredData(
124e14dc268SJim Ingham         nullptr, *subclass_options, error);
125e14dc268SJim Ingham     break;
126e14dc268SJim Ingham   case FileRegexResolver:
127e14dc268SJim Ingham     resolver = BreakpointResolverFileRegex::CreateFromStructuredData(
128e14dc268SJim Ingham         nullptr, *subclass_options, error);
129e14dc268SJim Ingham     break;
1303815e702SJim Ingham   case PythonResolver:
1313815e702SJim Ingham     resolver = BreakpointResolverScripted::CreateFromStructuredData(
1323815e702SJim Ingham         nullptr, *subclass_options, error);
1333815e702SJim Ingham     break;
134e14dc268SJim Ingham   case ExceptionResolver:
135e14dc268SJim Ingham     error.SetErrorString("Exception resolvers are hard.");
136e14dc268SJim Ingham     break;
137e14dc268SJim Ingham   default:
138e14dc268SJim Ingham     llvm_unreachable("Should never get an unresolvable resolver type.");
139e14dc268SJim Ingham   }
140e14dc268SJim Ingham 
141*6f1ce046SJonas Devlieghere   if (!resolver || error.Fail())
142e14dc268SJim Ingham     return result_sp;
143*6f1ce046SJonas Devlieghere 
144e14dc268SJim Ingham   // Add on the global offset option:
145e14dc268SJim Ingham   resolver->SetOffset(offset);
146e14dc268SJim Ingham   return BreakpointResolverSP(resolver);
147e14dc268SJim Ingham }
148e14dc268SJim Ingham 
WrapOptionsDict(StructuredData::DictionarySP options_dict_sp)149e14dc268SJim Ingham StructuredData::DictionarySP BreakpointResolver::WrapOptionsDict(
150e14dc268SJim Ingham     StructuredData::DictionarySP options_dict_sp) {
151e14dc268SJim Ingham   if (!options_dict_sp || !options_dict_sp->IsValid())
152e14dc268SJim Ingham     return StructuredData::DictionarySP();
153e14dc268SJim Ingham 
154e14dc268SJim Ingham   StructuredData::DictionarySP type_dict_sp(new StructuredData::Dictionary());
155e14dc268SJim Ingham   type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetResolverName());
156e14dc268SJim Ingham   type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);
157e14dc268SJim Ingham 
158e14dc268SJim Ingham   // Add the m_offset to the dictionary:
159e14dc268SJim Ingham   options_dict_sp->AddIntegerItem(GetKey(OptionNames::Offset), m_offset);
160e14dc268SJim Ingham 
161e14dc268SJim Ingham   return type_dict_sp;
162e14dc268SJim Ingham }
163e14dc268SJim Ingham 
SetBreakpoint(const BreakpointSP & bkpt)1646c17cc53STatyana Krasnukha void BreakpointResolver::SetBreakpoint(const BreakpointSP &bkpt) {
1656c17cc53STatyana Krasnukha   assert(bkpt);
16630fdc8d8SChris Lattner   m_breakpoint = bkpt;
1673815e702SJim Ingham   NotifyBreakpointSet();
16830fdc8d8SChris Lattner }
16930fdc8d8SChris Lattner 
ResolveBreakpointInModules(SearchFilter & filter,ModuleList & modules)170b9c1b51eSKate Stone void BreakpointResolver::ResolveBreakpointInModules(SearchFilter &filter,
171b9c1b51eSKate Stone                                                     ModuleList &modules) {
17230fdc8d8SChris Lattner   filter.SearchInModuleList(*this, modules);
17330fdc8d8SChris Lattner }
17430fdc8d8SChris Lattner 
ResolveBreakpoint(SearchFilter & filter)175b9c1b51eSKate Stone void BreakpointResolver::ResolveBreakpoint(SearchFilter &filter) {
17630fdc8d8SChris Lattner   filter.Search(*this);
17730fdc8d8SChris Lattner }
17830fdc8d8SChris Lattner 
179431b1584SAdrian Prantl namespace {
180431b1584SAdrian Prantl struct SourceLoc {
181431b1584SAdrian Prantl   uint32_t line = UINT32_MAX;
1823e2ed744SMed Ismail Bennani   uint16_t column;
SourceLoc__anon27966a7c0111::SourceLoc1833e2ed744SMed Ismail Bennani   SourceLoc(uint32_t l, llvm::Optional<uint16_t> c)
1843e2ed744SMed Ismail Bennani       : line(l), column(c ? *c : LLDB_INVALID_COLUMN_NUMBER) {}
SourceLoc__anon27966a7c0111::SourceLoc185431b1584SAdrian Prantl   SourceLoc(const SymbolContext &sc)
186431b1584SAdrian Prantl       : line(sc.line_entry.line),
1873e2ed744SMed Ismail Bennani         column(sc.line_entry.column ? sc.line_entry.column
1883e2ed744SMed Ismail Bennani                                     : LLDB_INVALID_COLUMN_NUMBER) {}
189431b1584SAdrian Prantl };
190431b1584SAdrian Prantl 
operator <(const SourceLoc lhs,const SourceLoc rhs)1913e2ed744SMed Ismail Bennani bool operator<(const SourceLoc lhs, const SourceLoc rhs) {
1923e2ed744SMed Ismail Bennani   if (lhs.line < rhs.line)
193431b1584SAdrian Prantl     return true;
1943e2ed744SMed Ismail Bennani   if (lhs.line > rhs.line)
195431b1584SAdrian Prantl     return false;
1963e2ed744SMed Ismail Bennani   //  uint32_t a_col = lhs.column ? lhs.column : LLDB_INVALID_COLUMN_NUMBER;
1973e2ed744SMed Ismail Bennani   //  uint32_t b_col = rhs.column ? rhs.column : LLDB_INVALID_COLUMN_NUMBER;
1983e2ed744SMed Ismail Bennani   return lhs.column < rhs.column;
199431b1584SAdrian Prantl }
200431b1584SAdrian Prantl } // namespace
201431b1584SAdrian Prantl 
SetSCMatchesByLine(SearchFilter & filter,SymbolContextList & sc_list,bool skip_prologue,llvm::StringRef log_ident,uint32_t line,llvm::Optional<uint16_t> column)2023e2ed744SMed Ismail Bennani void BreakpointResolver::SetSCMatchesByLine(
2033e2ed744SMed Ismail Bennani     SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue,
2043e2ed744SMed Ismail Bennani     llvm::StringRef log_ident, uint32_t line, llvm::Optional<uint16_t> column) {
2053dec0684SAdrian Prantl   llvm::SmallVector<SymbolContext, 16> all_scs;
2063dec0684SAdrian Prantl   for (uint32_t i = 0; i < sc_list.GetSize(); ++i)
2073dec0684SAdrian Prantl     all_scs.push_back(sc_list[i]);
2083dec0684SAdrian Prantl 
2093dec0684SAdrian Prantl   while (all_scs.size()) {
2103dec0684SAdrian Prantl     uint32_t closest_line = UINT32_MAX;
2113dec0684SAdrian Prantl 
2123dec0684SAdrian Prantl     // Move all the elements with a matching file spec to the end.
2133dec0684SAdrian Prantl     auto &match = all_scs[0];
2143dec0684SAdrian Prantl     auto worklist_begin = std::partition(
2153dec0684SAdrian Prantl         all_scs.begin(), all_scs.end(), [&](const SymbolContext &sc) {
2163dec0684SAdrian Prantl           if (sc.line_entry.file == match.line_entry.file ||
2173dec0684SAdrian Prantl               sc.line_entry.original_file == match.line_entry.original_file) {
2183dec0684SAdrian Prantl             // When a match is found, keep track of the smallest line number.
2193dec0684SAdrian Prantl             closest_line = std::min(closest_line, sc.line_entry.line);
2203dec0684SAdrian Prantl             return false;
2213dec0684SAdrian Prantl           }
2223dec0684SAdrian Prantl           return true;
2233dec0684SAdrian Prantl         });
2243dec0684SAdrian Prantl 
225431b1584SAdrian Prantl     // (worklist_begin, worklist_end) now contains all entries for one filespec.
226431b1584SAdrian Prantl     auto worklist_end = all_scs.end();
227431b1584SAdrian Prantl 
228431b1584SAdrian Prantl     if (column) {
229431b1584SAdrian Prantl       // If a column was requested, do a more precise match and only
23035ecfda0SMed Ismail Bennani       // return the first location that comes before or at the
231431b1584SAdrian Prantl       // requested location.
2323e2ed744SMed Ismail Bennani       SourceLoc requested(line, *column);
233431b1584SAdrian Prantl       // First, filter out all entries left of the requested column.
234431b1584SAdrian Prantl       worklist_end = std::remove_if(
235431b1584SAdrian Prantl           worklist_begin, worklist_end,
23635ecfda0SMed Ismail Bennani           [&](const SymbolContext &sc) { return requested < SourceLoc(sc); });
237431b1584SAdrian Prantl       // Sort the remaining entries by (line, column).
2389bbba276SJonas Devlieghere       llvm::sort(worklist_begin, worklist_end,
239431b1584SAdrian Prantl                  [](const SymbolContext &a, const SymbolContext &b) {
240431b1584SAdrian Prantl                    return SourceLoc(a) < SourceLoc(b);
241431b1584SAdrian Prantl                  });
242431b1584SAdrian Prantl 
243431b1584SAdrian Prantl       // Filter out all locations with a source location after the closest match.
244431b1584SAdrian Prantl       if (worklist_begin != worklist_end)
245431b1584SAdrian Prantl         worklist_end = std::remove_if(
246431b1584SAdrian Prantl             worklist_begin, worklist_end, [&](const SymbolContext &sc) {
247431b1584SAdrian Prantl               return SourceLoc(*worklist_begin) < SourceLoc(sc);
248431b1584SAdrian Prantl             });
249431b1584SAdrian Prantl     } else {
250431b1584SAdrian Prantl       // Remove all entries with a larger line number.
251431b1584SAdrian Prantl       // ResolveSymbolContext will always return a number that is >=
252431b1584SAdrian Prantl       // the line number you pass in. So the smaller line number is
253431b1584SAdrian Prantl       // always better.
254431b1584SAdrian Prantl       worklist_end = std::remove_if(worklist_begin, worklist_end,
255431b1584SAdrian Prantl                                     [&](const SymbolContext &sc) {
2563dec0684SAdrian Prantl                                       return closest_line != sc.line_entry.line;
2573dec0684SAdrian Prantl                                     });
258431b1584SAdrian Prantl     }
2593dec0684SAdrian Prantl 
2603dec0684SAdrian Prantl     // Sort by file address.
2619bbba276SJonas Devlieghere     llvm::sort(worklist_begin, worklist_end,
2623dec0684SAdrian Prantl                [](const SymbolContext &a, const SymbolContext &b) {
2633dec0684SAdrian Prantl                  return a.line_entry.range.GetBaseAddress().GetFileAddress() <
2643dec0684SAdrian Prantl                         b.line_entry.range.GetBaseAddress().GetFileAddress();
2653dec0684SAdrian Prantl                });
2663dec0684SAdrian Prantl 
2673dec0684SAdrian Prantl     // Go through and see if there are line table entries that are
2683dec0684SAdrian Prantl     // contiguous, and if so keep only the first of the contiguous range.
2693dec0684SAdrian Prantl     // We do this by picking the first location in each lexical block.
2703dec0684SAdrian Prantl     llvm::SmallDenseSet<Block *, 8> blocks_with_breakpoints;
2713dec0684SAdrian Prantl     for (auto first = worklist_begin; first != worklist_end; ++first) {
2723dec0684SAdrian Prantl       assert(!blocks_with_breakpoints.count(first->block));
2733dec0684SAdrian Prantl       blocks_with_breakpoints.insert(first->block);
2743dec0684SAdrian Prantl       worklist_end =
2753dec0684SAdrian Prantl           std::remove_if(std::next(first), worklist_end,
2763dec0684SAdrian Prantl                          [&](const SymbolContext &sc) {
2773dec0684SAdrian Prantl                            return blocks_with_breakpoints.count(sc.block);
2783dec0684SAdrian Prantl                          });
2793dec0684SAdrian Prantl     }
2803dec0684SAdrian Prantl 
2813dec0684SAdrian Prantl     // Make breakpoints out of the closest line number match.
2823dec0684SAdrian Prantl     for (auto &sc : llvm::make_range(worklist_begin, worklist_end))
2833dec0684SAdrian Prantl       AddLocation(filter, sc, skip_prologue, log_ident);
2843dec0684SAdrian Prantl 
2853dec0684SAdrian Prantl     // Remove all contexts processed by this iteration.
2863dec0684SAdrian Prantl     all_scs.erase(worklist_begin, all_scs.end());
2873dec0684SAdrian Prantl   }
2883dec0684SAdrian Prantl }
2893dec0684SAdrian Prantl 
AddLocation(SearchFilter & filter,const SymbolContext & sc,bool skip_prologue,llvm::StringRef log_ident)2903dec0684SAdrian Prantl void BreakpointResolver::AddLocation(SearchFilter &filter,
2913dec0684SAdrian Prantl                                      const SymbolContext &sc,
2923dec0684SAdrian Prantl                                      bool skip_prologue,
2933dec0684SAdrian Prantl                                      llvm::StringRef log_ident) {
294a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::Breakpoints);
295f642373cSJim Ingham   Address line_start = sc.line_entry.range.GetBaseAddress();
2963dec0684SAdrian Prantl   if (!line_start.IsValid()) {
29763e5fb76SJonas Devlieghere     LLDB_LOGF(log,
29863e5fb76SJonas Devlieghere               "error: Unable to set breakpoint %s at file address "
2993dec0684SAdrian Prantl               "0x%" PRIx64 "\n",
3003dec0684SAdrian Prantl               log_ident.str().c_str(), line_start.GetFileAddress());
3013dec0684SAdrian Prantl     return;
3023dec0684SAdrian Prantl   }
3033dec0684SAdrian Prantl 
3043dec0684SAdrian Prantl   if (!filter.AddressPasses(line_start)) {
30563e5fb76SJonas Devlieghere     LLDB_LOGF(log,
30663e5fb76SJonas Devlieghere               "Breakpoint %s at file address 0x%" PRIx64
3073dec0684SAdrian Prantl               " didn't pass the filter.\n",
3083dec0684SAdrian Prantl               log_ident.str().c_str(), line_start.GetFileAddress());
3093dec0684SAdrian Prantl   }
3103dec0684SAdrian Prantl 
311f642373cSJim Ingham   // If the line number is before the prologue end, move it there...
312f642373cSJim Ingham   bool skipped_prologue = false;
3133dec0684SAdrian Prantl   if (skip_prologue && sc.function) {
3143dec0684SAdrian Prantl     Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
315b9c1b51eSKate Stone     if (prologue_addr.IsValid() && (line_start == prologue_addr)) {
3163dec0684SAdrian Prantl       const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
317b9c1b51eSKate Stone       if (prologue_byte_size) {
318f642373cSJim Ingham         prologue_addr.Slide(prologue_byte_size);
319f642373cSJim Ingham 
320b9c1b51eSKate Stone         if (filter.AddressPasses(prologue_addr)) {
321f642373cSJim Ingham           skipped_prologue = true;
322f642373cSJim Ingham           line_start = prologue_addr;
323f642373cSJim Ingham         }
324f642373cSJim Ingham       }
325f642373cSJim Ingham     }
326f642373cSJim Ingham   }
327f642373cSJim Ingham 
3282411167fSJim Ingham   BreakpointLocationSP bp_loc_sp(AddLocation(line_start));
3296c17cc53STatyana Krasnukha   if (log && bp_loc_sp && !GetBreakpoint()->IsInternal()) {
330f642373cSJim Ingham     StreamString s;
331f642373cSJim Ingham     bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
33263e5fb76SJonas Devlieghere     LLDB_LOGF(log, "Added location (skipped prologue: %s): %s \n",
333b9c1b51eSKate Stone               skipped_prologue ? "yes" : "no", s.GetData());
334f642373cSJim Ingham   }
335f642373cSJim Ingham }
3362411167fSJim Ingham 
AddLocation(Address loc_addr,bool * new_location)337b9c1b51eSKate Stone BreakpointLocationSP BreakpointResolver::AddLocation(Address loc_addr,
338b9c1b51eSKate Stone                                                      bool *new_location) {
3392411167fSJim Ingham   loc_addr.Slide(m_offset);
3406c17cc53STatyana Krasnukha   return GetBreakpoint()->AddLocation(loc_addr, new_location);
3412411167fSJim Ingham }
3422411167fSJim Ingham 
SetOffset(lldb::addr_t offset)343b9c1b51eSKate Stone void BreakpointResolver::SetOffset(lldb::addr_t offset) {
344b9c1b51eSKate Stone   // There may already be an offset, so we are actually adjusting location
345b9c1b51eSKate Stone   // addresses by the difference.
3462411167fSJim Ingham   // lldb::addr_t slide = offset - m_offset;
3473dec0684SAdrian Prantl   // FIXME: We should go fix up all the already set locations for the new
3483dec0684SAdrian Prantl   // slide.
3492411167fSJim Ingham 
3502411167fSJim Ingham   m_offset = offset;
3512411167fSJim Ingham }
352