pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

edb-debugger-git: Porting to NetBSD in progress



Module Name:	pkgsrc-wip
Committed By:	Kamil Rytarowski <n54%gmx.com@localhost>
Pushed By:	kamil
Date:		Sun Feb 19 06:48:54 2017 +0100
Changeset:	3cce6f2d819f1aaeb1a3a89aad6206d8538f2b03

Modified Files:
	edb-debugger-git/distinfo
	edb-debugger-git/patches/patch-CMakeLists.txt
	edb-debugger-git/patches/patch-include_os_unix_netbsd_linker.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.ui
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.h
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.cpp
	edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.h

Log Message:
edb-debugger-git: Porting to NetBSD in progress

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=3cce6f2d819f1aaeb1a3a89aad6206d8538f2b03

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 edb-debugger-git/distinfo                          |  42 +-
 edb-debugger-git/patches/patch-CMakeLists.txt      |  11 +-
 .../patches/patch-include_os_unix_netbsd_linker.h  |   2 +-
 ...ugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp | 295 ++------
 ...plugins_DebuggerCore_unix_netbsd_DebuggerCore.h |   2 +-
 ...DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp |   2 +-
 ...s_DebuggerCore_unix_netbsd_DialogMemoryAccess.h |   2 +-
 ..._DebuggerCore_unix_netbsd_DialogMemoryAccess.ui |   2 +-
 ...gins_DebuggerCore_unix_netbsd_FeatureDetect.cpp |   2 +-
 ...lugins_DebuggerCore_unix_netbsd_FeatureDetect.h |   2 +-
 ...ins_DebuggerCore_unix_netbsd_PlatformCommon.cpp |   2 +-
 ...ugins_DebuggerCore_unix_netbsd_PlatformCommon.h |   2 +-
 ...gins_DebuggerCore_unix_netbsd_PlatformEvent.cpp | 310 +++++++--
 ...lugins_DebuggerCore_unix_netbsd_PlatformEvent.h |  55 +-
 ...ns_DebuggerCore_unix_netbsd_PlatformProcess.cpp | 752 ++++++++++++++++++++-
 ...gins_DebuggerCore_unix_netbsd_PlatformProcess.h |  60 +-
 ...ins_DebuggerCore_unix_netbsd_PlatformRegion.cpp |   2 +-
 ...ugins_DebuggerCore_unix_netbsd_PlatformRegion.h |   2 +-
 ...gins_DebuggerCore_unix_netbsd_PlatformState.cpp |   2 +-
 ...lugins_DebuggerCore_unix_netbsd_PlatformState.h |   2 +-
 ...ins_DebuggerCore_unix_netbsd_PlatformThread.cpp |   2 +-
 ...ugins_DebuggerCore_unix_netbsd_PlatformThread.h |   2 +-
 22 files changed, 1190 insertions(+), 365 deletions(-)

diffs:
diff --git a/edb-debugger-git/distinfo b/edb-debugger-git/distinfo
index 642f3d5fef..c398073feb 100644
--- a/edb-debugger-git/distinfo
+++ b/edb-debugger-git/distinfo
@@ -4,31 +4,31 @@ SHA1 (edb-debugger-0.9.21.tar.gz) = eff050b5ec53f02ebc96dbbb80f1731036e2c6f6
 RMD160 (edb-debugger-0.9.21.tar.gz) = d7821e07b607667090b1158b559053856ef077de
 SHA512 (edb-debugger-0.9.21.tar.gz) = 88a04cafb2c27a3af6bcfc48c841c795fb5bba348f64fe52957716c2c03e4cd056d045b241135c5be7fd7174d2c5a35fa5c95dc2b6aad4fb5c04f4fe36ab4f0d
 Size (edb-debugger-0.9.21.tar.gz) = 996932 bytes
-SHA1 (patch-CMakeLists.txt) = d714177643b1f8b3a37c8d6bd51953c5fb296239
+SHA1 (patch-CMakeLists.txt) = 8f64b4aa123f8d5007116ddec3e1bfcfa82f0cd8
 SHA1 (patch-include_os_unix_OSTypes.h) = 8209e8cd487b4b93532847df9166c0abecb00c48
-SHA1 (patch-include_os_unix_netbsd_linker.h) = d09a31187b4e7c0d4a20db6c32806cc8fd710538
+SHA1 (patch-include_os_unix_netbsd_linker.h) = 3331bd1eae1cd401df8b1b18ce86ae228fd0df6b
 SHA1 (patch-plugins_Analyzer_Analyzer.cpp) = 511efa03a82a96612d64fd43b9e6631e4d6aeb76
 SHA1 (patch-plugins_Assembler_DialogAssembler.cpp) = 2bd6418dc078aae0c84c6092f15619e202e43b31
 SHA1 (patch-plugins_DebuggerCore_CMakeLists.txt) = 18b3f0bd7c7c7ec4eaa6526c81b7c4299c7ee3f4
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp) = 716e48cbe859d12cd31a50040fc556e4f26fd659
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.h) = 6dc06aa1d0d05741cce3f8cffbee5d0c3c377be3
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp) = 5096c5fc7b1812545faf70194b1d02985fc1546f
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.h) = 390ce937f71b3b4c5c63dd668dc42115d2e0622c
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.ui) = fb6689928090b65e3cb6f6e69886199a447c2fa6
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.cpp) = d7a577e879e30447122985e09609cc195670157f
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.h) = 4e5a8906e904d76f4fa85a5e1919a37f57083d1e
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.cpp) = b1b07940d1a717ffd24ccd4bb028c098e5a6a8b6
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.h) = 7431b033535e272689814eb7647043aa5c9282c1
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.cpp) = 62e99fc234d072fa4ba82435216349eb76af2076
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.h) = 1781ca113c68b2e88051c7bf49bf388f61169ece
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.cpp) = 06bc435f25546ef3f27cf60ba815f7dc9d8f9706
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.h) = a4ddbd5c6f486695d4de27954ed65de4ec8bb288
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.cpp) = dc5b3caa442e041658da7aac8e59d51ccfe0c130
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.h) = 89533d8d73b58fa035832a3aaa302591ab03016e
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformState.cpp) = 347599efb4564a0bfac204108baa58032ea9415f
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformState.h) = 289f37da62a14eee3fc50c38812b202430701887
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.cpp) = e3fb003a591a6e9134b4e638307c9c202846c152
-SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.h) = bb93f03d6290c894ce543d2ea51f5023093a0fa3
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp) = 8800bc3d376aadc0ece903d8e0d5af3ab8c1f469
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.h) = c5572bd8844097e1e98b9dc39d27e93eaf764027
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp) = 07f547f9fc9155718fe4e84eb7ec6a057596ff0d
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.h) = e0c17871f6151de55415c355e1645c0c92d663f8
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.ui) = 8bacf6231f3cbc5db78ad7dbf1c191c28e94a85e
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.cpp) = a85e0e1df2ea02d3992fcb9ba3706c7a3e730442
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.h) = 58d8275733116887d66b9dbda5085b8acc2f68c3
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.cpp) = c6a0a101f2de0df887c32b04dbcbcc6b55117e88
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.h) = c696b28b1504ad63c39adcb09cf339b48578aab1
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.cpp) = 6e0e3f0d73fc90caafc260e74f6b14594fcc8565
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.h) = ae2b926f5f3a17c40f7008b0a9deaf146f3831a4
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.cpp) = 138df2d61e9f9321be716d3ec4d1f852c6a8bc6d
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.h) = afc6a7034720924a0a3d31cc92585f15310fa454
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.cpp) = 454dc33e2afd41f4a2b7e7218beb187c7585daaf
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.h) = 6d012fe9c687b920a300824c60a10cd2c2eaac5c
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformState.cpp) = 7e22120e55b5f2c206c71899eb02047790f4b4a1
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformState.h) = 9d2edb758a0de34261960e407f91305261fd5ad0
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.cpp) = d0bbc698352e9361b9ba6c26d09b220b196bf4b5
+SHA1 (patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.h) = b557502699a7b9053f09732708b5a2b2050b5d1c
 SHA1 (patch-plugins_HeapAnalyzer_DialogHeap.cpp) = a11c5aeb91168f4bf2f58fa35137fec2d5107ea4
 SHA1 (patch-plugins_ProcessProperties_DialogProcessProperties.cpp) = 31d9915e63a963fdd597dc141e3424fa8f05e81b
 SHA1 (patch-src_Debugger.cpp) = 3e0c929169c464f3697b28a5f00c1b8e877c7da3
diff --git a/edb-debugger-git/patches/patch-CMakeLists.txt b/edb-debugger-git/patches/patch-CMakeLists.txt
index 7592cec35e..f6d074be3c 100644
--- a/edb-debugger-git/patches/patch-CMakeLists.txt
+++ b/edb-debugger-git/patches/patch-CMakeLists.txt
@@ -1,7 +1,16 @@
 $NetBSD$
 
---- CMakeLists.txt.orig	2017-02-19 00:51:34.453399346 +0000
+--- CMakeLists.txt.orig	2017-02-18 21:21:09.000000000 +0000
 +++ CMakeLists.txt
+@@ -12,7 +12,7 @@ if (NOT QT_VERSION)
+ 	SET_PROPERTY(CACHE QT_VERSION PROPERTY STRINGS Qt5 Qt4) 
+ endif()
+ 
+-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "{PROJECT_SOURCE_DIR}/cmake/Modules/")
++set (CMAKE_MODULE_PATH "/tmp/pkgsrc-tmp/wip/edb-debugger-git/work/.buildlink/cmake-Modules" ${CMAKE_MODULE_PATH} "{PROJECT_SOURCE_DIR}/cmake/Modules/")
+ 
+ include("GNUInstallDirs")
+ 
 @@ -52,6 +52,10 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux"
  	include_directories("include/os/unix/linux")
  endif()
