Battery of NetBSD support improvements
Summary: Include initial support for: - single step mode (PT_STEP) - single step trap handling (TRAP_TRACE) - exec() trap (TRAP_EXEC) - add placeholder interfaces for FPR - initial code for NetBSD core(5) files - minor tweaks While there improve style of altered elf-core/ files. This code raises the number of passing tests on NetBSD to around 50% (600+/1200+). The introduced code is subject to improve afterwards for additional features and bug fixes. Sponsored by <The NetBSD Foundation> Reviewers: labath, joerg, emaste, kettenis Reviewed By: labath Subscribers: srhines, #lldb Tags: #lldb Differential Revision: https://reviews.llvm.org/D31450 llvm-svn: 299109
This commit is contained in:
parent
89653dfd2a
commit
3eef2b5e96
|
@ -679,7 +679,7 @@ Error Host::LaunchProcessPosixSpawn(const char *exe_path,
|
|||
sigemptyset(&no_signals);
|
||||
sigfillset(&all_signals);
|
||||
::posix_spawnattr_setsigmask(&attr, &no_signals);
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
::posix_spawnattr_setsigdefault(&attr, &no_signals);
|
||||
#else
|
||||
::posix_spawnattr_setsigdefault(&attr, &all_signals);
|
||||
|
|
|
@ -379,12 +379,13 @@ bool DYLDRendezvous::RemoveSOEntries() {
|
|||
}
|
||||
|
||||
bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) {
|
||||
// On Linux the executable is indicated by an empty path in the entry. On
|
||||
// FreeBSD and on Android it is the full path to the executable.
|
||||
// On some systes the executable is indicated by an empty path in the entry.
|
||||
// On others it is the full path to the executable.
|
||||
|
||||
auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
|
||||
switch (triple.getOS()) {
|
||||
case llvm::Triple::FreeBSD:
|
||||
case llvm::Triple::NetBSD:
|
||||
return entry.file_spec == m_exe_file_spec;
|
||||
case llvm::Triple::Linux:
|
||||
if (triple.isAndroid())
|
||||
|
|
|
@ -235,6 +235,24 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
|
|||
}
|
||||
SetState(StateType::eStateStopped, true);
|
||||
break;
|
||||
case TRAP_TRACE:
|
||||
for (const auto &thread_sp : m_threads) {
|
||||
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
|
||||
}
|
||||
SetState(StateType::eStateStopped, true);
|
||||
break;
|
||||
case TRAP_EXEC: {
|
||||
Error error = ReinitializeThreads();
|
||||
if (error.Fail()) {
|
||||
SetState(StateType::eStateInvalid);
|
||||
return;
|
||||
}
|
||||
|
||||
// Let our delegate know we have just exec'd.
|
||||
NotifyDidExec();
|
||||
|
||||
SetState(StateType::eStateStopped, true);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -389,11 +407,13 @@ Error NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
|
|||
return Error();
|
||||
}
|
||||
|
||||
Error error;
|
||||
|
||||
switch (action->state) {
|
||||
case eStateRunning: {
|
||||
// Run the thread, possibly feeding it the signal.
|
||||
Error error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(),
|
||||
(void *)1, action->signal);
|
||||
error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
|
||||
action->signal);
|
||||
if (!error.Success())
|
||||
return error;
|
||||
for (const auto &thread_sp : m_threads) {
|
||||
|
@ -403,7 +423,15 @@ Error NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
|
|||
break;
|
||||
}
|
||||
case eStateStepping:
|
||||
return Error("Not implemented");
|
||||
// Run the thread, possibly feeding it the signal.
|
||||
error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
|
||||
action->signal);
|
||||
if (!error.Success())
|
||||
return error;
|
||||
for (const auto &thread_sp : m_threads) {
|
||||
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStepping();
|
||||
}
|
||||
SetState(eStateStepping, true);
|
||||
break;
|
||||
|
||||
case eStateSuspended:
|
||||
|
@ -732,22 +760,11 @@ Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
|
|||
|
||||
ResolveProcessArchitecture(m_pid, m_arch);
|
||||
|
||||
/* Initialize threads */
|
||||
struct ptrace_lwpinfo info = {};
|
||||
error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
|
||||
error = ReinitializeThreads();
|
||||
if (error.Fail()) {
|
||||
SetState(StateType::eStateInvalid);
|
||||
return error;
|
||||
}
|
||||
while (info.pl_lwpid != 0) {
|
||||
NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
|
||||
thread_sp->SetStoppedBySignal(SIGSTOP);
|
||||
error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
|
||||
if (error.Fail()) {
|
||||
SetState(StateType::eStateInvalid);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set process stopped */
|
||||
SetState(StateType::eStateStopped);
|
||||
|
@ -850,9 +867,6 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
|
|||
::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Error &error) {
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
|
||||
|
||||
// Use a map to keep track of the threads which we have attached/need to
|
||||
// attach.
|
||||
Host::TidMap tids_to_attach;
|
||||
if (pid <= 1) {
|
||||
error.SetErrorToGenericError();
|
||||
error.SetErrorString("Attaching to process 1 is not allowed.");
|
||||
|
@ -874,21 +888,11 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
|
|||
m_pid = pid;
|
||||
|
||||
/* Initialize threads */
|
||||
struct ptrace_lwpinfo info = {};
|
||||
error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
|
||||
error = ReinitializeThreads();
|
||||
if (error.Fail()) {
|
||||
SetState(StateType::eStateInvalid);
|
||||
return -1;
|
||||
}
|
||||
while (info.pl_lwpid != 0) {
|
||||
NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
|
||||
thread_sp->SetStoppedBySignal(SIGSTOP);
|
||||
error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
|
||||
if (error.Fail()) {
|
||||
SetState(StateType::eStateInvalid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Let our process instance know the thread has stopped.
|
||||
SetState(StateType::eStateStopped);
|
||||
|
@ -989,3 +993,26 @@ NativeProcessNetBSD::GetAuxvData() const {
|
|||
|
||||
return buf;
|
||||
}
|
||||
|
||||
Error NativeProcessNetBSD::ReinitializeThreads() {
|
||||
// Clear old threads
|
||||
m_threads.clear();
|
||||
|
||||
// Initialize new thread
|
||||
struct ptrace_lwpinfo info = {};
|
||||
Error error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
|
||||
if (error.Fail()) {
|
||||
return error;
|
||||
}
|
||||
// Reinitialize from scratch threads and register them in process
|
||||
while (info.pl_lwpid != 0) {
|
||||
NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
|
||||
thread_sp->SetStoppedByExec();
|
||||
error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
|
||||
if (error.Fail()) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -131,6 +131,8 @@ private:
|
|||
void SigchldHandler();
|
||||
|
||||
::pid_t Attach(lldb::pid_t pid, Error &error);
|
||||
|
||||
Error ReinitializeThreads();
|
||||
};
|
||||
|
||||
} // namespace process_netbsd
|
||||
|
|
|
@ -41,6 +41,22 @@ Error NativeRegisterContextNetBSD::WriteGPR() {
|
|||
return DoWriteGPR(buf);
|
||||
}
|
||||
|
||||
Error NativeRegisterContextNetBSD::ReadFPR() {
|
||||
void *buf = GetFPRBuffer();
|
||||
if (!buf)
|
||||
return Error("FPR buffer is NULL");
|
||||
|
||||
return DoReadFPR(buf);
|
||||
}
|
||||
|
||||
Error NativeRegisterContextNetBSD::WriteFPR() {
|
||||
void *buf = GetFPRBuffer();
|
||||
if (!buf)
|
||||
return Error("FPR buffer is NULL");
|
||||
|
||||
return DoWriteFPR(buf);
|
||||
}
|
||||
|
||||
Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) {
|
||||
return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf,
|
||||
m_thread.GetID());
|
||||
|
@ -51,6 +67,16 @@ Error NativeRegisterContextNetBSD::DoWriteGPR(void *buf) {
|
|||
m_thread.GetID());
|
||||
}
|
||||
|
||||
Error NativeRegisterContextNetBSD::DoReadFPR(void *buf) {
|
||||
return NativeProcessNetBSD::PtraceWrapper(PT_GETFPREGS, GetProcessPid(), buf,
|
||||
m_thread.GetID());
|
||||
}
|
||||
|
||||
Error NativeRegisterContextNetBSD::DoWriteFPR(void *buf) {
|
||||
return NativeProcessNetBSD::PtraceWrapper(PT_SETFPREGS, GetProcessPid(), buf,
|
||||
m_thread.GetID());
|
||||
}
|
||||
|
||||
NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() {
|
||||
auto process_sp =
|
||||
std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess());
|
||||
|
|
|
@ -37,13 +37,24 @@ public:
|
|||
protected:
|
||||
virtual Error ReadGPR();
|
||||
virtual Error WriteGPR();
|
||||
|
||||
virtual Error ReadFPR();
|
||||
virtual Error WriteFPR();
|
||||
|
||||
virtual void *GetGPRBuffer() { return nullptr; }
|
||||
virtual size_t GetGPRSize() {
|
||||
return GetRegisterInfoInterface().GetGPRSize();
|
||||
}
|
||||
|
||||
virtual void *GetFPRBuffer() { return nullptr; }
|
||||
virtual size_t GetFPRSize() { return 0; }
|
||||
|
||||
virtual Error DoReadGPR(void *buf);
|
||||
virtual Error DoWriteGPR(void *buf);
|
||||
|
||||
virtual Error DoReadFPR(void *buf);
|
||||
virtual Error DoWriteFPR(void *buf);
|
||||
|
||||
virtual NativeProcessNetBSD &GetProcess();
|
||||
virtual ::pid_t GetProcessPid();
|
||||
};
|
||||
|
|
|
@ -154,6 +154,9 @@ int NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) {
|
|||
case GPRegSet:
|
||||
ReadGPR();
|
||||
return 0;
|
||||
case FPRegSet:
|
||||
ReadFPR();
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -164,6 +167,9 @@ int NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) {
|
|||
case GPRegSet:
|
||||
WriteGPR();
|
||||
return 0;
|
||||
case FPRegSet:
|
||||
WriteFPR();
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -48,13 +48,15 @@ public:
|
|||
|
||||
protected:
|
||||
void *GetGPRBuffer() override { return &m_gpr_x86_64; }
|
||||
void *GetFPRBuffer() override { return &m_fpr_x86_64; }
|
||||
|
||||
private:
|
||||
// Private member types.
|
||||
enum { GPRegSet };
|
||||
enum { GPRegSet, FPRegSet };
|
||||
|
||||
// Private member variables.
|
||||
struct reg m_gpr_x86_64;
|
||||
struct fpreg m_fpr_x86_64;
|
||||
|
||||
int GetSetForNativeRegNum(int reg_num) const;
|
||||
|
||||
|
|
|
@ -56,6 +56,18 @@ void NativeThreadNetBSD::SetStoppedByBreakpoint() {
|
|||
m_stop_info.details.signal.signo = SIGTRAP;
|
||||
}
|
||||
|
||||
void NativeThreadNetBSD::SetStoppedByTrace() {
|
||||
SetStopped();
|
||||
m_stop_info.reason = StopReason::eStopReasonTrace;
|
||||
m_stop_info.details.signal.signo = SIGTRAP;
|
||||
}
|
||||
|
||||
void NativeThreadNetBSD::SetStoppedByExec() {
|
||||
SetStopped();
|
||||
m_stop_info.reason = StopReason::eStopReasonExec;
|
||||
m_stop_info.details.signal.signo = SIGTRAP;
|
||||
}
|
||||
|
||||
void NativeThreadNetBSD::SetStopped() {
|
||||
const StateType new_state = StateType::eStateStopped;
|
||||
m_state = new_state;
|
||||
|
@ -67,6 +79,11 @@ void NativeThreadNetBSD::SetRunning() {
|
|||
m_stop_info.reason = StopReason::eStopReasonNone;
|
||||
}
|
||||
|
||||
void NativeThreadNetBSD::SetStepping() {
|
||||
m_state = StateType::eStateStepping;
|
||||
m_stop_info.reason = StopReason::eStopReasonNone;
|
||||
}
|
||||
|
||||
std::string NativeThreadNetBSD::GetName() { return std::string(""); }
|
||||
|
||||
lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
|
||||
|
|
|
@ -51,8 +51,11 @@ private:
|
|||
|
||||
void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
|
||||
void SetStoppedByBreakpoint();
|
||||
void SetStoppedByTrace();
|
||||
void SetStoppedByExec();
|
||||
void SetStopped();
|
||||
void SetRunning();
|
||||
void SetStepping();
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Member Variables
|
||||
|
|
|
@ -62,8 +62,8 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,
|
|||
// to ignore possible presence of the header extension.
|
||||
const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);
|
||||
|
||||
auto data_sp =
|
||||
DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0);
|
||||
auto data_sp = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(),
|
||||
header_size, 0);
|
||||
if (data_sp && data_sp->GetByteSize() == header_size &&
|
||||
elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) {
|
||||
elf::ELFHeader elf_header;
|
||||
|
@ -223,7 +223,7 @@ Error ProcessElfCore::DoLoadCore() {
|
|||
bool siginfo_signal_found = false;
|
||||
bool prstatus_signal_found = false;
|
||||
// Check we found a signal in a SIGINFO note.
|
||||
for (const auto &thread_data: m_thread_data) {
|
||||
for (const auto &thread_data : m_thread_data) {
|
||||
if (thread_data.signo != 0)
|
||||
siginfo_signal_found = true;
|
||||
if (thread_data.prstatus_sig != 0)
|
||||
|
@ -233,7 +233,7 @@ Error ProcessElfCore::DoLoadCore() {
|
|||
// If we don't have signal from SIGINFO use the signal from each threads
|
||||
// PRSTATUS note.
|
||||
if (prstatus_signal_found) {
|
||||
for (auto &thread_data: m_thread_data)
|
||||
for (auto &thread_data : m_thread_data)
|
||||
thread_data.signo = thread_data.prstatus_sig;
|
||||
} else if (m_thread_data.size() > 0) {
|
||||
// If all else fails force the first thread to be SIGSTOP
|
||||
|
@ -449,6 +449,11 @@ enum {
|
|||
};
|
||||
}
|
||||
|
||||
namespace NETBSD {
|
||||
|
||||
enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 };
|
||||
}
|
||||
|
||||
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
|
||||
static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
|
||||
ArchSpec &arch) {
|
||||
|
@ -485,13 +490,23 @@ static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) {
|
|||
thread_data.name = data.GetCStr(&offset, 20);
|
||||
}
|
||||
|
||||
static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data)
|
||||
{
|
||||
static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
|
||||
lldb::offset_t offset = 0;
|
||||
|
||||
|
||||
int version = data.GetU32(&offset);
|
||||
if (version != 1)
|
||||
return;
|
||||
return;
|
||||
|
||||
offset += 4;
|
||||
thread_data.signo = data.GetU32(&offset);
|
||||
}
|
||||
|
||||
static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
|
||||
lldb::offset_t offset = 0;
|
||||
|
||||
int version = data.GetU32(&offset);
|
||||
if (version != 1)
|
||||
return;
|
||||
|
||||
offset += 4;
|
||||
thread_data.signo = data.GetU32(&offset);
|
||||
|
@ -585,23 +600,38 @@ Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (note.n_name.substr(0, 11) == "NetBSD-CORE") {
|
||||
// NetBSD per-thread information is stored in notes named
|
||||
// "NetBSD-CORE@nnn" so match on the initial part of the string.
|
||||
m_os = llvm::Triple::NetBSD;
|
||||
if (note.n_type == NETBSD::NT_PROCINFO) {
|
||||
ParseNetBSDProcInfo(*thread_data, note_data);
|
||||
} else if (note.n_type == NETBSD::NT_AUXV) {
|
||||
m_auxv = DataExtractor(note_data);
|
||||
} else if (arch.GetMachine() == llvm::Triple::x86_64 &&
|
||||
note.n_type == NETBSD::NT_AMD64_REGS) {
|
||||
thread_data->gpregset = note_data;
|
||||
} else if (arch.GetMachine() == llvm::Triple::x86_64 &&
|
||||
note.n_type == NETBSD::NT_AMD64_FPREGS) {
|
||||
thread_data->fpregset = note_data;
|
||||
}
|
||||
} else if (note.n_name.substr(0, 7) == "OpenBSD") {
|
||||
// OpenBSD per-thread information is stored in notes named
|
||||
// "OpenBSD@nnn" so match on the initial part of the string.
|
||||
m_os = llvm::Triple::OpenBSD;
|
||||
switch (note.n_type) {
|
||||
case NT_OPENBSD_PROCINFO:
|
||||
ParseOpenBSDProcInfo(*thread_data, note_data);
|
||||
break;
|
||||
ParseOpenBSDProcInfo(*thread_data, note_data);
|
||||
break;
|
||||
case NT_OPENBSD_AUXV:
|
||||
m_auxv = DataExtractor(note_data);
|
||||
break;
|
||||
m_auxv = DataExtractor(note_data);
|
||||
break;
|
||||
case NT_OPENBSD_REGS:
|
||||
thread_data->gpregset = note_data;
|
||||
break;
|
||||
thread_data->gpregset = note_data;
|
||||
break;
|
||||
case NT_OPENBSD_FPREGS:
|
||||
thread_data->fpregset = note_data;
|
||||
break;
|
||||
thread_data->fpregset = note_data;
|
||||
break;
|
||||
}
|
||||
} else if (note.n_name == "CORE") {
|
||||
switch (note.n_type) {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
|
||||
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
|
||||
|
@ -112,6 +113,17 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
|
|||
break;
|
||||
}
|
||||
|
||||
case llvm::Triple::NetBSD: {
|
||||
switch (arch.GetMachine()) {
|
||||
case llvm::Triple::x86_64:
|
||||
reg_interface = new RegisterContextNetBSD_x86_64(arch);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case llvm::Triple::Linux: {
|
||||
switch (arch.GetMachine()) {
|
||||
case llvm::Triple::arm:
|
||||
|
@ -144,8 +156,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
|
|||
reg_interface = new RegisterInfoPOSIX_arm(arch);
|
||||
break;
|
||||
case llvm::Triple::x86:
|
||||
reg_interface = new RegisterContextOpenBSD_i386(arch);
|
||||
break;
|
||||
reg_interface = new RegisterContextOpenBSD_i386(arch);
|
||||
break;
|
||||
case llvm::Triple::x86_64:
|
||||
reg_interface = new RegisterContextOpenBSD_x86_64(arch);
|
||||
break;
|
||||
|
@ -260,7 +272,6 @@ Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {
|
|||
pr_cstime.tv_sec = data.GetPointer(&offset);
|
||||
pr_cstime.tv_usec = data.GetPointer(&offset);
|
||||
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -317,9 +328,7 @@ Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) {
|
|||
//----------------------------------------------------------------
|
||||
// Parse SIGINFO from NOTE entry
|
||||
//----------------------------------------------------------------
|
||||
ELFLinuxSigInfo::ELFLinuxSigInfo() {
|
||||
memset(this, 0, sizeof(ELFLinuxSigInfo));
|
||||
}
|
||||
ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
|
||||
|
||||
Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {
|
||||
Error error;
|
||||
|
|
Loading…
Reference in New Issue