| 
14 | 14 | #include <sys/utsname.h>  | 
15 | 15 | #endif  | 
16 | 16 | 
 
  | 
 | 17 | +#include "Plugins/Process/Utility/LinuxSignals.h"  | 
17 | 18 | #include "Utility/ARM64_DWARF_Registers.h"  | 
18 | 19 | #include "lldb/Core/Debugger.h"  | 
19 | 20 | #include "lldb/Core/PluginManager.h"  | 
@@ -480,3 +481,107 @@ CompilerType PlatformLinux::GetSiginfoType(const llvm::Triple &triple) {  | 
480 | 481 |   ast->CompleteTagDeclarationDefinition(siginfo_type);  | 
481 | 482 |   return siginfo_type;  | 
482 | 483 | }  | 
 | 484 | + | 
 | 485 | +static std::string GetDescriptionFromSiginfo(lldb::ValueObjectSP siginfo_sp) {  | 
 | 486 | +  if (!siginfo_sp)  | 
 | 487 | +    return "";  | 
 | 488 | + | 
 | 489 | +  lldb_private::LinuxSignals linux_signals;  | 
 | 490 | +  int code = siginfo_sp->GetChildMemberWithName("si_code")->GetValueAsSigned(0);  | 
 | 491 | +  int signo =  | 
 | 492 | +      siginfo_sp->GetChildMemberWithName("si_signo")->GetValueAsSigned(-1);  | 
 | 493 | + | 
 | 494 | +  auto sifields = siginfo_sp->GetChildMemberWithName("_sifields");  | 
 | 495 | +  if (!sifields)  | 
 | 496 | +    return linux_signals.GetSignalDescription(signo, code);  | 
 | 497 | + | 
 | 498 | +  // declare everything that we can populate later.  | 
 | 499 | +  std::optional<lldb::addr_t> addr;  | 
 | 500 | +  std::optional<lldb::addr_t> upper;  | 
 | 501 | +  std::optional<lldb::addr_t> lower;  | 
 | 502 | +  std::optional<uint32_t> pid;  | 
 | 503 | +  std::optional<uint32_t> uid;  | 
 | 504 | + | 
 | 505 | +  // The negative si_codes are special and mean this signal was sent from user  | 
 | 506 | +  // space not the kernel. These take precedence because they break some of the  | 
 | 507 | +  // invariants around kernel sent signals. Such as SIGSEGV won't have an  | 
 | 508 | +  // address.  | 
 | 509 | +  if (code < 0) {  | 
 | 510 | +    auto sikill = sifields->GetChildMemberWithName("_kill");  | 
 | 511 | +    if (sikill) {  | 
 | 512 | +      auto pid_sp = sikill->GetChildMemberWithName("si_pid");  | 
 | 513 | +      if (pid_sp)  | 
 | 514 | +        pid = pid_sp->GetValueAsUnsigned(-1);  | 
 | 515 | +      auto uid_sp = sikill->GetChildMemberWithName("si_uid");  | 
 | 516 | +      if (uid_sp)  | 
 | 517 | +        uid = uid_sp->GetValueAsUnsigned(-1);  | 
 | 518 | +    }  | 
 | 519 | +  } else {  | 
 | 520 | + | 
 | 521 | +    switch (signo) {  | 
 | 522 | +    case SIGILL:  | 
 | 523 | +    case SIGFPE:  | 
 | 524 | +    case SIGBUS: {  | 
 | 525 | +      auto sigfault = sifields->GetChildMemberWithName("_sigfault");  | 
 | 526 | +      if (!sigfault)  | 
 | 527 | +        break;  | 
 | 528 | + | 
 | 529 | +      auto addr_sp = sigfault->GetChildMemberWithName("si_addr");  | 
 | 530 | +      if (addr_sp)  | 
 | 531 | +        addr = addr_sp->GetValueAsUnsigned(-1);  | 
 | 532 | +      break;  | 
 | 533 | +    }  | 
 | 534 | +    case SIGSEGV: {  | 
 | 535 | +      auto sigfault = sifields->GetChildMemberWithName("_sigfault");  | 
 | 536 | +      if (!sigfault)  | 
 | 537 | +        break;  | 
 | 538 | + | 
 | 539 | +      auto addr_sp = sigfault->GetChildMemberWithName("si_addr");  | 
 | 540 | +      if (addr_sp)  | 
 | 541 | +        addr = addr_sp->GetValueAsUnsigned(-1);  | 
 | 542 | + | 
 | 543 | +      auto bounds_sp = sigfault->GetChildMemberWithName("_bounds");  | 
 | 544 | +      if (!bounds_sp)  | 
 | 545 | +        break;  | 
 | 546 | + | 
 | 547 | +      auto addr_bnds_sp = bounds_sp->GetChildMemberWithName("_addr_bnd");  | 
 | 548 | +      if (!addr_bnds_sp)  | 
 | 549 | +        break;  | 
 | 550 | + | 
 | 551 | +      auto lower_sp = addr_bnds_sp->GetChildMemberWithName("_lower");  | 
 | 552 | +      if (lower_sp)  | 
 | 553 | +        lower = lower_sp->GetValueAsUnsigned(-1);  | 
 | 554 | + | 
 | 555 | +      auto upper_sp = addr_bnds_sp->GetChildMemberWithName("_upper");  | 
 | 556 | +      if (upper_sp)  | 
 | 557 | +        upper = upper_sp->GetValueAsUnsigned(-1);  | 
 | 558 | + | 
 | 559 | +      break;  | 
 | 560 | +    }  | 
 | 561 | +    default:  | 
 | 562 | +      break;  | 
 | 563 | +    }  | 
 | 564 | +  }  | 
 | 565 | + | 
 | 566 | +  return linux_signals.GetSignalDescription(signo, code, addr, lower, upper,  | 
 | 567 | +                                            uid, pid);  | 
 | 568 | +}  | 
 | 569 | + | 
 | 570 | +lldb::StopInfoSP PlatformLinux::GetStopInfoFromSiginfo(Thread &thread) {  | 
 | 571 | +  ValueObjectSP siginfo_sp = thread.GetSiginfoValue();  | 
 | 572 | +  if (!siginfo_sp)  | 
 | 573 | +    return {};  | 
 | 574 | +  auto signo_sp = siginfo_sp->GetChildMemberWithName("si_signo");  | 
 | 575 | +  auto sicode_sp = siginfo_sp->GetChildMemberWithName("si_code");  | 
 | 576 | +  if (!signo_sp || !sicode_sp)  | 
 | 577 | +    return {};  | 
 | 578 | + | 
 | 579 | +  std::string siginfo_description = GetDescriptionFromSiginfo(siginfo_sp);  | 
 | 580 | +  if (siginfo_description.empty())  | 
 | 581 | +    return StopInfo::CreateStopReasonWithSignal(  | 
 | 582 | +        thread, signo_sp->GetValueAsUnsigned(-1));  | 
 | 583 | + | 
 | 584 | +  return StopInfo::CreateStopReasonWithSignal(  | 
 | 585 | +      thread, signo_sp->GetValueAsUnsigned(-1), siginfo_description.c_str(),  | 
 | 586 | +      sicode_sp->GetValueAsUnsigned(0));  | 
 | 587 | +}  | 
0 commit comments