Skip to content
Merged
3 changes: 3 additions & 0 deletions lldb/include/lldb/Target/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Host/File.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
Expand Down Expand Up @@ -960,6 +961,8 @@ class Platform : public PluginInterface {

virtual CompilerType GetSiginfoType(const llvm::Triple &triple);

virtual lldb::StopInfoSP GetStopInfoFromSiginfo(Thread &thread) { return {}; }

virtual Args GetExtraStartupCommands();

typedef std::function<Status(const ModuleSpec &module_spec,
Expand Down
6 changes: 4 additions & 2 deletions lldb/include/lldb/Target/UnixSignals.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class UnixSignals {
std::optional<int32_t> code = std::nullopt,
std::optional<lldb::addr_t> addr = std::nullopt,
std::optional<lldb::addr_t> lower = std::nullopt,
std::optional<lldb::addr_t> upper = std::nullopt) const;
std::optional<lldb::addr_t> upper = std::nullopt,
std::optional<uint32_t> pid = std::nullopt,
std::optional<uint32_t> uid = std::nullopt) const;

bool SignalIsValid(int32_t signo) const;

Expand Down Expand Up @@ -105,7 +107,7 @@ class UnixSignals {
llvm::StringRef description,
llvm::StringRef alias = llvm::StringRef());

enum SignalCodePrintOption { None, Address, Bounds };
enum SignalCodePrintOption { None, Address, Bounds, Sender };

// Instead of calling this directly, use a ADD_SIGCODE macro to get compile
// time checks when on the native platform.
Expand Down
105 changes: 105 additions & 0 deletions lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <sys/utsname.h>
#endif

#include "Plugins/Process/Utility/LinuxSignals.h"
#include "Utility/ARM64_DWARF_Registers.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
Expand Down Expand Up @@ -480,3 +481,107 @@ CompilerType PlatformLinux::GetSiginfoType(const llvm::Triple &triple) {
ast->CompleteTagDeclarationDefinition(siginfo_type);
return siginfo_type;
}

static std::string GetDescriptionFromSiginfo(lldb::ValueObjectSP siginfo_sp) {
if (!siginfo_sp)
return "";

lldb_private::LinuxSignals linux_signals;
int code = siginfo_sp->GetChildMemberWithName("si_code")->GetValueAsSigned(0);
int signo =
siginfo_sp->GetChildMemberWithName("si_signo")->GetValueAsSigned(-1);

auto sifields = siginfo_sp->GetChildMemberWithName("_sifields");
if (!sifields)
return linux_signals.GetSignalDescription(signo, code);

// declare everything that we can populate later.
std::optional<lldb::addr_t> addr;
std::optional<lldb::addr_t> upper;
std::optional<lldb::addr_t> lower;
std::optional<uint32_t> pid;
std::optional<uint32_t> uid;

// The negative si_codes are special and mean this signal was sent from user
// space not the kernel. These take precedence because they break some of the
// invariants around kernel sent signals. Such as SIGSEGV won't have an
// address.
if (code < 0) {
auto sikill = sifields->GetChildMemberWithName("_kill");
if (sikill) {
auto pid_sp = sikill->GetChildMemberWithName("si_pid");
if (pid_sp)
pid = pid_sp->GetValueAsUnsigned(-1);
auto uid_sp = sikill->GetChildMemberWithName("si_uid");
if (uid_sp)
uid = uid_sp->GetValueAsUnsigned(-1);
}
} else {

switch (signo) {
case SIGILL:
case SIGFPE:
case SIGBUS: {
auto sigfault = sifields->GetChildMemberWithName("_sigfault");
if (!sigfault)
break;

auto addr_sp = sigfault->GetChildMemberWithName("si_addr");
if (addr_sp)
addr = addr_sp->GetValueAsUnsigned(-1);
break;
}
case SIGSEGV: {
auto sigfault = sifields->GetChildMemberWithName("_sigfault");
if (!sigfault)
break;

auto addr_sp = sigfault->GetChildMemberWithName("si_addr");
if (addr_sp)
addr = addr_sp->GetValueAsUnsigned(-1);

auto bounds_sp = sigfault->GetChildMemberWithName("_bounds");
if (!bounds_sp)
break;

auto addr_bnds_sp = bounds_sp->GetChildMemberWithName("_addr_bnd");
if (!addr_bnds_sp)
break;

auto lower_sp = addr_bnds_sp->GetChildMemberWithName("_lower");
if (lower_sp)
lower = lower_sp->GetValueAsUnsigned(-1);

auto upper_sp = addr_bnds_sp->GetChildMemberWithName("_upper");
if (upper_sp)
upper = upper_sp->GetValueAsUnsigned(-1);

break;
}
default:
break;
}
}

return linux_signals.GetSignalDescription(signo, code, addr, lower, upper,
uid, pid);
}

lldb::StopInfoSP PlatformLinux::GetStopInfoFromSiginfo(Thread &thread) {
ValueObjectSP siginfo_sp = thread.GetSiginfoValue();
if (!siginfo_sp)
return {};
auto signo_sp = siginfo_sp->GetChildMemberWithName("si_signo");
auto sicode_sp = siginfo_sp->GetChildMemberWithName("si_code");
if (!signo_sp || !sicode_sp)
return {};

std::string siginfo_description = GetDescriptionFromSiginfo(siginfo_sp);
if (siginfo_description.empty())
return StopInfo::CreateStopReasonWithSignal(
thread, signo_sp->GetValueAsUnsigned(-1));

return StopInfo::CreateStopReasonWithSignal(
thread, signo_sp->GetValueAsUnsigned(-1), siginfo_description.c_str(),
sicode_sp->GetValueAsUnsigned(0));
}
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Platform/Linux/PlatformLinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class PlatformLinux : public PlatformPOSIX {

CompilerType GetSiginfoType(const llvm::Triple &triple) override;

lldb::StopInfoSP GetStopInfoFromSiginfo(Thread &thread) override;

std::vector<ArchSpec> m_supported_architectures;

private:
Expand Down
Loading
Loading