diff --git a/edb-debugger-git/patches/patch-include_os_unix_netbsd_linker.h b/edb-debugger-git/patches/patch-include_os_unix_netbsd_linker.h
index fdaf4c8ca4..5b0b0ac777 100644
--- a/edb-debugger-git/patches/patch-include_os_unix_netbsd_linker.h
+++ b/edb-debugger-git/patches/patch-include_os_unix_netbsd_linker.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- include/os/unix/netbsd/linker.h.orig	2017-02-19 00:51:04.539051677 +0000
+--- include/os/unix/netbsd/linker.h.orig	2017-02-19 02:09:05.286832064 +0000
 +++ include/os/unix/netbsd/linker.h
 @@ -0,0 +1,52 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp
index d4f570d5c4..d1441a6346 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.cpp
@@ -1,8 +1,8 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/DebuggerCore.cpp.orig	2017-02-19 00:51:04.557463589 +0000
+--- plugins/DebuggerCore/unix/netbsd/DebuggerCore.cpp.orig	2017-02-19 02:09:05.311209498 +0000
 +++ plugins/DebuggerCore/unix/netbsd/DebuggerCore.cpp
-@@ -0,0 +1,760 @@
+@@ -0,0 +1,593 @@
 +/*
 +Copyright (C) 2006 - 2015 Evan Teran
 +                          evan.teran%gmail.com@localhost
@@ -45,10 +45,14 @@ $NetBSD$
 +#include <cerrno>
 +#include <cstring>
 +
-+#include <cpuid.h>
++#include <sys/param.h>
++#include <sys/types.h>
++#include <sys/sysctl.h>
 +#include <sys/ptrace.h>
 +#include <sys/mman.h>
 +#include <sys/wait.h>
++#include <cpuid.h>
++
 +#include <unistd.h>
 +
 +namespace DebuggerCorePlugin {
@@ -236,45 +240,14 @@ $NetBSD$
 +
 +	auto e = std::make_shared<PlatformEvent>();
 +
-+	e->pid_    = pid();
-+	e->tid_    = tid;
++	e->pid_    = pid;
 +	e->status_ = status;
-+	ptrace_getsiginfo(tid, &e->siginfo_);
++	ptrace_getsiginfo(pid, &e->siginfo_);
 +
 +	return e;
 +}
 +
 +//------------------------------------------------------------------------------
-+// Name: stop_threads
-+// Desc:
-+//------------------------------------------------------------------------------
-+void DebuggerCore::stop_threads() {
-+	if(process_) {
-+		for(auto &thread: process_->threads()) {
-+			const edb::tid_t tid = thread->tid();
-+
-+			if(!waited_threads_.contains(tid)) {
-+
-+				if(auto thread_ptr = std::static_pointer_cast<PlatformThread>(thread)) {
-+
-+					thread->stop();
-+
-+					int thread_status;
-+					if(native::waitpid(tid, &thread_status, __WALL) > 0) {
-+						waited_threads_.insert(tid);
-+						thread_ptr->status_ = thread_status;
-+
-+						if(!WIFSTOPPED(thread_status) || WSTOPSIG(thread_status) != SIGSTOP) {
-+							qDebug("stop_threads(): [warning] paused thread [%d] received an event besides SIGSTOP: status=0x%x", tid,thread_status);
-+						}
-+					}
-+				}
-+			}
-+		}
-+	}
-+}
-+
-+//------------------------------------------------------------------------------
 +// Name: wait_debug_event
 +// Desc: waits for a debug event, msecs is a timeout
 +//      it will return false if an error or timeout occurs
@@ -284,9 +257,9 @@ $NetBSD$
 +	if(process_) {
 +		if(!native::wait_for_sigchld(msecs)) {
 +			int status;
-+			const edb::pid_t pid = native::waitpid(thread->tid(), &status, __WALL | WNOHANG);
-+			if(pid > 0) {
-+				return handle_event(tid, status);
++			const edb::pid_t wpid = native::waitpid(pid(), &status, __WALL | WNOHANG);
++			if(wpid > 0) {
++				return handle_event(pid(), status);
 +			}
 +		}
 +	}
@@ -294,46 +267,6 @@ $NetBSD$
 +}
 +
 +//------------------------------------------------------------------------------
-+// Name: attach_thread
-+// Desc: returns 0 if successful, errno if failed
-+//------------------------------------------------------------------------------
-+int DebuggerCore::attach_thread(edb::tid_t tid) {
-+	if(ptrace(PTRACE_ATTACH, tid, 0, 0) == 0) {
-+		// I *think* that the PTRACE_O_TRACECLONE is only valid on
-+		// stopped threads
-+		int status;
-+		const auto ret=native::waitpid(tid, &status, __WALL);
-+		if(ret > 0) {
-+
-+			auto newThread            = std::make_shared<PlatformThread>(this, process_, tid);
-+			newThread->status_        = status;
-+			newThread->signal_status_ = PlatformThread::Stopped;
-+
-+			threads_[tid] = newThread;
-+
-+			waited_threads_.insert(tid);
-+			if(ptrace_set_options(tid, PTRACE_O_TRACECLONE) == -1) {
-+				qDebug("[DebuggerCore] failed to set PTRACE_O_TRACECLONE: [%d] %s", tid, strerror(errno));
-+			}
-+
-+			if(edb::v1::config().close_behavior==Configuration::Kill ||
-+			   (edb::v1::config().close_behavior==Configuration::KillIfLaunchedDetachIfAttached &&
-+				  last_means_of_capture()==MeansOfCapture::Launch)) {
-+				if(ptrace_set_options(tid, PTRACE_O_EXITKILL) == -1) {
-+					qDebug("[DebuggerCore] failed to set PTRACE_O_EXITKILL: [%d] %s", tid, strerror(errno));
-+				}
-+			}
-+			return 0;
-+		}
-+		else if(ret==-1) {
-+			return errno;
-+		}
-+		else return -1; // unknown error
-+	}
-+	else return errno;
-+}
-+
-+//------------------------------------------------------------------------------
 +// Name: attach
 +// Desc:
 +//------------------------------------------------------------------------------
@@ -348,41 +281,13 @@ $NetBSD$
 +	// create this, so the threads created can refer to it
 +	process_ = new PlatformProcess(this, pid);
 +
-+	int lastErr=attach_thread(pid); // Fail early if we are going to
++	int lastErr=ptrace(PT_ATTACH, pid, NULL, 0); // Fail early if we are going to
 +	if(lastErr) return std::strerror(lastErr);
-+	lastErr=-2;
-+	bool attached;
-+	do {
-+		attached = false;
-+		QDir proc_directory(QString("/proc/%1/task/").arg(pid));
-+		for(const QString &s: proc_directory.entryList(QDir::NoDotAndDotDot | QDir::Dirs)) {
-+			// this can get tricky if the threads decide to spawn new threads
-+			// when we are attaching. I wish that linux had an atomic way to do this
-+			// all in one shot
-+			const edb::tid_t tid = s.toUInt();
-+			if(!threads_.contains(tid)) {
-+				const auto errnum=attach_thread(tid);
-+				if(errnum==0)
-+					attached = true;
-+				else
-+					lastErr=errnum;
-+			}
-+		}
-+	} while(attached);
-+
-+
-+	if(!threads_.empty()) {
-+		pid_            = pid;
-+		active_thread_  = pid;
-+		binary_info_    = edb::v1::get_binary_info(edb::v1::primary_code_region());
-+		detectDebuggeeBitness();
-+		return statusOK;
-+	} else {
-+		delete process_;
-+		process_ = nullptr;
-+	}
 +
-+	return std::strerror(lastErr);
++	pid_            = pid;
++	binary_info_    = edb::v1::get_binary_info(edb::v1::primary_code_region());
++	detectDebuggeeBitness();
++	return statusOK;
 +}
 +
 +//------------------------------------------------------------------------------
@@ -392,13 +297,9 @@ $NetBSD$
 +void DebuggerCore::detach() {
 +	if(process_) {
 +
-+		stop_threads();
-+
 +		clear_breakpoints();
 +
-+		for(auto thread: process_->threads()) {
-+			ptrace(PTRACE_DETACH, thread->tid(), 0, 0);
-+		}
++		ptrace(PT_DETACH, pid(), NULL, 0);
 +
 +		delete process_;
 +		process_ = nullptr;
@@ -415,9 +316,8 @@ $NetBSD$
 +	if(attached()) {
 +		clear_breakpoints();
 +
-+		::kill(pid(), SIGKILL);
++		ptrace(PT_KILL, pid(), NULL, 0);
 +
-+		// TODO: do i need to actually do this wait?
 +		native::waitpid(pid(), 0, __WALL);
 +
 +		delete process_;
@@ -428,56 +328,15 @@ $NetBSD$
 +}
 +
 +void DebuggerCore::detectDebuggeeBitness() {
-+
-+	const size_t offset=EDB_IS_64_BIT ?
-+						offsetof(UserRegsStructX86_64, cs) :
-+						offsetof(UserRegsStructX86,   xcs);
-+	errno=0;
-+	const edb::seg_reg_t cs=ptrace(PTRACE_PEEKUSER, active_thread_, offset, 0);
-+	if(!errno) {
-+		if(cs==USER_CS_32) {
-+			if(pointer_size_==sizeof(quint64)) {
-+				qDebug() << "Debuggee is now 32 bit";
-+				CapstoneEDB::init(CapstoneEDB::Architecture::ARCH_X86);
-+			}
-+			pointer_size_=sizeof(quint32);
-+			return;
-+		} else if(cs==USER_CS_64) {
-+			if(pointer_size_==sizeof(quint32)) {
-+				qDebug() << "Debuggee is now 64 bit";
-+				CapstoneEDB::init(CapstoneEDB::Architecture::ARCH_AMD64);
-+			}
-+			pointer_size_=sizeof(quint64);
-+			return;
-+		}
-+	}
-+}
-+
-+//------------------------------------------------------------------------------
-+// Name: get_state
-+// Desc:
-+//------------------------------------------------------------------------------
-+void DebuggerCore::get_state(State *state) {
-+	// TODO: assert that we are paused
-+	if(process_) {
-+		if(IThread::pointer thread = process_->current_thread()) {
-+			thread->get_state(state);
-+		}
-+	}
-+}
-+
-+//------------------------------------------------------------------------------
-+// Name: set_state
-+// Desc:
-+//------------------------------------------------------------------------------
-+void DebuggerCore::set_state(const State &state) {
-+
-+	// TODO: assert that we are paused
-+	if(process_) {
-+		if(IThread::pointer thread = process_->current_thread()) {
-+			thread->set_state(state);
-+		}
-+	}
++#if defined(__i386__)
++	qDebug() << "Debuggee is now 32 bit";
++	CapstoneEDB::init(CapstoneEDB::Architecture::ARCH_X86);
++#elif defined(__x86_64__)
++	qDebug() << "Debuggee is now 64 bit";
++	CapstoneEDB::init(CapstoneEDB::Architecture::ARCH_AMD64);
++#else
++#error portme
++#endif
 +}
 +
 +//------------------------------------------------------------------------------
@@ -492,7 +351,7 @@ $NetBSD$
 +
 +	lastMeansOfCapture=MeansOfCapture::Launch;
 +
-+	static constexpr std::size_t sharedMemSize=4096;
++	static std::size_t sharedMemSize=getpagesize();
 +	const auto sharedMem=static_cast<QChar*>(::mmap(nullptr,sharedMemSize,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0));
 +	std::memset(sharedMem,0,sharedMemSize);
 +
@@ -515,24 +374,9 @@ $NetBSD$
 +			Q_UNUSED(std_err);
 +		}
 +
-+		if(edb::v1::config().disableASLR) {
-+			const auto curPers=::personality(UINT32_MAX);
-+			// This shouldn't fail, but let's at least perror if it does anyway
-+			if(curPers==-1)
-+				perror("Failed to get current personality");
-+			else if(::personality(curPers|ADDR_NO_RANDOMIZE)==-1)
-+				perror("Failed to disable ASLR");
-+		}
-+
-+		if(edb::v1::config().disableLazyBinding && setenv("LD_BIND_NOW","1",true)==-1)
-+			perror("Failed to disable lazy binding");
-+
 +		// do the actual exec
 +		const QString error=execute_process(path, cwd, args);
-+#if defined __GNUG__ && __GNUC__ >= 5 || !defined __GNUG__ || \
-+		defined __clang__ && __clang_major__*100+__clang_minor__>=306
 +		static_assert(std::is_trivially_copyable<QChar>::value,"Can't copy string of QChar to shared memory");
-+#endif
 +		std::memcpy(sharedMem,error.constData(),std::min(sizeof(QChar)*error.size(),sharedMemSize-sizeof(QChar)/*prevent overwriting of last null*/));
 +
 +		// we should never get here!
