From 3eef2b5e96fd446bd6bf0341bb8cb26be47366e3 Mon Sep 17 00:00:00 2001 From: Kamil Rytarowski Date: Thu, 30 Mar 2017 20:25:29 +0000 Subject: [PATCH] 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 Reviewers: labath, joerg, emaste, kettenis Reviewed By: labath Subscribers: srhines, #lldb Tags: #lldb Differential Revision: https://reviews.llvm.org/D31450 llvm-svn: 299109 --- lldb/source/Host/common/Host.cpp | 2 +- .../POSIX-DYLD/DYLDRendezvous.cpp | 5 +- .../Process/NetBSD/NativeProcessNetBSD.cpp | 85 ++++++++++++------- .../Process/NetBSD/NativeProcessNetBSD.h | 2 + .../NetBSD/NativeRegisterContextNetBSD.cpp | 26 ++++++ .../NetBSD/NativeRegisterContextNetBSD.h | 11 +++ .../NativeRegisterContextNetBSD_x86_64.cpp | 6 ++ .../NativeRegisterContextNetBSD_x86_64.h | 4 +- .../Process/NetBSD/NativeThreadNetBSD.cpp | 17 ++++ .../Process/NetBSD/NativeThreadNetBSD.h | 3 + .../Process/elf-core/ProcessElfCore.cpp | 62 ++++++++++---- .../Process/elf-core/ThreadElfCore.cpp | 21 +++-- 12 files changed, 189 insertions(+), 55 deletions(-) diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 5b0fb8749f3e..7754d96ad331 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -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); diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 37d65b3ce0a1..c4917c08fa90 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -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()) diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 9c09727588d2..298faa48e1c3 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -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(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(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; +} diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index 8463220e61ee..ae946a8e004d 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -131,6 +131,8 @@ private: void SigchldHandler(); ::pid_t Attach(lldb::pid_t pid, Error &error); + + Error ReinitializeThreads(); }; } // namespace process_netbsd diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp index 009f82b1737f..1bb6324c97fe 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp @@ -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(m_thread.GetProcess()); diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h index 9834acb6f933..5ff59bc87c98 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h @@ -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(); }; diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index 0dcdcc9ca343..76e64ac48d66 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -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; } diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h index 3166d96d0a4e..f6f7d7f0976a 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -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; diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp index 8493e98e3d0f..f23621e45aad 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -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; } diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h index 94d3830894df..85fff5d5653f 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h @@ -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 diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 6bbe91488c32..68182f377479 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -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) { diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index f7f4653b5459..dda41e002c38 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -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;