9
9
#include " MinidumpFileBuilder.h"
10
10
11
11
#include " Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
12
+ #include " Plugins/Process/minidump/RegisterContextMinidump_ARM64.h"
12
13
13
14
#include " lldb/Core/Module.h"
14
15
#include " lldb/Core/ModuleList.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,44 @@ 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 =
358
+ reg_value.GetAsMemoryData (*reg_info, dst, 16 ,
359
+ lldb::ByteOrder::eByteOrderLittle,
360
+ error);
361
+ if (bytes_copied == 16 )
362
+ return ;
363
+ }
364
+ }
365
+ // If anything goes wrong, then zero out the register value.
366
+ memset (dst, 0 , 16 );
367
+ }
368
+
349
369
lldb_private::minidump::MinidumpContext_x86_64
350
- GetThreadContext_64 (RegisterContext *reg_ctx) {
370
+ GetThreadContext_x86_64 (RegisterContext *reg_ctx) {
351
371
lldb_private::minidump::MinidumpContext_x86_64 thread_context = {};
352
372
thread_context.p1_home = {};
353
373
thread_context.context_flags = static_cast <uint32_t >(
@@ -381,6 +401,73 @@ GetThreadContext_64(RegisterContext *reg_ctx) {
381
401
return thread_context;
382
402
}
383
403
404
+ minidump::RegisterContextMinidump_ARM64::Context
405
+ GetThreadContext_ARM64 (RegisterContext *reg_ctx) {
406
+ minidump::RegisterContextMinidump_ARM64::Context thread_context = {};
407
+ thread_context.context_flags = static_cast <uint32_t >(
408
+ minidump::RegisterContextMinidump_ARM64::Flags::ARM64_Flag |
409
+ minidump::RegisterContextMinidump_ARM64::Flags::Integer |
410
+ minidump::RegisterContextMinidump_ARM64::Flags::FloatingPoint);
411
+ char reg_name[16 ];
412
+ for (uint32_t i=0 ; i<31 ; ++i) {
413
+ snprintf (reg_name, sizeof (reg_name), " x%u" , i);
414
+ thread_context.x [i] = read_register_u64 (reg_ctx, reg_name);
415
+ }
416
+ // Work around a bug in debugserver where "sp" on arm64 doesn't have the alt
417
+ // name set to "x31"
418
+ thread_context.x [31 ] = read_register_u64 (reg_ctx, " sp" );
419
+ thread_context.pc = read_register_u64 (reg_ctx, " pc" );
420
+ thread_context.cpsr = read_register_u32 (reg_ctx, " cpsr" );
421
+ thread_context.fpsr = read_register_u32 (reg_ctx, " fpsr" );
422
+ thread_context.fpcr = read_register_u32 (reg_ctx, " fpcr" );
423
+ for (uint32_t i=0 ; i<32 ; ++i) {
424
+ snprintf (reg_name, sizeof (reg_name), " v%u" , i);
425
+ read_register_u128 (reg_ctx, reg_name, &thread_context.v [i*16 ]);
426
+ }
427
+ return thread_context;
428
+ }
429
+
430
+ class ArchThreadContexts {
431
+ llvm::Triple::ArchType m_arch;
432
+ union {
433
+ lldb_private::minidump::MinidumpContext_x86_64 x86_64;
434
+ lldb_private::minidump::RegisterContextMinidump_ARM64::Context arm64;
435
+ };
436
+ public:
437
+ ArchThreadContexts (llvm::Triple::ArchType arch) : m_arch(arch) {}
438
+
439
+ bool prepareRegisterContext (RegisterContext *reg_ctx) {
440
+ switch (m_arch) {
441
+ case llvm::Triple::ArchType::x86_64:
442
+ x86_64 = GetThreadContext_x86_64 (reg_ctx);
443
+ return true ;
444
+ case llvm::Triple::ArchType::aarch64:
445
+ arm64 = GetThreadContext_ARM64 (reg_ctx);
446
+ return true ;
447
+ default :
448
+ break ;
449
+ }
450
+ return false ;
451
+ }
452
+
453
+ const void *data () const {
454
+ return &x86_64;
455
+ }
456
+
457
+ size_t size () const {
458
+ switch (m_arch) {
459
+ case llvm::Triple::ArchType::x86_64:
460
+ return sizeof (x86_64);
461
+ case llvm::Triple::ArchType::aarch64:
462
+ return sizeof (arm64);
463
+ default :
464
+ break ;
465
+ }
466
+ return 0 ;
467
+ }
468
+
469
+ };
470
+
384
471
// Function returns start and size of the memory region that contains
385
472
// memory location pointed to by the current stack pointer.
386
473
llvm::Expected<std::pair<addr_t , addr_t >>
@@ -434,11 +521,19 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
434
521
return error;
435
522
}
436
523
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);
524
+ Target &target = process_sp->GetTarget ();
525
+ const ArchSpec &arch = target.GetArchitecture ();
526
+ ArchThreadContexts thread_context (arch.GetMachine ());
527
+ if (!thread_context.prepareRegisterContext (reg_ctx)) {
528
+ error.SetErrorStringWithFormat (" architecture %s not supported." ,
529
+ arch.GetTriple ().getArchName ().str ().c_str ());
530
+ return error;
531
+ }
532
+ uint64_t sp = reg_ctx->GetSP ();
533
+ auto expected_address_range = findStackHelper (process_sp, sp);
440
534
441
535
if (!expected_address_range) {
536
+ consumeError (expected_address_range.takeError ());
442
537
error.SetErrorString (" Unable to get the stack address." );
443
538
return error;
444
539
}
@@ -468,13 +563,14 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
468
563
469
564
LocationDescriptor thread_context_memory_locator;
470
565
thread_context_memory_locator.DataSize =
471
- static_cast <llvm::support::ulittle32_t >(sizeof ( thread_context));
566
+ static_cast <llvm::support::ulittle32_t >(thread_context. size ( ));
472
567
thread_context_memory_locator.RVA = static_cast <llvm::support::ulittle32_t >(
473
568
size_before + thread_stream_size + helper_data.GetByteSize ());
569
+ // Cache thie thread context memory so we can reuse for exceptions.
570
+ m_tid_to_reg_ctx[thread_sp->GetID ()] = thread_context_memory_locator;
571
+
572
+ helper_data.AppendData (thread_context.data (), thread_context.size ());
474
573
475
- helper_data.AppendData (
476
- &thread_context,
477
- sizeof (lldb_private::minidump::MinidumpContext_x86_64));
478
574
479
575
llvm::minidump::Thread t;
480
576
t.ThreadId = static_cast <llvm::support::ulittle32_t >(thread_sp->GetID ());
@@ -492,68 +588,55 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
492
588
return Status ();
493
589
}
494
590
495
- Status MinidumpFileBuilder::AddException (const lldb::ProcessSP &process_sp) {
496
- Status error;
591
+ void MinidumpFileBuilder::AddExceptions (const lldb::ProcessSP &process_sp) {
497
592
lldb_private::ThreadList thread_list = process_sp->GetThreadList ();
498
593
499
594
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));
595
+ for (uint32_t thread_idx = 0 ; thread_idx < num_threads; ++thread_idx) {
596
+ ThreadSP thread_sp (thread_list.GetThreadAtIndex (thread_idx));
504
597
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;
598
+ bool add_exception = false ;
599
+ if (stop_info_sp) {
600
+ switch (stop_info_sp->GetStopReason ()) {
601
+ case eStopReasonSignal:
602
+ case eStopReasonException:
603
+ add_exception = true ;
604
+ break ;
605
+ default :
606
+ break ;
607
+ }
608
+ }
609
+ if (add_exception) {
610
+ constexpr size_t minidump_exception_size =
611
+ sizeof (llvm::minidump::ExceptionStream);
612
+ AddDirectory (StreamType::Exception, minidump_exception_size);
613
+ StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
614
+ RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ());
615
+ Exception exp_record = {};
616
+ exp_record.ExceptionCode =
617
+ static_cast <llvm::support::ulittle32_t >(stop_info_sp->GetValue ());
618
+ exp_record.ExceptionFlags = static_cast <llvm::support::ulittle32_t >(0 );
619
+ exp_record.ExceptionRecord = static_cast <llvm::support::ulittle64_t >(0 );
620
+ exp_record.ExceptionAddress = reg_ctx_sp->GetPC ();
621
+ exp_record.NumberParameters = static_cast <llvm::support::ulittle32_t >(0 );
622
+ exp_record.UnusedAlignment = static_cast <llvm::support::ulittle32_t >(0 );
623
+ // exp_record.ExceptionInformation;
624
+
625
+ ExceptionStream exp_stream;
626
+ exp_stream.ThreadId =
627
+ static_cast <llvm::support::ulittle32_t >(thread_sp->GetID ());
628
+ exp_stream.UnusedAlignment = static_cast <llvm::support::ulittle32_t >(0 );
629
+ exp_stream.ExceptionRecord = exp_record;
630
+ auto Iter = m_tid_to_reg_ctx.find (thread_sp->GetID ());
631
+ if (Iter != m_tid_to_reg_ctx.end ()) {
632
+ exp_stream.ThreadContext = Iter->second ;
633
+ } else {
634
+ exp_stream.ThreadContext .DataSize = 0 ;
635
+ exp_stream.ThreadContext .RVA = 0 ;
636
+ }
637
+ m_data.AppendData (&exp_stream, minidump_exception_size);
638
+ }
513
639
}
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
640
}
558
641
559
642
lldb_private::Status
0 commit comments