@@ -572,40 +416,10 @@ $NetBSD$
 +											.arg(status,0,16)+(childError.isEmpty()?"":QObject::tr(".\nError returned by child:\n%1.").arg(childError));
 +			}
 +
-+			waited_threads_.insert(pid);
-+
-+			// enable following clones (threads)
-+			if(ptrace_set_options(pid, PTRACE_O_TRACECLONE) == -1) {
-+				const auto strerr=strerror(errno); // NOTE: must be called before end_debug_session, otherwise errno can change
-+				end_debug_session();
-+				return QObject::tr("[DebuggerCore] failed to set PTRACE_O_TRACECLONE: %1").arg(strerr);
-+			}
-+
-+#ifdef PTRACE_O_EXITKILL
-+			if(ptrace_set_options(pid, PTRACE_O_EXITKILL) == -1) {
-+				const auto strerr=strerror(errno); // NOTE: must be called before any other syscall, otherwise errno can change
-+				// Don't consider the error fatal: the option is only supported since Linux 3.8
-+				qDebug() << "[DebuggerCore] failed to set PTRACE_O_EXITKILL:" << strerr;
-+			}
-+#endif
-+
-+			// setup the first event data for the primary thread
-+			waited_threads_.insert(pid);
-+
 +			// create the process
 +			process_ = new PlatformProcess(this, pid);
 +
-+
-+			// the PID == primary TID
-+			auto newThread            = std::make_shared<PlatformThread>(this, process_, pid);
-+			newThread->status_        = status;
-+			newThread->signal_status_ = PlatformThread::Stopped;
-+
-+			threads_[pid]   = newThread;
-+
 +			pid_            = pid;
-+			active_thread_   = pid;
-+			binary_info_    = edb::v1::get_binary_info(edb::v1::primary_code_region());
 +
 +			detectDebuggeeBitness();
 +
@@ -630,10 +444,7 @@ $NetBSD$
 +//------------------------------------------------------------------------------
 +void DebuggerCore::reset() {
 +	threads_.clear();
-+	waited_threads_.clear();
 +	pid_           = 0;
-+	active_thread_ = 0;
-+	binary_info_   = nullptr;
 +}
 +
 +//------------------------------------------------------------------------------
