Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 mono (3.2.1+dfsg-1) experimental; urgency=low
 .
   * The "REJECT FALSE ICONS" release
 .
   [ Jo Shields ]
   * [b9108c7] Dirty patch to introduce a new System.Windows.Forms.WebBrowser
     back-end, which does absolutely nothing. This is to allow applications
     which create a WebBrowser object to continue to run without crashing,
     in the absence of a working browser back-end (which we lack right now).
     This patch is sufficient for
     http://www.java2s.com/Tutorial/CSharp/0460__GUI-Windows-Forms/AsimpleBrowser.htm
     to run without crashing. (Closes: #683289, #694948)
   * [d20f6ad] Update README.source for the latest +dfsg changes
   * [621d62b] Imported Upstream version 3.2.1+dfsg
   * [a469da4] Delete .git folders which are incorrectly supplied (sometimes)
     in upstream tarballs
   * [93dc83d] Remove IA64 as a build arch, it's abandoned upstream - add
     newly fixed MIPS (little endian) instead.
   * [45139df] Refresh debian/ - including new split-off packages - now SGen
     is default
   * [f8f6ae7] Rename libmono-2.0 packages to libmonoboehm-2.0 as appropriate.
   * [22f5059] Add new GAC'd assemblies from this release.
   * [7876094] Refreshed dh_makeclilibs version information to reflect ABI
     and API bumps.
   * [0916fab] Rename libmono-csharp4.0-cil.install to
     libmono-csharp4.0a-cil.install, due to heavy ABI breakage.
   * [c4437d1] Fix compilation failure to due to uninitialized variable.
   * [b53dbb2] Create a set of new packages for PCL Facades.
   * [1054a3b] Add Xamarin to copyright file
   * [3643568] Fix compilation failure to due to uninitialized variable.
   * [0873f74] Replace references to Novell in package descriptions with
     Xamarin.
 .
   [ Mirco Bauer ]
   * [c920c13] Removed mono_arch_get_lmf_addr from s390x specific symbols
   * [7b291a4] Added new armel specific symbols to libmono-2.0-1.symbols.armel
 .
   [ Atsushi Eno ]
   * [15e60b3] Add Assembly version attributes to hopefully fix bug #10002.
     (cherry picked from commit cd6dc32e0b936645bf2f89e1bf61c6ae04c3258a)
     The new files are modified by this commit but were not present in the
     packaged release.
   * [5b98c36] [rx] Add missing AssemblyInfos.
     (cherry picked from commit 7890e1e824b91b1fd30d375b8cfb19d5abb23c5a)
   * [7cb9532] remove wrong EOLs after Libs: in reactive.pc.in. Third
     attempt to fix bug #10002.
     (cherry picked from commit 5c228f3dd0e9b32a5b0d4aaaf0903ebaeae5a6d9)
   * [8583276] Fix build (giconv.c) (cherry picked from commit
     37e7f2fb50e2f357ae4068d3b7551ff411f9f77c)
 .
   [ Carlos Martín Nieto ]
   * [b85c794] Create package for Reactive Extensions.
     Now that they have a version, let's create binary packages for them.
 .
   [ Alex Rønne Petersen ]
   * [172471f] Support a MONO_ARCH_HAVE_TLS_INIT variable.
     Setting this on an architecture makes Mini call
     mono_arch_tls_init () on thread attach.
     This is primarily useful for architectures that have not
     had their LMF code ported to the new infrastructure due to
     a general lack of maintenance or hardware to do it on.
     (cherry picked from commit f87a4f127d1a0ea1cf4145f9605c5698af08c6cf)
   * [7cbea71] MIPS: Set USE_MUL to 0 by default (for now).
     Setting it to 1 breaks on Loongson CPUs which are the most common
     desktop MIPS CPUs supported by e.g. Debian.
     This change can be reverted when more investigation is done to find
     out why exactly this breaks.
     Thanks to Jo Shields (@directhex) for lots of testing and debugging
     and spotting this define that turned out to be the culprit.
     (cherry picked from commit 0e67acba31c39e37b1bc55afb28d157c36895c23)
 .
   [ Mark Probst ]
   * [e19428c] Fix race conditions in finalizer/weak link staging.
     (cherry picked from commit aef4b77ea79aa0a4c06e10bd5842da9df0d10973)
 .
   [ Jeffrey Stedfast ]
   * [090dda7] [eglib] Fixed g_utf8_to_utf16_general() to handle
     invalid utf8 (cherry picked from commit
     a81cd6dae81a7077a7f014948c78075da08f02f7)
 .
   [ Zoltan Varga ]
   * [49af7b0] [sgen] Use __builtin_ctzl () in OBJ_BITMAP_FOREACH_PTR () on 64
     bit platforms. Fixes #14834. (cherry picked from commit
     d2cc22580898df5d4a15e0f99ab513e1570a6082)
     Thanks to Andres G. Aragoneses (@knocte) for his help tracking this one
     down, as it broke Banshee.
Author: Jo Shields <directhex@apebox.org>
Bug-Debian: http://bugs.debian.org/683289
Bug-Debian: http://bugs.debian.org/694948

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: http://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- mono-3.2.1+dfsg.orig/configure.in
+++ mono-3.2.1+dfsg/configure.in
@@ -153,6 +153,17 @@ case "$host" in
 		with_sigaltstack=no
 		use_sigposix=yes
 		;;
+	*-*-kfreebsd*-gnu)
+		platform_win32=no
+		CPPFLAGS="$CPPFLAGS -DGC_FREEBSD_THREADS -D_GNU_SOURCE -D_REENTRANT -DUSE_MMAP -DUSE_MUNMAP -DTHREAD_LOCAL_ALLOC -pthread"
+		libmono_cflags="-D_REENTRANT -DTHREAD_LOCAL_ALLOC -pthread"
+		libmono_ldflags="-lpthread -pthread"
+		libdl="-ldl"
+		libgc_threads=pthreads
+		need_link_unlink=yes
+		with_sigaltstack=no
+		use_sigposix=yes
+		;;
 	*-*-*freebsd*)
 		host_win32=no
 		if test "x$PTHREAD_CFLAGS" = "x"; then
@@ -2501,7 +2512,7 @@ case "$host" in
 			sgen_supported=true
 			AOT_SUPPORTED="yes"
 			;;
-		  darwin*|openbsd*|freebsd*)
+		  darwin*|openbsd*|freebsd*|kfreebsd-gnu*)
 			sgen_supported=true
 		        ;;
 		esac
@@ -2519,7 +2530,7 @@ case "$host" in
 			sgen_supported=true
 			AOT_SUPPORTED="yes"
 			;;
-		  darwin*|openbsd*|freebsd*)
+		  darwin*|openbsd*|freebsd*|kfreebsd-gnu*)
 			sgen_supported=true
 			;;
 		esac
@@ -2858,6 +2869,11 @@ case "$host" in
 	LIBC="libc.so.12"
 	INTL="libintl.so.0"
 	;;
+     *-*-kfreebsd*-gnu)
+	LIBC="libc.so.0.1"
+	INTL="libc.so.0.1"
+	X11="libX11.so.6"
+	;;
     *-*-*freebsd*)
     	LIBC="libc.so"
 	INTL="libintl.so"
--- mono-3.2.1+dfsg.orig/Makefile.am
+++ mono-3.2.1+dfsg/Makefile.am
@@ -4,7 +4,7 @@ MOONLIGHT_SUBDIRS = $(libgc_dir) eglib/s
 MONOTOUCH_SUBDIRS = $(libgc_dir) eglib/src mono
 
 if CROSS_COMPILING
-SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) data runtime scripts man samples msvc $(docs_dir)
+SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) data runtime scripts man samples msvc
 # Keep in sync with SUBDIRS
 ## 'tools' is not normally built
 DIST_SUBDIRS = m4 po libgc eglib mono ikvm-native data runtime scripts man samples tools msvc docs
@@ -15,7 +15,7 @@ else
 if ONLY_MOONLIGHT
 SUBDIRS = $(MOONLIGHT_SUBDIRS) runtime
 else
-SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir)
+SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc
 # Keep in sync with SUBDIRS
 ## 'tools' is not normally built
 DIST_SUBDIRS = m4 po libgc eglib mono ikvm-native support data runtime scripts man samples tools msvc docs
--- mono-3.2.1+dfsg.orig/mono/io-layer/io.c
+++ mono-3.2.1+dfsg/mono/io-layer/io.c
@@ -4227,7 +4227,7 @@ get_fstypename (gchar *utfpath)
 }
 
 /* Linux has struct statfs which has a different layout */
