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