@@ -651,22 +462,44 @@ $NetBSD$
 +QMap<edb::pid_t, IProcess::pointer> DebuggerCore::enumerate_processes() const {
 +	QMap<edb::pid_t, IProcess::pointer> ret;
 +
-+	QDir proc_directory("/proc/");
-+	QFileInfoList entries = proc_directory.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
-+
-+	for(const QFileInfo &info: entries) {
-+		const QString filename = info.fileName();
-+		if(is_numeric(filename)) {
-+			const edb::pid_t pid = filename.toULong();
++	int err;
++	::kinfo_proc2 *result;
++	int mib[6];
++	size_t length = 0;
++
++	mib[0] = CTL_KERN;
++	mib[1] = KERN_PROC2;
++	mib[2] = KERN_PROC_ALL;
++	mib[3] = 0;
++	mib[4] = sizeof(struct kinfo_proc2);
++retry:
++	mib[5] = 0;
++
++	err = sysctl(mib, __arraycount(mib), NULL, &length, NULL, 0);
++	if (err == -1)
++		return ret;
++
++	result = (::kinfo_proc2 *)malloc(length);
++	if (result == NULL)
++		return ret;
++
++	mib[5] = length / sizeof(struct kinfo_proc2);
++        err = sysctl(mib, __arraycount(mib), result, &length, NULL, 0);
++	if (err == -1) {
++		if (errno == ENOMEM)
++			goto retry;
++
++		free(result);
++		return ret;
++	}
 +
-+			// NOTE(eteran): the const_cast is reasonable here.
-+			// While we don't want THIS function to mutate the DebuggerCore object
-+			// we do want the associated PlatformProcess to be able to trigger
-+			// non-const operations in the future, at least hypothetically.
-+			ret.insert(pid, std::make_shared<PlatformProcess>(const_cast<DebuggerCore*>(this), pid));
-+		}
++	for (size_t i = 0; i < length / sizeof(kinfo_proc2); i++) {
++		const edb::pid_t pid = result[i].p_pid;
++		ret.insert(pid, std::make_shared<PlatformProcess>(const_cast<DebuggerCore*>(this), pid));
 +	}
 +
++	free(result);
++
 +	return ret;
 +}
 +
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.h
index eefd58e805..a5621ad443 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DebuggerCore.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/DebuggerCore.h.orig	2017-02-19 00:51:04.563698490 +0000
+--- plugins/DebuggerCore/unix/netbsd/DebuggerCore.h.orig	2017-02-19 02:09:05.317531286 +0000
 +++ plugins/DebuggerCore/unix/netbsd/DebuggerCore.h
 @@ -0,0 +1,119 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp
index 2ab9500e88..276b07ad42 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.cpp
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.cpp.orig	2017-02-19 00:51:04.569868074 +0000
+--- plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.cpp.orig	2017-02-19 02:09:05.323748418 +0000
 +++ plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.cpp
 @@ -0,0 +1,38 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.h
index 4d90a800ca..1f221ff206 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.h.orig	2017-02-19 00:51:04.575933251 +0000
+--- plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.h.orig	2017-02-19 02:09:05.329914385 +0000
 +++ plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.h
 @@ -0,0 +1,44 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.ui b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.ui
index 987b9770e3..b7f292b8c0 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.ui
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_DialogMemoryAccess.ui
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.ui.orig	2017-02-19 01:11:03.492521515 +0000
+--- plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.ui.orig	2017-02-19 02:09:05.336211780 +0000
 +++ plugins/DebuggerCore/unix/netbsd/DialogMemoryAccess.ui
 @@ -0,0 +1,90 @@
 +<?xml version="1.0" encoding="UTF-8"?>
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.cpp
index bafcd94ef6..8e71f3383d 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.cpp
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/FeatureDetect.cpp.orig	2017-02-19 00:51:04.582071788 +0000
+--- plugins/DebuggerCore/unix/netbsd/FeatureDetect.cpp.orig	2017-02-19 02:09:05.342456556 +0000
 +++ plugins/DebuggerCore/unix/netbsd/FeatureDetect.cpp
 @@ -0,0 +1,174 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.h
index 35fdd5f1f8..0cf571360e 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_FeatureDetect.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/FeatureDetect.h.orig	2017-02-19 00:51:04.588144633 +0000
+--- plugins/DebuggerCore/unix/netbsd/FeatureDetect.h.orig	2017-02-19 02:09:05.348620261 +0000
 +++ plugins/DebuggerCore/unix/netbsd/FeatureDetect.h
 @@ -0,0 +1,30 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.cpp
index a4a4cc5dcf..1b57e44cbe 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.cpp
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformCommon.cpp.orig	2017-02-19 00:51:04.594319579 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformCommon.cpp.orig	2017-02-19 02:09:05.354823169 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformCommon.cpp
 @@ -0,0 +1,189 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.h
index c4a4598b28..be830778a4 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformCommon.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformCommon.h.orig	2017-02-19 00:51:04.600408397 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformCommon.h.orig	2017-02-19 02:09:05.360983490 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformCommon.h
 @@ -0,0 +1,97 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.cpp
index 1b8ab0c420..a2d6a8750a 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.cpp
@@ -1,8 +1,8 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformEvent.cpp.orig	2017-02-19 00:51:04.606553247 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformEvent.cpp.orig	2017-02-19 02:09:05.367273282 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformEvent.cpp
-@@ -0,0 +1,258 @@
+@@ -0,0 +1,428 @@
 +/*
 +Copyright (C) 2006 - 2015 Evan Teran
 +                          evan.teran%gmail.com@localhost
@@ -23,118 +23,288 @@ $NetBSD$
 +
 +#include "PlatformEvent.h"
 +#include "edb.h"
-+#include <cstdio>
-+#include <cstring>
-+#include <fcntl.h>
-+#include <kvm.h>
-+#include <sys/exec.h>
-+#include <sys/mman.h>
-+#include <sys/param.h>
-+#include <sys/proc.h>
-+#include <sys/ptrace.h>
-+#include <sys/signalvar.h>
-+#include <sys/sysctl.h>
-+#include <sys/types.h>
-+#include <sys/user.h>
-+#include <sys/wait.h>
-+#include <unistd.h>
-+#include <signal.h> // for the SIG* definitions
-+
-+namespace DebuggerCore {
++
++namespace DebuggerCorePlugin {
 +
 +//------------------------------------------------------------------------------
 +// Name:
 +//------------------------------------------------------------------------------
-+PlatformEvent::PlatformEvent() : status(0), pid(-1), tid(-1), fault_address_(0), fault_code_(0) {
++PlatformEvent::PlatformEvent() : pid_(0), tid_(0), status_(0) {
++	std::memset(&siginfo_, 0, sizeof(siginfo_t));
 +}
 +
 +//------------------------------------------------------------------------------
 +// Name:
 +//------------------------------------------------------------------------------
-+PlatformEvent *PlatformEvent::clone() const {
++IDebugEvent *PlatformEvent::clone() const {
 +	return new PlatformEvent(*this);
 +}
 +
 +//------------------------------------------------------------------------------
 +// Name:
 +//------------------------------------------------------------------------------
++IDebugEvent::Message PlatformEvent::createUnexpectedSignalMessage(const QString &name, int number) {
++	return Message(
++		tr("Unexpected Signal Encountered"),
++		tr("<p>The debugged application encountered a %1 (%2).</p>").arg(name).arg(number),
++		tr("% received").arg(name)
++		);
++}
++
++//------------------------------------------------------------------------------
++// Name:
++//------------------------------------------------------------------------------
 +IDebugEvent::Message PlatformEvent::error_description() const {
 +	Q_ASSERT(is_error());
 +
-+	auto fault_address = reinterpret_cast<edb::address_t>(fault_address_);
++	auto fault_address = edb::address_t::fromZeroExtended(siginfo_.si_addr);
 +
++	std::size_t debuggeePtrSize=edb::v1::pointer_size();
++	bool fullAddressKnown=debuggeePtrSize<=sizeof(void*);
++	const auto addressString=fault_address.toPointerString(fullAddressKnown);
++
++	Message message;
 +	switch(code()) {
 +	case SIGSEGV:
-+		return Message(
-+			tr("Illegal Access Fault"),
-+			tr(
-+				"<p>The debugged application encountered a segmentation fault.<br />The address <strong>0x%1</strong> could not be accessed.</p>"
-+				"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>").arg(edb::v1::format_pointer(fault_address))
-+			);
++		switch(siginfo_.si_code) {
++		case SEGV_MAPERR:
++			message=Message(
++				tr("Illegal Access Fault"),
++				tr("<p>The debugged application encountered a segmentation fault.<br />The address <strong>%1</strong> does not appear to be mapped.</p>").arg(addressString),
++				tr("SIGSEGV: SEGV_MAPERR: Accessed address %1 not mapped").arg(addressString)
++				);
++			break;
++		case SEGV_ACCERR:
++			message=Message(
++				tr("Illegal Access Fault"),
++				tr("<p>The debugged application encountered a segmentation fault.<br />The address <strong>%1</strong> could not be accessed.</p>").arg(addressString),
++				tr("SIGSEGV: SEGV_ACCERR: Access to address %1 not permitted").arg(addressString)
++				);
++			break;
++		default:
++			message=Message(
++				tr("Illegal Access Fault"),
++				tr("<p>The debugged application encountered a segmentation fault.<br />The instruction could not be executed.</p>"),
++				tr("SIGSEGV: Segmentation fault")
++				);
++			break;
++		}
++		break;
++
 +	case SIGILL:
-+		return Message(
++		message=Message(
 +			tr("Illegal Instruction Fault"),
-+			tr(
-+				"<p>The debugged application attempted to execute an illegal instruction.</p>"
-+				"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>")
++			tr("<p>The debugged application attempted to execute an illegal instruction.</p>"),
++			tr("SIGILL: Illegal instruction")
 +			);
++		break;
 +	case SIGFPE:
-+		switch(fault_code_) {
++		switch(siginfo_.si_code) {
 +		case FPE_INTDIV:
-+		return Message(
-+			tr("Divide By Zero"),
-+			tr(
-+				"<p>The debugged application tried to divide an integer value by an integer divisor of zero.</p>"
-+				"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>")
-+			);
++			message=Message(
++				tr("Divide By Zero"),
++				tr("<p>The debugged application tried to divide an integer value by an integer divisor of zero or encountered integer division overflow.</p>"),
++				tr("SIGFPE: FPE_INTDIV: Integer division by zero or division overflow")
++				);
++			break;
++		case FPE_FLTDIV:
++			message=Message(
++				tr("Divide By Zero"),
++				tr("<p>The debugged application tried to divide an floating-point value by a floating-point divisor of zero.</p>"),
++				tr("SIGFPE: FPE_FLTDIV: Floating-point division by zero")
++				);
++			break;
++		case FPE_FLTOVF:
++			message=Message(
++				tr("Numeric Overflow"),
++				tr("<p>The debugged application encountered a numeric overflow while performing a floating-point computation.</p>"),
++				tr("SIGFPE: FPE_FLTOVF: Numeric overflow exception")
++				);
++			break;
++		case FPE_FLTUND:
++			message=Message(
++				tr("Numeric Underflow"),
++				tr("<p>The debugged application encountered a numeric underflow while performing a floating-point computation.</p>"),
++				tr("SIGFPE: FPE_FLTUND: Numeric underflow exception")
++				);
++			break;
++		case FPE_FLTRES:
++			message=Message(
++				tr("Inexact Result"),
++				tr("<p>The debugged application encountered an inexact result of a floating-point computation it was performing.</p>"),
++				tr("SIGFPE: FPE_FLTRES: Inexact result exception")
++				);
++			break;
++		case FPE_FLTINV:
++			message=Message(
++				tr("Invalid Operation"),
++				tr("<p>The debugged application attempted to perform an invalid floating-point operation.</p>"),
++				tr("SIGFPE: FPE_FLTINV: Invalid floating-point operation")
++				);
++			break;
 +		default:
-+			return Message(
++			message=Message(
 +				tr("Floating Point Exception"),
-+				tr(
-+					"<p>The debugged application encountered a floating-point exception.</p>"
-+					"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>")
++				tr("<p>The debugged application encountered a floating-point exception.</p>"),
++				tr("SIGFPE: Floating-point exception")
 +				);
++			break;
 +		}
++		break;
 +
 +	case SIGABRT:
-+		return Message(
++		message=Message(
 +			tr("Application Aborted"),
-+			tr(
-+				"<p>The debugged application has aborted.</p>"
-+				"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>")
++			tr("<p>The debugged application has aborted.</p>"),
++			tr("SIGABRT: Application aborted")
 +			);
++		break;
 +	case SIGBUS:
-+		return Message(
++		message=Message(
 +			tr("Bus Error"),
-+			tr(
-+				"<p>The debugged application tried to read or write data that is misaligned.</p>"
-+				"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>")
++			tr("<p>The debugged application received a bus error. Typically, this means that it tried to read or write data that is misaligned.</p>"),
++			tr("SIGBUS: Bus error")
 +			);
++		break;
 +#ifdef SIGSTKFLT
 +	case SIGSTKFLT:
-+		return Message(
++		message=Message(
 +			tr("Stack Fault"),
-+			tr(
-+				"<p>The debugged application encountered a stack fault.</p>"
-+				"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>")
++			tr("<p>The debugged application encountered a stack fault.</p>"),
++			tr("SIGSTKFLT: Stack fault")
 +			);
++		break;
 +#endif
 +	case SIGPIPE:
-+		return Message(
++		message=Message(
 +			tr("Broken Pipe Fault"),
-+			tr(
-+				"<p>The debugged application encountered a broken pipe fault.</p>"
-+				"<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>")
++			tr("<p>The debugged application encountered a broken pipe fault.</p>"),
++			tr("SIGPIPE: Pipe broken")
 +			);
++		break;
++#ifdef SIGHUP
++	case SIGHUP:
++		message=createUnexpectedSignalMessage("SIGHUP", SIGHUP);
++		break;
++#endif
++#ifdef SIGINT
++	case SIGINT:
++		message=createUnexpectedSignalMessage("SIGINT", SIGINT);
++		break;
++#endif
++#ifdef SIGQUIT
++	case SIGQUIT:
++		message=createUnexpectedSignalMessage("SIGQUIT", SIGQUIT);
++		break;
++#endif
++#ifdef SIGTRAP
++	case SIGTRAP:
++		message=createUnexpectedSignalMessage("SIGTRAP", SIGTRAP);
++		break;
++#endif
++#ifdef SIGKILL
++	case SIGKILL:
++		message=createUnexpectedSignalMessage("SIGKILL", SIGKILL);
++		break;
++#endif
++#ifdef SIGUSR1
++	case SIGUSR1:
++		message=createUnexpectedSignalMessage("SIGUSR1", SIGUSR1);
++		break;
++#endif
++#ifdef SIGUSR2
++	case SIGUSR2:
++		message=createUnexpectedSignalMessage("SIGUSR2", SIGUSR2);
++		break;
++#endif
++#ifdef SIGALRM
++	case SIGALRM:
++		message=createUnexpectedSignalMessage("SIGALRM", SIGALRM);
++		break;
++#endif
++#ifdef SIGTERM
++	case SIGTERM:
++		message=createUnexpectedSignalMessage("SIGTERM", SIGTERM);
++		break;
++#endif
++#ifdef SIGCHLD
++	case SIGCHLD:
++		message=createUnexpectedSignalMessage("SIGCHLD", SIGCHLD);
++		break;
++#endif
++#ifdef SIGCONT
++	case SIGCONT:
++		message=createUnexpectedSignalMessage("SIGCONT", SIGCONT);
++		break;
++#endif
++#ifdef SIGSTOP
++	case SIGSTOP:
++		message=createUnexpectedSignalMessage("SIGSTOP", SIGSTOP);
++		break;
++#endif
++#ifdef SIGTSTP
++	case SIGTSTP:
++		message=createUnexpectedSignalMessage("SIGTSTP", SIGTSTP);
++		break;
++#endif
++#ifdef SIGTTIN
++	case SIGTTIN:
++		message=createUnexpectedSignalMessage("SIGTTIN", SIGTTIN);
++		break;
++#endif
++#ifdef SIGTTOU
++	case SIGTTOU:
++		message=createUnexpectedSignalMessage("SIGTTOU", SIGTTOU);
++		break;
++#endif
++#ifdef SIGURG
++	case SIGURG:
++		message=createUnexpectedSignalMessage("SIGURG", SIGURG);
++		break;
++#endif
++#ifdef SIGXCPU
++	case SIGXCPU:
++		message=createUnexpectedSignalMessage("SIGXCPU", SIGXCPU);
++		break;
++#endif
++#ifdef SIGXFSZ
++	case SIGXFSZ:
++		message=createUnexpectedSignalMessage("SIGXFSZ", SIGXFSZ);
++		break;
++#endif
++#ifdef SIGVTALRM
++	case SIGVTALRM:
++		message=createUnexpectedSignalMessage("SIGVTALRM", SIGVTALRM);
++		break;
++#endif
++#ifdef SIGPROF
++	case SIGPROF:
++		message=createUnexpectedSignalMessage("SIGPROF", SIGPROF);
++		break;
++#endif
++#ifdef SIGWINCH
++	case SIGWINCH:
++		message=createUnexpectedSignalMessage("SIGWINCH", SIGWINCH);
++		break;
++#endif
++#ifdef SIGIO
++	case SIGIO:
++		message=createUnexpectedSignalMessage("SIGIO", SIGIO);
++		break;
++#endif
 +	default:
 +		return Message();
 +	}
++
++	message.message+="<p>If you would like to pass this exception to the application press Shift+[F7/F8/F9]</p>";
++	message.statusMessage+=". Shift+Run/Step to pass signal to the program";
++	return message;
 +}
 +
 +//------------------------------------------------------------------------------
 +// Name:
 +//------------------------------------------------------------------------------
-+IDebugEvent::REASON PlatformEvent:: reason() const {
++IDebugEvent::REASON PlatformEvent::reason() const {
 +	// this basically converts our value into a 'switchable' value for convenience
 +
 +	if(stopped()) {
@@ -152,7 +322,7 @@ $NetBSD$
 +// Name:
 +//------------------------------------------------------------------------------
 +IDebugEvent::TRAP_REASON PlatformEvent::trap_reason() const {
-+	switch(fault_code_) {
++	switch(siginfo_.si_code) {
 +	case TRAP_TRACE: return TRAP_STEPPING;
 +	default:         return TRAP_BREAKPOINT;
 +	}
@@ -162,7 +332,7 @@ $NetBSD$
 +// Name:
 +//------------------------------------------------------------------------------
 +bool PlatformEvent::exited() const {
-+	return WIFEXITED(status) != 0;
++	return WIFEXITED(status_) != 0;
 +}
 +
 +//------------------------------------------------------------------------------
@@ -217,28 +387,28 @@ $NetBSD$
 +// Name:
 +//------------------------------------------------------------------------------
 +bool PlatformEvent::terminated() const {
-+	return WIFSIGNALED(status) != 0;
++	return WIFSIGNALED(status_) != 0;
 +}
 +
 +//------------------------------------------------------------------------------
 +// Name:
 +//------------------------------------------------------------------------------
 +bool PlatformEvent::stopped() const {
-+	return WIFSTOPPED(status) != 0;
++	return WIFSTOPPED(status_) != 0;
 +}
 +
 +//------------------------------------------------------------------------------
 +// Name:
 +//------------------------------------------------------------------------------
 +edb::pid_t PlatformEvent::process() const {
-+	return pid;
++	return pid_;
 +}
 +
 +//------------------------------------------------------------------------------
 +// Name:
 +//------------------------------------------------------------------------------
 +edb::tid_t PlatformEvent::thread() const {
-+	return tid;
++	return tid_;
 +}
 +
 +//------------------------------------------------------------------------------
@@ -246,15 +416,15 @@ $NetBSD$
 +//------------------------------------------------------------------------------
 +int PlatformEvent::code() const {
 +	if(stopped()) {
-+		return WSTOPSIG(status);
++		return WSTOPSIG(status_);
 +	}
 +
 +	if(terminated()) {
-+		return WTERMSIG(status);
++		return WTERMSIG(status_);
 +	}
 +
 +	if(exited()) {
-+		return WEXITSTATUS(status);
++		return WEXITSTATUS(status_);
 +	}
 +
 +	return 0;
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.h
index 33ce6485b9..8b8b82b929 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformEvent.h
@@ -1,8 +1,8 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformEvent.h.orig	2017-02-19 00:51:04.612693828 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformEvent.h.orig	2017-02-19 02:09:05.373398707 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformEvent.h
-@@ -0,0 +1,61 @@
+@@ -0,0 +1,70 @@
 +/*
 +Copyright (C) 2006 - 2015 Evan Teran
 +                          evan.teran%gmail.com@localhost
@@ -24,41 +24,50 @@ $NetBSD$
 +#ifndef PLATFORM_EVENT_20121005_H_
 +#define PLATFORM_EVENT_20121005_H_
 +
-+#include <QCoreApplication>
 +#include "IDebugEvent.h"
 +
-+namespace DebuggerCore {
++#include <QCoreApplication>
++#include <signal.h> // for the SIG* definitions
++
++namespace DebuggerCorePlugin {
 +
-+class PlatformEvent : IDebugEvent {
++class PlatformEvent : public IDebugEvent {
 +	Q_DECLARE_TR_FUNCTIONS(PlatformEvent)
 +	friend class DebuggerCore;
 +
 +public:
 +	PlatformEvent();
 +
++private:
++	PlatformEvent(const PlatformEvent &) = default;
++	PlatformEvent& operator=(const PlatformEvent &) = default;
++
 +public:
-+	virtual PlatformEvent *clone() const;
++	virtual IDebugEvent *clone() const override;
 +
 +public:
-+	virtual Message error_description() const;
-+	virtual REASON reason() const;
-+	virtual TRAP_REASON trap_reason() const;
-+	virtual bool exited() const;
-+	virtual bool is_error() const;
-+	virtual bool is_kill() const;
-+	virtual bool is_stop() const;
-+	virtual bool is_trap() const;
-+	virtual bool terminated() const;
-+	virtual bool stopped() const;
-+	virtual edb::pid_t process() const;
-+	virtual edb::tid_t thread() const;
-+	virtual int code() const;
++	virtual Message error_description() const override;
++	virtual REASON reason() const override;
++	virtual TRAP_REASON trap_reason() const override;
++	virtual bool exited() const override;
++	virtual bool is_error() const override;
++	virtual bool is_kill() const override;
++	virtual bool is_stop() const override;
++	virtual bool is_trap() const override;
++	virtual bool stopped() const override;
++	virtual bool terminated() const override;
++	virtual edb::pid_t process() const override;
++	virtual edb::tid_t thread() const override;
++	virtual int code() const override;
++
++private:
++	static IDebugEvent::Message createUnexpectedSignalMessage(const QString &name, int number);
 +
 +private:
-+	ptrace_siginfo_t siginfo_;
-+	edb::pid_t       pid_;
-+	edb::tid_t       tid_;
-+	int              status_;
++	ptrace_siginfo_t  siginfo_;
++	edb::pid_t        pid_;
++	edb::tid_t        tid_;
++	int               status_;
 +};
 +
 +}
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.cpp
index 78c67133b9..4ab08b24d1 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.cpp
@@ -1,8 +1,8 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformProcess.cpp.orig	2017-02-19 00:51:04.618831385 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformProcess.cpp.orig	2017-02-19 02:09:05.379589420 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformProcess.cpp
-@@ -0,0 +1,19 @@
+@@ -0,0 +1,767 @@
 +/*
 +Copyright (C) 2015 - 2015 Evan Teran
 +                          evan.teran%gmail.com@localhost
@@ -21,4 +21,752 @@ $NetBSD$
 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
++#define _LARGEFILE64_SOURCE
 +#include "PlatformProcess.h"
++#include "DebuggerCore.h"
++#include "PlatformCommon.h"
++#include "PlatformRegion.h"
++#include "MemoryRegions.h"
++#include "edb.h"
++#include "linker.h"
++
++#include <QByteArray>
++#include <QFile>
++#include <QFileInfo>
++#include <QTextStream>
++#include <QDateTime>
++
++#include <boost/functional/hash.hpp>
++#include <fstream>
++
++#include <sys/mman.h>
++#include <sys/ptrace.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <pwd.h>
++#include <elf.h>
++
++namespace DebuggerCorePlugin {
++namespace {
++
++// Used as size of ptrace word
++#define EDB_WORDSIZE sizeof(long)
++
++void set_ok(bool &ok, long value) {
++	ok = (value != -1) || (errno == 0);
++}
++
++QStringList split_max(const QString &str, const int &maxparts) {
++	int prev_idx = 0, idx = 0;
++	QStringList items;
++	for (const QChar &c : str) {
++		if (c == ' ') {
++			if (prev_idx < idx) {
++				if (items.size() < maxparts - 1)
++					items << str.mid(prev_idx, idx - prev_idx);
++				else {
++					items << str.right(str.size() - prev_idx);
++					break;
++				}
++			}
++			prev_idx = idx + 1;
++		}
++		++idx;
++	}
++	if (prev_idx < str.size() && items.size() < maxparts) {
++		items << str.right(str.size() - prev_idx);
++	}
++	return items;
++}
++
++//------------------------------------------------------------------------------
++// Name: process_map_line
++// Desc: parses the data from a line of a memory map file
++//------------------------------------------------------------------------------
++IRegion::pointer process_map_line(const QString &line) {
++
++	edb::address_t start;
++	edb::address_t end;
++	edb::address_t base;
++	IRegion::permissions_t permissions;
++	QString name;
++
++	const QStringList items = split_max(line, 6);
++	if(items.size() >= 3) {
++		bool ok;
++		const QStringList bounds = items[0].split("-");
++		if(bounds.size() == 2) {
++			start = edb::address_t::fromHexString(bounds[0],&ok);
++			if(ok) {
++				end = edb::address_t::fromHexString(bounds[1],&ok);
++				if(ok) {
++					base = edb::address_t::fromHexString(items[2],&ok);
++					if(ok) {
++						const QString perms = items[1];
++						permissions = 0;
++						if(perms[0] == 'r') permissions |= PROT_READ;
++						if(perms[1] == 'w') permissions |= PROT_WRITE;
++						if(perms[2] == 'x') permissions |= PROT_EXEC;
++
++						if(items.size() >= 6) {
++							name = items[5];
++						}
++
++						return std::make_shared<PlatformRegion>(start, end, base, name, permissions);
++					}
++				}
++			}
++		}
++	}
++	return nullptr;;
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++template<class Addr>
++QList<Module> loaded_modules_(const IProcess* process, const std::unique_ptr<IBinary> &binary_info_) {
++	QList<Module> ret;
++
++	if(binary_info_) {
++		edb::linux::r_debug<Addr> dynamic_info;
++		if(const edb::address_t debug_pointer = binary_info_->debug_pointer()) {
++			if(process) {
++				if(process->read_bytes(debug_pointer, &dynamic_info, sizeof(dynamic_info))) {
++					if(dynamic_info.r_map) {
++
++						auto link_address = edb::address_t::fromZeroExtended(dynamic_info.r_map);
++
++						while(link_address) {
++
++							edb::linux::link_map<Addr> map;
++							if(process->read_bytes(link_address, &map, sizeof(map))) {
++								char path[PATH_MAX];
++								if(!process->read_bytes(edb::address_t::fromZeroExtended(map.l_name), &path, sizeof(path))) {
++									path[0] = '\0';
++								}
++
++								if(map.l_addr) {
++									Module module;
++									module.name         = path;
++									module.base_address = map.l_addr;
++									ret.push_back(module);
++								}
++
++								link_address = edb::address_t::fromZeroExtended(map.l_next);
++							} else {
++								break;
++							}
++						}
++					}
++				}
++			}
++		}
++	}
++
++	// fallback
++	if(ret.isEmpty()) {
++		const QList<IRegion::pointer> r = edb::v1::memory_regions().regions();
++		QSet<QString> found_modules;
++
++		for(const IRegion::pointer &region: r) {
++
++			// we assume that modules will be listed by absolute path
++			if(region->name().startsWith("/")) {
++				if(!found_modules.contains(region->name())) {
++					Module module;
++					module.name         = region->name();
++					module.base_address = region->start();
++					found_modules.insert(region->name());
++					ret.push_back(module);
++				}
++			}
++		}
++	}
++
++	return ret;
++}
++
++}
++
++//------------------------------------------------------------------------------
++// Name: PlatformProcess
++// Desc:
++//------------------------------------------------------------------------------
++PlatformProcess::PlatformProcess(DebuggerCore *core, edb::pid_t pid) : core_(core), pid_(pid), ro_mem_file_(0), rw_mem_file_(0) {
++	if (!core_->proc_mem_read_broken_) {
++		QFile* memory_file = new QFile(QString("/proc/%1/mem").arg(pid_));
++		auto flags = QIODevice::ReadOnly | QIODevice::Unbuffered;
++		if (!core_->proc_mem_write_broken_) {
++			flags |= QIODevice::WriteOnly;
++		}
++		if (memory_file->open(flags)) {
++			ro_mem_file_ = memory_file;
++			if (!core_->proc_mem_write_broken_) {
++				rw_mem_file_ = memory_file;
++			}
++		} else {
++			delete memory_file;
++		}
++	}
++}
++
++//------------------------------------------------------------------------------
++// Name: ~PlatformProcess
++// Desc:
++//------------------------------------------------------------------------------
++PlatformProcess::~PlatformProcess() {
++	if (ro_mem_file_) {
++		delete ro_mem_file_;
++	}
++}
++
++//------------------------------------------------------------------------------
++// Name: seek_addr
++// Desc: seeks memory file to given address, taking possible negativity of the
++// address into account
++//------------------------------------------------------------------------------
++void seek_addr(QFile& file, edb::address_t address) {
++	if(address <= UINT64_MAX/2) {
++		file.seek(address);
++	} else {
++		const int fd=file.handle();
++		// Seek in two parts to avoid specifying negative offset: off64_t is a signed type
++		const off64_t halfAddressTruncated=address>>1;
++		lseek64(fd,halfAddressTruncated,SEEK_SET);
++		const off64_t secondHalfAddress=address-halfAddressTruncated;
++		lseek64(fd,secondHalfAddress,SEEK_CUR);
++	}
++}
++
++
++//------------------------------------------------------------------------------
++// Name: read_bytes
++// Desc: reads <len> bytes into <buf> starting at <address>
++// Note: returns the number of bytes read <N>
++// Note: if the read is short, only the first <N> bytes are defined
++//------------------------------------------------------------------------------
++std::size_t PlatformProcess::read_bytes(edb::address_t address, void* buf, std::size_t len) const {
++	quint64 read = 0;
++
++	Q_ASSERT(buf);
++	Q_ASSERT(core_->process_ == this);
++
++	auto ptr = reinterpret_cast<char *>(buf);
++
++	if(len != 0) {
++
++		// small reads take the fast path
++		if(len == 1) {
++
++			auto it = core_->breakpoints_.find(address);
++			if(it != core_->breakpoints_.end()) {
++				*ptr = (*it)->original_byte();
++				return 1;
++			}
++
++			if(ro_mem_file_) {
++				seek_addr(*ro_mem_file_, address);
++				read = ro_mem_file_->read(ptr, 1);
++				if (read == 1) {
++					return 1;
++				}
++				return 0;
++			} else {
++				bool ok;
++				quint8 x = read_byte_via_ptrace(address, &ok);
++				if(ok) {
++					*ptr = x;
++					return 1;
++				}
++				return 0;
++			}
++		}
++
++		if(ro_mem_file_) {
++			seek_addr(*ro_mem_file_, address);
++			read = ro_mem_file_->read(ptr, len);
++			if(read == 0 || read == quint64(-1)) {
++				return 0;
++			}
++		} else {
++			for(std::size_t index = 0; index < len; ++index) {
++
++				// read a byte, if we failed, we are done
++				bool ok;
++				const quint8 x = read_byte_via_ptrace(address + index, &ok);
++				if(!ok) {
++					break;
++				}
++
++				// store it
++				reinterpret_cast<char*>(buf)[index] = x;
++
++				++read;
++			}
++		}
++
++		// replace any breakpoints
++		for(const IBreakpoint::pointer &bp: core_->breakpoints_) {
++			if(bp->address() >= address && bp->address() < (address + read)) {
++				// show the original bytes in the buffer..
++				ptr[bp->address() - address] = bp->original_byte();
++			}
++		}
++	}
++
++	return read;
++}
++
++//------------------------------------------------------------------------------
++// Name: write_bytes
++// Desc: writes <len> bytes from <buf> starting at <address>
++//------------------------------------------------------------------------------
++std::size_t PlatformProcess::write_bytes(edb::address_t address, const void *buf, std::size_t len) {
++	quint64 written = 0;
++
++	Q_ASSERT(buf);
++	Q_ASSERT(core_->process_ == this);
++
++	if(len != 0) {
++		if(rw_mem_file_) {
++			seek_addr(*rw_mem_file_,address);
++			written = rw_mem_file_->write(reinterpret_cast<const char *>(buf), len);
++			if(written == 0 || written == quint64(-1)) {
++				return 0;
++			}
++		}
++		else {
++			// TODO write whole words at a time using ptrace_poke.
++			for(std::size_t byteIndex=0;byteIndex<len;++byteIndex) {
++				bool ok=false;
++				write_byte_via_ptrace(address+byteIndex, *(reinterpret_cast<const char*>(buf)+byteIndex), &ok);
++				if(!ok) return written;
++				++written;
++			}
++		}
++	}
++
++	return written;
++}
++
++//------------------------------------------------------------------------------
++// Name: read_pages
++// Desc: reads <count> pages from the process starting at <address>
++// Note: buf's size must be >= count * core_->page_size()
++// Note: address should be page aligned.
++//------------------------------------------------------------------------------
++std::size_t PlatformProcess::read_pages(edb::address_t address, void *buf, std::size_t count) const {
++	Q_ASSERT(buf);
++	Q_ASSERT(core_->process_ == this);
++	return read_bytes(address, buf, count * core_->page_size()) / core_->page_size();
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QDateTime PlatformProcess::start_time() const {
++	QFileInfo info(QString("/proc/%1/stat").arg(pid_));
++	return info.created();
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QList<QByteArray> PlatformProcess::arguments() const {
++	QList<QByteArray> ret;
++
++	if(pid_ != 0) {
++		const QString command_line_file(QString("/proc/%1/cmdline").arg(pid_));
++		QFile file(command_line_file);
++
++		if(file.open(QIODevice::ReadOnly | QIODevice::Text)) {
++			QTextStream in(&file);
++
++			QByteArray s;
++			QChar ch;
++
++			while(in.status() == QTextStream::Ok) {
++				in >> ch;
++				if(ch == '\0') {
++					if(!s.isEmpty()) {
++						ret << s;
++					}
++					s.clear();
++				} else {
++					s += ch;
++				}
++			}
++
++			if(!s.isEmpty()) {
++				ret << s;
++			}
++		}
++	}
++	return ret;
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QString PlatformProcess::current_working_directory() const {
++	return edb::v1::symlink_target(QString("/proc/%1/cwd").arg(pid_));
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QString PlatformProcess::executable() const {
++	return edb::v1::symlink_target(QString("/proc/%1/exe").arg(pid_));
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++edb::pid_t PlatformProcess::pid() const {
++	return pid_;
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++IProcess::pointer PlatformProcess::parent() const {
++
++	struct user_stat user_stat;
++	int n = get_user_stat(pid_, &user_stat);
++	if(n >= 4) {
++		return std::make_shared<PlatformProcess>(core_, user_stat.ppid);
++	}
++
++	return nullptr;
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++edb::address_t PlatformProcess::code_address() const {
++	struct user_stat user_stat;
++	int n = get_user_stat(pid_, &user_stat);
++	if(n >= 26) {
++		return user_stat.startcode;
++	}
++	return 0;
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++edb::address_t PlatformProcess::data_address() const {
++	struct user_stat user_stat;
++	int n = get_user_stat(pid_, &user_stat);
++	if(n >= 27) {
++		return user_stat.endcode + 1; // endcode == startdata ?
++	}
++	return 0;
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QList<IRegion::pointer> PlatformProcess::regions() const {
++	static QList<IRegion::pointer> regions;
++	static size_t totalHash = 0;
++
++	const QString map_file(QString("/proc/%1/maps").arg(pid_));
++
++	// hash the region file to see if it changed or not
++	{
++		std::ifstream mf(map_file.toStdString());
++		size_t newHash = 0;
++		std::string line;
++
++		while(std::getline(mf,line)) {
++			boost::hash_combine(newHash, line);
++		}
++
++		if(totalHash == newHash) {
++			return regions;
++		}
++
++		totalHash = newHash;
++		regions.clear();
++	}
++
++	// it changed, so let's process it
++	QFile file(map_file);
++    if(file.open(QIODevice::ReadOnly | QIODevice::Text)) {
++
++		QTextStream in(&file);
++		QString line = in.readLine();
++
++		while(!line.isNull()) {
++			if(IRegion::pointer region = process_map_line(line)) {
++				regions.push_back(region);
++			}
++			line = in.readLine();
++		}
++	}
++
++	return regions;
++}
++
++//------------------------------------------------------------------------------
++// Name: read_byte
++// Desc: the base implementation of reading a byte
++//------------------------------------------------------------------------------
++quint8 PlatformProcess::read_byte_via_ptrace(edb::address_t address, bool *ok) const {
++	// TODO(eteran): assert that we are paused
++
++	Q_ASSERT(ok);
++	Q_ASSERT(core_->process_ == this);
++
++	*ok = false;
++
++	// if this spot is unreadable, then just return 0xff, otherwise
++	// continue as normal.
++
++	// core_->page_size() - 1 will always be 0xf* because pagesizes
++	// are always 0x10*, so the masking works
++	// range of nBytesToNextPage is [1..n] where n=pagesize, and we have to adjust
++	// if nByteToNextPage < wordsize
++	const edb::address_t nBytesToNextPage = core_->page_size() - (address & (core_->page_size() - 1));
++
++	// Avoid crossing page boundary, since next page may be unreadable
++	const edb::address_t addressShift = nBytesToNextPage < EDB_WORDSIZE ? EDB_WORDSIZE - nBytesToNextPage : 0;
++	address -= addressShift;
++
++	const long value = ptrace_peek(address, ok);
++
++	if(*ok) {
++		quint8 result;
++		// We aren't interested in `value` as in number, it's just a buffer, so no endianness magic.
++		// Just have to compensate for `addressShift` when reading it.
++		std::memcpy(&result,reinterpret_cast<const char*>(&value)+addressShift,sizeof result);
++		return result;
++	}
++
++	return 0xff;
++}
++
++
++//------------------------------------------------------------------------------
++// Name: write_byte
++// Desc: writes a single byte at a given address via ptrace API.
++// Note: assumes the this will not trample any breakpoints, must be handled
++//       in calling code!
++//------------------------------------------------------------------------------
++void PlatformProcess::write_byte_via_ptrace(edb::address_t address, quint8 value, bool *ok) {
++	// TODO(eteran): assert that we are paused
++
++	Q_ASSERT(ok);
++	Q_ASSERT(core_->process_ == this);
++
++	*ok = false;
++
++	// core_->page_size() - 1 will always be 0xf* because pagesizes
++	// are always 0x10*, so the masking works
++	// range of nBytesToNextPage is [1..n] where n=pagesize, and we have to adjust
++	// if nBytesToNextPage < wordsize
++	const edb::address_t nBytesToNextPage = core_->page_size() - (address & (core_->page_size() - 1));
++
++	// Avoid crossing page boundary, since next page may be inaccessible
++	const edb::address_t addressShift = nBytesToNextPage < EDB_WORDSIZE ? EDB_WORDSIZE - nBytesToNextPage : 0;
++	address -= addressShift;
++
++	long word = ptrace_peek(address, ok);
++	if(!*ok) return;
++
++	// We aren't interested in `value` as in number, it's just a buffer, so no endianness magic.
++	// Just have to compensate for `addressShift` when writing it.
++	std::memcpy(reinterpret_cast<char*>(&word)+addressShift,&value,sizeof value);
++
++	*ok = ptrace_poke(address, word);
++}
++
++//------------------------------------------------------------------------------
++// Name: ptrace_peek
++// Desc:
++// Note: this will fail on newer versions of linux if called from a
++//       different thread than the one which attached to process
++//------------------------------------------------------------------------------
++long PlatformProcess::ptrace_peek(edb::address_t address, bool *ok) const {
++	Q_ASSERT(ok);
++	Q_ASSERT(core_->process_ == this);
++
++	if (EDB_IS_32_BIT && address > 0xffffffffULL) {
++		// 32 bit ptrace can't handle such long addresses
++		*ok = false;
++		return 0;
++	}
++
++	errno = 0;
++	// NOTE: on some Linux systems ptrace prototype has ellipsis instead of third and fourth arguments
++	// Thus we can't just pass address as is on IA32 systems: it'd put 64 bit integer on stack and cause UB
++	auto nativeAddress=reinterpret_cast<const void* const>(address.toUint());
++	const long v = ptrace(PTRACE_PEEKTEXT, pid_, nativeAddress, 0);
++	set_ok(*ok, v);
++	return v;
++}
++
++//------------------------------------------------------------------------------
++// Name: ptrace_poke
++// Desc:
++//------------------------------------------------------------------------------
++bool PlatformProcess::ptrace_poke(edb::address_t address, long value) {
++
++	Q_ASSERT(core_->process_ == this);
++
++	if (EDB_IS_32_BIT && address > 0xffffffffULL) {
++		// 32 bit ptrace can't handle such long addresses
++		return 0;
++	}
++
++	// NOTE: on some Linux systems ptrace prototype has ellipsis instead of third and fourth arguments
++	// Thus we can't just pass address as is on IA32 systems: it'd put 64 bit integer on stack and cause UB
++	auto nativeAddress=reinterpret_cast<const void* const>(address.toUint());
++	return ptrace(PTRACE_POKETEXT, pid_, nativeAddress, value) != -1;
++}
++
++//------------------------------------------------------------------------------
++// Name: threads
++// Desc:
++//------------------------------------------------------------------------------
++QList<IThread::pointer> PlatformProcess::threads() const {
++
++	Q_ASSERT(core_->process_ == this);
++
++	QList<IThread::pointer> threadList;
++
++	for(auto &thread : core_->threads_) {
++		threadList.push_back(thread);
++	}
++
++	return threadList;
++}
++
++//------------------------------------------------------------------------------
++// Name: current_thread
++// Desc:
++//------------------------------------------------------------------------------
++IThread::pointer PlatformProcess::current_thread() const {
++
++	Q_ASSERT(core_->process_ == this);
++
++	auto it = core_->threads_.find(core_->active_thread_);
++	if(it != core_->threads_.end()) {
++		return it.value();
++	}
++	return IThread::pointer();
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++edb::uid_t PlatformProcess::uid() const {
++
++	const QFileInfo info(QString("/proc/%1").arg(pid_));
++	return info.ownerId();
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QString PlatformProcess::user() const {
++	if(const struct passwd *const pwd = ::getpwuid(uid())) {
++		return pwd->pw_name;
++	}
++
++	return QString();
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QString PlatformProcess::name() const {
++	struct user_stat user_stat;
++	const int n = get_user_stat(pid_, &user_stat);
++	if(n >= 2) {
++		return user_stat.comm;
++	}
++
++	return QString();
++}
++
++//------------------------------------------------------------------------------
++// Name:
++// Desc:
++//------------------------------------------------------------------------------
++QList<Module> PlatformProcess::loaded_modules() const {
++	if(edb::v1::debuggeeIs64Bit()) {
++		return loaded_modules_<Elf64_Addr>(this, core_->binary_info_);
++	} else if(edb::v1::debuggeeIs32Bit()) {
++		return loaded_modules_<Elf32_Addr>(this, core_->binary_info_);
++	} else {
++		return QList<Module>();
++	}
++}
++
++//------------------------------------------------------------------------------
++// Name: pause
++// Desc: stops *all* threads of a process
++//------------------------------------------------------------------------------
++void PlatformProcess::pause() {
++	// belive it or not, I belive that this is sufficient for all threads
++	// this is because in the debug event handler above, a SIGSTOP is sent
++	// to all threads when any event arrives, so no need to explicitly do
++	// it here. We just need any thread to stop. So we'll just target the
++	// pid_ which will send it to any one of the threads in the process.
++	::kill(pid_, SIGSTOP);
++}
++
++//------------------------------------------------------------------------------
++// Name: resume
++// Desc: resumes ALL threads
++//------------------------------------------------------------------------------
++void PlatformProcess::resume(edb::EVENT_STATUS status) {
++	// TODO: assert that we are paused
++	Q_ASSERT(core_->process_ == this);
++
++	if(status != edb::DEBUG_STOP) {
++		if(IThread::pointer thread = current_thread()) {
++			thread->resume(status);
++
++			// resume the other threads passing the signal they originally reported had
++			for(auto &other_thread : threads()) {
++				if(core_->waited_threads_.contains(other_thread->tid())) {
++					other_thread->resume();
++				}
++			}
++		}
++	}
++}
++
++//------------------------------------------------------------------------------
++// Name: step
++// Desc: steps the currently active thread
++//------------------------------------------------------------------------------
++void PlatformProcess::step(edb::EVENT_STATUS status) {
++	// TODO: assert that we are paused
++	Q_ASSERT(core_->process_ == this);
++
++	if(status != edb::DEBUG_STOP) {
++		if(IThread::pointer thread = current_thread()) {
++			thread->step(status);
++		}
++	}
++}
++
++}
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.h
index 5c5f57bb38..94c4c0bf15 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformProcess.h
@@ -1,8 +1,8 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformProcess.h.orig	2017-02-19 00:51:04.624899484 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformProcess.h.orig	2017-02-19 02:09:05.385779377 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformProcess.h
-@@ -0,0 +1,27 @@
+@@ -0,0 +1,83 @@
 +/*
 +Copyright (C) 2015 - 2015 Evan Teran
 +                          evan.teran%gmail.com@localhost
@@ -25,8 +25,64 @@ $NetBSD$
 +#define PLATOFORM_PROCESS_20150517_H_
 +
 +#include "IProcess.h"
++#include "Status.h"
++
++#include <QFile>
++
++namespace DebuggerCorePlugin {
++
++class DebuggerCore;
 +
 +class PlatformProcess : public IProcess {
++	friend class PlatformThread;
++public:
++	PlatformProcess(DebuggerCore *core, edb::pid_t pid);
++	virtual ~PlatformProcess();
++
++private:
++	PlatformProcess(const PlatformProcess &) = delete;
++	PlatformProcess& operator=(const PlatformProcess &) = delete;
++
++public:
++	virtual QDateTime               start_time() const;
++	virtual QList<QByteArray>       arguments() const;
++	virtual QString                 current_working_directory() const;
++	virtual QString                 executable() const;
++	virtual edb::pid_t              pid() const;
++	virtual IProcess::pointer       parent() const;
++	virtual edb::address_t          code_address() const;
++	virtual edb::address_t          data_address() const;
++	virtual QList<IRegion::pointer> regions() const;
++	virtual QList<IThread::pointer> threads() const;
++	virtual IThread::pointer        current_thread() const;
++	virtual edb::uid_t              uid() const;
++	virtual QString                 user() const;
++	virtual QString                 name() const;
++	virtual QList<Module>           loaded_modules() const;
++
++public:
++	virtual void                    pause();
++	virtual void                    resume(edb::EVENT_STATUS status);
++	virtual void                    step(edb::EVENT_STATUS status);
++
++public:
++	virtual std::size_t write_bytes(edb::address_t address, const void *buf, size_t len);
++	virtual std::size_t read_bytes(edb::address_t address, void *buf, size_t len) const;
++	virtual std::size_t read_pages(edb::address_t address, void *buf, size_t count) const;
++
++private:
++	bool ptrace_poke(edb::address_t address, long value);
++	long ptrace_peek(edb::address_t address, bool *ok) const;
++	quint8 read_byte_via_ptrace(edb::address_t address, bool *ok) const;
++	void write_byte_via_ptrace(edb::address_t address, quint8 value, bool *ok);
++
++private:
++	DebuggerCore* core_;
++	edb::pid_t    pid_;
++	QFile*        ro_mem_file_;
++	QFile*        rw_mem_file_;
 +};
 +
++}
++
 +#endif
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.cpp
index 9284c129e2..7a2b1e08a8 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.cpp
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformRegion.cpp.orig	2017-02-19 00:51:04.630983695 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformRegion.cpp.orig	2017-02-19 02:10:30.313375160 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformRegion.cpp
 @@ -0,0 +1,96 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.h
index 55cac0300b..86f47b46a0 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformRegion.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformRegion.h.orig	2017-02-19 00:51:04.637111215 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformRegion.h.orig	2017-02-19 02:10:30.319608887 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformRegion.h
 @@ -0,0 +1,67 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.cpp
index ef6e473baf..6a38739b33 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.cpp
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformState.cpp.orig	2017-02-19 00:51:04.643353107 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformState.cpp.orig	2017-02-19 02:10:30.326045942 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformState.cpp
 @@ -0,0 +1,392 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.h
index 995f231ade..f8cebba0e9 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformState.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformState.h.orig	2017-02-19 00:51:04.649508333 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformState.h.orig	2017-02-19 02:10:30.332431989 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformState.h
 @@ -0,0 +1,68 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.cpp b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.cpp
index d2addd524c..438ce1037f 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.cpp
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.cpp
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformThread.cpp.orig	2017-02-19 00:51:04.655743013 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformThread.cpp.orig	2017-02-19 02:10:30.338910996 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformThread.cpp
 @@ -0,0 +1,444 @@
 +/*
diff --git a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.h b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.h
index 816a81f33d..46875e6997 100644
--- a/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.h
+++ b/edb-debugger-git/patches/patch-plugins_DebuggerCore_unix_netbsd_PlatformThread.h
@@ -1,6 +1,6 @@
 $NetBSD$
 
---- plugins/DebuggerCore/unix/netbsd/PlatformThread.h.orig	2017-02-19 00:51:04.661961825 +0000
+--- plugins/DebuggerCore/unix/netbsd/PlatformThread.h.orig	2017-02-19 02:10:30.345302936 +0000
 +++ plugins/DebuggerCore/unix/netbsd/PlatformThread.h
 @@ -0,0 +1,89 @@
 +/*


Home | Main Index | Thread Index | Old Index