8
8
9
9
#include " MinidumpFileBuilder.h"
10
10
11
+ #include " Plugins/Process/minidump/RegisterContextMinidump_ARM64.h"
11
12
#include " Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
12
13
13
14
#include " lldb/Core/Module.h"
@@ -293,7 +294,7 @@ Status MinidumpFileBuilder::AddModuleList(Target &target) {
293
294
}
294
295
295
296
uint16_t read_register_u16_raw (RegisterContext *reg_ctx,
296
- const std::string & reg_name) {
297
+ llvm::StringRef reg_name) {
297
298
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName (reg_name);
298
299
if (!reg_info)
299
300
return 0 ;
@@ -305,7 +306,7 @@ uint16_t read_register_u16_raw(RegisterContext *reg_ctx,
305
306
}
306
307
307
308
uint32_t read_register_u32_raw (RegisterContext *reg_ctx,
308
- const std::string & reg_name) {
309
+ llvm::StringRef reg_name) {
309
310
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName (reg_name);
310
311
if (!reg_info)
311
312
return 0 ;
@@ -317,7 +318,7 @@ uint32_t read_register_u32_raw(RegisterContext *reg_ctx,
317
318
}
318
319
319
320
uint64_t read_register_u64_raw (RegisterContext *reg_ctx,
320
- const std::string & reg_name) {
321
+ llvm::StringRef reg_name) {
321
322
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName (reg_name);
322
323
if (!reg_info)
323
324
return 0 ;
@@ -329,25 +330,42 @@ uint64_t read_register_u64_raw(RegisterContext *reg_ctx,
329
330
}
330
331
331
332
llvm::support::ulittle16_t read_register_u16 (RegisterContext *reg_ctx,
332
- const std::string & reg_name) {
333
+ llvm::StringRef reg_name) {
333
334
return static_cast <llvm::support::ulittle16_t >(
334
335
read_register_u16_raw (reg_ctx, reg_name));
335
336
}
336
337
337
338
llvm::support::ulittle32_t read_register_u32 (RegisterContext *reg_ctx,
338
- const std::string & reg_name) {
339
+ llvm::StringRef reg_name) {
339
340
return static_cast <llvm::support::ulittle32_t >(
340
341
read_register_u32_raw (reg_ctx, reg_name));
341
342
}
342
343
343
344
llvm::support::ulittle64_t read_register_u64 (RegisterContext *reg_ctx,
344
- const std::string & reg_name) {
345
+ llvm::StringRef reg_name) {
345
346
return static_cast <llvm::support::ulittle64_t >(
346
347
read_register_u64_raw (reg_ctx, reg_name));
347
348
}
348
349
350
+ void read_register_u128 (RegisterContext *reg_ctx, llvm::StringRef reg_name,
351
+ uint8_t *dst) {
352
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName (reg_name);
353
+ if (reg_info) {
354
+ lldb_private::RegisterValue reg_value;
355
+ if (reg_ctx->ReadRegister (reg_info, reg_value)) {
356
+ Status error;
357
+ uint32_t bytes_copied = reg_value.GetAsMemoryData (
358
+ *reg_info, dst, 16 , lldb::ByteOrder::eByteOrderLittle, error);
359
+ if (bytes_copied == 16 )
360
+ return ;
361
+ }
362
+ }
363
+ // If anything goes wrong, then zero out the register value.
364
+ memset (dst, 0 , 16 );
365
+ }
366
+
349
367
lldb_private::minidump::MinidumpContext_x86_64
350
- GetThreadContext_64 (RegisterContext *reg_ctx) {
368
+ GetThreadContext_x86_64 (RegisterContext *reg_ctx) {
351
369
lldb_private::minidump::MinidumpContext_x86_64 thread_context = {};
352
370
thread_context.p1_home = {};
353
371
thread_context.context_flags = static_cast <uint32_t >(
@@ -381,6 +399,71 @@ GetThreadContext_64(RegisterContext *reg_ctx) {
381
399
return thread_context;
382
400
}
383
401
402
+ minidump::RegisterContextMinidump_ARM64::Context
403
+ GetThreadContext_ARM64 (RegisterContext *reg_ctx) {
404
+ minidump::RegisterContextMinidump_ARM64::Context thread_context = {};
405
+ thread_context.context_flags = static_cast <uint32_t >(
406
+ minidump::RegisterContextMinidump_ARM64::Flags::ARM64_Flag |
407
+ minidump::RegisterContextMinidump_ARM64::Flags::Integer |
408
+ minidump::RegisterContextMinidump_ARM64::Flags::FloatingPoint);
409
+ char reg_name[16 ];
410
+ for (uint32_t i = 0 ; i < 31 ; ++i) {
411
+ snprintf (reg_name, sizeof (reg_name), " x%u" , i);
412
+ thread_context.x [i] = read_register_u64 (reg_ctx, reg_name);
413
+ }
414
+ // Work around a bug in debugserver where "sp" on arm64 doesn't have the alt
415
+ // name set to "x31"
416
+ thread_context.x [31 ] = read_register_u64 (reg_ctx, " sp" );
417
+ thread_context.pc = read_register_u64 (reg_ctx, " pc" );
418
+ thread_context.cpsr = read_register_u32 (reg_ctx, " cpsr" );
419
+ thread_context.fpsr = read_register_u32 (reg_ctx, " fpsr" );
420
+ thread_context.fpcr = read_register_u32 (reg_ctx, " fpcr" );
421
+ for (uint32_t i = 0 ; i < 32 ; ++i) {
422
+ snprintf (reg_name, sizeof (reg_name), " v%u" , i);
423
+ read_register_u128 (reg_ctx, reg_name, &thread_context.v [i * 16 ]);
424
+ }
425
+ return thread_context;
426
+ }
427
+
428
+ class ArchThreadContexts {
429
+ llvm::Triple::ArchType m_arch;
430
+ union {
431
+ lldb_private::minidump::MinidumpContext_x86_64 x86_64;
432
+ lldb_private::minidump::RegisterContextMinidump_ARM64::Context arm64;
433
+ };
434
+
435
+ public:
436
+ ArchThreadContexts (llvm::Triple::ArchType arch) : m_arch(arch) {}
437
+
438
+ bool prepareRegisterContext (RegisterContext *reg_ctx) {
439
+ switch (m_arch) {
440
+ case llvm::Triple::ArchType::x86_64:
441
+ x86_64 = GetThreadContext_x86_64 (reg_ctx);
442
+ return true ;
443
+ case llvm::Triple::ArchType::aarch64:
444
+ arm64 = GetThreadContext_ARM64 (reg_ctx);
445
+ return true ;
446
+ default :
447
+ break ;
448
+ }
449
+ return false ;
450
+ }
451
+
452
+ const void *data () const { return &x86_64; }
453
+
454
+ size_t size () const {
455
+ switch (m_arch) {
456
+ case llvm::Triple::ArchType::x86_64:
457
+ return sizeof (x86_64);
458
+ case llvm::Triple::ArchType::aarch64:
459
+ return sizeof (arm64);
460
+ default :
461
+ break ;
462
+ }
463
+ return 0 ;
464
+ }
465
+ };
466
+
384
467
// Function returns start and size of the memory region that contains
385
468
// memory location pointed to by the current stack pointer.
386
469
llvm::Expected<std::pair<addr_t , addr_t >>
@@ -434,11 +517,20 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
434
517
return error;
435
518
}
436
519
RegisterContext *reg_ctx = reg_ctx_sp.get ();
437
- auto thread_context = GetThreadContext_64 (reg_ctx);
438
- uint64_t rsp = read_register_u64_raw (reg_ctx, " rsp" );
439
- auto expected_address_range = findStackHelper (process_sp, rsp);
520
+ Target &target = process_sp->GetTarget ();
521
+ const ArchSpec &arch = target.GetArchitecture ();
522
+ ArchThreadContexts thread_context (arch.GetMachine ());
523
+ if (!thread_context.prepareRegisterContext (reg_ctx)) {
524
+ error.SetErrorStringWithFormat (
525
+ " architecture %s not supported." ,
526
+ arch.GetTriple ().getArchName ().str ().c_str ());
527
+ return error;
528
+ }
529
+ uint64_t sp = reg_ctx->GetSP ();
530
+ auto expected_address_range = findStackHelper (process_sp, sp);
440
531
441
532
if (!expected_address_range) {
533
+ consumeError (expected_address_range.takeError ());
442
534
error.SetErrorString (" Unable to get the stack address." );
443
535
return error;
444
536
}
@@ -468,13 +560,13 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
468
560
469
561
LocationDescriptor thread_context_memory_locator;
470
562
thread_context_memory_locator.DataSize =
471
- static_cast <llvm::support::ulittle32_t >(sizeof ( thread_context));
563
+ static_cast <llvm::support::ulittle32_t >(thread_context. size ( ));
472
564
thread_context_memory_locator.RVA = static_cast <llvm::support::ulittle32_t >(
473
565
size_before + thread_stream_size + helper_data.GetByteSize ());
566
+ // Cache thie thread context memory so we can reuse for exceptions.
567
+ m_tid_to_reg_ctx[thread_sp->GetID ()] = thread_context_memory_locator;
474
568
475
- helper_data.AppendData (
476
- &thread_context,
477
- sizeof (lldb_private::minidump::MinidumpContext_x86_64));
569
+ helper_data.AppendData (thread_context.data (), thread_context.size ());
478
570
479
571
llvm::minidump::Thread t;
480
572
t.ThreadId = static_cast <llvm::support::ulittle32_t >(thread_sp->GetID ());
@@ -492,68 +584,55 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
492
584
return Status ();
493
585
}
494
586
495
- Status MinidumpFileBuilder::AddException (const lldb::ProcessSP &process_sp) {
496
- Status error;
587
+ void MinidumpFileBuilder::AddExceptions (const lldb::ProcessSP &process_sp) {
497
588
lldb_private::ThreadList thread_list = process_sp->GetThreadList ();
498
589
499
590
const uint32_t num_threads = thread_list.GetSize ();
500
- uint32_t stop_reason_thread_idx = 0 ;
501
- for (stop_reason_thread_idx = 0 ; stop_reason_thread_idx < num_threads;
502
- ++stop_reason_thread_idx) {
503
- ThreadSP thread_sp (thread_list.GetThreadAtIndex (stop_reason_thread_idx));
591
+ for (uint32_t thread_idx = 0 ; thread_idx < num_threads; ++thread_idx) {
592
+ ThreadSP thread_sp (thread_list.GetThreadAtIndex (thread_idx));
504
593
StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
505
-
506
- if (stop_info_sp && stop_info_sp->IsValid ())
507
- break ;
508
- }
509
-
510
- if (stop_reason_thread_idx == num_threads) {
511
- error.SetErrorString (" No stop reason thread found." );
512
- return error;
594
+ bool add_exception = false ;
595
+ if (stop_info_sp) {
596
+ switch (stop_info_sp->GetStopReason ()) {
597
+ case eStopReasonSignal:
598
+ case eStopReasonException:
599
+ add_exception = true ;
600
+ break ;
601
+ default :
602
+ break ;
603
+ }
604
+ }
605
+ if (add_exception) {
606
+ constexpr size_t minidump_exception_size =
607
+ sizeof (llvm::minidump::ExceptionStream);
608
+ AddDirectory (StreamType::Exception, minidump_exception_size);
609
+ StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
610
+ RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ());
611
+ Exception exp_record = {};
612
+ exp_record.ExceptionCode =
613
+ static_cast <llvm::support::ulittle32_t >(stop_info_sp->GetValue ());
614
+ exp_record.ExceptionFlags = static_cast <llvm::support::ulittle32_t >(0 );
615
+ exp_record.ExceptionRecord = static_cast <llvm::support::ulittle64_t >(0 );
616
+ exp_record.ExceptionAddress = reg_ctx_sp->GetPC ();
617
+ exp_record.NumberParameters = static_cast <llvm::support::ulittle32_t >(0 );
618
+ exp_record.UnusedAlignment = static_cast <llvm::support::ulittle32_t >(0 );
619
+ // exp_record.ExceptionInformation;
620
+
621
+ ExceptionStream exp_stream;
622
+ exp_stream.ThreadId =
623
+ static_cast <llvm::support::ulittle32_t >(thread_sp->GetID ());
624
+ exp_stream.UnusedAlignment = static_cast <llvm::support::ulittle32_t >(0 );
625
+ exp_stream.ExceptionRecord = exp_record;
626
+ auto Iter = m_tid_to_reg_ctx.find (thread_sp->GetID ());
627
+ if (Iter != m_tid_to_reg_ctx.end ()) {
628
+ exp_stream.ThreadContext = Iter->second ;
629
+ } else {
630
+ exp_stream.ThreadContext .DataSize = 0 ;
631
+ exp_stream.ThreadContext .RVA = 0 ;
632
+ }
633
+ m_data.AppendData (&exp_stream, minidump_exception_size);
634
+ }
513
635
}
514
-
515
- constexpr size_t minidump_exception_size =
516
- sizeof (llvm::minidump::ExceptionStream);
517
- AddDirectory (StreamType::Exception, minidump_exception_size);
518
- size_t size_before = GetCurrentDataEndOffset ();
519
-
520
- ThreadSP thread_sp (thread_list.GetThreadAtIndex (stop_reason_thread_idx));
521
- RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ());
522
- RegisterContext *reg_ctx = reg_ctx_sp.get ();
523
- auto thread_context = GetThreadContext_64 (reg_ctx);
524
- StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
525
-
526
- DataBufferHeap helper_data;
527
-
528
- LocationDescriptor thread_context_memory_locator;
529
- thread_context_memory_locator.DataSize =
530
- static_cast <llvm::support::ulittle32_t >(sizeof (thread_context));
531
- thread_context_memory_locator.RVA = static_cast <llvm::support::ulittle32_t >(
532
- size_before + minidump_exception_size + helper_data.GetByteSize ());
533
-
534
- helper_data.AppendData (
535
- &thread_context, sizeof (lldb_private::minidump::MinidumpContext_x86_64));
536
-
537
- Exception exp_record = {};
538
- exp_record.ExceptionCode =
539
- static_cast <llvm::support::ulittle32_t >(stop_info_sp->GetValue ());
540
- exp_record.ExceptionFlags = static_cast <llvm::support::ulittle32_t >(0 );
541
- exp_record.ExceptionRecord = static_cast <llvm::support::ulittle64_t >(0 );
542
- exp_record.ExceptionAddress = read_register_u64 (reg_ctx, " rip" );
543
- exp_record.NumberParameters = static_cast <llvm::support::ulittle32_t >(0 );
544
- exp_record.UnusedAlignment = static_cast <llvm::support::ulittle32_t >(0 );
545
- // exp_record.ExceptionInformation;
546
-
547
- ExceptionStream exp_stream;
548
- exp_stream.ThreadId =
549
- static_cast <llvm::support::ulittle32_t >(thread_sp->GetID ());
550
- exp_stream.UnusedAlignment = static_cast <llvm::support::ulittle32_t >(0 );
551
- exp_stream.ExceptionRecord = exp_record;
552
- exp_stream.ThreadContext = thread_context_memory_locator;
553
-
554
- m_data.AppendData (&exp_stream, minidump_exception_size);
555
- m_data.AppendData (helper_data.GetBytes (), helper_data.GetByteSize ());
556
- return error;
557
636
}
558
637
559
638
lldb_private::Status
0 commit comments