LLDB mainline
AbortWithPayloadFrameRecognizer.cpp
Go to the documentation of this file.
1//===-- AbortWithPayloadFrameRecognizer.cpp -------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "lldb/Core/Value.h"
12#include "lldb/Target/ABI.h"
13#include "lldb/Target/Process.h"
15#include "lldb/Target/Target.h"
16#include "lldb/Target/Thread.h"
18#include "lldb/Utility/Log.h"
21
23
24using namespace lldb;
25using namespace lldb_private;
26
27namespace lldb_private {
29 // There are two user-level API's that this recognizer captures,
30 // abort_with_reason and abort_with_payload. But they both call the private
31 // __abort_with_payload, the abort_with_reason call fills in a null payload.
32 static ConstString module_name("libsystem_kernel.dylib");
33 static ConstString sym_name("__abort_with_payload");
34
35 if (!process)
36 return;
37
39 std::make_shared<AbortWithPayloadFrameRecognizer>(), module_name,
41 /*first_instruction_only*/ false);
42}
43
46 // We have two jobs:
47 // 1) to add the data passed to abort_with_payload to the
48 // ExtraCrashInformation dictionary.
49 // 2) To make up faux arguments for this frame.
50 static constexpr llvm::StringLiteral namespace_key("namespace");
51 static constexpr llvm::StringLiteral code_key("code");
52 static constexpr llvm::StringLiteral payload_addr_key("payload_addr");
53 static constexpr llvm::StringLiteral payload_size_key("payload_size");
54 static constexpr llvm::StringLiteral reason_key("reason");
55 static constexpr llvm::StringLiteral flags_key("flags");
56 static constexpr llvm::StringLiteral info_key("abort_with_payload");
57
59
60 if (!frame_sp) {
61 LLDB_LOG(log, "abort_with_payload recognizer: invalid frame.");
62 return {};
63 }
64
65 Thread *thread = frame_sp->GetThread().get();
66 if (!thread) {
67 LLDB_LOG(log, "abort_with_payload recognizer: invalid thread.");
68 return {};
69 }
70
71 Process *process = thread->GetProcess().get();
72 if (!thread) {
73 LLDB_LOG(log, "abort_with_payload recognizer: invalid process.");
74 }
75
76 TypeSystemClangSP scratch_ts_sp =
78 if (!scratch_ts_sp) {
79 LLDB_LOG(log, "abort_with_payload recognizer: invalid scratch typesystem.");
80 return {};
81 }
82
83 // The abort_with_payload signature is:
84 // abort_with_payload(uint32_t reason_namespace, uint64_t reason_code,
85 // void* payload, uint32_t payload_size,
86 // const char* reason_string, uint64_t reason_flags);
87
88 ValueList arg_values;
89 Value input_value_32;
90 Value input_value_64;
91 Value input_value_void_ptr;
92 Value input_value_char_ptr;
93
94 CompilerType clang_void_ptr_type =
95 scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
96 CompilerType clang_char_ptr_type =
97 scratch_ts_sp->GetBasicType(eBasicTypeChar).GetPointerType();
98 CompilerType clang_uint64_type =
99 scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
100 64);
101 CompilerType clang_uint32_type =
102 scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
103 32);
104 CompilerType clang_char_star_type =
105 scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
106 64);
107
109 input_value_32.SetCompilerType(clang_uint32_type);
111 input_value_64.SetCompilerType(clang_uint64_type);
112 input_value_void_ptr.SetValueType(Value::ValueType::Scalar);
113 input_value_void_ptr.SetCompilerType(clang_void_ptr_type);
114 input_value_char_ptr.SetValueType(Value::ValueType::Scalar);
115 input_value_char_ptr.SetCompilerType(clang_char_ptr_type);
116
117 arg_values.PushValue(input_value_32);
118 arg_values.PushValue(input_value_64);
119 arg_values.PushValue(input_value_void_ptr);
120 arg_values.PushValue(input_value_32);
121 arg_values.PushValue(input_value_char_ptr);
122 arg_values.PushValue(input_value_64);
123
124 lldb::ABISP abi_sp = process->GetABI();
125 bool success = abi_sp->GetArgumentValues(*thread, arg_values);
126 if (!success)
127 return {};
128
129 Value *cur_value;
130 StackFrame *frame = frame_sp.get();
132
133 auto add_to_arguments = [&](llvm::StringRef name, Value *value,
134 bool dynamic) {
135 ValueObjectSP cur_valobj_sp =
136 ValueObjectConstResult::Create(frame, *value, ConstString(name));
138 *cur_valobj_sp, eValueTypeVariableArgument);
139 ValueObjectSP dyn_valobj_sp;
140 if (dynamic) {
141 dyn_valobj_sp = cur_valobj_sp->GetDynamicValue(eDynamicDontRunTarget);
142 if (dyn_valobj_sp)
143 cur_valobj_sp = dyn_valobj_sp;
144 }
145 arguments_sp->Append(cur_valobj_sp);
146 };
147
148 // Decode the arg_values:
149
150 uint32_t namespace_val = 0;
151 cur_value = arg_values.GetValueAtIndex(0);
152 add_to_arguments(namespace_key, cur_value, false);
153 namespace_val = cur_value->GetScalar().UInt(namespace_val);
154
155 uint32_t code_val = 0;
156 cur_value = arg_values.GetValueAtIndex(1);
157 add_to_arguments(code_key, cur_value, false);
158 code_val = cur_value->GetScalar().UInt(code_val);
159
160 lldb::addr_t payload_addr = LLDB_INVALID_ADDRESS;
161 cur_value = arg_values.GetValueAtIndex(2);
162 add_to_arguments(payload_addr_key, cur_value, true);
163 payload_addr = cur_value->GetScalar().ULongLong(payload_addr);
164
165 uint32_t payload_size = 0;
166 cur_value = arg_values.GetValueAtIndex(3);
167 add_to_arguments(payload_size_key, cur_value, false);
168 payload_size = cur_value->GetScalar().UInt(payload_size);
169
171 cur_value = arg_values.GetValueAtIndex(4);
172 add_to_arguments(reason_key, cur_value, false);
173 reason_addr = cur_value->GetScalar().ULongLong(payload_addr);
174
175 // For the reason string, we want the string not the address, so fetch that.
176 std::string reason_string;
178 process->ReadCStringFromMemory(reason_addr, reason_string, error);
179 if (error.Fail()) {
180 // Even if we couldn't read the string, return the other data.
181 LLDB_LOG(log, "Couldn't fetch reason string: {0}.", error);
182 reason_string = "<error fetching reason string>";
183 }
184
185 uint32_t flags_val = 0;
186 cur_value = arg_values.GetValueAtIndex(5);
187 add_to_arguments(flags_key, cur_value, false);
188 flags_val = cur_value->GetScalar().UInt(flags_val);
189
190 // Okay, we've gotten all the argument values, now put them in a
191 // StructuredData, and add that to the Process ExtraCrashInformation:
193 abort_dict_sp->AddIntegerItem(namespace_key, namespace_val);
194 abort_dict_sp->AddIntegerItem(code_key, code_val);
195 abort_dict_sp->AddIntegerItem(payload_addr_key, payload_addr);
196 abort_dict_sp->AddIntegerItem(payload_size_key, payload_size);
197 abort_dict_sp->AddStringItem(reason_key, reason_string);
198 abort_dict_sp->AddIntegerItem(flags_key, flags_val);
199
200 // This will overwrite the abort_with_payload information in the dictionary
201 // already. But we can only crash on abort_with_payload once, so that
202 // shouldn't matter.
203 process->GetExtendedCrashInfoDict()->AddItem(info_key, abort_dict_sp);
204
206 new AbortWithPayloadRecognizedStackFrame(frame_sp, arguments_sp));
207}
208
210 lldb::StackFrameSP &frame_sp, ValueObjectListSP &args_sp)
212 m_arguments = args_sp;
213 m_stop_desc = "abort with payload or reason";
214}
215
216} // namespace lldb_private
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:369
lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame_sp) override
AbortWithPayloadRecognizedStackFrame(lldb::StackFrameSP &frame_sp, lldb::ValueObjectListSP &args_sp)
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
A uniqued constant string class.
Definition: ConstString.h:40
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
size_t ReadCStringFromMemory(lldb::addr_t vm_addr, char *cstr, size_t cstr_max_len, Status &error)
Read a NULL terminated C string from memory.
Definition: Process.cpp:2142
StructuredData::DictionarySP GetExtendedCrashInfoDict()
Fetch extended crash information held by the process.
Definition: Process.h:2543
const lldb::ABISP & GetABI()
Definition: Process.cpp:1504
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1246
This class provides extra information about a stack frame that was provided by a specific stack frame...
unsigned int UInt(unsigned int fail_value=0) const
Definition: Scalar.cpp:321
unsigned long long ULongLong(unsigned long long fail_value=0) const
Definition: Scalar.cpp:335
static lldb::TypeSystemClangSP GetForTarget(Target &target, std::optional< IsolatedASTKind > ast_kind=DefaultAST, bool create_on_demand=true)
Returns the scratch TypeSystemClang for the given target.
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, ConstString module, llvm::ArrayRef< ConstString > symbols, Mangled::NamePreference symbol_mangling, bool first_instruction_only=true)
Add a new recognizer that triggers on a given symbol name.
This base class provides an interface to stack frames.
Definition: StackFrame.h:44
An error handling class.
Definition: Status.h:115
std::shared_ptr< Dictionary > DictionarySP
StackFrameRecognizerManager & GetFrameRecognizerManager()
Definition: Target.h:1487
lldb::ProcessSP GetProcess() const
Definition: Thread.h:157
void PushValue(const Value &value)
Definition: Value.cpp:687
Value * GetValueAtIndex(size_t idx)
Definition: Value.cpp:691
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS)
A collection of ValueObject values that.
static lldb::ValueObjectSP Create(ValueObject &parent, lldb::ValueType type)
const Scalar & GetScalar() const
Definition: Value.h:112
@ Scalar
A raw scalar value.
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:268
void SetValueType(ValueType value_type)
Definition: Value.h:89
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
void RegisterAbortWithPayloadFrameRecognizer(Process *process)
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::ABI > ABISP
Definition: lldb-forward.h:317
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:424
std::shared_ptr< lldb_private::RecognizedStackFrame > RecognizedStackFrameSP
Definition: lldb-forward.h:403
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:484
std::shared_ptr< lldb_private::ValueObjectList > ValueObjectListSP
Definition: lldb-forward.h:488
@ eEncodingUint
unsigned integer
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
Definition: lldb-forward.h:470
uint64_t addr_t
Definition: lldb-types.h:80
@ eDynamicDontRunTarget
@ eValueTypeVariableArgument
function argument variables