@@ -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,28 @@ 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
+ std::optional<std::vector<const minidump::ExceptionStream *>>
212
+ exception_streams = m_minidump_parser->GetExceptionStreams ();
213
+
214
+ if (exception_streams) {
215
+ for (const auto *exception_stream : *exception_streams) {
216
+ if (!exception_stream) {
217
+ error.SetErrorString (
218
+ " Minidump returned null pointer for exception stream" );
219
+ return error;
220
+ }
221
+ if (!m_exceptions_by_tid
222
+ .try_emplace (exception_stream->ThreadId , exception_stream)
223
+ .second ) {
224
+ // We only cast to avoid the warning around converting little endian in
225
+ // printf.
226
+ error.SetErrorStringWithFormat (
227
+ " Duplicate exception stream for tid %" PRIu32,
228
+ (uint32_t )exception_stream->ThreadId );
229
+ return error;
230
+ }
231
+ }
232
+ }
213
233
214
234
SetUnixSignals (UnixSignals::Create (GetArchitecture ()));
215
235
@@ -232,60 +252,57 @@ Status ProcessMinidump::DoDestroy() { return Status(); }
232
252
233
253
void ProcessMinidump::RefreshStateAfterStop () {
234
254
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
- }
255
+ for (const auto &[_, exception_stream] : m_exceptions_by_tid) {
256
+ constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF ;
257
+ if (exception_stream->ExceptionRecord .ExceptionCode ==
258
+ BreakpadDumpRequested) {
259
+ // This "ExceptionCode" value is a sentinel that is sometimes used
260
+ // when generating a dump for a process that hasn't crashed.
261
+
262
+ // TODO: The definition and use of this "dump requested" constant
263
+ // in Breakpad are actually Linux-specific, and for similar use
264
+ // cases on Mac/Windows it defines different constants, referring
265
+ // to them as "simulated" exceptions; consider moving this check
266
+ // down to the OS-specific paths and checking each OS for its own
267
+ // constant.
268
+ return ;
269
+ }
252
270
253
- lldb::StopInfoSP stop_info;
254
- lldb::ThreadSP stop_thread;
271
+ lldb::StopInfoSP stop_info;
272
+ lldb::ThreadSP stop_thread;
255
273
256
- Process::m_thread_list.SetSelectedThreadByID (m_active_exception ->ThreadId );
257
- stop_thread = Process::m_thread_list.GetSelectedThread ();
258
- ArchSpec arch = GetArchitecture ();
274
+ Process::m_thread_list.SetSelectedThreadByID (exception_stream ->ThreadId );
275
+ stop_thread = Process::m_thread_list.GetSelectedThread ();
276
+ ArchSpec arch = GetArchitecture ();
259
277
260
- if (arch.GetTriple ().getOS () == llvm::Triple::Linux) {
261
- uint32_t signo = m_active_exception->ExceptionRecord .ExceptionCode ;
278
+ if (arch.GetTriple ().getOS () == llvm::Triple::Linux) {
279
+ uint32_t signo = exception_stream->ExceptionRecord .ExceptionCode ;
280
+ if (signo == 0 ) {
281
+ // No stop.
282
+ return ;
283
+ }
262
284
263
- if (signo == 0 ) {
264
- // No stop.
265
- return ;
285
+ stop_info = StopInfo::CreateStopReasonWithSignal (*stop_thread, signo);
286
+ } else if (arch.GetTriple ().getVendor () == llvm::Triple::Apple) {
287
+ stop_info = StopInfoMachException::CreateStopReasonWithMachException (
288
+ *stop_thread, exception_stream->ExceptionRecord .ExceptionCode , 2 ,
289
+ exception_stream->ExceptionRecord .ExceptionFlags ,
290
+ exception_stream->ExceptionRecord .ExceptionAddress , 0 );
291
+ } else {
292
+ std::string desc;
293
+ llvm::raw_string_ostream desc_stream (desc);
294
+ desc_stream << " Exception "
295
+ << llvm::format_hex (
296
+ exception_stream->ExceptionRecord .ExceptionCode , 8 )
297
+ << " encountered at address "
298
+ << llvm::format_hex (
299
+ exception_stream->ExceptionRecord .ExceptionAddress , 8 );
300
+ stop_info = StopInfo::CreateStopReasonWithException (
301
+ *stop_thread, desc_stream.str ().c_str ());
266
302
}
267
303
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);
304
+ stop_thread->SetStopInfo (stop_info);
305
+ }
289
306
}
290
307
291
308
bool ProcessMinidump::IsAlive () { return true ; }
@@ -387,10 +404,8 @@ bool ProcessMinidump::DoUpdateThreadList(ThreadList &old_thread_list,
387
404
LocationDescriptor context_location = thread.Context ;
388
405
389
406
// 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
- }
407
+ if (m_exceptions_by_tid.count (thread.ThreadId ) > 0 )
408
+ context_location = m_exceptions_by_tid[thread.ThreadId ]->ThreadContext ;
394
409
395
410
llvm::ArrayRef<uint8_t > context;
396
411
if (!m_is_wow64)
0 commit comments