[LLDB][Minidump] Support minidumps where there are multiple exception… · llvm/llvm-project@4926835 (original) (raw)
`@@ -157,8 +157,7 @@ ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp,
`
157
157
`const FileSpec &core_file,
`
158
158
` DataBufferSP core_data)
`
159
159
` : PostMortemProcess(target_sp, listener_sp, core_file),
`
160
``
`-
m_core_data(std::move(core_data)), m_active_exception(nullptr),
`
161
``
`-
m_is_wow64(false) {}
`
``
160
`+
m_core_data(std::move(core_data)), m_is_wow64(false) {}
`
162
161
``
163
162
`ProcessMinidump::~ProcessMinidump() {
`
164
163
`Clear();
`
`@@ -209,7 +208,20 @@ Status ProcessMinidump::DoLoadCore() {
`
209
208
`GetTarget().SetArchitecture(arch, true /set_platform/);
`
210
209
``
211
210
` m_thread_list = m_minidump_parser->GetThreads();
`
212
``
`-
m_active_exception = m_minidump_parser->GetExceptionStream();
`
``
211
`+
auto exception_stream_it = m_minidump_parser->GetExceptionStreams();
`
``
212
`+
for (auto exception_stream : exception_stream_it) {
`
``
213
`+
// If we can't read an exception stream skip it
`
``
214
`+
// We should probably serve a warning
`
``
215
`+
if (!exception_stream)
`
``
216
`+
continue;
`
``
217
+
``
218
`+
if (!m_exceptions_by_tid
`
``
219
`+
.try_emplace(exception_stream->ThreadId, exception_stream.get())
`
``
220
`+
.second) {
`
``
221
`+
return Status::FromErrorStringWithFormatv(
`
``
222
`+
"Duplicate exception stream for tid {0}", exception_stream->ThreadId);
`
``
223
`+
}
`
``
224
`+
}
`
213
225
``
214
226
`SetUnixSignals(UnixSignals::Create(GetArchitecture()));
`
215
227
``
`@@ -232,60 +244,57 @@ Status ProcessMinidump::DoDestroy() { return Status(); }
`
232
244
``
233
245
`void ProcessMinidump::RefreshStateAfterStop() {
`
234
246
``
235
``
`-
if (!m_active_exception)
`
236
``
`-
return;
`
237
``
-
238
``
`-
constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF;
`
239
``
`-
if (m_active_exception->ExceptionRecord.ExceptionCode ==
`
240
``
`-
BreakpadDumpRequested) {
`
241
``
`-
// This "ExceptionCode" value is a sentinel that is sometimes used
`
242
``
`-
// when generating a dump for a process that hasn't crashed.
`
243
``
-
244
``
`-
// TODO: The definition and use of this "dump requested" constant
`
245
``
`-
// in Breakpad are actually Linux-specific, and for similar use
`
246
``
`-
// cases on Mac/Windows it defines different constants, referring
`
247
``
`-
// to them as "simulated" exceptions; consider moving this check
`
248
``
`-
// down to the OS-specific paths and checking each OS for its own
`
249
``
`-
// constant.
`
250
``
`-
return;
`
251
``
`-
}
`
``
247
`+
for (const auto &[_, exception_stream] : m_exceptions_by_tid) {
`
``
248
`+
constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF;
`
``
249
`+
if (exception_stream.ExceptionRecord.ExceptionCode ==
`
``
250
`+
BreakpadDumpRequested) {
`
``
251
`+
// This "ExceptionCode" value is a sentinel that is sometimes used
`
``
252
`+
// when generating a dump for a process that hasn't crashed.
`
``
253
+
``
254
`+
// TODO: The definition and use of this "dump requested" constant
`
``
255
`+
// in Breakpad are actually Linux-specific, and for similar use
`
``
256
`+
// cases on Mac/Windows it defines different constants, referring
`
``
257
`+
// to them as "simulated" exceptions; consider moving this check
`
``
258
`+
// down to the OS-specific paths and checking each OS for its own
`
``
259
`+
// constant.
`
``
260
`+
return;
`
``
261
`+
}
`
252
262
``
253
``
`-
lldb::StopInfoSP stop_info;
`
254
``
`-
lldb::ThreadSP stop_thread;
`
``
263
`+
lldb::StopInfoSP stop_info;
`
``
264
`+
lldb::ThreadSP stop_thread;
`
255
265
``
256
``
`-
Process::m_thread_list.SetSelectedThreadByID(m_active_exception->ThreadId);
`
257
``
`-
stop_thread = Process::m_thread_list.GetSelectedThread();
`
258
``
`-
ArchSpec arch = GetArchitecture();
`
``
266
`+
Process::m_thread_list.SetSelectedThreadByID(exception_stream.ThreadId);
`
``
267
`+
stop_thread = Process::m_thread_list.GetSelectedThread();
`
``
268
`+
ArchSpec arch = GetArchitecture();
`
259
269
``
260
``
`-
if (arch.GetTriple().getOS() == llvm::Triple::Linux) {
`
261
``
`-
uint32_t signo = m_active_exception->ExceptionRecord.ExceptionCode;
`
``
270
`+
if (arch.GetTriple().getOS() == llvm::Triple::Linux) {
`
``
271
`+
uint32_t signo = exception_stream.ExceptionRecord.ExceptionCode;
`
``
272
`+
if (signo == 0) {
`
``
273
`+
// No stop.
`
``
274
`+
return;
`
``
275
`+
}
`
262
276
``
263
``
`-
if (signo == 0) {
`
264
``
`-
// No stop.
`
265
``
`-
return;
`
``
277
`+
stop_info = StopInfo::CreateStopReasonWithSignal(*stop_thread, signo);
`
``
278
`+
} else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {
`
``
279
`+
stop_info = StopInfoMachException::CreateStopReasonWithMachException(
`
``
280
`+
*stop_thread, exception_stream.ExceptionRecord.ExceptionCode, 2,
`
``
281
`+
exception_stream.ExceptionRecord.ExceptionFlags,
`
``
282
`+
exception_stream.ExceptionRecord.ExceptionAddress, 0);
`
``
283
`+
} else {
`
``
284
`+
std::string desc;
`
``
285
`+
llvm::raw_string_ostream desc_stream(desc);
`
``
286
`+
desc_stream << "Exception "
`
``
287
`+
<< llvm::format_hex(
`
``
288
`+
exception_stream.ExceptionRecord.ExceptionCode, 8)
`
``
289
`+
<< " encountered at address "
`
``
290
`+
<< llvm::format_hex(
`
``
291
`+
exception_stream.ExceptionRecord.ExceptionAddress, 8);
`
``
292
`+
stop_info = StopInfo::CreateStopReasonWithException(
`
``
293
`+
*stop_thread, desc_stream.str().c_str());
`
266
294
` }
`
267
295
``
268
``
`-
stop_info = StopInfo::CreateStopReasonWithSignal(
`
269
``
`-
*stop_thread, signo);
`
270
``
`-
} else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {
`
271
``
`-
stop_info = StopInfoMachException::CreateStopReasonWithMachException(
`
272
``
`-
*stop_thread, m_active_exception->ExceptionRecord.ExceptionCode, 2,
`
273
``
`-
m_active_exception->ExceptionRecord.ExceptionFlags,
`
274
``
`-
m_active_exception->ExceptionRecord.ExceptionAddress, 0);
`
275
``
`-
} else {
`
276
``
`-
std::string desc;
`
277
``
`-
llvm::raw_string_ostream desc_stream(desc);
`
278
``
`-
desc_stream << "Exception "
`
279
``
`-
<< llvm::format_hex(
`
280
``
`-
m_active_exception->ExceptionRecord.ExceptionCode, 8)
`
281
``
`-
<< " encountered at address "
`
282
``
`-
<< llvm::format_hex(
`
283
``
`-
m_active_exception->ExceptionRecord.ExceptionAddress, 8);
`
284
``
`-
stop_info = StopInfo::CreateStopReasonWithException(
`
285
``
`-
*stop_thread, desc_stream.str().c_str());
`
286
``
`-
}
`
287
``
-
288
``
`-
stop_thread->SetStopInfo(stop_info);
`
``
296
`+
stop_thread->SetStopInfo(stop_info);
`
``
297
`+
}
`
289
298
`}
`
290
299
``
291
300
`bool ProcessMinidump::IsAlive() { return true; }
`
`@@ -387,10 +396,9 @@ bool ProcessMinidump::DoUpdateThreadList(ThreadList &old_thread_list,
`
387
396
` LocationDescriptor context_location = thread.Context;
`
388
397
``
389
398
`// If the minidump contains an exception context, use it
`
390
``
`-
if (m_active_exception != nullptr &&
`
391
``
`-
m_active_exception->ThreadId == thread.ThreadId) {
`
392
``
`-
context_location = m_active_exception->ThreadContext;
`
393
``
`-
}
`
``
399
`+
if (auto it = m_exceptions_by_tid.find(thread.ThreadId);
`
``
400
`+
it != m_exceptions_by_tid.end())
`
``
401
`+
context_location = it->second.ThreadContext;
`
394
402
``
395
403
` llvm::ArrayRef context;
`
396
404
`if (!m_is_wow64)
`