summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xlldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64bin0 -> 13616 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.corebin0 -> 101872 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c14
-rwxr-xr-xlldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64bin0 -> 15816 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.corebin0 -> 121208 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c32
-rwxr-xr-xlldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64bin0 -> 15456 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.corebin0 -> 121192 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c30
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile15
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py225
-rw-r--r--lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp184
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterUtilities.h37
13 files changed, 507 insertions, 30 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64 b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64
new file mode 100755
index 00000000000..56fa077bd6a
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.core b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.core
new file mode 100644
index 00000000000..d2d40500455
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.core
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c
new file mode 100644
index 00000000000..972e9678af5
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c
@@ -0,0 +1,14 @@
+static void bar(char *boom) {
+ char F = 'b';
+ *boom = 47; // Frame bar
+}
+
+static void foo(char *boom, void (*boomer)(char *)) {
+ char F = 'f';
+ boomer(boom); // Frame foo
+}
+
+void main(void) {
+ char F = 'm';
+ foo(0, bar); // Frame main
+}
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64 b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64
new file mode 100755
index 00000000000..00f61dfce84
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.core b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.core
new file mode 100644
index 00000000000..f9c2b562fba
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.core
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c
new file mode 100644
index 00000000000..ce583aaada9
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c
@@ -0,0 +1,32 @@
+#include <lwp.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+static void bar() {
+ char F = 'b';
+ kill(getpid(), SIGSEGV); // Frame bar
+}
+
+static void foo(void (*boomer)()) {
+ char F = 'f';
+ boomer(); // Frame foo
+}
+
+static void lwp_main(void *unused) {
+ char F = 'l';
+ foo(bar); // Frame lwp_main
+}
+
+int main(int argc, char **argv) {
+ ucontext_t uc;
+ lwpid_t lid;
+ static const size_t ssize = 16 * 1024;
+ void *stack;
+
+ stack = malloc(ssize);
+ _lwp_makecontext(&uc, lwp_main, NULL, NULL, stack, ssize);
+ _lwp_create(&uc, 0, &lid);
+ _lwp_wait(lid, NULL);
+}
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64 b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64
new file mode 100755
index 00000000000..d304de160f0
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.core b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.core
new file mode 100644
index 00000000000..5f68687c56e
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.core
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c
new file mode 100644
index 00000000000..1cd86631edd
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c
@@ -0,0 +1,30 @@
+#include <lwp.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+static void bar(char *boom) {
+ char F = 'b';
+ *boom = 47; // Frame bar
+}
+
+static void foo(char *boom, void (*boomer)(char *)) {
+ char F = 'f';
+ boomer(boom); // Frame foo
+}
+
+void lwp_main(void *unused) {
+ char F = 'l';
+ foo(0, bar); // Frame lwp_main
+}
+
+int main(int argc, char **argv) {
+ ucontext_t uc;
+ lwpid_t lid;
+ static const size_t ssize = 16 * 1024;
+ void *stack;
+
+ stack = malloc(ssize);
+ _lwp_makecontext(&uc, lwp_main, NULL, NULL, stack, ssize);
+ _lwp_create(&uc, 0, &lid);
+ _lwp_wait(lid, NULL);
+}
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile
new file mode 100644
index 00000000000..62c719d3d2f
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile
@@ -0,0 +1,15 @@
+ARCH = $(shell uname -m)
+PROGRAMS = 1lwp_SIGSEGV 2lwp_t2_SIGSEGV 2lwp_process_SIGSEGV
+EXECS = $(patsubst %,%.$(ARCH),$(PROGRAMS))
+CORES = $(patsubst %,%.core,$(EXECS))
+
+all: $(CORES) $(EXECS)
+clean:
+ rm -f $(CORES) $(EXECS)
+
+%.core: %
+ sysctl -w proc.$$$$.corename=$@; ulimit -s 16; ! ./$<
+%.$(ARCH): %.c
+ $(CC) -o $@ -g $<
+
+.PHONY: all clean
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py
new file mode 100644
index 00000000000..ca234ecc1f6
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py
@@ -0,0 +1,225 @@
+"""
+Test NetBSD core file debugging.
+"""
+
+from __future__ import division, print_function
+
+import shutil
+import signal
+import struct
+import os
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class NetBSDCoreCommonTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ super(NetBSDCoreCommonTestCase, self).setUp()
+ self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+ def tearDown(self):
+ lldb.DBG.SetSelectedPlatform(self._initial_platform)
+ super(NetBSDCoreCommonTestCase, self).tearDown()
+
+ def check_memory_regions(self, process, region_count):
+ region_list = process.GetMemoryRegions()
+ self.assertEqual(region_list.GetSize(), region_count)
+
+ region = lldb.SBMemoryRegionInfo()
+
+ # Check we have the right number of regions.
+ self.assertEqual(region_list.GetSize(), region_count)
+
+ # Check that getting a region beyond the last in the list fails.
+ self.assertFalse(
+ region_list.GetMemoryRegionAtIndex(
+ region_count, region))
+
+ # Check each region is valid.
+ for i in range(region_list.GetSize()):
+ # Check we can actually get this region.
+ self.assertTrue(region_list.GetMemoryRegionAtIndex(i, region))
+
+ # Every region in the list should be mapped.
+ self.assertTrue(region.IsMapped())
+
+ # Test the address at the start of a region returns it's enclosing
+ # region.
+ begin_address = region.GetRegionBase()
+ region_at_begin = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(begin_address, region_at_begin)
+ self.assertEqual(region, region_at_begin)
+
+ # Test an address in the middle of a region returns it's enclosing
+ # region.
+ middle_address = (region.GetRegionBase() +
+ region.GetRegionEnd()) // 2
+ region_at_middle = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(
+ middle_address, region_at_middle)
+ self.assertEqual(region, region_at_middle)
+
+ # Test the address at the end of a region returns it's enclosing
+ # region.
+ end_address = region.GetRegionEnd() - 1
+ region_at_end = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(end_address, region_at_end)
+ self.assertEqual(region, region_at_end)
+
+ # Check that quering the end address does not return this region but
+ # the next one.
+ next_region = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(
+ region.GetRegionEnd(), next_region)
+ self.assertNotEqual(region, next_region)
+ self.assertEqual(
+ region.GetRegionEnd(),
+ next_region.GetRegionBase())
+
+ # Check that query beyond the last region returns an unmapped region
+ # that ends at LLDB_INVALID_ADDRESS
+ last_region = lldb.SBMemoryRegionInfo()
+ region_list.GetMemoryRegionAtIndex(region_count - 1, last_region)
+ end_region = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(
+ last_region.GetRegionEnd(), end_region)
+ self.assertFalse(end_region.IsMapped())
+ self.assertEqual(
+ last_region.GetRegionEnd(),
+ end_region.GetRegionBase())
+ self.assertEqual(end_region.GetRegionEnd(), lldb.LLDB_INVALID_ADDRESS)
+
+ def check_state(self, process):
+ with open(os.devnull) as devnul:
+ # sanitize test output
+ self.dbg.SetOutputFileHandle(devnul, False)
+ self.dbg.SetErrorFileHandle(devnul, False)
+
+ self.assertTrue(process.is_stopped)
+
+ # Process.Continue
+ error = process.Continue()
+ self.assertFalse(error.Success())
+ self.assertTrue(process.is_stopped)
+
+ # Thread.StepOut
+ thread = process.GetSelectedThread()
+ thread.StepOut()
+ self.assertTrue(process.is_stopped)
+
+ # command line
+ self.dbg.HandleCommand('s')
+ self.assertTrue(process.is_stopped)
+ self.dbg.HandleCommand('c')
+ self.assertTrue(process.is_stopped)
+
+ # restore file handles
+ self.dbg.SetOutputFileHandle(None, False)
+ self.dbg.SetErrorFileHandle(None, False)
+
+ def check_backtrace(self, thread, filename, backtrace):
+ self.assertGreaterEqual(thread.GetNumFrames(), len(backtrace))
+ src = filename.rpartition('.')[0] + '.c'
+ for i in range(len(backtrace)):
+ frame = thread.GetFrameAtIndex(i)
+ self.assertTrue(frame)
+ self.assertEqual(frame.GetFunctionName(), backtrace[i])
+ if not backtrace[i].startswith('_'):
+ self.assertEqual(frame.GetLineEntry().GetLine(),
+ line_number(src, "Frame " + backtrace[i]))
+ self.assertEqual(
+ frame.FindVariable("F").GetValueAsUnsigned(), ord(
+ backtrace[i][0]))
+
+ def do_test(self, filename, pid, region_count):
+ target = self.dbg.CreateTarget(filename)
+ process = target.LoadCore(filename + ".core")
+
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), self.THREAD_COUNT)
+ self.assertEqual(process.GetProcessID(), pid)
+
+ self.check_state(process)
+
+ self.check_stack(process, pid, filename)
+
+ self.check_memory_regions(process, region_count)
+
+ self.dbg.DeleteTarget(target)
+
+
+class NetBSD1LWPCoreTestCase(NetBSDCoreCommonTestCase):
+ THREAD_COUNT = 1
+
+ def check_stack(self, process, pid, filename):
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread)
+ self.assertEqual(thread.GetThreadID(), 1)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+ backtrace = ["bar", "foo", "main"]
+ self.check_backtrace(thread, filename, backtrace)
+
+ @skipIfLLVMTargetMissing("X86")
+ def test_amd64(self):
+ """Test single-threaded amd64 core dump."""
+ self.do_test("1lwp_SIGSEGV.amd64", pid=693, region_count=21)
+
+
+class NetBSD2LWPT2CoreTestCase(NetBSDCoreCommonTestCase):
+ THREAD_COUNT = 2
+
+ def check_stack(self, process, pid, filename):
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread)
+ self.assertEqual(thread.GetThreadID(), 2)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+ backtrace = ["bar", "foo", "lwp_main"]
+ self.check_backtrace(thread, filename, backtrace)
+
+ # thread 1 should have no signal
+ thread = process.GetThreadByID(1)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), 0)
+
+ @skipIfLLVMTargetMissing("X86")
+ def test_amd64(self):
+ """Test double-threaded amd64 core dump where thread 2 is signalled."""
+ self.do_test("2lwp_t2_SIGSEGV.amd64", pid=622, region_count=24)
+
+
+class NetBSD2LWPProcessSigCoreTestCase(NetBSDCoreCommonTestCase):
+ THREAD_COUNT = 2
+
+ def check_stack(self, process, pid, filename):
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread)
+ self.assertEqual(thread.GetThreadID(), 2)
+ self.assertEqual(thread.GetThreadID(), 2)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+ backtrace = ["_kill", "bar", "foo", "lwp_main"]
+ self.check_backtrace(thread, filename, backtrace)
+
+ # thread 1 should have the same signal
+ thread = process.GetThreadByID(1)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+
+ @skipIfLLVMTargetMissing("X86")
+ def test_amd64(self):
+ """Test double-threaded amd64 core dump where process is signalled."""
+ self.do_test("2lwp_process_SIGSEGV.amd64", pid=141, region_count=24)
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 9db6ebcafb0..c2579577a5c 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -446,16 +446,48 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data,
thread_data.gpregset = DataExtractor(data, offset, len);
}
-static void ParseNetBSDProcInfo(ThreadData &thread_data,
- const DataExtractor &data) {
+static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data,
+ uint32_t &cpi_nlwps,
+ uint32_t &cpi_signo,
+ uint32_t &cpi_siglwp,
+ uint32_t &cpi_pid) {
lldb::offset_t offset = 0;
- int version = data.GetU32(&offset);
+ uint32_t version = data.GetU32(&offset);
if (version != 1)
- return;
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Unsupported procinfo version",
+ llvm::inconvertibleErrorCode());
- offset += 4;
- thread_data.signo = data.GetU32(&offset);
+ uint32_t cpisize = data.GetU32(&offset);
+ if (cpisize != NETBSD::NT_PROCINFO_SIZE)
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Unsupported procinfo size",
+ llvm::inconvertibleErrorCode());
+
+ cpi_signo = data.GetU32(&offset); /* killing signal */
+
+ offset += NETBSD::NT_PROCINFO_CPI_SIGCODE_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_SIGPEND_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_SIGMASK_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_SIGIGNORE_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_SIGCATCH_SIZE;
+ cpi_pid = data.GetU32(&offset);
+ offset += NETBSD::NT_PROCINFO_CPI_PPID_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_PGRP_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_SID_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_RUID_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_EUID_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_SVUID_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_RGID_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_EGID_SIZE;
+ offset += NETBSD::NT_PROCINFO_CPI_SVGID_SIZE;
+ cpi_nlwps = data.GetU32(&offset); /* number of LWPs */
+
+ offset += NETBSD::NT_PROCINFO_CPI_NAME_SIZE;
+ cpi_siglwp = data.GetU32(&offset); /* LWP target of killing signal */
+
+ return llvm::Error::success();
}
static void ParseOpenBSDProcInfo(ThreadData &thread_data,
@@ -541,37 +573,133 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
return llvm::Error::success();
}
+/// 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
+///
llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
ThreadData thread_data;
- for (const auto &note : notes) {
- // NetBSD per-thread information is stored in notes named "NetBSD-CORE@nnn"
- // so match on the initial part of the string.
- if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE"))
- continue;
+ bool had_nt_regs = false;
- switch (note.info.n_type) {
- case NETBSD::NT_PROCINFO:
- ParseNetBSDProcInfo(thread_data, note.data);
- break;
- case NETBSD::NT_AUXV:
- m_auxv = note.data;
- break;
+ // 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
+ uint32_t pr_pid;
- case NETBSD::NT_AMD64_REGS:
- if (GetArchitecture().GetMachine() == llvm::Triple::x86_64)
- thread_data.gpregset = note.data;
- break;
- default:
- thread_data.notes.push_back(note);
- break;
+ for (const auto &note : notes) {
+ llvm::StringRef name = note.info.n_name;
+
+ if (name == "NetBSD-CORE") {
+ if (note.info.n_type == NETBSD::NT_PROCINFO) {
+ llvm::Error error = ParseNetBSDProcInfo(note.data, nlwps, signo,
+ siglwp, pr_pid);
+ if (error)
+ return error;
+ SetID(pr_pid);
+ } else if (note.info.n_type == NETBSD::NT_AUXV) {
+ m_auxv = note.data;
+ }
+ } else if (name.consume_front("NetBSD-CORE@")) {
+ lldb::tid_t tid;
+ if (name.getAsInteger(10, tid))
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Cannot convert LWP ID "
+ "to integer",
+ llvm::inconvertibleErrorCode());
+
+ switch (GetArchitecture().GetMachine()) {
+ case llvm::Triple::x86_64: {
+ // Assume order PT_GETREGS, PT_GETFPREGS
+ if (note.info.n_type == NETBSD::AMD64::NT_REGS) {
+ // If this is the next thread, push the previous one first.
+ if (had_nt_regs) {
+ m_thread_data.push_back(thread_data);
+ thread_data = ThreadData();
+ had_nt_regs = false;
+ }
+
+ thread_data.gpregset = note.data;
+ thread_data.tid = tid;
+ if (thread_data.gpregset.GetByteSize() == 0)
+ return llvm::make_error<llvm::StringError>(
+ "Could not find general purpose registers note in core file.",
+ llvm::inconvertibleErrorCode());
+ had_nt_regs = true;
+ } else if (note.info.n_type == NETBSD::AMD64::NT_FPREGS) {
+ if (!had_nt_regs || tid != thread_data.tid)
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Unexpected order "
+ "of NOTEs PT_GETFPREG before PT_GETREG",
+ llvm::inconvertibleErrorCode());
+ thread_data.notes.push_back(note);
+ }
+ } break;
+ default:
+ break;
+ }
}
}
- if (thread_data.gpregset.GetByteSize() == 0) {
+
+ // Push the last thread.
+ if (had_nt_regs)
+ m_thread_data.push_back(thread_data);
+
+ if (m_thread_data.empty())
return llvm::make_error<llvm::StringError>(
- "Could not find general purpose registers note in core file.",
+ "Error parsing NetBSD core(5) notes: No threads information "
+ "specified in notes",
+ llvm::inconvertibleErrorCode());
+
+ if (m_thread_data.size() != nlwps)
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Mismatch between the number "
+ "of LWPs in netbsd_elfcore_procinfo and the number of LWPs specified "
+ "by MD notes",
llvm::inconvertibleErrorCode());
+
+ // Signal targeted at the whole process.
+ if (siglwp == 0) {
+ for (auto &data : m_thread_data)
+ data.signo = signo;
}
- m_thread_data.push_back(thread_data);
+ // Signal destined for a particular LWP.
+ else {
+ bool passed = false;
+
+ for (auto &data : m_thread_data) {
+ if (data.tid == siglwp) {
+ data.signo = signo;
+ passed = true;
+ break;
+ }
+ }
+
+ if (!passed)
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Signal passed to unknown LWP",
+ llvm::inconvertibleErrorCode());
+ }
+
return llvm::Error::success();
}
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
index a2c76d1ac20..26b0fdd6143 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
@@ -27,9 +27,42 @@ enum {
}
namespace NETBSD {
-enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 };
+enum { NT_PROCINFO = 1, NT_AUXV = 2 };
+
+/* Size in bytes */
+enum { NT_PROCINFO_SIZE = 160 };
+
+/* Size in bytes */
+enum {
+ NT_PROCINFO_CPI_VERSION_SIZE = 4,
+ NT_PROCINFO_CPI_CPISIZE_SIZE = 4,
+ NT_PROCINFO_CPI_SIGNO_SIZE = 4,
+ NT_PROCINFO_CPI_SIGCODE_SIZE = 4,
+ NT_PROCINFO_CPI_SIGPEND_SIZE = 16,
+ NT_PROCINFO_CPI_SIGMASK_SIZE = 16,
+ NT_PROCINFO_CPI_SIGIGNORE_SIZE = 16,
+ NT_PROCINFO_CPI_SIGCATCH_SIZE = 16,
+ NT_PROCINFO_CPI_PID_SIZE = 4,
+ NT_PROCINFO_CPI_PPID_SIZE = 4,
+ NT_PROCINFO_CPI_PGRP_SIZE = 4,
+ NT_PROCINFO_CPI_SID_SIZE = 4,
+ NT_PROCINFO_CPI_RUID_SIZE = 4,
+ NT_PROCINFO_CPI_EUID_SIZE = 4,
+ NT_PROCINFO_CPI_SVUID_SIZE = 4,
+ NT_PROCINFO_CPI_RGID_SIZE = 4,
+ NT_PROCINFO_CPI_EGID_SIZE = 4,
+ NT_PROCINFO_CPI_SVGID_SIZE = 4,
+ NT_PROCINFO_CPI_NLWPS_SIZE = 4,
+ NT_PROCINFO_CPI_NAME_SIZE = 32,
+ NT_PROCINFO_CPI_SIGLWP_SIZE = 4,
+};
+
+namespace AMD64 {
+enum { NT_REGS = 33, NT_FPREGS = 35 };
}
+} // namespace NETBSD
+
namespace OPENBSD {
enum {
NT_PROCINFO = 10,
@@ -91,7 +124,7 @@ constexpr RegsetDesc FPR_Desc[] = {
// The result from FXSAVE is in NT_PRXFPREG for i386 core files
{llvm::Triple::Linux, llvm::Triple::x86, LINUX::NT_PRXFPREG},
{llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_FPREGSET},
- {llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::NT_AMD64_FPREGS},
+ {llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::AMD64::NT_FPREGS},
{llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS},
};
OpenPOWER on IntegriCloud