pkgsrc-WIP-changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lldb-netbsd: Support threads in NetBSD core(5) files
Module Name: pkgsrc-wip
Committed By: Kamil Rytarowski <n54%gmx.com@localhost>
Pushed By: kamil
Date: Mon Apr 17 22:48:38 2017 +0200
Changeset: 03f54f03f532e3f9a6d9404c716e46b04369ba37
Modified Files:
lldb-netbsd/distinfo
Added Files:
lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.cpp
lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.h
Log Message:
lldb-netbsd: Support threads in NetBSD core(5) files
This is proof-of-concept. There is need to sort out bugs.
Sponsored by <The NetBSD Foundation>
To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=03f54f03f532e3f9a6d9404c716e46b04369ba37
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
diffstat:
lldb-netbsd/distinfo | 2 +
...rce_Plugins_Process_elf-core_ProcessElfCore.cpp | 277 +++++++++++++++++++++
...ource_Plugins_Process_elf-core_ProcessElfCore.h | 23 ++
3 files changed, 302 insertions(+)
diffs:
diff --git a/lldb-netbsd/distinfo b/lldb-netbsd/distinfo
index 03491bbdc9..6b77cfff4f 100644
--- a/lldb-netbsd/distinfo
+++ b/lldb-netbsd/distinfo
@@ -21,3 +21,5 @@ SHA1 (patch-source_Plugins_Process_NetBSD_NativeRegisterContextNetBSD__x86__64.h
SHA1 (patch-source_Plugins_Process_NetBSD_NativeThreadNetBSD.cpp) = d788ea7d92ffa31f2d6477e11129fc9b9fd0b8eb
SHA1 (patch-source_Plugins_Process_NetBSD_NativeThreadNetBSD.h) = d2586e2ecdc2c979c59fc1a6a569e7870d3334ba
SHA1 (patch-source_Plugins_Process_Utility_RegisterInfos__x86__64.h) = 47d7dc03b7da83ff7f02b684b2188da53bf269d3
+SHA1 (patch-source_Plugins_Process_elf-core_ProcessElfCore.cpp) = 7b0415ae0da4760a5fd98b5b8d2d0931d852765c
+SHA1 (patch-source_Plugins_Process_elf-core_ProcessElfCore.h) = 902ce5e0187aa2649986db08c79af7291b852727
diff --git a/lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.cpp b/lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.cpp
new file mode 100644
index 0000000000..4926ff8a93
--- /dev/null
+++ b/lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.cpp
@@ -0,0 +1,277 @@
+$NetBSD$
+
+--- source/Plugins/Process/elf-core/ProcessElfCore.cpp.orig 2017-04-07 18:27:43.000000000 +0000
++++ source/Plugins/Process/elf-core/ProcessElfCore.cpp
+@@ -219,7 +219,7 @@ Error ProcessElfCore::DoLoadCore() {
+ ArchSpec core_arch(m_core_module_sp->GetArchitecture());
+ target_arch.MergeFrom(core_arch);
+ GetTarget().SetArchitecture(target_arch);
+-
++
+ SetUnixSignals(UnixSignals::Create(GetArchitecture()));
+
+ // Ensure we found at least one thread that was stopped on a signal.
+@@ -373,7 +373,8 @@ size_t ProcessElfCore::DoReadMemory(lldb
+ lldb::addr_t bytes_left =
+ 0; // Number of bytes available in the core file from the given address
+
+- // Don't proceed if core file doesn't contain the actual data for this address range.
++ // Don't proceed if core file doesn't contain the actual data for this address
++ // range.
+ if (file_start == file_end)
+ return 0;
+
+@@ -458,9 +459,14 @@ enum {
+
+ namespace NETBSD {
+
+-enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 };
++enum { NT_PROCINFO = 1, NT_PROCINFO_SIZE = 160, NT_AUXV = 2 };
++
++namespace AMD64 {
++enum { NT_REGS = 33, NT_FPREGS = 35 };
+ }
+
++} // namespace NETBSD
++
+ // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
+ static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
+ ArchSpec &arch) {
+@@ -497,15 +503,27 @@ static void ParseFreeBSDThrMisc(ThreadDa
+ thread_data.name = data.GetCStr(&offset, 20);
+ }
+
+-static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
++static Error ParseNetBSDProcInfo(DataExtractor &data, uint32_t &cpi_nlwps,
++ uint32_t &cpi_signo, uint32_t &cpi_siglwp) {
+ lldb::offset_t offset = 0;
+
+- int version = data.GetU32(&offset);
++ uint32_t version = data.GetU32(&offset);
+ if (version != 1)
+- return;
++ return Error("Unsupported procinfo version");
+
+- offset += 4;
+- thread_data.signo = data.GetU32(&offset);
++ uint32_t cpisize = data.GetU32(&offset);
++ if (cpisize != NETBSD::NT_PROCINFO_SIZE)
++ return Error("Unsupported procinfo version");
++
++ cpi_signo = data.GetU32(&offset); /* killing signal */
++
++ offset += 104;
++ cpi_nlwps = data.GetU32(&offset); /* number of LWPs */
++
++ offset += 31;
++ cpi_siglwp = data.GetU32(&offset); /* LWP target of killing signal */
++
++ return Error();
+ }
+
+ static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
+@@ -524,12 +542,28 @@ static void ParseOpenBSDProcInfo(ThreadD
+ /// 1) A PT_NOTE segment is composed of one or more NOTE entries.
+ /// 2) NOTE Entry contains a standard header followed by variable size data.
+ /// (see ELFNote structure)
+-/// 3) A Thread Context in a core file usually described by 3 NOTE entries.
++Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
++ const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
++
++ assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
++
++ switch (GetArchitecture().GetTriple().getOS()) {
++ case llvm::Triple::NetBSD:
++ return ParseThreadContextsFromNoteSegmentNetBSD(segment_header,
++ segment_data);
++ default:
++ return ParseThreadContextsFromNoteSegmentGeneric(segment_header,
++ segment_data);
++ }
++}
++
++/// Generic (Linux, ...) specific Thread context from PT_NOTE segment
++/// 1) A Thread Context in a core file usually described by 3 NOTE entries.
+ /// a) NT_PRSTATUS - Register context
+ /// b) NT_PRPSINFO - Process info(pid..)
+ /// c) NT_FPREGSET - Floating point registers
+-/// 4) The NOTE entries can be in any order
+-/// 5) If a core file contains multiple thread contexts then there is two data
++/// 2) The NOTE entries can be in any order
++/// 3) If a core file contains multiple thread contexts then there is two data
+ /// forms
+ /// a) Each thread context(2 or more NOTE entries) contained in its own
+ /// segment (PT_NOTE)
+@@ -540,8 +574,9 @@ static void ParseOpenBSDProcInfo(ThreadD
+ /// new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry.
+ /// For case (b) there may be either one NT_PRPSINFO per thread, or a single
+ /// one that applies to all threads (depending on the platform type).
+-Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
++Error ProcessElfCore::ParseThreadContextsFromNoteSegmentGeneric(
+ const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
++
+ assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
+
+ lldb::offset_t offset = 0;
+@@ -607,21 +642,6 @@ Error ProcessElfCore::ParseThreadContext
+ 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.
+@@ -659,7 +679,7 @@ Error ProcessElfCore::ParseThreadContext
+ // The result from FXSAVE is in NT_PRXFPREG for i386 core files
+ if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64)
+ thread_data->fpregset = note_data;
+- else if(arch.IsMIPS())
++ else if (arch.IsMIPS())
+ thread_data->fpregset = note_data;
+ break;
+ case NT_PRPSINFO:
+@@ -717,6 +737,121 @@ Error ProcessElfCore::ParseThreadContext
+ return error;
+ }
+
++/// NetBSD specific Thread context from PT_NOTE segment
++///
++/// NetBSD ELF core files use notes to provide information about
++/// the process's state. The note name is "NetBSD-CORE" for
++/// information that is global to the process, and "NetBSD-CORE@nn",
++/// where "nn" is the lwpid of the LWP that the information belongs
++/// to (such as register state).
++///
++/// NetBSD uses the following note identifiers:
++///
++/// ELF_NOTE_NETBSD_CORE_PROCINFO (value 1)
++/// Note is a "netbsd_elfcore_procinfo" structure.
++/// ELF_NOTE_NETBSD_CORE_AUXV (value 2; since NetBSD 8.0)
++/// Note is an array of AuxInfo structures.
++///
++/// NetBSD also uses ptrace(2) request numbers (the ones that exist in
++/// machine-dependent space) to identify register info notes. The
++/// info in such notes is in the same format that ptrace(2) would
++/// export that information.
++///
++/// For more information see /usr/include/sys/exec_elf.h
++///
++Error ProcessElfCore::ParseThreadContextsFromNoteSegmentNetBSD(
++ const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
++
++ assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
++
++ lldb::offset_t offset = 0;
++ ArchSpec arch = GetArchitecture();
++ m_os = llvm::Triple::NetBSD;
++
++ /*
++ * To be extracted from struct netbsd_elfcore_procinfo
++ * Used to sanity check of the LWPs of the process
++ */
++ uint32_t nlwps = 0;
++ uint32_t signo; /* killing signal */
++ uint32_t siglwp; /* LWP target of killing signal */
++
++ while (offset < segment_header->p_filesz) {
++ ELFNote note = ELFNote();
++ note.Parse(segment_data, &offset);
++
++ size_t note_start, note_size;
++ note_start = offset;
++ note_size = llvm::alignTo(note.n_descsz, 4);
++
++ // Store the NOTE information in the current thread
++ DataExtractor note_data(segment_data, note_start, note_size);
++ note_data.SetAddressByteSize(
++ m_core_module_sp->GetArchitecture().GetAddressByteSize());
++
++ if ((note.n_name == "NetBSD-CORE") &&
++ (note.n_type == NETBSD::NT_PROCINFO)) {
++ ParseNetBSDProcInfo(note_data, nlwps, signo, siglwp);
++ } else if ((note.n_name == "NetBSD-CORE") &&
++ (note.n_type == NETBSD::NT_AUXV)) {
++ m_auxv = DataExtractor(note_data);
++ } else if ((note.n_name.substr(0, 12) == "NetBSD-CORE@")) {
++ switch (arch.GetMachine()) {
++ case llvm::Triple::x86_64: {
++ /* Assume orfer PT_GETREGS, PT_GETFPREGS */
++ if (note.n_type == NETBSD::AMD64::NT_REGS) {
++ m_thread_data.push_back(ThreadData());
++ m_thread_data.back().gpregset = note_data;
++ if (!llvm::StringRef(note.n_name.substr(12))
++ .getAsInteger(10, m_thread_data.back().tid))
++ return Error("Unsupported NOTE type");
++ } else if (note.n_type == NETBSD::AMD64::NT_FPREGS) {
++ if (m_thread_data.empty())
++ return Error(
++ "Unexpected order of NOTEs PT_GETFPREG before PT_GETREG");
++ m_thread_data.back().fpregset = note_data;
++ } else {
++ return Error("Unsupported NOTE type");
++ }
++ } break;
++ default:
++ return Error("Unsupported architecture");
++ }
++ } else {
++ return Error("Unsupported NOTE type");
++ }
++ }
++
++ if (m_thread_data.empty())
++ return Error("Missing thread information in NOTEs");
++
++ if (m_thread_data.size() != nlwps)
++ return Error("Mismatch number of LWPs in NOTEs");
++
++ /* The whole process signal */
++ if (siglwp == 0) {
++ std::for_each(
++ m_thread_data.begin(), m_thread_data.end(),
++ [&signo](ThreadData &thread_data) { thread_data.signo = signo; });
++ }
++ /* Signal destinated for a particular LWP */
++ else {
++ bool passed = false;
++
++ for (auto it = m_thread_data.begin(); it != m_thread_data.end(); ++it) {
++ if (it->tid == siglwp) {
++ it->signo = signo;
++ passed = true;
++ break;
++ }
++ }
++ if (!passed)
++ return Error("Signal passed to unknown LWP");
++ }
++
++ return Error();
++}
++
+ uint32_t ProcessElfCore::GetNumThreadContexts() {
+ if (!m_thread_data_valid)
+ DoLoadCore();
+@@ -730,7 +865,7 @@ ArchSpec ProcessElfCore::GetArchitecture
+ core_file->GetArchitecture(arch);
+
+ ArchSpec target_arch = GetTarget().GetArchitecture();
+-
++
+ if (target_arch.IsMIPS())
+ return target_arch;
+
diff --git a/lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.h b/lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.h
new file mode 100644
index 0000000000..972698ea77
--- /dev/null
+++ b/lldb-netbsd/patches/patch-source_Plugins_Process_elf-core_ProcessElfCore.h
@@ -0,0 +1,23 @@
+$NetBSD$
+
+--- source/Plugins/Process/elf-core/ProcessElfCore.h.orig 2017-02-04 18:35:34.000000000 +0000
++++ source/Plugins/Process/elf-core/ProcessElfCore.h
+@@ -125,6 +125,18 @@ private:
+ lldb_private::ConstString path;
+ };
+
++ // Parse thread(s) data structuresNetBSD(prstatus, prpsinfo) from given NOTE
++ // segment
++ lldb_private::Error ParseThreadContextsFromNoteSegmentNetBSD(
++ const elf::ELFProgramHeader *segment_header,
++ lldb_private::DataExtractor segment_data);
++
++ // Parse thread(s) data structuresGeneric(prstatus, prpsinfo) from given NOTE
++ // segment
++ lldb_private::Error ParseThreadContextsFromNoteSegmentGeneric(
++ const elf::ELFProgramHeader *segment_header,
++ lldb_private::DataExtractor segment_data);
++
+ //------------------------------------------------------------------
+ // For ProcessElfCore only
+ //------------------------------------------------------------------
Home |
Main Index |
Thread Index |
Old Index