LLDB  mainline
AssertFrameRecognizer.cpp
Go to the documentation of this file.
2 #include "lldb/Core/Module.h"
3 #include "lldb/Symbol/Function.h"
5 #include "lldb/Target/Process.h"
7 #include "lldb/Target/Target.h"
8 #include "lldb/Target/Thread.h"
9 #include "lldb/Utility/LLDBLog.h"
10 
11 using namespace llvm;
12 using namespace lldb;
13 using namespace lldb_private;
14 
15 namespace lldb_private {
16 
17 /// Stores a function module spec, symbol name and possibly an alternate symbol
18 /// name.
21  std::vector<ConstString> symbols;
22 
23  // The symbols are regular expressions. In such case all symbols are matched
24  // with their trailing @VER symbol version stripped.
25  bool symbols_are_regex = false;
26 };
27 
28 /// Fetches the abort frame location depending on the current platform.
29 ///
30 /// \param[in] os
31 /// The target's os type.
32 /// \param[in,out] location
33 /// The struct that will contain the abort module spec and symbol names.
34 /// \return
35 /// \b true, if the platform is supported
36 /// \b false, otherwise.
37 bool GetAbortLocation(llvm::Triple::OSType os, SymbolLocation &location) {
38  switch (os) {
39  case llvm::Triple::Darwin:
40  case llvm::Triple::MacOSX:
41  location.module_spec = FileSpec("libsystem_kernel.dylib");
42  location.symbols.push_back(ConstString("__pthread_kill"));
43  break;
44  case llvm::Triple::Linux:
45  location.module_spec = FileSpec("libc.so.6");
46  location.symbols.push_back(ConstString("raise"));
47  location.symbols.push_back(ConstString("__GI_raise"));
48  location.symbols.push_back(ConstString("gsignal"));
49  location.symbols.push_back(ConstString("pthread_kill"));
50  location.symbols_are_regex = true;
51  break;
52  default:
53  Log *log = GetLog(LLDBLog::Unwind);
54  LLDB_LOG(log, "AssertFrameRecognizer::GetAbortLocation Unsupported OS");
55  return false;
56  }
57 
58  return true;
59 }
60 
61 /// Fetches the assert frame location depending on the current platform.
62 ///
63 /// \param[in] os
64 /// The target's os type.
65 /// \param[in,out] location
66 /// The struct that will contain the assert module spec and symbol names.
67 /// \return
68 /// \b true, if the platform is supported
69 /// \b false, otherwise.
70 bool GetAssertLocation(llvm::Triple::OSType os, SymbolLocation &location) {
71  switch (os) {
72  case llvm::Triple::Darwin:
73  case llvm::Triple::MacOSX:
74  location.module_spec = FileSpec("libsystem_c.dylib");
75  location.symbols.push_back(ConstString("__assert_rtn"));
76  break;
77  case llvm::Triple::Linux:
78  location.module_spec = FileSpec("libc.so.6");
79  location.symbols.push_back(ConstString("__assert_fail"));
80  location.symbols.push_back(ConstString("__GI___assert_fail"));
81  break;
82  default:
83  Log *log = GetLog(LLDBLog::Unwind);
84  LLDB_LOG(log, "AssertFrameRecognizer::GetAssertLocation Unsupported OS");
85  return false;
86  }
87 
88  return true;
89 }
90 
92  Target &target = process->GetTarget();
93  llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
94  SymbolLocation location;
95 
96  if (!GetAbortLocation(os, location))
97  return;
98 
99  if (!location.symbols_are_regex) {
101  std::make_shared<AssertFrameRecognizer>(),
102  location.module_spec.GetFilename(), location.symbols,
103  /*first_instruction_only*/ false);
104  return;
105  }
106  std::string module_re = "^";
107  for (char c : location.module_spec.GetFilename().GetStringRef()) {
108  if (c == '.')
109  module_re += '\\';
110  module_re += c;
111  }
112  module_re += '$';
113  std::string symbol_re = "^(";
114  for (auto it = location.symbols.cbegin(); it != location.symbols.cend();
115  ++it) {
116  if (it != location.symbols.cbegin())
117  symbol_re += '|';
118  symbol_re += it->GetStringRef();
119  }
120  // Strip the trailing @VER symbol version.
121  symbol_re += ")(@.*)?$";
123  std::make_shared<AssertFrameRecognizer>(),
124  std::make_shared<RegularExpression>(std::move(module_re)),
125  std::make_shared<RegularExpression>(std::move(symbol_re)),
126  /*first_instruction_only*/ false);
127 }
128 
129 } // namespace lldb_private
130 
131 lldb::RecognizedStackFrameSP
132 AssertFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
133  ThreadSP thread_sp = frame_sp->GetThread();
134  ProcessSP process_sp = thread_sp->GetProcess();
135  Target &target = process_sp->GetTarget();
136  llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
137  SymbolLocation location;
138 
139  if (!GetAssertLocation(os, location))
140  return RecognizedStackFrameSP();
141 
142  const uint32_t frames_to_fetch = 6;
143  const uint32_t last_frame_index = frames_to_fetch - 1;
144  StackFrameSP prev_frame_sp = nullptr;
145 
146  // Fetch most relevant frame
147  for (uint32_t frame_index = 0; frame_index < frames_to_fetch; frame_index++) {
148  prev_frame_sp = thread_sp->GetStackFrameAtIndex(frame_index);
149 
150  if (!prev_frame_sp) {
151  Log *log = GetLog(LLDBLog::Unwind);
152  LLDB_LOG(log, "Abort Recognizer: Hit unwinding bound ({1} frames)!",
153  frames_to_fetch);
154  break;
155  }
156 
157  SymbolContext sym_ctx =
158  prev_frame_sp->GetSymbolContext(eSymbolContextEverything);
159 
160  if (!sym_ctx.module_sp ||
161  !sym_ctx.module_sp->GetFileSpec().FileEquals(location.module_spec))
162  continue;
163 
164  ConstString func_name = sym_ctx.GetFunctionName();
165 
166  if (llvm::is_contained(location.symbols, func_name)) {
167  // We go a frame beyond the assert location because the most relevant
168  // frame for the user is the one in which the assert function was called.
169  // If the assert location is the last frame fetched, then it is set as
170  // the most relevant frame.
171 
172  StackFrameSP most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(
173  std::min(frame_index + 1, last_frame_index));
174 
175  // Pass assert location to AbortRecognizedStackFrame to set as most
176  // relevant frame.
177  return lldb::RecognizedStackFrameSP(
178  new AssertRecognizedStackFrame(most_relevant_frame_sp));
179  }
180  }
181 
182  return RecognizedStackFrameSP();
183 }
184 
185 AssertRecognizedStackFrame::AssertRecognizedStackFrame(
186  StackFrameSP most_relevant_frame_sp)
187  : m_most_relevant_frame(most_relevant_frame_sp) {
188  m_stop_desc = "hit program assert";
189 }
190 
192  return m_most_relevant_frame;
193 }
lldb_private::Target::GetFrameRecognizerManager
StackFrameRecognizerManager & GetFrameRecognizerManager()
Definition: Target.h:1427
llvm
Definition: Debugger.h:50
lldb_private::Process
Definition: Process.h:338
Module.h
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1219
lldb_private::AssertRecognizedStackFrame::m_most_relevant_frame
lldb::StackFrameSP m_most_relevant_frame
Definition: AssertFrameRecognizer.h:37
lldb_private::FileSpec::GetFilename
const ConstString & GetFilename() const
Filename string const get accessor.
Definition: FileSpec.h:239
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:454
lldb_private::SymbolLocation::symbols
std::vector< ConstString > symbols
Definition: AssertFrameRecognizer.cpp:21
lldb_private::SymbolLocation::symbols_are_regex
bool symbols_are_regex
Definition: AssertFrameRecognizer.cpp:25
lldb_private::SymbolContext
Definition: SymbolContext.h:33
lldb_private::Target
Definition: Target.h:469
AssertFrameRecognizer.h
Process.h
Target.h
lldb_private::FileSpec
Definition: FileSpec.h:55
lldb_private::SymbolLocation
Stores a function module spec, symbol name and possibly an alternate symbol name.
Definition: AssertFrameRecognizer.cpp:19
lldb_private::ConstString::GetStringRef
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:201
lldb_private::GetAssertLocation
bool GetAssertLocation(llvm::Triple::OSType os, SymbolLocation &location)
Fetches the assert frame location depending on the current platform.
Definition: AssertFrameRecognizer.cpp:70
StackFrameList.h
lldb_private::ConstString
Definition: ConstString.h:39
lldb_private::SymbolContext::GetFunctionName
ConstString GetFunctionName(Mangled::NamePreference preference=Mangled::ePreferDemangled) const
Find a name of the innermost function for the symbol context.
Definition: SymbolContext.cpp:650
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
Thread.h
lldb_private::RecognizedStackFrame::m_stop_desc
std::string m_stop_desc
Definition: StackFrameRecognizer.h:46
lldb_private::StackFrameRecognizerManager::AddRecognizer
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, ConstString module, llvm::ArrayRef< ConstString > symbols, bool first_instruction_only=true)
lldb_private::RegisterAssertFrameRecognizer
void RegisterAssertFrameRecognizer(Process *process)
Registers the assert stack frame recognizer.
Definition: AssertFrameRecognizer.cpp:91
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:989
uint32_t
lldb_private::SymbolContext::module_sp
lldb::ModuleSP module_sp
The Module for a given query.
Definition: SymbolContext.h:318
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:337
Function.h
SymbolContext.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::SymbolLocation::module_spec
FileSpec module_spec
Definition: AssertFrameRecognizer.cpp:20
lldb_private::AssertRecognizedStackFrame
Definition: AssertFrameRecognizer.h:31
lldb_private::Log
Definition: Log.h:115
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
lldb
Definition: SBAddress.h:15
lldb_private::GetAbortLocation
bool GetAbortLocation(llvm::Triple::OSType os, SymbolLocation &location)
Fetches the abort frame location depending on the current platform.
Definition: AssertFrameRecognizer.cpp:37
LLDBLog.h
lldb_private::AssertRecognizedStackFrame::GetMostRelevantFrame
lldb::StackFrameSP GetMostRelevantFrame() override
Definition: AssertFrameRecognizer.cpp:191