-#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__)
+#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__)
 gboolean
 GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesize, int *outserial, int *maxcomp, int *fsflags, gunichar2 *fsbuffer, int fsbuffersize)
 {
--- mono-3.2.1+dfsg.orig/mono/mini/mini-mips.c
+++ mono-3.2.1+dfsg/mono/mini/mini-mips.c
@@ -31,7 +31,8 @@
 #define ALWAYS_SAVE_RA		1	/* call-handler & switch currently clobber ra */
 
 #define PROMOTE_R4_TO_R8	1	/* promote single values in registers to doubles */
-#define USE_MUL			1	/* use mul instead of mult/mflo for multiply */
+#define USE_MUL			0	/* use mul instead of mult/mflo for multiply
+							   remember to update cpu-mips.md if you change this */
 
 /* Emit a call sequence to 'v', using 'D' as a scratch register if necessary */
 #define mips_call(c,D,v) do {	\
--- mono-3.2.1+dfsg.orig/mono/mini/Makefile.am
+++ mono-3.2.1+dfsg/mono/mini/Makefile.am
@@ -205,7 +205,7 @@ buildver-boehm.h: libmini-static.la $(mo
 else
 buildver-boehm.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntime-static.la
 endif
-	@echo "const char *build_date = \"`date`\";" > buildver-boehm.h
+	@echo "const char *build_date;" > buildver-boehm.h
 mono_boehm-main.$(OBJEXT): buildver-boehm.h
 endif
 
@@ -214,7 +214,7 @@ buildver-sgen.h: libmini-static.la $(mon
 else
 buildver-sgen.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntimesgen-static.la
 endif
-	@echo "const char *build_date = \"`date`\";" > buildver-sgen.h
+	@echo "const char *build_date;" > buildver-sgen.h
 mono_sgen-main-sgen.$(OBJEXT): buildver-sgen.h
 
 if DTRACE_G_REQUIRED
@@ -765,16 +765,7 @@ EXTRA_DIST = TestDriver.cs ldscript ldsc
 	Makefile.am.in
 
 version.h: Makefile
-	if test -d $(top_srcdir)/.git; then \
-		(cd $(top_srcdir); \
-			LANG=C; export LANG; \
-			branch=`git branch | grep '^\*' | cut -d ' ' -f 2`; \
-			version=`git log --no-color --first-parent -n1 --pretty=format:%h`; \
-			echo "#define FULL_VERSION \"$$branch/$$version\""; \
-		); \
-	else \
-		echo "#define FULL_VERSION \"tarball\""; \
-	fi > version.h
+	echo "#define FULL_VERSION \"Debian $$(dpkg-parsechangelog -l$(top_srcdir)/debian/changelog | grep ^Vers | cut -d\  -f2)\"" > version.h
 
 # Utility target for patching libtool to speed up linking
 patch-libtool:
--- mono-3.2.1+dfsg.orig/mono/mini/mini-amd64.h
+++ mono-3.2.1+dfsg/mono/mini/mini-amd64.h
@@ -290,7 +290,7 @@ typedef struct MonoCompileArch {
 
 #define MONO_ARCH_NOMAP32BIT
 
-#elif defined (__FreeBSD__)
+#elif defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
 
 #define REG_RAX 7
 #define REG_RCX 4
--- mono-3.2.1+dfsg.orig/mono/mini/mini-x86.h
+++ mono-3.2.1+dfsg/mono/mini/mini-x86.h
@@ -48,7 +48,7 @@ struct sigcontext {
 #endif /* __HAIKU__ */
 
 #if defined( __linux__) || defined(__sun) || defined(__APPLE__) || defined(__NetBSD__) || \
-       defined(__FreeBSD__) || defined(__OpenBSD__)
+       defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
 #define MONO_ARCH_USE_SIGACTION
 #endif
 
--- mono-3.2.1+dfsg.orig/mono/mini/cpu-mips.md
+++ mono-3.2.1+dfsg/mono/mini/cpu-mips.md
@@ -177,7 +177,7 @@ not_null: src1:i len:0
 # 32 bit opcodes
 int_add: dest:i src1:i src2:i len:4
 int_sub: dest:i src1:i src2:i len:4
-int_mul: dest:i src1:i src2:i len:4
+int_mul: dest:i src1:i src2:i len:16
 int_div: dest:i src1:i src2:i len:84
 int_div_un: dest:i src1:i src2:i len:40
 int_rem: dest:i src1:i src2:i len:84
@@ -278,7 +278,7 @@ icompare_imm: src1:i len:12
 # 64 bit opcodes
 long_add: dest:i src1:i src2:i len:4
 long_sub: dest:i src1:i src2:i len:4
-long_mul: dest:i src1:i src2:i len:8
+long_mul: dest:i src1:i src2:i len:32
 long_mul_imm: dest:i src1:i len:4
 long_div: dest:i src1:i src2:i len:40
 long_div_un: dest:i src1:i src2:i len:16
--- mono-3.2.1+dfsg.orig/mono/metadata/sgen-os-posix.c
+++ mono-3.2.1+dfsg/mono/metadata/sgen-os-posix.c
@@ -35,7 +35,7 @@
 #include "metadata/sgen-archdep.h"
 #include "metadata/object-internals.h"
 
-#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
+#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 const static int suspend_signal_num = SIGXFSZ;
 #else
 const static int suspend_signal_num = SIGPWR;
--- mono-3.2.1+dfsg.orig/mono/metadata/security.c
+++ mono-3.2.1+dfsg/mono/metadata/security.c
@@ -13,6 +13,7 @@
 
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/appdomain.h>
+#include <mono/metadata/assembly.h>
 #include <mono/metadata/image.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/object-internals.h>
--- mono-3.2.1+dfsg.orig/mono/metadata/sgen-protocol.h
+++ mono-3.2.1+dfsg/mono/metadata/sgen-protocol.h
@@ -49,7 +49,9 @@ enum {
 	SGEN_PROTOCOL_CARD_SCAN,
 	SGEN_PROTOCOL_CEMENT,
 	SGEN_PROTOCOL_CEMENT_RESET,
-	SGEN_PROTOCOL_DISLINK_UPDATE
+	SGEN_PROTOCOL_DISLINK_UPDATE,
+	SGEN_PROTOCOL_DISLINK_UPDATE_STAGED,
+	SGEN_PROTOCOL_DISLINK_PROCESS_STAGED
 };
 
 typedef struct {
@@ -167,8 +169,22 @@ typedef struct {
 	gpointer link;
 	gpointer obj;
 	int track;
+	int staged;
 } SGenProtocolDislinkUpdate;
 
+typedef struct {
+	gpointer link;
+	gpointer obj;
+	int track;
+	int index;
+} SGenProtocolDislinkUpdateStaged;
+
+typedef struct {
+	gpointer link;
+	gpointer obj;
+	int index;
+} SGenProtocolDislinkProcessStaged;
+
 /* missing: finalizers, dislinks, roots, non-store wbarriers */
 
 void binary_protocol_init (const char *filename) MONO_INTERNAL;
@@ -201,7 +217,9 @@ void binary_protocol_missing_remset (gpo
 void binary_protocol_card_scan (gpointer start, int size) MONO_INTERNAL;
 void binary_protocol_cement (gpointer ptr, gpointer vtable, int size) MONO_INTERNAL;
 void binary_protocol_cement_reset (void) MONO_INTERNAL;
-void binary_protocol_dislink_update (gpointer link, gpointer obj, int track) MONO_INTERNAL;
+void binary_protocol_dislink_update (gpointer link, gpointer obj, int track, int staged) MONO_INTERNAL;
+void binary_protocol_dislink_update_staged (gpointer link, gpointer obj, int track, int index) MONO_INTERNAL;
+void binary_protocol_dislink_process_staged (gpointer link, gpointer obj, int index) MONO_INTERNAL;
 
 #else
 
@@ -232,6 +250,8 @@ void binary_protocol_dislink_update (gpo
 #define binary_protocol_card_scan(start, size)
 #define binary_protocol_cement(ptr, vtable, size)
 #define binary_protocol_cement_reset()
-#define binary_protocol_dislink_update(link,obj,track)
+#define binary_protocol_dislink_update(link,obj,track,staged)
+#define binary_protocol_dislink_update_staged(link,obj,track,index)
+#define binary_protocol_dislink_process_staged(link,obj,index)
 
 #endif
--- mono-3.2.1+dfsg.orig/mono/metadata/sgen-descriptor.h
+++ mono-3.2.1+dfsg/mono/metadata/sgen-descriptor.h
@@ -170,21 +170,43 @@ sgen_gc_descr_has_references (mword desc
 		}	\
 	} while (0)
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && SIZEOF_VOID_P==4
 #define OBJ_BITMAP_FOREACH_PTR(desc,obj)       do {    \
 		/* there are pointers */        \
 		void **_objptr = (void**)(obj); \
 		gsize _bmap = (desc) >> 16;     \
 		_objptr += OBJECT_HEADER_WORDS; \
 		{ \
-			int _index = __builtin_ctz (_bmap); \
+			int _index = __builtin_ctz (_bmap);		\
 			_objptr += _index; \
 			_bmap >>= (_index + 1);				\
 			HANDLE_PTR (_objptr, (obj));		\
 			_objptr ++;							\
 			} \
 		while (_bmap) { \
-			int _index = __builtin_ctz (_bmap); \
+			int _index = __builtin_ctz (_bmap);		\
+			_objptr += _index; \
+			_bmap >>= (_index + 1);				\
+			HANDLE_PTR (_objptr, (obj));		\
+			_objptr ++;							\
+		}										\
+	} while (0)
+#elif defined(__GNUC__) && SIZEOF_VOID_P==8
+/* Same as above, but use _builtin_ctzl () */
+#define OBJ_BITMAP_FOREACH_PTR(desc,obj)       do {    \
+		/* there are pointers */        \
+		void **_objptr = (void**)(obj); \
+		gsize _bmap = (desc) >> 16;     \
+		_objptr += OBJECT_HEADER_WORDS; \
+		{ \
+			int _index = __builtin_ctzl (_bmap);		\
+			_objptr += _index; \
+			_bmap >>= (_index + 1);				\
+			HANDLE_PTR (_objptr, (obj));		\
+			_objptr ++;							\
+			} \
+		while (_bmap) { \
+			int _index = __builtin_ctzl (_bmap);		\
 			_objptr += _index; \
 			_bmap >>= (_index + 1);				\
 			HANDLE_PTR (_objptr, (obj));		\
--- mono-3.2.1+dfsg.orig/mono/metadata/sgen-gc.h
+++ mono-3.2.1+dfsg/mono/metadata/sgen-gc.h
@@ -768,6 +768,8 @@ const char* sgen_safe_name (void* obj) M
 
 gboolean sgen_object_is_live (void *obj) MONO_INTERNAL;
 
+void  sgen_init_fin_weak_hash (void) MONO_INTERNAL;
+
 gboolean sgen_need_bridge_processing (void) MONO_INTERNAL;
 void sgen_bridge_reset_data (void) MONO_INTERNAL;
 void sgen_bridge_processing_stw_step (void) MONO_INTERNAL;
--- mono-3.2.1+dfsg.orig/mono/metadata/sgen-fin-weak-hash.c
+++ mono-3.2.1+dfsg/mono/metadata/sgen-fin-weak-hash.c
@@ -31,6 +31,7 @@
 #include "metadata/sgen-gray.h"
 #include "metadata/sgen-protocol.h"
 #include "utils/dtrace.h"
+#include "utils/mono-counters.h"
 
 #define ptr_in_nursery sgen_ptr_in_nursery
 
@@ -230,12 +231,66 @@ register_for_finalization (MonoObject *o
 	}
 }
 
+/*
+ * We're using (mostly) non-locking staging queues for finalizers and weak links to speed
+ * up registering them.  Otherwise we'd have to take the GC lock.
+ *
+ * The queues are arrays of `StageEntry`, plus a `next_entry` index.  Threads add entries to
+ * the queue via `add_stage_entry()` in a linear fashion until it fills up, in which case
+ * `process_stage_entries()` is called to drain it.  A garbage collection will also drain
+ * the queues via the same function.  That implies that `add_stage_entry()`, since it
+ * doesn't take a lock, must be able to run concurrently with `process_stage_entries()`,
+ * though it doesn't have to make progress while the queue is drained.  In fact, once it
+ * detects that the queue is being drained, it blocks until the draining is done.
+ *
+ * The protocol must guarantee that entries in the queue are causally ordered, otherwise two
+ * entries for the same location might get switched, resulting in the earlier one being
+ * committed and the later one ignored.
+ *
+ * `next_entry` is the index of the next entry to be filled, or `-1` if the queue is
+ * currently being drained.  Each entry has a state:
+ *
+ * `STAGE_ENTRY_FREE`: The entry is free.  Its data fields must be `NULL`.
+ *
+ * `STAGE_ENTRY_BUSY`: The entry is currently being filled in.
+ *
+ * `STAGE_ENTRY_USED`: The entry is completely filled in and must be processed in the next
+ * draining round.
+ *
+ * `STAGE_ENTRY_INVALID`: The entry was busy during queue draining and therefore
+ * invalidated.  Entries that are `BUSY` can obviously not be processed during a drain, but
+ * we can't leave them in place because new entries might be inserted before them, including
+ * from the same thread, violating causality.  An alternative would be not to reset
+ * `next_entry` to `0` after a drain, but to the index of the last `BUSY` entry plus one,
+ * but that can potentially waste the whole queue.
+ *
+ * State transitions:
+ *
+ * | from    | to      | filler? | drainer? |
+ * +---------+---------+---------+----------+
+ * | FREE    | BUSY    | X       |          |
+ * | BUSY    | FREE    | X       |          |
+ * | BUSY    | USED    | X       |          |
+ * | BUSY    | INVALID |         | X        |
+ * | USED    | FREE    |         | X        |
+ * | INVALID | FREE    | X       |          |
+ *
+ * `next_entry` can be incremented either by the filler thread that set the corresponding
+ * entry to `BUSY`, or by another filler thread that's trying to get a `FREE` slot.  If that
+ * other thread wasn't allowed to increment, it would block on the first filler thread.
+ *
+ * An entry's state, once it's set from `FREE` to `BUSY` by a filler thread, can only be
+ * changed by that same thread or by the drained.  The drainer can only set a `BUSY` thread
+ * to `INVALID`, so it needs to be set to `FREE` again by the original filler thread.
+ */
+
 #define STAGE_ENTRY_FREE	0
 #define STAGE_ENTRY_BUSY	1
 #define STAGE_ENTRY_USED	2
+#define STAGE_ENTRY_INVALID	3
 
 typedef struct {
-	gint32 state;
+	volatile gint32 state;
 	MonoObject *obj;
 	void *user_data;
 } StageEntry;
@@ -245,75 +300,217 @@ typedef struct {
 static volatile gint32 next_fin_stage_entry = 0;
 static StageEntry fin_stage_entries [NUM_FIN_STAGE_ENTRIES];
 
+/*
+ * This is used to lock the stage when processing is forced, i.e. when it's triggered by a
+ * garbage collection.  In that case, the world is already stopped and there's only one
+ * thread operating on the queue.
+ */
+static void
+lock_stage_for_processing (volatile gint32 *next_entry)
+{
+	*next_entry = -1;
+}
+
+/*
+ * When processing is triggered by an overflow, we don't want to take the GC lock
+ * immediately, and then set `next_index` to `-1`, because another thread might have drained
+ * the queue in the mean time.  Instead, we make sure the overflow is still there, we
+ * atomically set `next_index`, and only once that happened do we take the GC lock.
+ */
+static gboolean
+try_lock_stage_for_processing (int num_entries, volatile gint32 *next_entry)
+{
+	gint32 old = *next_entry;
+	if (old < num_entries)
+		return FALSE;
+	return InterlockedCompareExchange (next_entry, -1, old) == old;
+}
+
 /* LOCKING: requires that the GC lock is held */
 static void
-process_stage_entries (int num_entries, volatile gint32 *next_entry, StageEntry *entries, void (*process_func) (MonoObject*, void*))
+process_stage_entries (int num_entries, volatile gint32 *next_entry, StageEntry *entries, void (*process_func) (MonoObject*, void*, int))
 {
 	int i;
-	int num_registered = 0;
-	int num_busy = 0;
+
+	/*
+	 * This can happen if after setting `next_index` to `-1` in
+	 * `try_lock_stage_for_processing()`, a GC was triggered, which then drained the
+	 * queue and reset `next_entry`.
+	 *
+	 * We have the GC lock now, so if it's still `-1`, we can't be interrupted by a GC.
+	 */
+	if (*next_entry != -1)
+		return;
 
 	for (i = 0; i < num_entries; ++i) {
-		gint32 state = entries [i].state;
+		gint32 state;
 
-		if (state == STAGE_ENTRY_BUSY)
-			++num_busy;
+	retry:
+		state = entries [i].state;
 
-		if (state != STAGE_ENTRY_USED ||
-				InterlockedCompareExchange (&entries [i].state, STAGE_ENTRY_BUSY, STAGE_ENTRY_USED) != STAGE_ENTRY_USED) {
+		switch (state) {
+		case STAGE_ENTRY_FREE:
+		case STAGE_ENTRY_INVALID:
 			continue;
+		case STAGE_ENTRY_BUSY:
+			/* BUSY -> INVALID */
+			/*
+			 * This must be done atomically, because the filler thread can set
+			 * the entry to `USED`, in which case we must process it, so we must
+			 * detect that eventuality.
+			 */
+			if (InterlockedCompareExchange (&entries [i].state, STAGE_ENTRY_INVALID, STAGE_ENTRY_BUSY) != STAGE_ENTRY_BUSY)
+				goto retry;
+			continue;
+		case STAGE_ENTRY_USED:
+			break;
+		default:
+			SGEN_ASSERT (0, FALSE, "Invalid stage entry state");
+			break;
 		}
 
-		process_func (entries [i].obj, entries [i].user_data);
+		/* state is USED */
+
+		process_func (entries [i].obj, entries [i].user_data, i);
 
 		entries [i].obj = NULL;
 		entries [i].user_data = NULL;
 
 		mono_memory_write_barrier ();
 
+		/* USED -> FREE */
+		/*
+		 * This transition only happens here, so we don't have to do it atomically.
+		 */
 		entries [i].state = STAGE_ENTRY_FREE;
-
-		++num_registered;
 	}
 
-	*next_entry = 0;
+	mono_memory_write_barrier ();
 
-	/* g_print ("stage busy %d reg %d\n", num_busy, num_registered); */
+	*next_entry = 0;
 }
 
-static gboolean
+#ifdef HEAVY_STATISTICS
+static long long stat_overflow_abort = 0;
+static long long stat_wait_for_processing = 0;
+static long long stat_increment_other_thread = 0;
+static long long stat_index_decremented = 0;
+static long long stat_entry_invalidated = 0;
+static long long stat_success = 0;
+#endif
+
+static int
 add_stage_entry (int num_entries, volatile gint32 *next_entry, StageEntry *entries, MonoObject *obj, void *user_data)
 {
-	gint32 index;
-
-	do {
-		do {
-			index = *next_entry;
-			if (index >= num_entries)
-				return FALSE;
-		} while (InterlockedCompareExchange (next_entry, index + 1, index) != index);
+	gint32 index, new_next_entry, old_next_entry;
+	gint32 previous_state;
 
+ retry:
+	for (;;) {
+		index = *next_entry;
+		if (index >= num_entries) {
+			HEAVY_STAT (++stat_overflow_abort);
+			return -1;
+		}
+		if (index < 0) {
+			/*
+			 * Backed-off waiting is way more efficient than even using a
+			 * dedicated lock for this.
+			 */
+			while ((index = *next_entry) < 0) {
+				/*
+				 * This seems like a good value.  Determined by timing
+				 * sgen-weakref-stress.exe.
+				 */
+				g_usleep (200);
+				HEAVY_STAT (++stat_wait_for_processing);
+			}
+			continue;
+		}
+		/* FREE -> BUSY */
+		if (entries [index].state != STAGE_ENTRY_FREE ||
+				InterlockedCompareExchange (&entries [index].state, STAGE_ENTRY_BUSY, STAGE_ENTRY_FREE) != STAGE_ENTRY_FREE) {
+			/*
+			 * If we can't get the entry it must be because another thread got
+			 * it first.  We don't want to wait for that thread to increment
+			 * `next_entry`, so we try to do it ourselves.  Whether we succeed
+			 * or not, we start over.
+			 */
+			if (*next_entry == index) {
+				InterlockedCompareExchange (next_entry, index + 1, index);
+				//g_print ("tried increment for other thread\n");
+				HEAVY_STAT (++stat_increment_other_thread);
+			}
+			continue;
+		}
+		/* state is BUSY now */
+		mono_memory_write_barrier ();
 		/*
-		 * We don't need a write barrier here.  *next_entry is just a
-		 * help for finding an index, its value is irrelevant for
-		 * correctness.
+		 * Incrementing `next_entry` must happen after setting the state to `BUSY`.
+		 * If it were the other way around, it would be possible that after a filler
+		 * incremented the index, other threads fill up the queue, the queue is
+		 * drained, the original filler finally fills in the slot, but `next_entry`
+		 * ends up at the start of the queue, and new entries are written in the
+		 * queue in front of, not behind, the original filler's entry.
+		 *
+		 * We don't actually require that the CAS succeeds, but we do require that
+		 * the value of `next_entry` is not lower than our index.  Since the drainer
+		 * sets it to `-1`, that also takes care of the case that the drainer is
+		 * currently running.
 		 */
-	} while (entries [index].state != STAGE_ENTRY_FREE ||
-			InterlockedCompareExchange (&entries [index].state, STAGE_ENTRY_BUSY, STAGE_ENTRY_FREE) != STAGE_ENTRY_FREE);
+		old_next_entry = InterlockedCompareExchange (next_entry, index + 1, index);
+		if (old_next_entry < index) {
+			/* BUSY -> FREE */
+			/* INVALID -> FREE */
+			/*
+			 * The state might still be `BUSY`, or the drainer could have set it
+			 * to `INVALID`.  In either case, there's no point in CASing.  Set
+			 * it to `FREE` and start over.
+			 */
+			entries [index].state = STAGE_ENTRY_FREE;
+			HEAVY_STAT (++stat_index_decremented);
+			continue;
+		}
+		break;
+	}
+
+	SGEN_ASSERT (0, index >= 0 && index < num_entries, "Invalid index");
 
 	entries [index].obj = obj;
 	entries [index].user_data = user_data;
 
 	mono_memory_write_barrier ();
 
-	entries [index].state = STAGE_ENTRY_USED;
+	new_next_entry = *next_entry;
+	mono_memory_read_barrier ();
+	/* BUSY -> USED */
+	/*
+	 * A `BUSY` entry will either still be `BUSY` or the drainer will have set it to
+	 * `INVALID`.  In the former case, we set it to `USED` and we're finished.  In the
+	 * latter case, we reset it to `FREE` and start over.
+	 */
+	previous_state = InterlockedCompareExchange (&entries [index].state, STAGE_ENTRY_USED, STAGE_ENTRY_BUSY);
+	if (previous_state == STAGE_ENTRY_BUSY) {
+		SGEN_ASSERT (0, new_next_entry >= index || new_next_entry < 0, "Invalid next entry index - as long as we're busy, other thread can only increment or invalidate it");
+		HEAVY_STAT (++stat_success);
+		return index;
+	}
+
+	SGEN_ASSERT (0, previous_state == STAGE_ENTRY_INVALID, "Invalid state transition - other thread can only make busy state invalid");
+	entries [index].obj = NULL;
+	entries [index].user_data = NULL;
+	mono_memory_write_barrier ();
+	/* INVALID -> FREE */
+	entries [index].state = STAGE_ENTRY_FREE;
 
-	return TRUE;
+	HEAVY_STAT (++stat_entry_invalidated);
+
+	goto retry;
 }
 
 /* LOCKING: requires that the GC lock is held */
 static void
-process_fin_stage_entry (MonoObject *obj, void *user_data)
+process_fin_stage_entry (MonoObject *obj, void *user_data, int index)
 {
 	if (ptr_in_nursery (obj))
 		register_for_finalization (obj, user_data, GENERATION_NURSERY);
@@ -325,16 +522,19 @@ process_fin_stage_entry (MonoObject *obj
 void
 sgen_process_fin_stage_entries (void)
 {
+	lock_stage_for_processing (&next_fin_stage_entry);
 	process_stage_entries (NUM_FIN_STAGE_ENTRIES, &next_fin_stage_entry, fin_stage_entries, process_fin_stage_entry);
 }
 
 void
 mono_gc_register_for_finalization (MonoObject *obj, void *user_data)
 {
-	while (!add_stage_entry (NUM_FIN_STAGE_ENTRIES, &next_fin_stage_entry, fin_stage_entries, obj, user_data)) {
-		LOCK_GC;
-		sgen_process_fin_stage_entries ();
-		UNLOCK_GC;
+	while (add_stage_entry (NUM_FIN_STAGE_ENTRIES, &next_fin_stage_entry, fin_stage_entries, obj, user_data) == -1) {
+		if (try_lock_stage_for_processing (NUM_FIN_STAGE_ENTRIES, &next_fin_stage_entry)) {
+			LOCK_GC;
+			process_stage_entries (NUM_FIN_STAGE_ENTRIES, &next_fin_stage_entry, fin_stage_entries, process_fin_stage_entry);
+			UNLOCK_GC;
+		}
 	}
 }
 
@@ -478,7 +678,7 @@ sgen_null_link_in_range (int generation,
 			if (!major_collector.is_object_live (object)) {
 				if (sgen_gc_is_object_ready_for_finalization (object)) {
 					*link = NULL;
-					binary_protocol_dislink_update (link, NULL, 0);
+					binary_protocol_dislink_update (link, NULL, 0, 0);
 					SGEN_LOG (5, "Dislink nullified at %p to GCed object %p", link, object);
 					SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
 					continue;
@@ -500,14 +700,14 @@ sgen_null_link_in_range (int generation,
 						g_assert (copy);
 						*link = HIDE_POINTER (copy, track);
 						add_or_remove_disappearing_link ((MonoObject*)copy, link, GENERATION_OLD);
-						binary_protocol_dislink_update (link, copy, track);
+						binary_protocol_dislink_update (link, copy, track, 0);
 
 						SGEN_LOG (5, "Upgraded dislink at %p to major because object %p moved to %p", link, object, copy);
 
 						continue;
 					} else {
 						*link = HIDE_POINTER (copy, track);
-						binary_protocol_dislink_update (link, copy, track);
+						binary_protocol_dislink_update (link, copy, track, 0);
 						SGEN_LOG (5, "Updated dislink at %p to %p", link, DISLINK_OBJECT (link));
 					}
 				}
@@ -530,7 +730,7 @@ sgen_null_links_for_domain (MonoDomain *
 
 			if (*link) {
 				*link = NULL;
-				binary_protocol_dislink_update (link, NULL, 0);
+				binary_protocol_dislink_update (link, NULL, 0, 0);
 				free = FALSE;
 				/*
 				 * This can happen if finalizers are not ran, i.e. Environment.Exit ()
@@ -563,7 +763,7 @@ sgen_null_links_with_predicate (int gene
 
 		if (!is_alive) {
 			*link = NULL;
-			binary_protocol_dislink_update (link, NULL, 0);
+			binary_protocol_dislink_update (link, NULL, 0, 0);
 			SGEN_LOG (5, "Dislink nullified by predicate at %p to GCed object %p", link, object);
 			SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
 			continue;
@@ -592,10 +792,13 @@ sgen_remove_finalizers_for_domain (MonoD
 
 /* LOCKING: requires that the GC lock is held */
 static void
-process_dislink_stage_entry (MonoObject *obj, void *_link)
+process_dislink_stage_entry (MonoObject *obj, void *_link, int index)
 {
 	void **link = _link;
 
+	if (index >= 0)
+		binary_protocol_dislink_process_staged (link, obj, index);
+
 	add_or_remove_disappearing_link (NULL, link, GENERATION_NURSERY);
 	add_or_remove_disappearing_link (NULL, link, GENERATION_OLD);
 	if (obj) {
@@ -615,6 +818,7 @@ static StageEntry dislink_stage_entries
 void
 sgen_process_dislink_stage_entries (void)
 {
+	lock_stage_for_processing (&next_dislink_stage_entry);
 	process_stage_entries (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry, dislink_stage_entries, process_dislink_stage_entry);
 }
 
@@ -640,25 +844,43 @@ sgen_register_disappearing_link (MonoObj
 	else
 		*link = NULL;
 
-	binary_protocol_dislink_update (link, obj, track);
-
 #if 1
 	if (in_gc) {
-		process_dislink_stage_entry (obj, link);
+		binary_protocol_dislink_update (link, obj, track, 0);
+		process_dislink_stage_entry (obj, link, -1);
 	} else {
-		while (!add_stage_entry (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry, dislink_stage_entries, obj, link)) {
-			LOCK_GC;
-			sgen_process_dislink_stage_entries ();
-			UNLOCK_GC;
+		int index;
+		binary_protocol_dislink_update (link, obj, track, 1);
+		while ((index = add_stage_entry (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry, dislink_stage_entries, obj, link)) == -1) {
+			if (try_lock_stage_for_processing (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry)) {
+				LOCK_GC;
+				process_stage_entries (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry, dislink_stage_entries, process_dislink_stage_entry);
+				UNLOCK_GC;
+			}
 		}
+		binary_protocol_dislink_update_staged (link, obj, track, index);
 	}
 #else
 	if (!in_gc)
 		LOCK_GC;
-	process_dislink_stage_entry (obj, link);
+	binary_protocol_dislink_update (link, obj, track, 0);
+	process_dislink_stage_entry (obj, link, -1);
 	if (!in_gc)
 		UNLOCK_GC;
 #endif
 }
 
+void
+sgen_init_fin_weak_hash (void)
+{
+#ifdef HEAVY_STATISTICS
+	mono_counters_register ("FinWeak Successes", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_success);
+	mono_counters_register ("FinWeak Overflow aborts", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_overflow_abort);
+	mono_counters_register ("FinWeak Wait for processing", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_wait_for_processing);
+	mono_counters_register ("FinWeak Increment other thread", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_increment_other_thread);
+	mono_counters_register ("FinWeak Index decremented", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_index_decremented);
+	mono_counters_register ("FinWeak Entry invalidated", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_entry_invalidated);
+#endif
+}
+
 #endif /* HAVE_SGEN_GC */
--- mono-3.2.1+dfsg.orig/mono/metadata/sgen-protocol.c
+++ mono-3.2.1+dfsg/mono/metadata/sgen-protocol.c
@@ -368,12 +368,26 @@ binary_protocol_cement_reset (void)
 }
 
 void
-binary_protocol_dislink_update (gpointer link, gpointer obj, int track)
+binary_protocol_dislink_update (gpointer link, gpointer obj, int track, int staged)
 {
-	SGenProtocolDislinkUpdate entry = { link, obj, track };
+	SGenProtocolDislinkUpdate entry = { link, obj, track, staged };
 	protocol_entry (SGEN_PROTOCOL_DISLINK_UPDATE, &entry, sizeof (SGenProtocolDislinkUpdate));
 }
 
+void
+binary_protocol_dislink_update_staged (gpointer link, gpointer obj, int track, int index)
+{
+	SGenProtocolDislinkUpdateStaged entry = { link, obj, track, index };
+	protocol_entry (SGEN_PROTOCOL_DISLINK_UPDATE_STAGED, &entry, sizeof (SGenProtocolDislinkUpdateStaged));
+}
+
+void
+binary_protocol_dislink_process_staged (gpointer link, gpointer obj, int index)
+{
+	SGenProtocolDislinkProcessStaged entry = { link, obj, index };
+	protocol_entry (SGEN_PROTOCOL_DISLINK_PROCESS_STAGED, &entry, sizeof (SGenProtocolDislinkProcessStaged));
+}
+
 #endif
 
 #endif /* HAVE_SGEN_GC */
--- mono-3.2.1+dfsg.orig/mono/metadata/sgen-gc.c
+++ mono-3.2.1+dfsg/mono/metadata/sgen-gc.c
@@ -4865,6 +4865,7 @@ mono_gc_base_init (void)
 	init_stats ();
 	sgen_init_internal_allocator ();
 	sgen_init_nursery_allocator ();
+	sgen_init_fin_weak_hash ();
 
 	sgen_register_fixed_internal_mem_type (INTERNAL_MEM_SECTION, SGEN_SIZEOF_GC_MEM_SECTION);
 	sgen_register_fixed_internal_mem_type (INTERNAL_MEM_FINALIZE_READY_ENTRY, sizeof (FinalizeReadyEntry));
--- mono-3.2.1+dfsg.orig/mono/tests/sgen-descriptors.cs
+++ mono-3.2.1+dfsg/mono/tests/sgen-descriptors.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Runtime.InteropServices;
 
 public struct SmallMixed
 {
@@ -47,6 +48,13 @@ public class HugePtrFree {
 	public LargeStruct2 c;
 }
 
+[StructLayout (LayoutKind.Sequential)]
+public class Non32bitBitmap {
+	public object o;
+	public long i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31, i32, i33, i34, i35;
+	public object o2;
+}
+
 /*
 This is a stress test for descriptors.
 */
@@ -54,10 +62,10 @@ class Driver {
 	static char[] FOO = new char[] { 'f', 'o', 'b' };
 
 	static void Fill (int cycles) {
-		object[] root = new object [12];
+		object[] root = new object [13];
 		object[] current = root;
 		for (int i = 0; i < cycles; ++i) {
-			current [0] = new object [12];
+			current [0] = new object [13];
 			current [1] = new int [6];
 			current [2] = new int [2,3];
 			current [3] = new string (FOO);
@@ -72,6 +80,9 @@ class Driver {
 				current [10] = new HugePtrFree ();
 			if ((i %  10000) == 0)
 				current [11] = new LargeStruct2 [1];
+
+			/* Test for 64 bit bitmap descriptors (#14834) */
+			current [12] = new Non32bitBitmap () { o = new object (), i32 = 1, i33 = 1, i34 = 1, i35 = 1, o2 = new object () };
 	
 			current = (object[])current [0];
 		}
--- mono-3.2.1+dfsg.orig/mono/tests/Makefile.am
+++ mono-3.2.1+dfsg/mono/tests/Makefile.am
@@ -340,7 +340,6 @@ BASE_TEST_CS_SRC=		\
 	modules.cs	\
 	bug-81673.cs	\
 	bug-81691.cs	\
-	bug-80307.cs	\
 	bug-415577.cs	\
 	filter-stack.cs	\
 	vararg2.cs	\
--- mono-3.2.1+dfsg.orig/mono/utils/mono-sigcontext.h
+++ mono-3.2.1+dfsg/mono/utils/mono-sigcontext.h
@@ -16,14 +16,14 @@
 
 #if defined(TARGET_X86)
 
-#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__DragonFly__)
 #include <ucontext.h>
 #endif
 #if defined(__APPLE__)
 #include <AvailabilityMacros.h>
 #endif
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
 	#define UCONTEXT_REG_EAX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_eax)
 	#define UCONTEXT_REG_EBX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_ebx)
 	#define UCONTEXT_REG_ECX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_ecx)
@@ -154,7 +154,7 @@ typedef struct ucontext {
 
 #elif defined(TARGET_AMD64)
 
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 #include <ucontext.h>
 #endif
 
@@ -176,7 +176,7 @@ typedef struct ucontext {
 	#define UCONTEXT_REG_R13(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r13)
 	#define UCONTEXT_REG_R14(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r14)
 	#define UCONTEXT_REG_R15(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r15)
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 	#define UCONTEXT_REG_RAX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rax)
 	#define UCONTEXT_REG_RBX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rbx)
 	#define UCONTEXT_REG_RCX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rcx)
--- mono-3.2.1+dfsg.orig/mcs/class/Mono.WebBrowser/Mono.WebBrowser.dll.sources
+++ mono-3.2.1+dfsg/mcs/class/Mono.WebBrowser/Mono.WebBrowser.dll.sources
@@ -133,6 +133,9 @@ Mono.Mozilla/interfaces/nsIWebNavigation
 Mono.Mozilla/interfaces/extras/NodeType.cs
 Mono.Mozilla/interfaces/extras/nsIWriteSegmentFun.cs
 Mono.Mozilla/interfaces/extras/Options.cs
+Mono.NullBrowser/Base.cs
+Mono.NullBrowser/WebBrowser.cs
+Mono.NullBrowser/DOM/Navigation.cs
 Mono.WebBrowser/DOM/IDocumentType.cs
 Mono.WebBrowser/DOM/IDOMImplementation.cs
 Mono.WebBrowser/DOM/IMediaList.cs
--- /dev/null
+++ mono-3.2.1+dfsg/mcs/class/Mono.WebBrowser/Mono.NullBrowser/WebBrowser.cs
@@ -0,0 +1,414 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2007, 2008 Novell, Inc.
+// Copyright (c) 2013 Jo Shields
+//
+// Authors:
+//	Andreia Gaita (avidigal@novell.com)
+//	Jo Shields (directhex@apebox.org)
+//
+
+#undef debug
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Diagnostics;
+using Mono.WebBrowser;
+using Mono.WebBrowser.DOM;
+
+namespace Mono.NullBrowser
+{
+	internal class WebBrowser : IWebBrowser
+	{
+		bool loaded;
+		internal bool created = false;
+		bool creating = false;
+
+                internal DOM.Navigation navigation;
+
+		internal Platform platform;
+		internal Platform enginePlatform;
+		System.ComponentModel.EventHandlerList events;
+		System.ComponentModel.EventHandlerList domEvents;
+
+		string statusText;
+
+		bool streamingMode;
+		
+		internal Hashtable documents;
+
+		int width;
+		int height;
+		bool isDirty;
+		
+		public WebBrowser (Platform platform)
+		{
+			this.platform = platform;
+			loaded = Base.Init (this, platform);
+			documents = new Hashtable ();
+		}
+
+		public bool Load (IntPtr handle, int width, int height)
+		{
+			loaded = Base.Bind (this, handle, width, height);
+			return loaded;
+		}
+
+		bool Created {
+			get {
+				if (!creating && !created) {
+					creating = true;
+					created = Base.Create (this);
+					if (created && isDirty) {
+						isDirty = false;
+						Base.Resize (this, width, height);
+					}
+				}
+				return created;
+			}
+		}
+
+		public void Shutdown ()
+		{
+			Base.Shutdown (this);
+		}
+		
+		internal void Reset ()
+		{
+			this.DomEvents.Dispose ();
+			this.domEvents = null;
+			this.documents.Clear ();
+		}
+
+		public bool Initialized {
+			get { return this.loaded; }
+		}
+		
+		public IWindow Window {
+			get {
+				return null;
+			}
+		}
+
+		public IDocument Document {
+			get {
+				return null;
+			}
+		}
+
+		public INavigation Navigation {
+			get {
+                                if (!Created) return null;
+
+                                if (navigation == null) {
+
+                                        navigation = new DOM.Navigation ();
+                                }
+                                return navigation as INavigation;
+			}
+		}
+		
+		public string StatusText {
+			get { return statusText; }
+		}
+		
+		public bool Offline {
+			get {
+				return false;
+			}
+			set {
+			}
+		}
+		
+		internal System.ComponentModel.EventHandlerList DomEvents {
+			get {
+				if (domEvents == null)
+					domEvents = new System.ComponentModel.EventHandlerList();
+
+				return domEvents;
+			}
+		}
+
+		internal System.ComponentModel.EventHandlerList Events {
+			get {
+				if (events == null)
+					events = new System.ComponentModel.EventHandlerList();
+
+				return events;
+			}
+		}
+		
+		#region Layout
+		public void FocusIn (FocusOption focus)
+		{
+			if (!created) return;
+			Base.Focus (this, focus);
+		}
+		public void FocusOut ()
+		{
+			if (!created) return;
+			Base.Blur (this);
+		}
+		
+		public void Activate ()
+		{
+			if (!Created) return;
+			Base.Activate (this);
+		}
+		public void Deactivate ()
+		{
+			if (!created) return;
+			Base.Deactivate (this);
+		}
+
+		public void Resize (int width, int height)
+		{
+			this.width = width;
+			this.height = height;
+			isDirty = true;
+			if (!created) return;
+			Base.Resize (this, width, height);			
+		}
+
+		public void Render (byte[] data)
+		{
+			if (!Created) return;
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			string html = System.Text.ASCIIEncoding.UTF8.GetString (data);
+			Render (html);
+		}
+
+		public void Render (string html)
+		{
+			if (!Created) return;
+			Render (html, "file:///", "text/html");
+		}
+
+				
+		public void Render (string html, string uri, string contentType)
+		{
+			if (!Created) return;
+			throw new Mono.WebBrowser.Exception (Mono.WebBrowser.Exception.ErrorCodes.Navigation);
+
+			IntPtr native_html = Marshal.StringToHGlobalAnsi (html);
+			Marshal.FreeHGlobal (native_html);
+
+
+		}
+		
+		public void ExecuteScript (string script) {
+			if (!Created) return;
+			Base.EvalScript (this, script);
+		}
+				
+		internal void AttachEvent (INode node, string eve, EventHandler handler) {
+			string key = String.Intern (node.GetHashCode() + ":" + eve);
+#if debug
+			Console.Error.WriteLine ("Event Attached: " + key);
+#endif
+			DomEvents.AddHandler (key, handler);
+		}
+
+		internal void DetachEvent (INode node, string eve, EventHandler handler) {
+			string key = String.Intern (node.GetHashCode() + ":" + eve);
+#if debug			
+			Console.Error.WriteLine ("Event Detached: " + key);
+#endif			
+			DomEvents.RemoveHandler (key, handler);
+		}
+		
+		#endregion
+
+		#region Events
+		internal static object KeyDownEvent = new object ();
+		internal static object KeyPressEvent = new object ();
+		internal static object KeyUpEvent = new object ();
+		internal static object MouseClickEvent = new object ();
+		internal static object MouseDoubleClickEvent = new object ();
+		internal static object MouseDownEvent = new object ();
+		internal static object MouseEnterEvent = new object ();
+		internal static object MouseLeaveEvent = new object ();
+		internal static object MouseMoveEvent = new object ();
+		internal static object MouseUpEvent = new object ();
+		internal static object FocusEvent = new object ();
+		internal static object BlurEvent = new object ();
+		internal static object CreateNewWindowEvent = new object ();
+		internal static object AlertEvent = new object ();
+			
+		internal static object LoadStartedEvent = new object ();
+		internal static object LoadCommitedEvent = new object ();
+		internal static object ProgressChangedEvent = new object ();
+		internal static object LoadFinishedEvent = new object ();	
+		
+		internal static object LoadEvent = new object ();
+		internal static object UnloadEvent = new object ();
+		internal static object StatusChangedEvent = new object ();
+		internal static object SecurityChangedEvent = new object ();
+		internal static object ProgressEvent = new object ();
+		internal static object ContextMenuEvent = new object ();
+		
+		internal static object NavigationRequestedEvent = new object ();
+		
+		public event NodeEventHandler KeyDown
+		{
+			add { Events.AddHandler (KeyDownEvent, value); }
+			remove { Events.RemoveHandler (KeyDownEvent, value); }
+		}
+
+		public event NodeEventHandler KeyPress
+		{
+			add { Events.AddHandler (KeyPressEvent, value); }
+			remove { Events.RemoveHandler (KeyPressEvent, value); }
+		}
+		public event NodeEventHandler KeyUp
+		{
+			add { Events.AddHandler (KeyUpEvent, value); }
+			remove { Events.RemoveHandler (KeyUpEvent, value); }
+		}
+		public event NodeEventHandler MouseClick
+		{
+			add { Events.AddHandler (MouseClickEvent, value); }
+			remove { Events.RemoveHandler (MouseClickEvent, value); }
+		}
+		public event NodeEventHandler MouseDoubleClick
+		{
+			add { Events.AddHandler (MouseDoubleClickEvent, value); }
+			remove { Events.RemoveHandler (MouseDoubleClickEvent, value); }
+		}
+		public event NodeEventHandler MouseDown
+		{
+			add { Events.AddHandler (MouseDownEvent, value); }
+			remove { Events.RemoveHandler (MouseDownEvent, value); }
+		}
+		public event NodeEventHandler MouseEnter
+		{
+			add { Events.AddHandler (MouseEnterEvent, value); }
+			remove { Events.RemoveHandler (MouseEnterEvent, value); }
+		}
+		public event NodeEventHandler MouseLeave
+		{
+			add { Events.AddHandler (MouseLeaveEvent, value); }
+			remove { Events.RemoveHandler (MouseLeaveEvent, value); }
+		}
+		public event NodeEventHandler MouseMove
+		{
+			add { Events.AddHandler (MouseMoveEvent, value); }
+			remove { Events.RemoveHandler (MouseMoveEvent, value); }
+		}
+		public event NodeEventHandler MouseUp
+		{
+			add { Events.AddHandler (MouseUpEvent, value); }
+			remove { Events.RemoveHandler (MouseUpEvent, value); }
+		}
+		public event EventHandler Focus
+		{
+			add { Events.AddHandler (FocusEvent, value); }
+			remove { Events.RemoveHandler (FocusEvent, value); }
+		}
+		public event EventHandler Blur
+		{
+			add { Events.AddHandler (BlurEvent, value); }
+			remove { Events.RemoveHandler (BlurEvent, value); }
+		}
+		public event CreateNewWindowEventHandler CreateNewWindow
+		{
+			add { Events.AddHandler (CreateNewWindowEvent, value); }
+			remove { Events.RemoveHandler (CreateNewWindowEvent, value); }
+		}
+		public event AlertEventHandler Alert
+		{
+			add { Events.AddHandler (AlertEvent, value); }
+			remove { Events.RemoveHandler (AlertEvent, value); }
+		}
+		public event EventHandler Loaded
+		{
+			add { Events.AddHandler (LoadEvent, value); }
+			remove { Events.RemoveHandler (LoadEvent, value); }
+		}
+		public event EventHandler Unloaded
+		{
+			add { Events.AddHandler (UnloadEvent, value); }
+			remove { Events.RemoveHandler (UnloadEvent, value); }
+		}
+
+ 		public event StatusChangedEventHandler StatusChanged
+		{
+			add { Events.AddHandler (StatusChangedEvent, value); }
+			remove { Events.RemoveHandler (StatusChangedEvent, value); }
+		}
+		
+ 		public event SecurityChangedEventHandler SecurityChanged
+		{
+			add { Events.AddHandler (SecurityChangedEvent, value); }
+			remove { Events.RemoveHandler (SecurityChangedEvent, value); }
+		}
+
+		public event LoadStartedEventHandler LoadStarted
+		{
+			add { Events.AddHandler (LoadStartedEvent, value); }
+			remove { Events.RemoveHandler (LoadStartedEvent, value); }
+		}
+		
+		public event LoadCommitedEventHandler LoadCommited
+		{
+			add { Events.AddHandler (LoadCommitedEvent, value); }
+			remove { Events.RemoveHandler (LoadCommitedEvent, value); }
+		}		
+		
+		public event ProgressChangedEventHandler ProgressChanged
+		{
+			add { Events.AddHandler (ProgressChangedEvent, value); }
+			remove { Events.RemoveHandler (ProgressChangedEvent, value); }
+		}
+		
+		public event LoadFinishedEventHandler LoadFinished
+		{
+			add { Events.AddHandler (LoadFinishedEvent, value); }
+			remove { Events.RemoveHandler (LoadFinishedEvent, value); }
+		}
+
+		public event ContextMenuEventHandler ContextMenuShown
+		{
+			add { Events.AddHandler (ContextMenuEvent, value); }
+			remove { Events.RemoveHandler (ContextMenuEvent, value); }
+		}
+
+		public event NavigationRequestedEventHandler NavigationRequested
+		{
+			add { }
+			remove { }
+		}
+
+		internal static object GenericEvent = new object ();
+		internal event EventHandler Generic
+		{
+			add { Events.AddHandler (GenericEvent, value); }
+			remove { Events.RemoveHandler (GenericEvent, value); }
+		}
+
+		#endregion
+
+
+	}
+}
--- /dev/null
+++ mono-3.2.1+dfsg/mcs/class/Mono.WebBrowser/Mono.NullBrowser/Base.cs
@@ -0,0 +1,174 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2007, 2008 Novell, Inc.
+//
+// Authors:
+//	Andreia Gaita (avidigal@novell.com)
+//
+
+using System;
+using System.Text;
+using System.Collections;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using Mono.WebBrowser;
+
+namespace Mono.NullBrowser
+{
+	internal class Base
+	{
+		private static Hashtable boundControls;
+		private static bool initialized;
+		private static object initLock = new object ();
+		private static string monoMozDir;
+
+		private static bool isInitialized ()
+		{
+			if (!initialized)
+				return false;
+			return true;
+		}
+
+		static Base ()
+		{
+			boundControls = new Hashtable ();
+		}
+
+		public Base () { }
+
+		public static bool Init (WebBrowser control, Platform platform)
+		{
+			lock (initLock) {
+				if (!initialized) {
+				
+					initialized = true;
+				}
+			}
+			return initialized;
+		}
+
+		public static bool Bind (WebBrowser control, IntPtr handle, int width, int height)
+		{
+			if (!isInitialized ())
+				return false;
+
+			
+			return true;
+		}
+
+		public static bool Create (IWebBrowser control) {
+			if (!isInitialized ())
+				return false;
+
+			return true;
+		}
+
+		public static void Shutdown (IWebBrowser control)
+		{
+			lock (initLock) {
+				if (!initialized)
+					return;
+					
+				
+				boundControls.Remove (control);
+				if (boundControls.Count == 0) {
+					initialized = false;
+				}
+			}
+		}
+
+		// layout
+		public static void Focus (IWebBrowser control, FocusOption focus)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+
+		public static void Blur (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		public static void Activate (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		public static void Deactivate (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		public static void Resize (IWebBrowser control, int width, int height)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		// navigation
+		public static void Home (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+
+		public static IntPtr StringInit ()
+		{
+			return IntPtr.Zero;
+		}
+
+		public static void StringFinish (HandleRef str)
+		{
+		}
+
+		public static string StringGet (HandleRef str)
+		{
+			return String.Empty;
+		}
+
+		public static void StringSet (HandleRef str, string text)
+		{
+		}
+
+
+		public static object GetProxyForObject (IWebBrowser control, Guid iid, object obj)
+		{
+			return null;
+		}
+
+		public static string EvalScript (IWebBrowser control, string script)
+		{
+			return null;
+		}
+
+
+	}
+}
--- /dev/null
+++ mono-3.2.1+dfsg/mcs/class/Mono.WebBrowser/Mono.NullBrowser/DOM/Navigation.cs
@@ -0,0 +1,127 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2007, 2008 Novell, Inc.
+//
+// Authors:
+//	Andreia Gaita (avidigal@novell.com)
+//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using Mono.WebBrowser;
+using Mono.WebBrowser.DOM;
+
+namespace Mono.NullBrowser.DOM
+{
+	internal class Navigation: INavigation
+	{
+
+
+		#region INavigation Members
+
+		public bool CanGoBack {
+			get {
+				return false;
+			}
+		}
+
+		public bool CanGoForward {
+			get {
+				return false;
+			}
+		}
+
+		public bool Back ()
+		{
+			return false;
+		}
+
+		public bool Forward ()
+		{
+			return false;
+		}
+
+		public void Home ()
+		{
+		}
+
+		public void Reload ()
+		{
+		}
+
+		public void Reload (ReloadOption option)
+		{
+		}
+
+		public void Stop ()
+		{
+		}
+		
+		
+		/// <summary>
+		/// Navigate to the page in the history, by index.
+		/// </summary>
+		/// <param name="index">
+		/// A <see cref="System.Int32"/> representing an absolute index in the 
+		/// history (that is, > -1 and < history length
+		/// </param>
+		public void Go (int index)
+		{
+		}
+
+		/// <summary>
+		/// 
+		/// </summary>
+		/// <param name="index">
+		/// A <see cref="System.Int32"/> representing an index in the 
+		/// history, that can be relative or absolute depending on the relative argument
+		/// </param>
+		/// <param name="relative">
+		/// A <see cref="System.Boolean"/> indicating whether the index is relative to 
+		/// the current place in history or not (i.e., if relative = true, index can be
+		/// positive or negative, and index=-1 means load the previous page in the history.
+		/// if relative = false, index must be > -1, and index = 0 means load the first
+		/// page of the history.
+		/// </param>
+		public void Go (int index, bool relative) {
+		}
+		
+		public void Go (string url)
+		{
+		}
+
+		public void Go (string url, LoadFlags flags) 
+		{
+		}
+
+		public int HistoryCount {
+			get {
+				return 0;
+			}
+		}
+
+		#endregion
+
+		public override int GetHashCode () {
+			return 0;
+		}		
+	}
+}
--- mono-3.2.1+dfsg.orig/mcs/class/Mono.WebBrowser/Mono.WebBrowser/Manager.cs
+++ mono-3.2.1+dfsg/mcs/class/Mono.WebBrowser/Mono.WebBrowser/Manager.cs
@@ -52,8 +52,15 @@ namespace Mono.WebBrowser
 				}
 			}
 #endif
-			if (browserEngine == null || browserEngine == "mozilla")
-				return new Mono.Mozilla.WebBrowser (platform);
+			if (browserEngine == "mozilla") {
+				try {
+					return new Mono.Mozilla.WebBrowser (platform);
+				} catch {
+					browserEngine = null;
+				}
+			}
+			if (browserEngine == null)
+				return new Mono.NullBrowser.WebBrowser (platform);
 			throw new Exception (Mono.WebBrowser.Exception.ErrorCodes.EngineNotSupported, browserEngine);
 		}
 
--- mono-3.2.1+dfsg.orig/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Engine.cs
+++ mono-3.2.1+dfsg/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Engine.cs
@@ -553,14 +553,16 @@ namespace Microsoft.Build.BuildEngine {
 
 		public string DefaultToolsVersion {
 			get {
-				// This is used as the fall back version if the
-				// project can't find a version to use
-				// Hard-coded to 2.0, so it allows even vs2005 projects
-				// to build correctly, as they won't have a ToolsVersion
-				// set!
-				return String.IsNullOrEmpty (defaultToolsVersion)
-						? "2.0"
-						: defaultToolsVersion;
+				if (String.IsNullOrEmpty (defaultToolsVersion))
+#if NET_4_0
+					return "4.0";
+#elif NET_3_5
+					return "3.5";
+#else
+					return "2.0";
+#endif
+				
+				return defaultToolsVersion;
 			}
 			set {
 				if (Toolsets [value] == null)
--- mono-3.2.1+dfsg.orig/mcs/class/corlib/System/Console.cs
+++ mono-3.2.1+dfsg/mcs/class/corlib/System/Console.cs
@@ -133,8 +133,7 @@ namespace System
 				int code_page = 0;
 				Encoding.InternalCodePage (ref code_page);
 
-				if (code_page != -1 && ((code_page & 0x0fffffff) == 3 // UTF8Encoding.UTF8_CODE_PAGE
-					|| ((code_page & 0x10000000) != 0)))
+				if (code_page == UTF8Encoding.UTF8_CODE_PAGE || ((code_page & 0x10000000) != 0))
 					inputEncoding = outputEncoding = Encoding.UTF8Unmarked;
 				else
 					inputEncoding = outputEncoding = Encoding.Default;
--- mono-3.2.1+dfsg.orig/eglib/src/giconv.c
+++ mono-3.2.1+dfsg/eglib/src/giconv.c
@@ -901,7 +901,7 @@ eg_utf8_to_utf16_general (const gchar *s
 	size_t inleft;
 	char *inptr;
 	gunichar c;
-	int n;
+	int u, n;
 	
 	g_return_val_if_fail (str != NULL, NULL);
 	
@@ -910,6 +910,7 @@ eg_utf8_to_utf16_general (const gchar *s
 			g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, "Conversions with embedded nulls must pass the string length");
 			return NULL;
 		}
+		
 		len = strlen (str);
 	}
 	
@@ -917,29 +918,18 @@ eg_utf8_to_utf16_general (const gchar *s
 	inleft = len;
 	
 	while (inleft > 0) {
-		if ((n = decode_utf8 (inptr, inleft, &c)) < 0) {
-			if (errno == EILSEQ) {
-				g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
-					     "Illegal byte sequence encounted in the input.");
-			} else if (items_read) {
-				/* partial input is ok if we can let our caller know... */
-				break;
-			} else {
-				g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
-					     "Partial byte sequence encountered in the input.");
-			}
-			
-			if (items_read)
-				*items_read = inptr - str;
-			
-			if (items_written)
-				*items_written = 0;
-			
-			return NULL;
-		} else if (c == 0 && !include_nuls)
+		if ((n = decode_utf8 (inptr, inleft, &c)) < 0)
+			goto error;
+		
+		if (c == 0 && !include_nuls)
 			break;
 		
-		outlen += g_unichar_to_utf16 (c, NULL);
+		if ((u = g_unichar_to_utf16 (c, NULL)) < 0) {
+			errno = EILSEQ;
+			goto error;
+		}
+		
+		outlen += u;
 		inleft -= n;
 		inptr += n;
 	}
@@ -957,7 +947,8 @@ eg_utf8_to_utf16_general (const gchar *s
 	while (inleft > 0) {
 		if ((n = decode_utf8 (inptr, inleft, &c)) < 0)
 			break;
-		else if (c == 0 && !include_nuls)
+		
+		if (c == 0 && !include_nuls)
 			break;
 		
 		outptr += g_unichar_to_utf16 (c, outptr);
@@ -968,6 +959,25 @@ eg_utf8_to_utf16_general (const gchar *s
 	*outptr = '\0';
 	
 	return outbuf;
+	
+ error:
+	if (errno == EILSEQ) {
+		g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+			     "Illegal byte sequence encounted in the input.");
+	} else if (items_read) {
+		/* partial input is ok if we can let our caller know... */
+	} else {
+		g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
+			     "Partial byte sequence encountered in the input.");
+	}
+	
+	if (items_read)
+		*items_read = inptr - str;
+	
+	if (items_written)
+		*items_written = 0;
+	
+	return NULL;
 }
 
 gunichar2 *
--- mono-3.2.1+dfsg.orig/data/mono.pc.in
+++ mono-3.2.1+dfsg/data/mono.pc.in
@@ -1,5 +1,5 @@
-prefix=${pcfiledir}/../..
-exec_prefix=${pcfiledir}/../..
+prefix=@prefix@
+exec_prefix=${prefix}
 libdir=${prefix}/@reloc_libdir@
 includedir=${prefix}/include/mono-@API_VER@
 sysconfdir=@sysconfdir@
--- mono-3.2.1+dfsg.orig/data/mono-cairo.pc.in
+++ mono-3.2.1+dfsg/data/mono-cairo.pc.in
@@ -1,5 +1,5 @@
-prefix=${pcfiledir}/../..
-exec_prefix=${pcfiledir}/../..
+prefix=@prefix@
+exec_prefix=${prefix}
 libdir=${prefix}/@reloc_libdir@
 includedir=${prefix}/include
 
--- mono-3.2.1+dfsg.orig/tools/sgen/sgen-grep-binprot.c
+++ mono-3.2.1+dfsg/tools/sgen/sgen-grep-binprot.c
@@ -44,6 +44,8 @@ read_entry (FILE *in, void **data)
 	case SGEN_PROTOCOL_CEMENT: size = sizeof (SGenProtocolCement); break;
 	case SGEN_PROTOCOL_CEMENT_RESET: size = 0; break;
 	case SGEN_PROTOCOL_DISLINK_UPDATE: size = sizeof (SGenProtocolDislinkUpdate); break;
+	case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: size = sizeof (SGenProtocolDislinkUpdateStaged); break;
+	case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: size = sizeof (SGenProtocolDislinkProcessStaged); break;
 	default: assert (0);
 	}
 
@@ -185,13 +187,27 @@ print_entry (int type, void *data)
 	}
 	case SGEN_PROTOCOL_DISLINK_UPDATE: {
 		SGenProtocolDislinkUpdate *entry = data;
-		printf ("dislink_update link %p obj %p", entry->link, entry->obj);
+		printf ("dislink_update link %p obj %p staged %d", entry->link, entry->obj, entry->staged);
 		if (entry->obj)
 			printf (" track %d\n", entry->track);
 		else
 			printf ("\n");
 		break;
 	}
+	case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
+		SGenProtocolDislinkUpdateStaged *entry = data;
+		printf ("dislink_update_staged link %p obj %p index %d", entry->link, entry->obj, entry->index);
+		if (entry->obj)
+			printf (" track %d\n", entry->track);
+		else
+			printf ("\n");
+		break;
+	}
+	case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
+		SGenProtocolDislinkProcessStaged *entry = data;
+		printf ("dislink_process_staged link %p obj %p index %d\n", entry->link, entry->obj, entry->index);
+		break;
+	}
 	default:
 		assert (0);
 	}
@@ -280,6 +296,14 @@ is_match (gpointer ptr, int type, void *
 		SGenProtocolDislinkUpdate *entry = data;
 		return ptr == entry->obj || ptr == entry->link;
 	}
+	case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
+		SGenProtocolDislinkUpdateStaged *entry = data;
+		return ptr == entry->obj || ptr == entry->link;
+	}
+	case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
+		SGenProtocolDislinkProcessStaged *entry = data;
+		return ptr == entry->obj || ptr == entry->link;
+	}
 	default:
 		assert (0);
 	}
--- mono-3.2.1+dfsg.orig/libgc/configure.in
+++ mono-3.2.1+dfsg/libgc/configure.in
@@ -114,6 +114,17 @@ case "$THREADS" in
 	AC_DEFINE(THREAD_LOCAL_ALLOC)
 	THREADDLLIBS="-lpthread -lrt"
 	;;
+     *-*-kfreebsd*-gnu)
+	AC_DEFINE(GC_FREEBSD_THREADS)
+	INCLUDES="$INCLUDES -pthread"
+	THREADDLLIBS=-pthread
+	AC_DEFINE(_REENTRANT)
+	if test "${enable_parallel_mark}" = yes; then
+		AC_DEFINE(PARALLEL_MARK)
+	fi
+	AC_DEFINE(THREAD_LOCAL_ALLOC)
+	AC_DEFINE(USE_COMPILER_TLS)
+	;;
       *-*-freebsd*)
 	AC_DEFINE(GC_FREEBSD_THREADS)
 	if test "x$PTHREAD_CFLAGS" != "x"; then
--- mono-3.2.1+dfsg.orig/libgc/dyn_load.c
+++ mono-3.2.1+dfsg/libgc/dyn_load.c
@@ -26,7 +26,7 @@
  * None of this is safe with dlclose and incremental collection.
  * But then not much of anything is safe in the presence of dlclose.
  */
-#if (defined(__linux__) || defined(__native_client__)) && !defined(_GNU_SOURCE)
+#if (defined(__linux__) || defined(__GLIBC__) || defined(__native_client__)) && !defined(_GNU_SOURCE)
     /* Can't test LINUX, since this must be define before other includes */
 #   define _GNU_SOURCE
 #endif
@@ -394,7 +394,7 @@ GC_bool GC_register_main_static_data()
 /* For glibc 2.2.4+.  Unfortunately, it doesn't work for older	*/
 /* versions.  Thanks to Jakub Jelinek for most of the code.	*/
 
-# if (defined(LINUX) || defined(NACL)) /* Are others OK here, too? */ \
+# if (defined(LINUX) || defined (__GLIBC__) || defined(NACL)) /* Are others OK here, too? */ \
      && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
          || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) 
 
--- mono-3.2.1+dfsg.orig/libgc/include/gc.h
+++ mono-3.2.1+dfsg/libgc/include/gc.h
@@ -493,7 +493,7 @@ GC_API GC_PTR GC_malloc_atomic_ignore_of
 #   define GC_RETURN_ADDR (GC_word)__return_address
 #endif
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__GLIBC__)
 # include <features.h>
 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
      && !defined(__ia64__)
--- mono-3.2.1+dfsg.orig/libgc/include/private/gcconfig.h
+++ mono-3.2.1+dfsg/libgc/include/private/gcconfig.h
@@ -55,7 +55,7 @@
 # endif
 
 /* And one for FreeBSD: */
-# if defined(__FreeBSD__) && !defined(FREEBSD)
+# if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !defined(FREEBSD)
 #    define FREEBSD
 # endif
 
@@ -1371,8 +1371,15 @@
 #	ifndef GC_FREEBSD_THREADS
 #	    define MPROTECT_VDB
 #	endif
-#      define SIG_SUSPEND SIGTSTP
-#      define SIG_THR_RESTART SIGCONT
+#       ifdef __GLIBC__
+#           define SIG_SUSPEND          (32+6)
+#           define SIG_THR_RESTART      (32+5)
+            extern int _end[];
+#           define DATAEND (_end)
+#       else
+#           define SIG_SUSPEND SIGTSTP
+#           define SIG_THR_RESTART SIGCONT
+#       endif
 #	define FREEBSD_STACKBOTTOM
 #	ifdef __ELF__
 #	    define DYNAMIC_LOADING
@@ -2143,6 +2150,28 @@
 	extern char * GC_FreeBSDGetDataStart();
 #	define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
 #   endif
+#   ifdef FREEBSD
+#	define OS_TYPE "FREEBSD"
+#	ifndef GC_FREEBSD_THREADS
+#	    define MPROTECT_VDB
+#	endif
+#	ifdef __GLIBC__
+#	    define SIG_SUSPEND		(32+6)
+#	    define SIG_THR_RESTART	(32+5)
+	    extern int _end[];
+#	    define DATAEND (_end)
+#	else
+#	    define SIG_SUSPEND SIGUSR1
+#	    define SIG_THR_RESTART SIGUSR2
+#	endif
+#	define FREEBSD_STACKBOTTOM
+#	ifdef __ELF__
+#	    define DYNAMIC_LOADING
+#	endif
+	extern char etext[];
+	extern char * GC_FreeBSDGetDataStart();
+#	define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
+#   endif
 #   ifdef NETBSD
 #	define OS_TYPE "NETBSD"
 #	ifdef __ELF__
@@ -2230,7 +2259,7 @@
 #   define SUNOS5SIGS
 # endif
 
-# if defined(FREEBSD) && (__FreeBSD__ >= 4)
+# if defined(FREEBSD) && ((__FreeBSD__ >= 4) || (__FreeBSD_kernel__ >= 4))
 #   define SUNOS5SIGS
 # endif
 
@@ -2293,7 +2322,7 @@
 #   define CACHE_LINE_SIZE 32	/* Wild guess	*/
 # endif
 
-# ifdef LINUX
+# if defined(LINUX) || defined(__GLIBC__)
 #   define REGISTER_LIBRARIES_EARLY
     /* We sometimes use dl_iterate_phdr, which may acquire an internal	*/
     /* lock.  This isn't safe after the world has stopped.  So we must	*/
@@ -2374,7 +2403,7 @@
 #if defined(SPARC)
 # define CAN_SAVE_CALL_ARGS
 #endif
-#if (defined(I386) || defined(X86_64)) && defined(LINUX)
+#if (defined(I386) || defined(X86_64)) && (defined(LINUX) || defined(__GLIBC__))
 	    /* SAVE_CALL_CHAIN is supported if the code is compiled to save	*/
 	    /* frame pointers by default, i.e. no -fomit-frame-pointer flag.	*/
 # define CAN_SAVE_CALL_ARGS
--- mono-3.2.1+dfsg.orig/support/syslog.c
+++ mono-3.2.1+dfsg/support/syslog.c
@@ -38,7 +38,16 @@ Mono_Posix_Syscall_closelog (void)
 int
 Mono_Posix_Syscall_syslog (int priority, const char* message)
 {
+#ifdef __GNUC__
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wformat-security"
+#endif
+
 	syslog (priority, message);
+
+#ifdef __GNUC__
+	#pragma GCC diagnostic pop
+#endif
 	return 0;
 }
 
