[132917] trunk/dports/devel/ld64

jeremyhu at macports.org jeremyhu at macports.org
Fri Feb 13 00:55:20 PST 2015


Revision: 132917
          https://trac.macports.org/changeset/132917
Author:   jeremyhu at macports.org
Date:     2015-02-13 00:55:20 -0800 (Fri, 13 Feb 2015)
Log Message:
-----------
ld64-97: Move the large ld64-97-standalone-libunwind-headers.patch to distfiles

Modified Paths:
--------------
    trunk/dports/devel/ld64/Portfile

Removed Paths:
-------------
    trunk/dports/devel/ld64/files/ld64-97-standalone-libunwind-headers.patch

Modified: trunk/dports/devel/ld64/Portfile
===================================================================
--- trunk/dports/devel/ld64/Portfile	2015-02-13 08:53:30 UTC (rev 132916)
+++ trunk/dports/devel/ld64/Portfile	2015-02-13 08:55:20 UTC (rev 132917)
@@ -20,7 +20,11 @@
     # XCode 3.2.6
     version             97.17
 
-    checksums           rmd160  d52df7d7f741c8bedd29cbac73dbb9db992b4795 \
+    checksums           ld64-97-standalone-libunwind-headers.patch \
+                        rmd160  f6da71e097aa61b1055b3fdc12cd39aafed5f492 \
+                        sha256  370d02757ea628b5dd145c099e42fc4eb88cc09cf459a59e32d14bbc9b4a105e \
+                        ld64-97.17.tar.gz \
+                        rmd160  d52df7d7f741c8bedd29cbac73dbb9db992b4795 \
                         sha256  02bd46af0809eaa415d096d7d41c3e8e7d80f7d8d181840866fb87f036b4e089
 
     set makefile	"Makefile-97"

Deleted: trunk/dports/devel/ld64/files/ld64-97-standalone-libunwind-headers.patch
===================================================================
--- trunk/dports/devel/ld64/files/ld64-97-standalone-libunwind-headers.patch	2015-02-13 08:53:30 UTC (rev 132916)
+++ trunk/dports/devel/ld64/files/ld64-97-standalone-libunwind-headers.patch	2015-02-13 08:55:20 UTC (rev 132917)
@@ -1,4438 +0,0 @@
-From ce433767d79be40375b69dd3139d04978401df3d Mon Sep 17 00:00:00 2001
-From: Nick Kledzik <kledzik at apple.com>
-Date: Fri, 18 Mar 2011 20:57:25 +0000
-Subject: [PATCH] ld64 should build stand-alone and not need libunwind headers
-
-(cherry picked from commit 231841085f71586b0b2d8f6b63b9317783e80c9e)
----
- src/ld/MachOReaderRelocatable.hpp              |    6 +-
- src/ld/dwarf2.h                                |  219 +++
- src/ld/parsers/libunwind/AddressSpace.hpp      |  439 ++++++
- src/ld/parsers/libunwind/DwarfInstructions.hpp | 1726 ++++++++++++++++++++++++
- src/ld/parsers/libunwind/DwarfParser.hpp       |  819 +++++++++++
- src/ld/parsers/libunwind/InternalMacros.h      |  105 ++
- src/ld/parsers/libunwind/Registers.hpp         | 1050 ++++++++++++++
- 7 files changed, 4361 insertions(+), 3 deletions(-)
- create mode 100644 src/ld/parsers/libunwind/AddressSpace.hpp
- create mode 100644 src/ld/parsers/libunwind/DwarfInstructions.hpp
- create mode 100644 src/ld/parsers/libunwind/DwarfParser.hpp
- create mode 100644 src/ld/parsers/libunwind/InternalMacros.h
- create mode 100644 src/ld/parsers/libunwind/Registers.hpp
-
-diff --git a/src/ld/MachOReaderRelocatable.hpp b/src/ld/MachOReaderRelocatable.hpp
-index 2aa7926..b8e5960 100644
---- src/ld/MachOReaderRelocatable.hpp
-+++ src/ld/MachOReaderRelocatable.hpp
-@@ -40,9 +40,9 @@
- #include "dwarf2.h"
- #include "debugline.h"
- 
--#include <libunwind/DwarfInstructions.hpp>
--#include <libunwind/AddressSpace.hpp>
--#include <libunwind/Registers.hpp>
-+#include "libunwind/DwarfInstructions.hpp"
-+#include "libunwind/AddressSpace.hpp"
-+#include "libunwind/Registers.hpp"
- 
- //
- //
-diff --git a/src/ld/dwarf2.h b/src/ld/dwarf2.h
-index 7a7b4f2..411dbbc 100644
---- src/ld/dwarf2.h
-+++ src/ld/dwarf2.h
-@@ -87,4 +87,223 @@ enum {
-   DW_LNE_define_file
- };
- 
-+
-+// dwarf unwind instructions
-+enum {
-+	DW_CFA_nop                 = 0x0,
-+	DW_CFA_set_loc             = 0x1,
-+	DW_CFA_advance_loc1        = 0x2,
-+	DW_CFA_advance_loc2        = 0x3,
-+	DW_CFA_advance_loc4        = 0x4,
-+	DW_CFA_offset_extended     = 0x5,
-+	DW_CFA_restore_extended    = 0x6,
-+	DW_CFA_undefined           = 0x7,
-+	DW_CFA_same_value          = 0x8,
-+	DW_CFA_register            = 0x9,
-+	DW_CFA_remember_state      = 0xA,
-+	DW_CFA_restore_state       = 0xB,
-+	DW_CFA_def_cfa             = 0xC,
-+	DW_CFA_def_cfa_register    = 0xD,
-+	DW_CFA_def_cfa_offset      = 0xE,
-+	DW_CFA_def_cfa_expression  = 0xF,
-+	DW_CFA_expression         = 0x10,
-+	DW_CFA_offset_extended_sf = 0x11,
-+	DW_CFA_def_cfa_sf         = 0x12,
-+	DW_CFA_def_cfa_offset_sf  = 0x13,
-+	DW_CFA_val_offset         = 0x14,
-+	DW_CFA_val_offset_sf      = 0x15,
-+	DW_CFA_val_expression     = 0x16,
-+	DW_CFA_advance_loc        = 0x40, // high 2 bits are 0x1, lower 6 bits are delta
-+	DW_CFA_offset             = 0x80, // high 2 bits are 0x2, lower 6 bits are register
-+	DW_CFA_restore            = 0xC0, // high 2 bits are 0x3, lower 6 bits are register
-+	
-+	// GNU extensions
-+    DW_CFA_GNU_window_save				= 0x2D,
-+    DW_CFA_GNU_args_size				= 0x2E,
-+    DW_CFA_GNU_negative_offset_extended = 0x2F
-+};
-+
-+
-+// FSF exception handling Pointer-Encoding constants 
-+// Used in CFI augmentation by gcc compiler
-+enum {
-+	DW_EH_PE_ptr       = 0x00,
-+	DW_EH_PE_uleb128   = 0x01,
-+	DW_EH_PE_udata2    = 0x02,
-+	DW_EH_PE_udata4    = 0x03,
-+	DW_EH_PE_udata8    = 0x04,
-+	DW_EH_PE_signed    = 0x08,
-+	DW_EH_PE_sleb128   = 0x09,
-+	DW_EH_PE_sdata2    = 0x0A,
-+	DW_EH_PE_sdata4    = 0x0B,
-+	DW_EH_PE_sdata8    = 0x0C,
-+	DW_EH_PE_absptr    = 0x00,
-+	DW_EH_PE_pcrel     = 0x10,
-+	DW_EH_PE_textrel   = 0x20,
-+	DW_EH_PE_datarel   = 0x30,
-+	DW_EH_PE_funcrel   = 0x40,
-+	DW_EH_PE_aligned   = 0x50,
-+	DW_EH_PE_indirect  = 0x80,
-+	DW_EH_PE_omit      = 0xFF
-+};
-+
-+
-+// DWARF  expressions
-+enum {
-+	DW_OP_addr               = 0x03, // constant address (size target specific)
-+	DW_OP_deref              = 0x06,
-+	DW_OP_const1u            = 0x08, // 1-byte constant
-+	DW_OP_const1s            = 0x09, // 1-byte constant
-+	DW_OP_const2u            = 0x0A, // 2-byte constant
-+	DW_OP_const2s            = 0x0B, // 2-byte constant
-+	DW_OP_const4u            = 0x0C, // 4-byte constant
-+	DW_OP_const4s            = 0x0D, // 4-byte constant
-+	DW_OP_const8u            = 0x0E, // 8-byte constant
-+	DW_OP_const8s            = 0x0F, // 8-byte constant
-+	DW_OP_constu             = 0x10, // ULEB128 constant
-+	DW_OP_consts             = 0x11, // SLEB128 constant
-+	DW_OP_dup                = 0x12,
-+	DW_OP_drop               = 0x13,
-+	DW_OP_over               = 0x14,
-+	DW_OP_pick               = 0x15, // 1-byte stack index
-+	DW_OP_swap               = 0x16,
-+	DW_OP_rot                = 0x17,
-+	DW_OP_xderef             = 0x18,
-+	DW_OP_abs                = 0x19,
-+	DW_OP_and                = 0x1A,
-+	DW_OP_div                = 0x1B,
-+	DW_OP_minus              = 0x1C,
-+	DW_OP_mod                = 0x1D,
-+	DW_OP_mul                = 0x1E,
-+	DW_OP_neg                = 0x1F,
-+	DW_OP_not                = 0x20,
-+	DW_OP_or                 = 0x21,
-+	DW_OP_plus               = 0x22,
-+	DW_OP_plus_uconst        = 0x23, // ULEB128 addend
-+	DW_OP_shl                = 0x24,
-+	DW_OP_shr                = 0x25,
-+	DW_OP_shra               = 0x26,
-+	DW_OP_xor                = 0x27,
-+	DW_OP_skip               = 0x2F, // signed 2-byte constant
-+	DW_OP_bra                = 0x28, // signed 2-byte constant
-+	DW_OP_eq                 = 0x29,
-+	DW_OP_ge                 = 0x2A,
-+	DW_OP_gt                 = 0x2B,
-+	DW_OP_le                 = 0x2C,
-+	DW_OP_lt                 = 0x2D,
-+	DW_OP_ne                 = 0x2E,
-+	DW_OP_lit0               = 0x30, // Literal 0
-+	DW_OP_lit1               = 0x31, // Literal 1
-+	DW_OP_lit2               = 0x32, // Literal 2
-+	DW_OP_lit3               = 0x33, // Literal 3
-+	DW_OP_lit4               = 0x34, // Literal 4
-+	DW_OP_lit5               = 0x35, // Literal 5
-+	DW_OP_lit6               = 0x36, // Literal 6
-+	DW_OP_lit7               = 0x37, // Literal 7
-+	DW_OP_lit8               = 0x38, // Literal 8
-+	DW_OP_lit9               = 0x39, // Literal 9
-+	DW_OP_lit10              = 0x3A, // Literal 10
-+	DW_OP_lit11              = 0x3B, // Literal 11
-+	DW_OP_lit12              = 0x3C, // Literal 12
-+	DW_OP_lit13              = 0x3D, // Literal 13
-+	DW_OP_lit14              = 0x3E, // Literal 14
-+	DW_OP_lit15              = 0x3F, // Literal 15
-+	DW_OP_lit16              = 0x40, // Literal 16
-+	DW_OP_lit17              = 0x41, // Literal 17
-+	DW_OP_lit18              = 0x42, // Literal 18
-+	DW_OP_lit19              = 0x43, // Literal 19
-+	DW_OP_lit20              = 0x44, // Literal 20
-+	DW_OP_lit21              = 0x45, // Literal 21
-+	DW_OP_lit22              = 0x46, // Literal 22
-+	DW_OP_lit23              = 0x47, // Literal 23
-+	DW_OP_lit24              = 0x48, // Literal 24
-+	DW_OP_lit25              = 0x49, // Literal 25
-+	DW_OP_lit26              = 0x4A, // Literal 26
-+	DW_OP_lit27              = 0x4B, // Literal 27
-+	DW_OP_lit28              = 0x4C, // Literal 28
-+	DW_OP_lit29              = 0x4D, // Literal 29
-+	DW_OP_lit30              = 0x4E, // Literal 30
-+	DW_OP_lit31              = 0x4F, // Literal 31
-+	DW_OP_reg0               = 0x50, // Contents of reg0
-+	DW_OP_reg1               = 0x51, // Contents of reg1
-+	DW_OP_reg2               = 0x52, // Contents of reg2
-+	DW_OP_reg3               = 0x53, // Contents of reg3
-+	DW_OP_reg4               = 0x54, // Contents of reg4
-+	DW_OP_reg5               = 0x55, // Contents of reg5
-+	DW_OP_reg6               = 0x56, // Contents of reg6
-+	DW_OP_reg7               = 0x57, // Contents of reg7
-+	DW_OP_reg8               = 0x58, // Contents of reg8
-+	DW_OP_reg9               = 0x59, // Contents of reg9
-+	DW_OP_reg10              = 0x5A, // Contents of reg10
-+	DW_OP_reg11              = 0x5B, // Contents of reg11
-+	DW_OP_reg12              = 0x5C, // Contents of reg12
-+	DW_OP_reg13              = 0x5D, // Contents of reg13
-+	DW_OP_reg14              = 0x5E, // Contents of reg14
-+	DW_OP_reg15              = 0x5F, // Contents of reg15
-+	DW_OP_reg16              = 0x60, // Contents of reg16
-+	DW_OP_reg17              = 0x61, // Contents of reg17
-+	DW_OP_reg18              = 0x62, // Contents of reg18
-+	DW_OP_reg19              = 0x63, // Contents of reg19
-+	DW_OP_reg20              = 0x64, // Contents of reg20
-+	DW_OP_reg21              = 0x65, // Contents of reg21
-+	DW_OP_reg22              = 0x66, // Contents of reg22
-+	DW_OP_reg23              = 0x67, // Contents of reg23
-+	DW_OP_reg24              = 0x68, // Contents of reg24
-+	DW_OP_reg25              = 0x69, // Contents of reg25
-+	DW_OP_reg26              = 0x6A, // Contents of reg26
-+	DW_OP_reg27              = 0x6B, // Contents of reg27
-+	DW_OP_reg28              = 0x6C, // Contents of reg28
-+	DW_OP_reg29              = 0x6D, // Contents of reg29
-+	DW_OP_reg30              = 0x6E, // Contents of reg30
-+	DW_OP_reg31              = 0x6F, // Contents of reg31
-+	DW_OP_breg0              = 0x70, // base register 0 + SLEB128 offset
-+	DW_OP_breg1              = 0x71, // base register 1 + SLEB128 offset
-+	DW_OP_breg2              = 0x72, // base register 2 + SLEB128 offset
-+	DW_OP_breg3              = 0x73, // base register 3 + SLEB128 offset
-+	DW_OP_breg4              = 0x74, // base register 4 + SLEB128 offset
-+	DW_OP_breg5              = 0x75, // base register 5 + SLEB128 offset
-+	DW_OP_breg6              = 0x76, // base register 6 + SLEB128 offset
-+	DW_OP_breg7              = 0x77, // base register 7 + SLEB128 offset
-+	DW_OP_breg8              = 0x78, // base register 8 + SLEB128 offset
-+	DW_OP_breg9              = 0x79, // base register 9 + SLEB128 offset
-+	DW_OP_breg10             = 0x7A, // base register 10 + SLEB128 offset
-+	DW_OP_breg11             = 0x7B, // base register 11 + SLEB128 offset
-+	DW_OP_breg12             = 0x7C, // base register 12 + SLEB128 offset
-+	DW_OP_breg13             = 0x7D, // base register 13 + SLEB128 offset
-+	DW_OP_breg14             = 0x7E, // base register 14 + SLEB128 offset
-+	DW_OP_breg15             = 0x7F, // base register 15 + SLEB128 offset
-+	DW_OP_breg16             = 0x80, // base register 16 + SLEB128 offset
-+	DW_OP_breg17             = 0x81, // base register 17 + SLEB128 offset
-+	DW_OP_breg18             = 0x82, // base register 18 + SLEB128 offset
-+	DW_OP_breg19             = 0x83, // base register 19 + SLEB128 offset
-+	DW_OP_breg20             = 0x84, // base register 20 + SLEB128 offset
-+	DW_OP_breg21             = 0x85, // base register 21 + SLEB128 offset
-+	DW_OP_breg22             = 0x86, // base register 22 + SLEB128 offset
-+	DW_OP_breg23             = 0x87, // base register 23 + SLEB128 offset
-+	DW_OP_breg24             = 0x88, // base register 24 + SLEB128 offset
-+	DW_OP_breg25             = 0x89, // base register 25 + SLEB128 offset
-+	DW_OP_breg26             = 0x8A, // base register 26 + SLEB128 offset
-+	DW_OP_breg27             = 0x8B, // base register 27 + SLEB128 offset
-+	DW_OP_breg28             = 0x8C, // base register 28 + SLEB128 offset
-+	DW_OP_breg29             = 0x8D, // base register 29 + SLEB128 offset
-+	DW_OP_breg30             = 0x8E, // base register 30 + SLEB128 offset
-+	DW_OP_breg31             = 0x8F, // base register 31 + SLEB128 offset
-+	DW_OP_regx               = 0x90, // ULEB128 register
-+	DW_OP_fbreg              = 0x91, // SLEB128 offset
-+	DW_OP_bregx              = 0x92, // ULEB128 register followed by SLEB128 offset
-+	DW_OP_piece              = 0x93, // ULEB128 size of piece addressed
-+	DW_OP_deref_size         = 0x94, // 1-byte size of data retrieved
-+	DW_OP_xderef_size        = 0x95, // 1-byte size of data retrieved
-+	DW_OP_nop                = 0x96,
-+	DW_OP_push_object_addres = 0x97,
-+	DW_OP_call2              = 0x98, // 2-byte offset of DIE
-+	DW_OP_call4              = 0x99, // 4-byte offset of DIE
-+	DW_OP_call_ref           = 0x9A, // 4- or 8-byte offset of DIE
-+	DW_OP_lo_user            = 0xE0,
-+	DW_OP_APPLE_uninit       = 0xF0,
-+	DW_OP_hi_user            = 0xFF
-+};
-+
-+
-+
- #endif
-diff --git a/src/ld/parsers/libunwind/AddressSpace.hpp b/src/ld/parsers/libunwind/AddressSpace.hpp
-new file mode 100644
-index 0000000..bebd3e6
---- /dev/null
-+++ src/ld/parsers/libunwind/AddressSpace.hpp
-@@ -0,0 +1,439 @@
-+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
-+ *
-+ * Copyright (c) 2008 Apple Inc. All rights reserved.
-+ *
-+ * @APPLE_LICENSE_HEADER_START@
-+ *
-+ * This file contains Original Code and/or Modifications of Original Code
-+ * as defined in and that are subject to the Apple Public Source License
-+ * Version 2.0 (the 'License'). You may not use this file except in
-+ * compliance with the License. Please obtain a copy of the License at
-+ * http://www.opensource.apple.com/apsl/ and read it before using this
-+ * file.
-+ *
-+ * The Original Code and all software distributed under the License are
-+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-+ * Please see the License for the specific language governing rights and
-+ * limitations under the License.
-+ *
-+ * @APPLE_LICENSE_HEADER_END@
-+ */
-+ 
-+//
-+//	C++ interface to lower levels of libuwind 
-+//
-+
-+#ifndef __ADDRESSSPACE_HPP__
-+#define __ADDRESSSPACE_HPP__
-+
-+#include <stdint.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <dlfcn.h>
-+#include <mach-o/loader.h>
-+#include <mach-o/getsect.h>
-+#include <mach-o/dyld_priv.h>
-+#include <mach/i386/thread_status.h>
-+#include <Availability.h>
-+
-+#include "FileAbstraction.hpp"
-+#include "libunwind.h"
-+#include "InternalMacros.h"
-+#include "dwarf2.h"
-+
-+
-+#if 0
-+#if __i386__ || __x86_64__ 
-+// In 10.6 and later i386 and x86_64 don't have a __dyld section
-+// We need one to access private _dyld_func_lookup function.
-+
-+struct __DATA__dyld { long lazy; int (*lookup)(const char*, void**); };
-+
-+static volatile struct __DATA__dyld  myDyldSection __attribute__ ((section ("__DATA,__dyld"))) = { 0, NULL };
-+
-+
-+static int my_dyld_func_lookup(const char* dyld_func_name, void **address)
-+{
-+	return (*myDyldSection.lookup)(dyld_func_name, address);
-+}
-+#else
-+	#define my_dyld_func_lookup _dyld_func_lookup
-+#endif
-+
-+
-+bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info)
-+{
-+    static void* (*p)(void*, dyld_unwind_sections*) = NULL;
-+
-+	if(p == NULL)
-+	    my_dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p);
-+	return p(addr, info);
-+}
-+#endif // 0
-+
-+
-+
-+namespace libunwind {
-+
-+///
-+/// LocalAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread
-+/// in the same process.  It compiles away and making local unwinds very fast.
-+///
-+class LocalAddressSpace
-+{
-+public:
-+	
-+	#if __LP64__
-+		typedef uint64_t	pint_t;
-+		typedef  int64_t	sint_t;
-+	#else
-+		typedef uint32_t	pint_t;
-+		typedef  int32_t	sint_t;
-+	#endif
-+		uint8_t			get8(pint_t addr)	{ return *((uint8_t*)addr); }
-+		uint16_t		get16(pint_t addr)	{ return *((uint16_t*)addr); }
-+		uint32_t		get32(pint_t addr)	{ return *((uint32_t*)addr); }
-+		uint64_t		get64(pint_t addr)	{ return *((uint64_t*)addr); }
-+		double			getDouble(pint_t addr)	{ return *((double*)addr); }
-+		v128			getVector(pint_t addr)	{ return *((v128*)addr); }
-+		uintptr_t		getP(pint_t addr);
-+	static uint64_t		getULEB128(pint_t& addr, pint_t end);
-+	static int64_t		getSLEB128(pint_t& addr, pint_t end);
-+	
-+		pint_t			getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
-+		bool			findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset);
-+		bool			findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart);
-+	
-+};
-+
-+LocalAddressSpace sThisAddress;
-+
-+inline uintptr_t LocalAddressSpace::getP(pint_t addr)
-+{
-+#if __LP64__
-+	return get64(addr);
-+#else
-+	return get32(addr);
-+#endif
-+}
-+
-+/* Read a ULEB128 into a 64-bit word.   */
-+inline uint64_t
-+LocalAddressSpace::getULEB128(pint_t& addr, pint_t end)
-+{
-+	const uint8_t* p = (uint8_t*)addr;
-+	const uint8_t* pend = (uint8_t*)end;
-+	uint64_t result = 0;
-+	int bit = 0;
-+	do  {
-+		uint64_t b;
-+
-+		if ( p == pend )
-+			ABORT("truncated uleb128 expression");
-+
-+		b = *p & 0x7f;
-+
-+		if (bit >= 64 || b << bit >> bit != b) {
-+			ABORT("malformed uleb128 expression");
-+		}
-+		else {
-+			result |= b << bit;
-+			bit += 7;
-+		}
-+	} while ( *p++ >= 0x80 );
-+	addr = (pint_t)p;
-+	return result;
-+}
-+
-+/* Read a SLEB128 into a 64-bit word.  */
-+inline int64_t
-+LocalAddressSpace::getSLEB128(pint_t& addr, pint_t end)
-+{
-+	const uint8_t* p = (uint8_t*)addr;
-+	int64_t result = 0;
-+	int bit = 0;
-+	uint8_t byte;
-+	do {
-+		byte = *p++;
-+		result |= ((byte & 0x7f) << bit);
-+		bit += 7;
-+	} while (byte & 0x80);
-+	// sign extend negative numbers
-+	if ( (byte & 0x40) != 0 )
-+		result |= (-1LL) << bit;
-+	addr = (pint_t)p;
-+	return result;
-+}
-+
-+LocalAddressSpace::pint_t
-+LocalAddressSpace::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding)
-+{
-+	pint_t startAddr = addr;
-+	const uint8_t* p = (uint8_t*)addr;
-+	pint_t result;
-+	
-+	// first get value
-+	switch (encoding & 0x0F) {
-+		case DW_EH_PE_ptr:
-+			result = getP(addr);
-+			p += sizeof(pint_t);
-+			addr = (pint_t)p;
-+			break;
-+		case DW_EH_PE_uleb128:
-+			result = getULEB128(addr, end);
-+			break;
-+		case DW_EH_PE_udata2:
-+			result = get16(addr);
-+			p += 2;
-+			addr = (pint_t)p;
-+			break;
-+		case DW_EH_PE_udata4:
-+			result = get32(addr);
-+			p += 4;
-+			addr = (pint_t)p;
-+			break;
-+		case DW_EH_PE_udata8:
-+			result = get64(addr);
-+			p += 8;
-+			addr = (pint_t)p;
-+			break;
-+		case DW_EH_PE_sleb128:
-+			result = getSLEB128(addr, end);
-+			break;
-+		case DW_EH_PE_sdata2:
-+			result = (int16_t)get16(addr);
-+			p += 2;
-+			addr = (pint_t)p;
-+			break;
-+		case DW_EH_PE_sdata4:
-+			result = (int32_t)get32(addr);
-+			p += 4;
-+			addr = (pint_t)p;
-+			break;
-+		case DW_EH_PE_sdata8:
-+			result = get64(addr);
-+			p += 8;
-+			addr = (pint_t)p;
-+			break;
-+		default:
-+			ABORT("unknown pointer encoding");
-+	}
-+	
-+	// then add relative offset
-+	switch ( encoding & 0x70 ) {
-+		case DW_EH_PE_absptr:
-+			// do nothing
-+			break;
-+		case DW_EH_PE_pcrel:
-+			result += startAddr;
-+			break;
-+		case DW_EH_PE_textrel:
-+			ABORT("DW_EH_PE_textrel pointer encoding not supported");
-+			break;
-+		case DW_EH_PE_datarel:
-+			ABORT("DW_EH_PE_datarel pointer encoding not supported");
-+			break;
-+		case DW_EH_PE_funcrel:
-+			ABORT("DW_EH_PE_funcrel pointer encoding not supported");
-+			break;
-+		case DW_EH_PE_aligned:
-+			ABORT("DW_EH_PE_aligned pointer encoding not supported");
-+			break;
-+		default:
-+			ABORT("unknown pointer encoding");
-+			break;
-+	}
-+	
-+	if ( encoding & DW_EH_PE_indirect )
-+		result = getP(result);
-+	
-+	return result;
-+}
-+
-+
-+inline bool LocalAddressSpace::findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart)
-+{
-+	dyld_unwind_sections info;
-+	if ( _dyld_find_unwind_sections((void*)addr, &info) ) {
-+		mh				= (pint_t)info.mh;
-+		dwarfStart		= (pint_t)info.dwarf_section;
-+		dwarfLen		= (pint_t)info.dwarf_section_length;
-+		compactStart	= (pint_t)info.compact_unwind_section;
-+		return true;
-+	}
-+	return false;
-+}
-+
-+
-+inline bool	LocalAddressSpace::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset)
-+{
-+	dl_info dyldInfo;
-+	if ( dladdr((void*)addr, &dyldInfo) ) {
-+		if ( dyldInfo.dli_sname != NULL ) {
-+			strlcpy(buf, dyldInfo.dli_sname, bufLen);
-+			*offset = (addr - (pint_t)dyldInfo.dli_saddr);
-+			return true;
-+		}
-+	}
-+	return false;
-+}
-+
-+
-+
-+#if UNW_REMOTE
-+
-+///
-+/// OtherAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread
-+/// in the another process.  The other process can be a different endianness and a different
-+/// pointer size and is handled by the P template parameter.  
-+///
-+template <typename P>
-+class OtherAddressSpace
-+{
-+public:
-+						OtherAddressSpace(task_t task) : fTask(task) {}
-+
-+		typedef typename P::uint_t	pint_t;
-+
-+		uint8_t			get8(pint_t addr);
-+		uint16_t		get16(pint_t addr);
-+		uint32_t		get32(pint_t addr);
-+		uint64_t		get64(pint_t addr);
-+		pint_t			getP(pint_t addr);
-+		uint64_t		getULEB128(pint_t& addr, pint_t end);
-+		int64_t			getSLEB128(pint_t& addr, pint_t end);
-+		pint_t			getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
-+		bool			findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset);
-+		bool			findUnwindSections(pint_t addr, unwind_sections& info);
-+private:
-+		void*			localCopy(pint_t addr);
-+
-+
-+		task_t			fTask;
-+};
-+
-+
-+template <typename P>
-+uint8_t OtherAddressSpace<P>::get8(pint_t addr)
-+{
-+	return *((uint8_t*)localCopy(addr));
-+}
-+
-+template <typename P>
-+uint16_t OtherAddressSpace<P>::get16(pint_t addr)
-+{
-+	return P::E::get16(*(uint16_t*)localCopy(addr));
-+}
-+
-+template <typename P>
-+uint32_t OtherAddressSpace<P>::get32(pint_t addr)
-+{
-+	return P::E::get32(*(uint32_t*)localCopy(addr));
-+}
-+
-+template <typename P>
-+uint64_t OtherAddressSpace<P>::get64(pint_t addr)
-+{
-+	return P::E::get64(*(uint64_t*)localCopy(addr));
-+}
-+
-+template <typename P>
-+typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr)
-+{
-+	return P::getP(*(uint64_t*)localCopy(addr));
-+}
-+
-+template <typename P>
-+uint64_t OtherAddressSpace<P>::getULEB128(pint_t& addr, pint_t end)
-+{
-+	uintptr_t size = (end - addr);
-+	LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t)localCopy(addr);
-+	LocalAddressSpace::pint_t sladdr = laddr;
-+	uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr+size);
-+	addr += (laddr-sladdr);
-+	return result;
-+}
-+
-+template <typename P>
-+int64_t OtherAddressSpace<P>::getSLEB128(pint_t& addr, pint_t end)
-+{
-+	uintptr_t size = (end - addr);
-+	LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t)localCopy(addr);
-+	LocalAddressSpace::pint_t sladdr = laddr;
-+	uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr+size);
-+	addr += (laddr-sladdr);
-+	return result;
-+}
-+
-+template <typename P>
-+void* OtherAddressSpace<P>::localCopy(pint_t addr)
-+{
-+	// FIX ME
-+}
-+
-+template <typename P>
-+bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset)
-+{
-+	// FIX ME
-+}
-+
-+
-+
-+///
-+/// unw_addr_space is the base class that abstract unw_addr_space_t type in libunwind.h points to.  
-+///
-+struct unw_addr_space
-+{
-+	cpu_type_t				cpuType;
-+	task_t					taskPort;
-+};
-+
-+
-+///
-+/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points to when examining
-+/// a 32-bit intel process.
-+///
-+struct unw_addr_space_i386 : public unw_addr_space
-+{
-+													unw_addr_space_i386(task_t task) : oas(task) {}
-+	OtherAddressSpace<Pointer32<LittleEndian> >		oas;
-+};
-+
-+
-+///
-+/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t points to when examining
-+/// a 64-bit intel process.
-+///
-+struct unw_addr_space_x86_64 : public unw_addr_space
-+{
-+													unw_addr_space_x86_64(task_t task) : oas(task) {}
-+	OtherAddressSpace<Pointer64<LittleEndian> >		oas;
-+};
-+
-+
-+///
-+/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points to when examining
-+/// a 32-bit PowerPC process.
-+///
-+struct unw_addr_space_ppc : public unw_addr_space
-+{
-+													unw_addr_space_ppc(task_t task) : oas(task) {}
-+	OtherAddressSpace<Pointer32<BigEndian> >		oas;
-+};
-+
-+
-+#endif // UNW_REMOTE
-+
-+
-+} // namespace libunwind 
-+
-+
-+
-+#endif // __ADDRESSSPACE_HPP__
-+
-+
-+
-+
-diff --git a/src/ld/parsers/libunwind/DwarfInstructions.hpp b/src/ld/parsers/libunwind/DwarfInstructions.hpp
-new file mode 100644
-index 0000000..b04582d
---- /dev/null
-+++ src/ld/parsers/libunwind/DwarfInstructions.hpp
-@@ -0,0 +1,1726 @@
-+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
-+ *
-+ * Copyright (c) 2008 Apple Inc. All rights reserved.
-+ *
-+ * @APPLE_LICENSE_HEADER_START@
-+ *
-+ * This file contains Original Code and/or Modifications of Original Code
-+ * as defined in and that are subject to the Apple Public Source License
-+ * Version 2.0 (the 'License'). You may not use this file except in
-+ * compliance with the License. Please obtain a copy of the License at
-+ * http://www.opensource.apple.com/apsl/ and read it before using this
-+ * file.
-+ *
-+ * The Original Code and all software distributed under the License are
-+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-+ * Please see the License for the specific language governing rights and
-+ * limitations under the License.
-+ *
-+ * @APPLE_LICENSE_HEADER_END@
-+ */
-+ 
-+//
-+// processor specific parsing of dwarf unwind instructions
-+//
-+
-+#ifndef __DWARF_INSTRUCTIONS_HPP__
-+#define __DWARF_INSTRUCTIONS_HPP__
-+
-+#include <stdint.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+#include <algorithm>
-+#include <vector>
-+
-+#include <libunwind.h>
-+#include <mach-o/compact_unwind_encoding.h>
-+
-+#include "dwarf2.h"
-+#include "AddressSpace.hpp"
-+#include "Registers.hpp"
-+#include "DwarfParser.hpp"
-+#include "InternalMacros.h"
-+//#include "CompactUnwinder.hpp"
-+
-+#define EXTRACT_BITS(value, mask) \
-+	( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) )
-+
-+#define CFI_INVALID_ADDRESS ((pint_t)(-1))
-+
-+namespace libunwind {
-+
-+///
-+/// Used by linker when parsing __eh_frame section
-+///  
-+template <typename A>
-+struct CFI_Reference {
-+	typedef typename A::pint_t		pint_t;	
-+	uint8_t		encodingOfTargetAddress;
-+	uint32_t	offsetInCFI;
-+	pint_t		targetAddress;
-+};
-+template <typename A>
-+struct CFI_Atom_Info {
-+	typedef typename A::pint_t		pint_t;	
-+	pint_t			address;
-+	uint32_t		size;
-+	bool			isCIE;
-+	union {
-+		struct {
-+			CFI_Reference<A>	function;
-+			CFI_Reference<A>	cie;
-+			CFI_Reference<A>	lsda;
-+			uint32_t		compactUnwindInfo;
-+		}			fdeInfo;
-+		struct {
-+			CFI_Reference<A>	personality;
-+		}			cieInfo;
-+	} u;
-+};
-+
-+typedef void (*WarnFunc)(void* ref, uint64_t funcAddr, const char* msg);  
-+
-+///
-+/// DwarfInstructions maps abtract dwarf unwind instructions to a particular architecture
-+///  
-+template <typename A, typename R>
-+class DwarfInstructions
-+{
-+public:
-+	typedef typename A::pint_t		pint_t;	
-+	typedef typename A::sint_t		sint_t;	
-+
-+	static const char* parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
-+						CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn);
-+
-+
-+	static compact_unwind_encoding_t createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 
-+																pint_t* lsda, pint_t* personality,
-+																char warningBuffer[1024]);
-+
-+	static int stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers);
-+										
-+private:
-+
-+	enum {
-+		DW_X86_64_RET_ADDR = 16
-+	};
-+
-+	enum {
-+		DW_X86_RET_ADDR = 8
-+	};
-+
-+	static pint_t evaluateExpression(pint_t expression, A& addressSpace, const R& registers, pint_t initialStackValue);
-+	static pint_t getSavedRegister(A& addressSpace, const R& registers, pint_t cfa, 
-+										const typename CFI_Parser<A>::RegisterLocation& savedReg);
-+	static double getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa, 
-+										const typename CFI_Parser<A>::RegisterLocation& savedReg);
-+	static v128 getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa, 
-+										const typename CFI_Parser<A>::RegisterLocation& savedReg);
-+										
-+	// x86 specific variants
-+	static int    lastRestoreReg(const Registers_x86&);
-+	static bool   isReturnAddressRegister(int regNum, const Registers_x86&);
-+	static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86&);
-+
-+	static uint32_t getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure);
-+	static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86&);
-+	static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
-+												const Registers_x86&, const typename CFI_Parser<A>::PrologInfo& prolog,
-+												char warningBuffer[1024]);
-+
-+	// x86_64 specific variants
-+	static int    lastRestoreReg(const Registers_x86_64&);
-+	static bool   isReturnAddressRegister(int regNum, const Registers_x86_64&);
-+	static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86_64&);
-+
-+	static uint32_t getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure);
-+	static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86_64&);
-+	static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
-+												const Registers_x86_64&, const typename CFI_Parser<A>::PrologInfo& prolog,
-+												char warningBuffer[1024]);
-+	
-+	// ppc specific variants
-+	static int    lastRestoreReg(const Registers_ppc&);
-+	static bool   isReturnAddressRegister(int regNum, const Registers_ppc&);
-+	static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_ppc&);
-+	static compact_unwind_encoding_t encodeToUseDwarf(const Registers_ppc&);
-+	static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
-+												const Registers_ppc&, const typename CFI_Parser<A>::PrologInfo& prolog,
-+												char warningBuffer[1024]);
-+};
-+
-+
-+											
-+
-+template <typename A, typename R>
-+const char* DwarfInstructions<A,R>::parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
-+												CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn)
-+{
-+	typename CFI_Parser<A>::CIE_Info cieInfo;
-+	CFI_Atom_Info<A>* entry = infos;
-+	CFI_Atom_Info<A>* end = &infos[infosCount];
-+	const pint_t ehSectionEnd = ehSectionStart + sectionLength;
-+	for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
-+		pint_t currentCFI = p;
-+		uint64_t cfiLength = addressSpace.get32(p);
-+		p += 4;
-+		if ( cfiLength == 0xffffffff ) {
-+			// 0xffffffff means length is really next 8 bytes
-+			cfiLength = addressSpace.get64(p);
-+			p += 8;
-+		}
-+		if ( cfiLength == 0 ) 
-+			return NULL;	// end marker
-+		if ( entry >= end )
-+			return "too little space allocated for parseCFIs";
-+		pint_t nextCFI = p + cfiLength;
-+		uint32_t id = addressSpace.get32(p);
-+		if ( id == 0 ) {
-+			// is CIE
-+			const char* err = CFI_Parser<A>::parseCIE(addressSpace, currentCFI, &cieInfo);
-+			if ( err != NULL ) 
-+				return err;
-+			entry->address = currentCFI;
-+			entry->size = nextCFI - currentCFI;
-+			entry->isCIE = true;
-+			entry->u.cieInfo.personality.targetAddress = cieInfo.personality;
-+			entry->u.cieInfo.personality.offsetInCFI = cieInfo.personalityOffsetInCIE;
-+			entry->u.cieInfo.personality.encodingOfTargetAddress = cieInfo.personalityEncoding;
-+			++entry;
-+		}
-+		else {
-+			// is FDE
-+			entry->address = currentCFI;
-+			entry->size = nextCFI - currentCFI;
-+			entry->isCIE = false;
-+			entry->u.fdeInfo.function.targetAddress = CFI_INVALID_ADDRESS;
-+			entry->u.fdeInfo.cie.targetAddress = CFI_INVALID_ADDRESS;
-+			entry->u.fdeInfo.lsda.targetAddress = CFI_INVALID_ADDRESS;
-+			uint32_t ciePointer = addressSpace.get32(p);
-+			pint_t cieStart = p-ciePointer;
-+			// validate pointer to CIE is within section
-+			if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) )
-+				return "FDE points to CIE outside __eh_frame section";
-+			// optimize usual case where cie is same for all FDEs
-+			if ( cieStart != cieInfo.cieStart ) {
-+				const char* err = CFI_Parser<A>::parseCIE(addressSpace, cieStart, &cieInfo);
-+				if ( err != NULL ) 
-+					return err;
-+			}
-+			entry->u.fdeInfo.cie.targetAddress = cieStart;
-+			entry->u.fdeInfo.cie.offsetInCFI = p-currentCFI;
-+			entry->u.fdeInfo.cie.encodingOfTargetAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
-+			p += 4;
-+			// parse pc begin and range
-+			pint_t offsetOfFunctionAddress = p-currentCFI;
-+			pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding);
-+			pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F);
-+			//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
-+			// test if pc is within the function this FDE covers
-+			entry->u.fdeInfo.function.targetAddress = pcStart;
-+			entry->u.fdeInfo.function.offsetInCFI = offsetOfFunctionAddress;
-+			entry->u.fdeInfo.function.encodingOfTargetAddress = cieInfo.pointerEncoding;
-+			// check for augmentation length
-+			if ( cieInfo.fdesHaveAugmentationData ) {
-+				uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
-+				pint_t endOfAug = p + augLen;
-+				if ( cieInfo.lsdaEncoding != 0 ) {
-+					// peek at value (without indirection).  Zero means no lsda
-+					pint_t lsdaStart = p;
-+					if ( addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding & 0x0F) != 0 ) {
-+						// reset pointer and re-parse lsda address
-+						p = lsdaStart;
-+						pint_t offsetOfLSDAAddress = p-currentCFI;
-+						entry->u.fdeInfo.lsda.targetAddress = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding);
-+						entry->u.fdeInfo.lsda.offsetInCFI = offsetOfLSDAAddress;
-+						entry->u.fdeInfo.lsda.encodingOfTargetAddress = cieInfo.lsdaEncoding;
-+					}
-+				}
-+				p = endOfAug;
-+			}
-+			// compute compact unwind encoding
-+			typename CFI_Parser<A>::FDE_Info fdeInfo;
-+			fdeInfo.fdeStart = currentCFI;
-+			fdeInfo.fdeLength = nextCFI - currentCFI;
-+			fdeInfo.fdeInstructions = p;
-+			fdeInfo.pcStart = pcStart;
-+			fdeInfo.pcEnd = pcStart +  pcRange;
-+			fdeInfo.lsda = entry->u.fdeInfo.lsda.targetAddress;
-+			typename CFI_Parser<A>::PrologInfo prolog;
-+			R dummy; // for proper selection of architecture specific functions
-+			if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) {
-+				char warningBuffer[1024];
-+				entry->u.fdeInfo.compactUnwindInfo = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer);
-+				if ( fdeInfo.lsda != CFI_INVALID_ADDRESS ) 
-+					entry->u.fdeInfo.compactUnwindInfo |= UNWIND_HAS_LSDA;
-+				if ( warningBuffer[0] != '\0' )
-+					warn(ref, fdeInfo.pcStart, warningBuffer);
-+			}
-+			else {
-+				warn(ref, CFI_INVALID_ADDRESS, "dwarf unwind instructions could not be parsed");
-+				entry->u.fdeInfo.compactUnwindInfo = encodeToUseDwarf(dummy);
-+			}
-+			++entry;
-+		}
-+		p = nextCFI;
-+	}
-+	if ( entry != end )
-+		return "wrong entry count for parseCFIs";
-+	return NULL; // success
-+}
-+
-+
-+
-+
-+template <typename A, typename R>
-+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 
-+																		pint_t* lsda, pint_t* personality,
-+																		char warningBuffer[1024])
-+{
-+	typename CFI_Parser<A>::FDE_Info fdeInfo;
-+	typename CFI_Parser<A>::CIE_Info cieInfo;
-+	R dummy; // for proper selection of architecture specific functions
-+	if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) {
-+		typename CFI_Parser<A>::PrologInfo prolog;
-+		if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) {
-+			*lsda = fdeInfo.lsda;
-+			*personality = cieInfo.personality;
-+			compact_unwind_encoding_t encoding;
-+			encoding = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer);
-+			if ( fdeInfo.lsda != 0 ) 
-+				encoding |= UNWIND_HAS_LSDA;
-+			return encoding;
-+		}
-+		else {
-+			strcpy(warningBuffer, "dwarf unwind instructions could not be parsed");
-+			return encodeToUseDwarf(dummy);
-+		}
-+	}
-+	else {
-+		strcpy(warningBuffer, "dwarf FDE could not be parsed");
-+		return encodeToUseDwarf(dummy);
-+	}
-+}
-+
-+
-+template <typename A, typename R>
-+typename A::pint_t DwarfInstructions<A,R>::getSavedRegister(A& addressSpace, const R& registers, pint_t cfa,
-+													const typename CFI_Parser<A>::RegisterLocation& savedReg)
-+{
-+	switch ( savedReg.location ) {
-+		case CFI_Parser<A>::kRegisterInCFA:
-+			return addressSpace.getP(cfa + savedReg.value);
-+
-+		case CFI_Parser<A>::kRegisterAtExpression:
-+			return addressSpace.getP(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
-+
-+		case CFI_Parser<A>::kRegisterIsExpression:
-+			return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
-+
-+		case CFI_Parser<A>::kRegisterInRegister:
-+			return registers.getRegister(savedReg.value);
-+
-+		case CFI_Parser<A>::kRegisterUnused:
-+		case CFI_Parser<A>::kRegisterOffsetFromCFA:
-+			// FIX ME
-+			break;
-+	}
-+	ABORT("unsupported restore location for register");
-+}
-+
-+template <typename A, typename R>
-+double DwarfInstructions<A,R>::getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa,
-+													const typename CFI_Parser<A>::RegisterLocation& savedReg)
-+{
-+	switch ( savedReg.location ) {
-+		case CFI_Parser<A>::kRegisterInCFA:
-+			return addressSpace.getDouble(cfa + savedReg.value);
-+
-+		case CFI_Parser<A>::kRegisterAtExpression:
-+			return addressSpace.getDouble(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
-+
-+		case CFI_Parser<A>::kRegisterIsExpression:
-+		case CFI_Parser<A>::kRegisterUnused:
-+		case CFI_Parser<A>::kRegisterOffsetFromCFA:
-+		case CFI_Parser<A>::kRegisterInRegister:
-+			// FIX ME
-+			break;
-+	}
-+	ABORT("unsupported restore location for float register");
-+}
-+
-+template <typename A, typename R>
-+v128 DwarfInstructions<A,R>::getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa,
-+													const typename CFI_Parser<A>::RegisterLocation& savedReg)
-+{
-+	switch ( savedReg.location ) {
-+		case CFI_Parser<A>::kRegisterInCFA:
-+			return addressSpace.getVector(cfa + savedReg.value);
-+
-+		case CFI_Parser<A>::kRegisterAtExpression:
-+			return addressSpace.getVector(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
-+
-+		case CFI_Parser<A>::kRegisterIsExpression:
-+		case CFI_Parser<A>::kRegisterUnused:
-+		case CFI_Parser<A>::kRegisterOffsetFromCFA:
-+		case CFI_Parser<A>::kRegisterInRegister:
-+			// FIX ME
-+			break;
-+	}
-+	ABORT("unsupported restore location for vector register");
-+}
-+
-+
-+template <typename A, typename R>
-+int DwarfInstructions<A,R>::stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers)
-+{
-+	//fprintf(stderr, "stepWithDwarf(pc=0x%0llX, fdeStart=0x%0llX)\n", (uint64_t)pc, (uint64_t)fdeStart);
-+	typename CFI_Parser<A>::FDE_Info fdeInfo;
-+	typename CFI_Parser<A>::CIE_Info cieInfo;
-+	if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) {
-+		typename CFI_Parser<A>::PrologInfo prolog;
-+		if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
-+			R newRegisters = registers;
-+			
-+			// get pointer to cfa (architecture specific)
-+			pint_t cfa = getCFA(addressSpace, prolog, registers);
-+
-+			// restore registers that dwarf says were saved
-+			pint_t returnAddress = 0;
-+			for (int i=0; i <= lastRestoreReg(newRegisters); ++i) {
-+				if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
-+					if ( registers.validFloatRegister(i) )
-+						newRegisters.setFloatRegister(i, getSavedFloatRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
-+					else if ( registers.validVectorRegister(i) )
-+						newRegisters.setVectorRegister(i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
-+					else if ( isReturnAddressRegister(i, registers) )
-+						returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]);
-+					else if ( registers.validRegister(i) )
-+						newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
-+					else
-+						return UNW_EBADREG;
-+				}
-+			}
-+			
-+			// by definition the CFA is the stack pointer at the call site, so restoring SP means setting it to CFA
-+			newRegisters.setSP(cfa);
-+
-+			// return address is address after call site instruction, so setting IP to that does a return
-+			newRegisters.setIP(returnAddress);
-+			
-+			// do the actual step by replacing the register set with the new ones
-+			registers = newRegisters;
-+
-+			return UNW_STEP_SUCCESS;
-+		}
-+	}
-+	return UNW_EBADFRAME;
-+}
-+
-+
-+
-+template <typename A, typename R>
-+typename A::pint_t DwarfInstructions<A,R>::evaluateExpression(pint_t expression, A& addressSpace, 
-+														const R& registers, pint_t initialStackValue)
-+{
-+	const bool log = false;
-+	pint_t p = expression;
-+	pint_t expressionEnd = expression+20; // just need something until length is read
-+	uint64_t length = addressSpace.getULEB128(p, expressionEnd);
-+	expressionEnd = p + length;
-+	if (log) fprintf(stderr, "evaluateExpression(): length=%llu\n", length);
-+	pint_t stack[100];
-+	pint_t* sp = stack;
-+	*(++sp) = initialStackValue;
-+	
-+	while ( p < expressionEnd ) {
-+		if (log) {
-+			for(pint_t* t = sp; t > stack; --t) {
-+				fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
-+			}
-+		}
-+		uint8_t opcode = addressSpace.get8(p++);
-+		sint_t svalue;
-+		pint_t value;
-+		uint32_t reg;
-+		switch (opcode) {
-+			case DW_OP_addr:
-+				// push immediate address sized value
-+				value = addressSpace.getP(p);
-+				p += sizeof(pint_t);
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
-+				break;
-+		
-+			case DW_OP_deref:
-+				// pop stack, dereference, push result
-+				value = *sp--;
-+				*(++sp) = addressSpace.getP(value);
-+				if (log) fprintf(stderr, "dereference 0x%llX\n", (uint64_t)value);
-+				break;
-+		
-+			case DW_OP_const1u:
-+				// push immediate 1 byte value
-+				value = addressSpace.get8(p);
-+				p += 1;
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
-+				break;
-+				
-+			case DW_OP_const1s:
-+				// push immediate 1 byte signed value
-+				svalue = (int8_t)addressSpace.get8(p);
-+				p += 1;
-+				*(++sp) = svalue;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
-+				break;
-+		
-+			case DW_OP_const2u:
-+				// push immediate 2 byte value
-+				value = addressSpace.get16(p);
-+				p += 2;
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
-+				break;
-+				
-+			case DW_OP_const2s:
-+				// push immediate 2 byte signed value
-+				svalue = (int16_t)addressSpace.get16(p);
-+				p += 2;
-+				*(++sp) = svalue;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
-+				break;
-+		
-+			case DW_OP_const4u:
-+				// push immediate 4 byte value
-+				value = addressSpace.get32(p);
-+				p += 4;
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
-+				break;
-+				
-+			case DW_OP_const4s:
-+				// push immediate 4 byte signed value
-+				svalue = (int32_t)addressSpace.get32(p);
-+				p += 4;
-+				*(++sp) = svalue;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
-+				break;
-+				
-+			case DW_OP_const8u:
-+				// push immediate 8 byte value
-+				value = addressSpace.get64(p);
-+				p += 8;
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
-+				break;
-+				
-+			case DW_OP_const8s:
-+				// push immediate 8 byte signed value
-+				value = (int32_t)addressSpace.get64(p);
-+				p += 8;
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
-+				break;
-+		
-+			case DW_OP_constu:
-+				// push immediate ULEB128 value
-+				value = addressSpace.getULEB128(p, expressionEnd);
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
-+				break;
-+				
-+			case DW_OP_consts:
-+				// push immediate SLEB128 value
-+				svalue = addressSpace.getSLEB128(p, expressionEnd);
-+				*(++sp) = svalue;
-+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
-+				break;
-+		
-+			case DW_OP_dup:
-+				// push top of stack
-+				value = *sp;
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "duplicate top of stack\n");
-+				break;
-+				
-+			case DW_OP_drop:
-+				// pop
-+				--sp; 
-+				if (log) fprintf(stderr, "pop top of stack\n");
-+				break;
-+				
-+			case DW_OP_over:
-+				// dup second
-+				value = sp[-1];
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "duplicate second in stack\n");
-+				break;
-+
-+			case DW_OP_pick:
-+				// pick from
-+				reg = addressSpace.get8(p);
-+				p += 1;
-+				value = sp[-reg];
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "duplicate %d in stack\n", reg);
-+				break;
-+
-+			case DW_OP_swap:
-+				// swap top two
-+				value = sp[0];
-+				sp[0] = sp[-1];
-+				sp[-1] = value;
-+				if (log) fprintf(stderr, "swap top of stack\n");
-+				break;
-+
-+			case DW_OP_rot:
-+				// rotate top three
-+				value = sp[0];
-+				sp[0] = sp[-1];
-+				sp[-1] = sp[-2];
-+				sp[-2] = value;
-+				if (log) fprintf(stderr, "rotate top three of stack\n");
-+				break;
-+
-+			case DW_OP_xderef:
-+				// pop stack, dereference, push result
-+				value = *sp--;
-+				*sp = *((uint64_t*)value);
-+				if (log) fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t)value);
-+				break;
-+			
-+			case DW_OP_abs:
-+				svalue = *sp;
-+				if ( svalue < 0 )
-+					*sp = -svalue;
-+				if (log) fprintf(stderr, "abs\n");
-+				break;
-+		
-+			case DW_OP_and:
-+				value = *sp--;
-+				*sp &= value;
-+				if (log) fprintf(stderr, "and\n");
-+				break;
-+			
-+			case DW_OP_div:
-+				svalue = *sp--;
-+				*sp = *sp / svalue;
-+				if (log) fprintf(stderr, "div\n");
-+				break;
-+			
-+			case DW_OP_minus:
-+				svalue = *sp--;
-+				*sp = *sp - svalue;
-+				if (log) fprintf(stderr, "minus\n");
-+				break;
-+
-+			case DW_OP_mod:
-+				svalue = *sp--;
-+				*sp = *sp % svalue;
-+				if (log) fprintf(stderr, "module\n");
-+				break;
-+
-+			case DW_OP_mul:
-+				svalue = *sp--;
-+				*sp = *sp * svalue;
-+				if (log) fprintf(stderr, "mul\n");
-+				break;
-+
-+			case DW_OP_neg:
-+				*sp =  0 - *sp;
-+				if (log) fprintf(stderr, "neg\n");
-+				break;
-+
-+			case DW_OP_not:
-+				svalue = *sp;
-+				*sp =  ~svalue;
-+				if (log) fprintf(stderr, "not\n");
-+				break;
-+
-+			case DW_OP_or:
-+				value = *sp--;
-+				*sp |= value;
-+				if (log) fprintf(stderr, "or\n");
-+				break;
-+
-+			case DW_OP_plus:
-+				value = *sp--;
-+				*sp += value;
-+				if (log) fprintf(stderr, "plus\n");
-+				break;
-+
-+			case DW_OP_plus_uconst:
-+				// pop stack, add uelb128 constant, push result
-+				*sp += addressSpace.getULEB128(p, expressionEnd);
-+				if (log) fprintf(stderr, "add constant\n");
-+				break;
-+		
-+			case DW_OP_shl:
-+				value = *sp--;
-+				*sp = *sp << value;
-+				if (log) fprintf(stderr, "shift left\n");
-+				break;
-+			
-+			case DW_OP_shr:
-+				value = *sp--;
-+				*sp = *sp >> value;
-+				if (log) fprintf(stderr, "shift left\n");
-+				break;
-+				
-+			case DW_OP_shra:
-+				value = *sp--;
-+				svalue = *sp;
-+				*sp = svalue >> value;
-+				if (log) fprintf(stderr, "shift left arithmetric\n");
-+				break;
-+			
-+			case DW_OP_xor:
-+				value = *sp--;
-+				*sp ^= value;
-+				if (log) fprintf(stderr, "xor\n");
-+				break;
-+
-+			case DW_OP_skip:
-+				svalue = (int16_t)addressSpace.get16(p);
-+				p += 2;
-+				p += svalue;
-+				if (log) fprintf(stderr, "skip %lld\n", (uint64_t)svalue);
-+				break;
-+			
-+			case DW_OP_bra:
-+				svalue = (int16_t)addressSpace.get16(p);
-+				p += 2;
-+				if ( *sp-- )
-+					p += svalue;
-+				if (log) fprintf(stderr, "bra %lld\n", (uint64_t)svalue);
-+				break;
-+			
-+			case DW_OP_eq:
-+				value = *sp--;
-+				*sp = (*sp == value);
-+				if (log) fprintf(stderr, "eq\n");
-+				break;
-+			
-+			case DW_OP_ge:
-+				value = *sp--;
-+				*sp = (*sp >= value);
-+				if (log) fprintf(stderr, "ge\n");
-+				break;
-+				
-+			case DW_OP_gt:
-+				value = *sp--;
-+				*sp = (*sp > value);
-+				if (log) fprintf(stderr, "gt\n");
-+				break;
-+				
-+			case DW_OP_le:
-+				value = *sp--;
-+				*sp = (*sp <= value);
-+				if (log) fprintf(stderr, "le\n");
-+				break;
-+				
-+			case DW_OP_lt:
-+				value = *sp--;
-+				*sp = (*sp < value);
-+				if (log) fprintf(stderr, "lt\n");
-+				break;
-+				
-+			case DW_OP_ne:
-+				value = *sp--;
-+				*sp = (*sp != value);
-+				if (log) fprintf(stderr, "ne\n");
-+				break;
-+			
-+			case DW_OP_lit0:
-+			case DW_OP_lit1:
-+			case DW_OP_lit2:
-+			case DW_OP_lit3:
-+			case DW_OP_lit4:
-+			case DW_OP_lit5:
-+			case DW_OP_lit6:
-+			case DW_OP_lit7:
-+			case DW_OP_lit8:
-+			case DW_OP_lit9:
-+			case DW_OP_lit10:
-+			case DW_OP_lit11:
-+			case DW_OP_lit12:
-+			case DW_OP_lit13:
-+			case DW_OP_lit14:
-+			case DW_OP_lit15:
-+			case DW_OP_lit16:
-+			case DW_OP_lit17:
-+			case DW_OP_lit18:
-+			case DW_OP_lit19:
-+			case DW_OP_lit20:
-+			case DW_OP_lit21:
-+			case DW_OP_lit22:
-+			case DW_OP_lit23:
-+			case DW_OP_lit24:
-+			case DW_OP_lit25:
-+			case DW_OP_lit26:
-+			case DW_OP_lit27:
-+			case DW_OP_lit28:
-+			case DW_OP_lit29:
-+			case DW_OP_lit30:
-+			case DW_OP_lit31:
-+				value = opcode - DW_OP_lit0;
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "push literal 0x%llX\n", (uint64_t)value);
-+				break;
-+		
-+			case DW_OP_reg0:
-+			case DW_OP_reg1:
-+			case DW_OP_reg2:
-+			case DW_OP_reg3:
-+			case DW_OP_reg4:
-+			case DW_OP_reg5:
-+			case DW_OP_reg6:
-+			case DW_OP_reg7:
-+			case DW_OP_reg8:
-+			case DW_OP_reg9:
-+			case DW_OP_reg10:
-+			case DW_OP_reg11:
-+			case DW_OP_reg12:
-+			case DW_OP_reg13:
-+			case DW_OP_reg14:
-+			case DW_OP_reg15:
-+			case DW_OP_reg16:
-+			case DW_OP_reg17:
-+			case DW_OP_reg18:
-+			case DW_OP_reg19:
-+			case DW_OP_reg20:
-+			case DW_OP_reg21:
-+			case DW_OP_reg22:
-+			case DW_OP_reg23:
-+			case DW_OP_reg24:
-+			case DW_OP_reg25:
-+			case DW_OP_reg26:
-+			case DW_OP_reg27:
-+			case DW_OP_reg28:
-+			case DW_OP_reg29:
-+			case DW_OP_reg30:
-+			case DW_OP_reg31:
-+				reg = opcode - DW_OP_reg0;
-+				*(++sp) = registers.getRegister(reg);
-+				if (log) fprintf(stderr, "push reg %d\n", reg);
-+				break;
-+		
-+			case DW_OP_regx:
-+				reg = addressSpace.getULEB128(p, expressionEnd);
-+				*(++sp) = registers.getRegister(reg);
-+				if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
-+				break;			
-+
-+			case DW_OP_breg0:
-+			case DW_OP_breg1:
-+			case DW_OP_breg2:
-+			case DW_OP_breg3:
-+			case DW_OP_breg4:
-+			case DW_OP_breg5:
-+			case DW_OP_breg6:
-+			case DW_OP_breg7:
-+			case DW_OP_breg8:
-+			case DW_OP_breg9:
-+			case DW_OP_breg10:
-+			case DW_OP_breg11:
-+			case DW_OP_breg12:
-+			case DW_OP_breg13:
-+			case DW_OP_breg14:
-+			case DW_OP_breg15:
-+			case DW_OP_breg16:
-+			case DW_OP_breg17:
-+			case DW_OP_breg18:
-+			case DW_OP_breg19:
-+			case DW_OP_breg20:
-+			case DW_OP_breg21:
-+			case DW_OP_breg22:
-+			case DW_OP_breg23:
-+			case DW_OP_breg24:
-+			case DW_OP_breg25:
-+			case DW_OP_breg26:
-+			case DW_OP_breg27:
-+			case DW_OP_breg28:
-+			case DW_OP_breg29:
-+			case DW_OP_breg30:
-+			case DW_OP_breg31:
-+				reg = opcode - DW_OP_breg0;
-+				svalue = addressSpace.getSLEB128(p, expressionEnd);
-+				*(++sp) = registers.getRegister(reg) + svalue;
-+				if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
-+				break;
-+			
-+			case DW_OP_bregx:
-+				reg = addressSpace.getULEB128(p, expressionEnd);
-+				svalue = addressSpace.getSLEB128(p, expressionEnd);
-+				*(++sp) = registers.getRegister(reg) + svalue;
-+				if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
-+				break;
-+			
-+			case DW_OP_fbreg:
-+				ABORT("DW_OP_fbreg not implemented");
-+				break;
-+				
-+			case DW_OP_piece:
-+				ABORT("DW_OP_piece not implemented");
-+				break;
-+				
-+			case DW_OP_deref_size:
-+				// pop stack, dereference, push result
-+				value = *sp--;
-+				switch ( addressSpace.get8(p++) ) {
-+					case 1:
-+						value = addressSpace.get8(value);
-+						break;
-+					case 2:
-+						value = addressSpace.get16(value);
-+						break;
-+					case 4:
-+						value = addressSpace.get32(value);
-+						break;
-+					case 8:
-+						value = addressSpace.get64(value);
-+						break;
-+					default:
-+						ABORT("DW_OP_deref_size with bad size");
-+				}
-+				*(++sp) = value;
-+				if (log) fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t)value);
-+				break;
-+			
-+			case DW_OP_xderef_size:
-+			case DW_OP_nop:
-+			case DW_OP_push_object_addres:
-+			case DW_OP_call2:
-+			case DW_OP_call4:
-+			case DW_OP_call_ref:
-+			default:
-+				ABORT("dwarf opcode not implemented");
-+		}
-+	
-+	}
-+	if (log) fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t)*sp);
-+	return *sp;
-+}
-+
-+
-+
-+//
-+//	x86_64 specific functions
-+//
-+
-+template <typename A, typename R>
-+int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86_64&) 
-+{
-+	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_64_RET_ADDR );
-+	return DW_X86_64_RET_ADDR; 
-+}
-+
-+template <typename A, typename R>
-+bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86_64&) 
-+{
-+	return (regNum == DW_X86_64_RET_ADDR); 
-+}
-+
-+template <typename A, typename R>
-+typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
-+										const Registers_x86_64& registers)
-+{
-+	if ( prolog.cfaRegister != 0 )
-+		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
-+	else if ( prolog.cfaExpression != 0 )
-+		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
-+	else
-+		ABORT("getCFA(): unknown location for x86_64 cfa");
-+}
-+
-+
-+
-+template <typename A, typename R>
-+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86_64&) 
-+{
-+	return UNWIND_X86_64_MODE_DWARF;
-+}
-+
-+template <typename A, typename R>
-+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86&) 
-+{
-+	return UNWIND_X86_MODE_DWARF;
-+}
-+
-+
-+
-+template <typename A, typename R>
-+uint32_t DwarfInstructions<A,R>::getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure)
-+{
-+	if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 32) ) {
-+		failure = true;
-+		return 0;
-+	}
-+	unsigned int slotIndex = regOffsetFromBaseOffset/8;
-+	
-+	switch ( reg ) {
-+		case UNW_X86_64_RBX:
-+			return UNWIND_X86_64_REG_RBX << (slotIndex*3);
-+		case UNW_X86_64_R12:
-+			return UNWIND_X86_64_REG_R12 << (slotIndex*3);
-+		case UNW_X86_64_R13:
-+			return UNWIND_X86_64_REG_R13 << (slotIndex*3);
-+		case UNW_X86_64_R14:
-+			return UNWIND_X86_64_REG_R14 << (slotIndex*3);
-+		case UNW_X86_64_R15:
-+			return UNWIND_X86_64_REG_R15 << (slotIndex*3);
-+	}
-+	
-+	// invalid register
-+	failure = true;
-+	return 0;
-+}
-+
-+
-+
-+template <typename A, typename R>
-+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
-+												const Registers_x86_64& r, const typename CFI_Parser<A>::PrologInfo& prolog,
-+												char warningBuffer[1024])
-+{
-+	warningBuffer[0] = '\0';
-+	
-+	if ( prolog.registerSavedTwiceInCIE == DW_X86_64_RET_ADDR ) {
-+		warningBuffer[0] = '\0';	// silently disable conversion to compact unwind by linker
-+		return UNWIND_X86_64_MODE_DWARF;
-+	}
-+	// don't create compact unwind info for unsupported dwarf kinds
-+	if ( prolog.registerSavedMoreThanOnce ) {
-+		strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
-+		return UNWIND_X86_64_MODE_DWARF;
-+	}
-+	if ( prolog.cfaOffsetWasNegative ) {
-+		strcpy(warningBuffer, "cfa had negative offset (dwarf might contain epilog)");
-+		return UNWIND_X86_64_MODE_DWARF;
-+	}
-+	if ( prolog.spExtraArgSize != 0 ) {
-+		strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
-+		return UNWIND_X86_64_MODE_DWARF;
-+	}
-+	if ( prolog.sameValueUsed ) {
-+		strcpy(warningBuffer, "dwarf uses DW_CFA_same_value");
-+		return UNWIND_X86_64_MODE_DWARF;
-+	}
-+
-+	// figure out which kind of frame this function uses
-+	bool standardRBPframe = ( 
-+		 (prolog.cfaRegister == UNW_X86_64_RBP) 
-+	  && (prolog.cfaRegisterOffset == 16)
-+	  && (prolog.savedRegisters[UNW_X86_64_RBP].location == CFI_Parser<A>::kRegisterInCFA)
-+	  && (prolog.savedRegisters[UNW_X86_64_RBP].value == -16) );
-+	bool standardRSPframe = (prolog.cfaRegister == UNW_X86_64_RSP);
-+	if ( !standardRBPframe && !standardRSPframe ) {
-+		// no compact encoding for this
-+		strcpy(warningBuffer, "does not use RBP or RSP based frame");
-+		return UNWIND_X86_64_MODE_DWARF;
-+	}
-+	
-+	// scan which registers are saved
-+	int saveRegisterCount = 0;
-+	bool rbxSaved = false;
-+	bool r12Saved = false;
-+	bool r13Saved = false;
-+	bool r14Saved = false;
-+	bool r15Saved = false;
-+	bool rbpSaved = false;
-+	for (int i=0; i < 64; ++i) {
-+		if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
-+			if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) {
-+				sprintf(warningBuffer, "register %d saved somewhere other that in frame", i);
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			switch (i) {
-+				case UNW_X86_64_RBX:
-+					rbxSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_64_R12:
-+					r12Saved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_64_R13:
-+					r13Saved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_64_R14:
-+					r14Saved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_64_R15:
-+					r15Saved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_64_RBP:
-+					rbpSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case DW_X86_64_RET_ADDR:
-+					break;
-+				default:
-+					sprintf(warningBuffer, "non-standard register %d being saved in prolog", i);
-+					return UNWIND_X86_64_MODE_DWARF;
-+			}
-+		}
-+	}
-+	const int64_t cfaOffsetRBX = prolog.savedRegisters[UNW_X86_64_RBX].value;
-+	const int64_t cfaOffsetR12 = prolog.savedRegisters[UNW_X86_64_R12].value;
-+	const int64_t cfaOffsetR13 = prolog.savedRegisters[UNW_X86_64_R13].value;
-+	const int64_t cfaOffsetR14 = prolog.savedRegisters[UNW_X86_64_R14].value;
-+	const int64_t cfaOffsetR15 = prolog.savedRegisters[UNW_X86_64_R15].value;
-+	const int64_t cfaOffsetRBP = prolog.savedRegisters[UNW_X86_64_RBP].value;
-+	
-+	// encode standard RBP frames
-+	compact_unwind_encoding_t  encoding = 0;
-+	if ( standardRBPframe ) {
-+		//		|              |
-+		//		+--------------+   <- CFA
-+		//		|   ret addr   |
-+		//		+--------------+
-+		//		|     rbp      |
-+		//		+--------------+   <- rbp
-+		//		~              ~
-+		//		+--------------+   
-+		//		|  saved reg3  |
-+		//		+--------------+   <- CFA - offset+16
-+		//		|  saved reg2  |
-+		//		+--------------+   <- CFA - offset+8
-+		//		|  saved reg1  |
-+		//		+--------------+   <- CFA - offset
-+		//		|              |
-+		//		+--------------+
-+		//		|              |
-+		//						   <- rsp
-+		//
-+		encoding = UNWIND_X86_64_MODE_RBP_FRAME;
-+		
-+		// find save location of farthest register from rbp
-+		int furthestCfaOffset = 0;
-+		if ( rbxSaved & (cfaOffsetRBX < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetRBX;
-+		if ( r12Saved & (cfaOffsetR12 < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetR12;
-+		if ( r13Saved & (cfaOffsetR13 < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetR13;
-+		if ( r14Saved & (cfaOffsetR14 < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetR14;
-+		if ( r15Saved & (cfaOffsetR15 < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetR15;
-+		
-+		if ( furthestCfaOffset == 0 ) {
-+			// no registers saved, nothing more to encode
-+			return encoding;
-+		}
-+		
-+		// add stack offset to encoding
-+		int rbpOffset = furthestCfaOffset + 16;
-+		int encodedOffset = rbpOffset/(-8);
-+		if ( encodedOffset > 255 ) {
-+			strcpy(warningBuffer, "offset of saved registers too far to encode");
-+			return UNWIND_X86_64_MODE_DWARF;
-+		}
-+		encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_64_RBP_FRAME_OFFSET));
-+		
-+		// add register saved from each stack location
-+		bool encodingFailure = false;
-+		if ( rbxSaved )
-+			encoding |= getRBPEncodedRegister(UNW_X86_64_RBX, cfaOffsetRBX - furthestCfaOffset, encodingFailure);
-+		if ( r12Saved )
-+			encoding |= getRBPEncodedRegister(UNW_X86_64_R12, cfaOffsetR12 - furthestCfaOffset, encodingFailure);
-+		if ( r13Saved )
-+			encoding |= getRBPEncodedRegister(UNW_X86_64_R13, cfaOffsetR13 - furthestCfaOffset, encodingFailure);
-+		if ( r14Saved )
-+			encoding |= getRBPEncodedRegister(UNW_X86_64_R14, cfaOffsetR14 - furthestCfaOffset, encodingFailure);
-+		if ( r15Saved )
-+			encoding |= getRBPEncodedRegister(UNW_X86_64_R15, cfaOffsetR15 - furthestCfaOffset, encodingFailure);
-+		
-+		if ( encodingFailure ){
-+			strcpy(warningBuffer, "saved registers not contiguous");
-+			return UNWIND_X86_64_MODE_DWARF;
-+		}
-+
-+		return encoding;
-+	}
-+	else {
-+		//		|              |
-+		//		+--------------+   <- CFA
-+		//		|   ret addr   |
-+		//		+--------------+
-+		//		|  saved reg1  |
-+		//		+--------------+   <- CFA - 16
-+		//		|  saved reg2  |
-+		//		+--------------+   <- CFA - 24
-+		//		|  saved reg3  |
-+		//		+--------------+   <- CFA - 32
-+		//		|  saved reg4  |
-+		//		+--------------+   <- CFA - 40
-+		//		|  saved reg5  |
-+		//		+--------------+   <- CFA - 48
-+		//		|  saved reg6  |
-+		//		+--------------+   <- CFA - 56
-+		//		|              |
-+		//						   <- esp
-+		//
-+
-+		// for RSP based frames we need to encode stack size in unwind info
-+		encoding = UNWIND_X86_64_MODE_STACK_IMMD;
-+		uint64_t stackValue = prolog.cfaRegisterOffset / 8;
-+		uint32_t stackAdjust = 0;
-+		bool immedStackSize = true;
-+		const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_64_FRAMELESS_STACK_SIZE);
-+		if ( stackValue > stackMaxImmedValue ) {
-+			// stack size is too big to fit as an immediate value, so encode offset of subq instruction in function
-+			if	( prolog.codeOffsetAtStackDecrement == 0 ) {
-+				strcpy(warningBuffer, "stack size is large but stack subq instruction not found");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4;		
-+			try {
-+				uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
-+				stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/8;
-+			}
-+			catch (...) {
-+				strcpy(warningBuffer, "stack size is large but stack subq instruction not found");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			stackValue = functionContentAdjustStackIns - funcAddr;
-+			immedStackSize = false;
-+			if ( stackAdjust > 7 ) {
-+				strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			encoding = UNWIND_X86_64_MODE_STACK_IND;
-+		}	
-+		
-+		
-+		// validate that saved registers are all within 6 slots abutting return address
-+		int registers[6];
-+		for (int i=0; i < 6;++i)
-+			registers[i] = 0;
-+		if ( r15Saved ) {
-+			if ( cfaOffsetR15 < -56 ) {
-+				strcpy(warningBuffer, "r15 is saved too far from return address");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetR15+56)/8] = UNWIND_X86_64_REG_R15;
-+		}
-+		if ( r14Saved ) {
-+			if ( cfaOffsetR14 < -56 ) {
-+				strcpy(warningBuffer, "r14 is saved too far from return address");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetR14+56)/8] = UNWIND_X86_64_REG_R14;
-+		}
-+		if ( r13Saved ) {
-+			if ( cfaOffsetR13 < -56 ) {
-+				strcpy(warningBuffer, "r13 is saved too far from return address");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetR13+56)/8] = UNWIND_X86_64_REG_R13;
-+		}
-+		if ( r12Saved ) {
-+			if ( cfaOffsetR12 < -56 ) {
-+				strcpy(warningBuffer, "r12 is saved too far from return address");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetR12+56)/8] = UNWIND_X86_64_REG_R12;
-+		}
-+		if ( rbxSaved ) {
-+			if ( cfaOffsetRBX < -56 ) {
-+				strcpy(warningBuffer, "rbx is saved too far from return address");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetRBX+56)/8] = UNWIND_X86_64_REG_RBX;
-+		}
-+		if ( rbpSaved ) {
-+			if ( cfaOffsetRBP < -56 ) {
-+				strcpy(warningBuffer, "rbp is saved too far from return address");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetRBP+56)/8] = UNWIND_X86_64_REG_RBP;
-+		}
-+		
-+		// validate that saved registers are contiguous and abut return address on stack
-+		for (int i=0; i < saveRegisterCount; ++i) {
-+			if ( registers[5-i] == 0 ) {
-+				strcpy(warningBuffer, "registers not save contiguously in stack");
-+				return UNWIND_X86_64_MODE_DWARF;
-+			}
-+		}
-+				
-+		// encode register permutation
-+		// the 10-bits are encoded differently depending on the number of registers saved
-+		int renumregs[6];
-+		for (int i=6-saveRegisterCount; i < 6; ++i) {
-+			int countless = 0;
-+			for (int j=6-saveRegisterCount; j < i; ++j) {
-+				if ( registers[j] < registers[i] )
-+					++countless;
-+			}
-+			renumregs[i] = registers[i] - countless -1;
-+		}
-+		uint32_t permutationEncoding = 0;
-+		switch ( saveRegisterCount ) {
-+			case 6:
-+				permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
-+				break;
-+			case 5:
-+				permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
-+				break;
-+			case 4:
-+				permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
-+				break;
-+			case 3:
-+				permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
-+				break;
-+			case 2:
-+				permutationEncoding |= (5*renumregs[4] + renumregs[5]);
-+				break;
-+			case 1:
-+				permutationEncoding |= (renumregs[5]);
-+				break;
-+		}
-+		
-+		encoding |= (stackValue << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_SIZE));
-+		encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_ADJUST));
-+		encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT));
-+		encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION));
-+		return encoding;
-+	}
-+}
-+
-+
-+
-+
-+//
-+//	x86 specific functions
-+//
-+template <typename A, typename R>
-+int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86&) 
-+{
-+	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_RET_ADDR );
-+	return DW_X86_RET_ADDR; 
-+}
-+
-+template <typename A, typename R>
-+bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86&) 
-+{
-+	return (regNum == DW_X86_RET_ADDR); 
-+}
-+
-+template <typename A, typename R>
-+typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
-+										const Registers_x86& registers)
-+{
-+	if ( prolog.cfaRegister != 0 )
-+		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
-+	else if ( prolog.cfaExpression != 0 )
-+		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
-+	else
-+		ABORT("getCFA(): unknown location for x86 cfa");
-+}
-+
-+
-+
-+
-+
-+template <typename A, typename R>
-+uint32_t DwarfInstructions<A,R>::getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure)
-+{
-+	if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 16) ) {
-+		failure = true;
-+		return 0;
-+	}
-+	unsigned int slotIndex = regOffsetFromBaseOffset/4;
-+	
-+	switch ( reg ) {
-+		case UNW_X86_EBX:
-+			return UNWIND_X86_REG_EBX << (slotIndex*3);
-+		case UNW_X86_ECX:
-+			return UNWIND_X86_REG_ECX << (slotIndex*3);
-+		case UNW_X86_EDX:
-+			return UNWIND_X86_REG_EDX << (slotIndex*3);
-+		case UNW_X86_EDI:
-+			return UNWIND_X86_REG_EDI << (slotIndex*3);
-+		case UNW_X86_ESI:
-+			return UNWIND_X86_REG_ESI << (slotIndex*3);
-+	}
-+	
-+	// invalid register
-+	failure = true;
-+	return 0;
-+}
-+
-+template <typename A, typename R>
-+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
-+												const Registers_x86& r, const typename CFI_Parser<A>::PrologInfo& prolog,
-+												char warningBuffer[1024])
-+{
-+	warningBuffer[0] = '\0';
-+	
-+	if ( prolog.registerSavedTwiceInCIE == DW_X86_RET_ADDR ) {
-+		warningBuffer[0] = '\0';	// silently disable conversion to compact unwind by linker
-+		return UNWIND_X86_64_MODE_DWARF;
-+	}
-+	// don't create compact unwind info for unsupported dwarf kinds
-+	if ( prolog.registerSavedMoreThanOnce ) {
-+		strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
-+		return UNWIND_X86_MODE_DWARF;
-+	}
-+	if ( prolog.spExtraArgSize != 0 ) {
-+		strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
-+		return UNWIND_X86_MODE_DWARF;
-+	}
-+	if ( prolog.sameValueUsed ) {
-+		strcpy(warningBuffer, "dwarf uses DW_CFA_same_value");
-+		return UNWIND_X86_MODE_DWARF;
-+	}
-+	
-+	// figure out which kind of frame this function uses
-+	bool standardEBPframe = ( 
-+		 (prolog.cfaRegister == UNW_X86_EBP) 
-+	  && (prolog.cfaRegisterOffset == 8)
-+	  && (prolog.savedRegisters[UNW_X86_EBP].location == CFI_Parser<A>::kRegisterInCFA)
-+	  && (prolog.savedRegisters[UNW_X86_EBP].value == -8) );
-+	bool standardESPframe = (prolog.cfaRegister == UNW_X86_ESP);
-+	if ( !standardEBPframe && !standardESPframe ) {
-+		// no compact encoding for this
-+		strcpy(warningBuffer, "does not use EBP or ESP based frame");
-+		return UNWIND_X86_MODE_DWARF;
-+	}
-+	
-+	// scan which registers are saved
-+	int saveRegisterCount = 0;
-+	bool ebxSaved = false;
-+	bool ecxSaved = false;
-+	bool edxSaved = false;
-+	bool esiSaved = false;
-+	bool ediSaved = false;
-+	bool ebpSaved = false;
-+	for (int i=0; i < 64; ++i) {
-+		if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
-+			if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) {
-+				sprintf(warningBuffer, "register %d saved somewhere other that in frame", i);
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			switch (i) {
-+				case UNW_X86_EBX:
-+					ebxSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_ECX:
-+					ecxSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_EDX:
-+					edxSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_ESI:
-+					esiSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_EDI:
-+					ediSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case UNW_X86_EBP:
-+					ebpSaved = true;
-+					++saveRegisterCount;
-+					break;
-+				case DW_X86_RET_ADDR:
-+					break;
-+				default:
-+					sprintf(warningBuffer, "non-standard register %d being saved in prolog", i);
-+					return UNWIND_X86_MODE_DWARF;
-+			}
-+		}
-+	}
-+	const int32_t cfaOffsetEBX = prolog.savedRegisters[UNW_X86_EBX].value;
-+	const int32_t cfaOffsetECX = prolog.savedRegisters[UNW_X86_ECX].value;
-+	const int32_t cfaOffsetEDX = prolog.savedRegisters[UNW_X86_EDX].value;
-+	const int32_t cfaOffsetEDI = prolog.savedRegisters[UNW_X86_EDI].value;
-+	const int32_t cfaOffsetESI = prolog.savedRegisters[UNW_X86_ESI].value;
-+	const int32_t cfaOffsetEBP = prolog.savedRegisters[UNW_X86_EBP].value;
-+	
-+	// encode standard RBP frames
-+	compact_unwind_encoding_t  encoding = 0;
-+	if ( standardEBPframe ) {
-+		//		|              |
-+		//		+--------------+   <- CFA
-+		//		|   ret addr   |
-+		//		+--------------+
-+		//		|     ebp      |
-+		//		+--------------+   <- ebp
-+		//		~              ~
-+		//		+--------------+   
-+		//		|  saved reg3  |
-+		//		+--------------+   <- CFA - offset+8
-+		//		|  saved reg2  |
-+		//		+--------------+   <- CFA - offset+e
-+		//		|  saved reg1  |
-+		//		+--------------+   <- CFA - offset
-+		//		|              |
-+		//		+--------------+
-+		//		|              |
-+		//						   <- esp
-+		//
-+		encoding = UNWIND_X86_MODE_EBP_FRAME;
-+		
-+		// find save location of farthest register from ebp
-+		int furthestCfaOffset = 0;
-+		if ( ebxSaved & (cfaOffsetEBX < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetEBX;
-+		if ( ecxSaved & (cfaOffsetECX < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetECX;
-+		if ( edxSaved & (cfaOffsetEDX < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetEDX;
-+		if ( ediSaved & (cfaOffsetEDI < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetEDI;
-+		if ( esiSaved & (cfaOffsetESI < furthestCfaOffset) )
-+			furthestCfaOffset = cfaOffsetESI;
-+		
-+		if ( furthestCfaOffset == 0 ) {
-+			// no registers saved, nothing more to encode
-+			return encoding;
-+		}
-+		
-+		// add stack offset to encoding
-+		int ebpOffset = furthestCfaOffset + 8;
-+		int encodedOffset = ebpOffset/(-4);
-+		if ( encodedOffset > 255 ) {
-+			strcpy(warningBuffer, "offset of saved registers too far to encode");
-+			return UNWIND_X86_MODE_DWARF;
-+		}
-+		encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_EBP_FRAME_OFFSET));
-+		
-+		// add register saved from each stack location
-+		bool encodingFailure = false;
-+		if ( ebxSaved )
-+			encoding |= getEBPEncodedRegister(UNW_X86_EBX, cfaOffsetEBX - furthestCfaOffset, encodingFailure);
-+		if ( ecxSaved )
-+			encoding |= getEBPEncodedRegister(UNW_X86_ECX, cfaOffsetECX - furthestCfaOffset, encodingFailure);
-+		if ( edxSaved )
-+			encoding |= getEBPEncodedRegister(UNW_X86_EDX, cfaOffsetEDX - furthestCfaOffset, encodingFailure);
-+		if ( ediSaved )
-+			encoding |= getEBPEncodedRegister(UNW_X86_EDI, cfaOffsetEDI - furthestCfaOffset, encodingFailure);
-+		if ( esiSaved )
-+			encoding |= getEBPEncodedRegister(UNW_X86_ESI, cfaOffsetESI - furthestCfaOffset, encodingFailure);
-+		
-+		if ( encodingFailure ){
-+			strcpy(warningBuffer, "saved registers not contiguous");
-+			return UNWIND_X86_MODE_DWARF;
-+		}
-+
-+		return encoding;
-+	}
-+	else {
-+		//		|              |
-+		//		+--------------+   <- CFA
-+		//		|   ret addr   |
-+		//		+--------------+
-+		//		|  saved reg1  |
-+		//		+--------------+   <- CFA - 8
-+		//		|  saved reg2  |
-+		//		+--------------+   <- CFA - 12
-+		//		|  saved reg3  |
-+		//		+--------------+   <- CFA - 16
-+		//		|  saved reg4  |
-+		//		+--------------+   <- CFA - 20
-+		//		|  saved reg5  |
-+		//		+--------------+   <- CFA - 24
-+		//		|  saved reg6  |
-+		//		+--------------+   <- CFA - 28
-+		//		|              |
-+		//						   <- esp
-+		//
-+
-+		// for ESP based frames we need to encode stack size in unwind info
-+		encoding = UNWIND_X86_MODE_STACK_IMMD;
-+		uint64_t stackValue = prolog.cfaRegisterOffset / 4;
-+		uint32_t stackAdjust = 0;
-+		bool immedStackSize = true;
-+		const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_FRAMELESS_STACK_SIZE);
-+		if ( stackValue > stackMaxImmedValue ) {
-+			// stack size is too big to fit as an immediate value, so encode offset of subq instruction in function
-+			pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4;		
-+			uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
-+			stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/4;
-+			stackValue = functionContentAdjustStackIns - funcAddr;
-+			immedStackSize = false;
-+			if ( stackAdjust > 7 ) {
-+				strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			encoding = UNWIND_X86_MODE_STACK_IND;
-+		}	
-+		
-+		
-+		// validate that saved registers are all within 6 slots abutting return address
-+		int registers[6];
-+		for (int i=0; i < 6;++i)
-+			registers[i] = 0;
-+		if ( ebxSaved ) {
-+			if ( cfaOffsetEBX < -28 ) {
-+				strcpy(warningBuffer, "ebx is saved too far from return address");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetEBX+28)/4] = UNWIND_X86_REG_EBX;
-+		}
-+		if ( ecxSaved ) {
-+			if ( cfaOffsetECX < -28 ) {
-+				strcpy(warningBuffer, "ecx is saved too far from return address");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetECX+28)/4] = UNWIND_X86_REG_ECX;
-+		}
-+		if ( edxSaved ) {
-+			if ( cfaOffsetEDX < -28 ) {
-+				strcpy(warningBuffer, "edx is saved too far from return address");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetEDX+28)/4] = UNWIND_X86_REG_EDX;
-+		}
-+		if ( ediSaved ) {
-+			if ( cfaOffsetEDI < -28 ) {
-+				strcpy(warningBuffer, "edi is saved too far from return address");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetEDI+28)/4] = UNWIND_X86_REG_EDI;
-+		}
-+		if ( esiSaved ) {
-+			if ( cfaOffsetESI < -28 ) {
-+				strcpy(warningBuffer, "esi is saved too far from return address");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetESI+28)/4] = UNWIND_X86_REG_ESI;
-+		}
-+		if ( ebpSaved ) {
-+			if ( cfaOffsetEBP < -28 ) {
-+				strcpy(warningBuffer, "ebp is saved too far from return address");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+			registers[(cfaOffsetEBP+28)/4] = UNWIND_X86_REG_EBP;
-+		}
-+		
-+		// validate that saved registers are contiguous and abut return address on stack
-+		for (int i=0; i < saveRegisterCount; ++i) {
-+			if ( registers[5-i] == 0 ) {
-+				strcpy(warningBuffer, "registers not save contiguously in stack");
-+				return UNWIND_X86_MODE_DWARF;
-+			}
-+		}
-+				
-+		// encode register permutation
-+		// the 10-bits are encoded differently depending on the number of registers saved
-+		int renumregs[6];
-+		for (int i=6-saveRegisterCount; i < 6; ++i) {
-+			int countless = 0;
-+			for (int j=6-saveRegisterCount; j < i; ++j) {
-+				if ( registers[j] < registers[i] )
-+					++countless;
-+			}
-+			renumregs[i] = registers[i] - countless -1;
-+		}
-+		uint32_t permutationEncoding = 0;
-+		switch ( saveRegisterCount ) {
-+			case 6:
-+				permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
-+				break;
-+			case 5:
-+				permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
-+				break;
-+			case 4:
-+				permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
-+				break;
-+			case 3:
-+				permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
-+				break;
-+			case 2:
-+				permutationEncoding |= (5*renumregs[4] + renumregs[5]);
-+				break;
-+			case 1:
-+				permutationEncoding |= (renumregs[5]);
-+				break;
-+		}
-+		
-+		encoding |= (stackValue << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_SIZE));
-+		encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_ADJUST));
-+		encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_COUNT));
-+		encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION));
-+		return encoding;
-+	}
-+}
-+
-+
-+
-+
-+
-+
-+
-+//
-+//	ppc specific functions
-+//
-+template <typename A, typename R>
-+int DwarfInstructions<A,R>::lastRestoreReg(const Registers_ppc&) 
-+{
-+	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)UNW_PPC_SPEFSCR );
-+	return UNW_PPC_SPEFSCR; 
-+}
-+
-+template <typename A, typename R>
-+bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_ppc&) 
-+{
-+	return (regNum == UNW_PPC_LR); 
-+}
-+
-+template <typename A, typename R>
-+typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
-+										const Registers_ppc& registers)
-+{	
-+	if ( prolog.cfaRegister != 0 )
-+		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
-+	else if ( prolog.cfaExpression != 0 )
-+		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
-+	else
-+		ABORT("getCFA(): unknown location for ppc cfa");
-+}
-+
-+
-+template <typename A, typename R>
-+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_ppc&) 
-+{
-+	return UNWIND_X86_MODE_DWARF;
-+}
-+
-+
-+template <typename A, typename R>
-+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
-+												const Registers_ppc& r, const typename CFI_Parser<A>::PrologInfo& prolog,
-+												char warningBuffer[1024])
-+{
-+	warningBuffer[0] = '\0';
-+	return UNWIND_X86_MODE_DWARF;
-+}
-+
-+
-+
-+
-+} // namespace libunwind
-+
-+
-+#endif // __DWARF_INSTRUCTIONS_HPP__
-+
-+
-+
-+
-diff --git a/src/ld/parsers/libunwind/DwarfParser.hpp b/src/ld/parsers/libunwind/DwarfParser.hpp
-new file mode 100644
-index 0000000..3824d2e
---- /dev/null
-+++ src/ld/parsers/libunwind/DwarfParser.hpp
-@@ -0,0 +1,819 @@
-+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
-+ *
-+ * Copyright (c) 2008 Apple Inc. All rights reserved.
-+ *
-+ * @APPLE_LICENSE_HEADER_START@
-+ *
-+ * This file contains Original Code and/or Modifications of Original Code
-+ * as defined in and that are subject to the Apple Public Source License
-+ * Version 2.0 (the 'License'). You may not use this file except in
-+ * compliance with the License. Please obtain a copy of the License at
-+ * http://www.opensource.apple.com/apsl/ and read it before using this
-+ * file.
-+ *
-+ * The Original Code and all software distributed under the License are
-+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-+ * Please see the License for the specific language governing rights and
-+ * limitations under the License.
-+ *
-+ * @APPLE_LICENSE_HEADER_END@
-+ */
-+ 
-+//
-+// processor specific parsing of dwarf unwind instructions
-+//
-+
-+#ifndef __DWARF_PARSER_HPP__
-+#define __DWARF_PARSER_HPP__
-+
-+#include <stdint.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+#include <vector>
-+
-+#include "libunwind.h"
-+#include "dwarf2.h"
-+
-+#include "AddressSpace.hpp"
-+
-+
-+namespace libunwind {
-+
-+
-+///
-+/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
-+/// See Dwarf Spec for details: 
-+///    http://www.linux-foundation.org/spec/booksets/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
-+///
-+template <typename A>
-+class CFI_Parser
-+{
-+public:
-+	typedef typename A::pint_t		pint_t;	
-+
-+	///
-+	/// Information encoded in a CIE (Common Information Entry)
-+	///  
-+	struct CIE_Info {
-+		pint_t		cieStart;
-+		pint_t		cieLength;
-+		pint_t		cieInstructions;
-+		uint8_t		pointerEncoding;
-+		uint8_t		lsdaEncoding;
-+		uint8_t		personalityEncoding;
-+		uint8_t		personalityOffsetInCIE;
-+		pint_t		personality;
-+		int			codeAlignFactor;
-+		int			dataAlignFactor;
-+		bool		isSignalFrame;
-+		bool		fdesHaveAugmentationData;
-+	};
-+	
-+	///
-+	/// Information about an FDE (Frame Description Entry)
-+	///  
-+	struct FDE_Info {
-+		pint_t		fdeStart;
-+		pint_t		fdeLength;
-+		pint_t		fdeInstructions;
-+		pint_t		pcStart;
-+		pint_t		pcEnd;
-+		pint_t		lsda;
-+	};
-+
-+	///
-+	/// Used by linker when parsing __eh_frame section
-+	///  
-+	struct FDE_Reference {
-+		pint_t		address;
-+		uint32_t	offsetInFDE;
-+		uint8_t		encodingOfAddress;
-+	};
-+	struct FDE_Atom_Info {
-+		pint_t			fdeAddress;
-+		FDE_Reference	function;
-+		FDE_Reference	cie;
-+		FDE_Reference	lsda;
-+	};
-+	struct CIE_Atom_Info {
-+		pint_t			cieAddress;
-+		FDE_Reference	personality;
-+	};
-+	
-+	
-+	///
-+	/// Information about a frame layout and registers saved determined 
-+	/// by "running" the dwarf FDE "instructions"
-+	///  
-+	enum { kMaxRegisterNumber = 120 };
-+	enum RegisterSavedWhere { kRegisterUnused, kRegisterInCFA, kRegisterOffsetFromCFA,
-+							kRegisterInRegister, kRegisterAtExpression, kRegisterIsExpression } ;
-+	struct RegisterLocation {
-+		RegisterSavedWhere	location;
-+		int64_t				value;
-+	};
-+	struct PrologInfo {
-+		uint32_t			cfaRegister;		
-+		int32_t				cfaRegisterOffset;	// CFA = (cfaRegister)+cfaRegisterOffset
-+		int64_t				cfaExpression;		// CFA = expression
-+		uint32_t			spExtraArgSize;
-+		uint32_t			codeOffsetAtStackDecrement;
-+		uint8_t				registerSavedTwiceInCIE;
-+		bool				registersInOtherRegisters;
-+		bool				registerSavedMoreThanOnce;
-+		bool				cfaOffsetWasNegative;
-+		bool				sameValueUsed;
-+		RegisterLocation	savedRegisters[kMaxRegisterNumber];	// from where to restore registers
-+	};
-+
-+	struct PrologInfoStackEntry {
-+								PrologInfoStackEntry(PrologInfoStackEntry* n, const PrologInfo& i)
-+									: next(n), info(i) {}
-+		PrologInfoStackEntry*	next;
-+		PrologInfo				info;
-+	};
-+
-+	static bool findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo);
-+	static const char* decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo);
-+	static bool parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results);
-+	static const char* getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
-+								std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies);
-+	static uint32_t getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength);
-+
-+	static const char* parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo);
-+
-+private:
-+	static bool parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo, 
-+								pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results);
-+};
-+
-+
-+///
-+/// Parse a FDE into a CIE_Info and an FDE_Info 
-+///  
-+template <typename A>
-+const char* CFI_Parser<A>::decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo)
-+{
-+	pint_t p = fdeStart;
-+	uint64_t cfiLength = addressSpace.get32(p);
-+	p += 4;
-+	if ( cfiLength == 0xffffffff ) {
-+		// 0xffffffff means length is really next 8 bytes
-+		cfiLength = addressSpace.get64(p);
-+		p += 8;
-+	}
-+	if ( cfiLength == 0 ) 
-+		return "FDE has zero length";	// end marker
-+	uint32_t ciePointer = addressSpace.get32(p);
-+	if ( ciePointer == 0 ) 
-+		return "FDE is really a CIE";	// this is a CIE not an FDE
-+	pint_t nextCFI = p + cfiLength;
-+	pint_t cieStart = p-ciePointer;
-+	const char* err = parseCIE(addressSpace, cieStart, cieInfo);
-+	if (err != NULL)
-+		return err;
-+	p += 4;
-+	// parse pc begin and range
-+	pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
-+	pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
-+	// parse rest of info
-+	fdeInfo->lsda = 0;
-+	// check for augmentation length
-+	if ( cieInfo->fdesHaveAugmentationData ) {
-+		uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
-+		pint_t endOfAug = p + augLen;
-+		if ( cieInfo->lsdaEncoding != 0 ) {
-+			// peek at value (without indirection).  Zero means no lsda
-+			pint_t lsdaStart = p;
-+			if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) {
-+				// reset pointer and re-parse lsda address
-+				p = lsdaStart;
-+				fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
-+			}
-+		}
-+		p = endOfAug;
-+	}
-+	fdeInfo->fdeStart = fdeStart;
-+	fdeInfo->fdeLength = nextCFI - fdeStart;
-+	fdeInfo->fdeInstructions = p;
-+	fdeInfo->pcStart = pcStart;
-+	fdeInfo->pcEnd = pcStart+pcRange;
-+	return NULL; // success
-+}
-+
-+
-+///
-+/// Scan an eh_frame section to find an FDE for a pc
-+///  
-+template <typename A>
-+bool CFI_Parser<A>::findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo)
-+{
-+	//fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
-+	pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
-+	const pint_t ehSectionEnd = p + sectionLength;
-+	while ( p < ehSectionEnd ) {
-+		pint_t currentCFI = p;
-+		//fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
-+		uint64_t cfiLength = addressSpace.get32(p);
-+		p += 4;
-+		if ( cfiLength == 0xffffffff ) {
-+			// 0xffffffff means length is really next 8 bytes
-+			cfiLength = addressSpace.get64(p);
-+			p += 8;
-+		}
-+		if ( cfiLength == 0 ) 
-+			return false;	// end marker
-+		uint32_t id = addressSpace.get32(p);
-+		if ( id == 0 ) {
-+			// skip over CIEs
-+			p += cfiLength;
-+		}
-+		else {
-+			// process FDE to see if it covers pc
-+			pint_t nextCFI = p + cfiLength;
-+			uint32_t ciePointer = addressSpace.get32(p);
-+			pint_t cieStart = p-ciePointer;
-+			// validate pointer to CIE is within section
-+			if ( (ehSectionStart <= cieStart) && (cieStart < ehSectionEnd) ) {
-+				if ( parseCIE(addressSpace, cieStart, cieInfo) == NULL ) {
-+					p += 4;
-+					// parse pc begin and range
-+					pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
-+					pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
-+					//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
-+					// test if pc is within the function this FDE covers
-+					if ( (pcStart < pc) && (pc <= pcStart+pcRange) ) {
-+						// parse rest of info
-+						fdeInfo->lsda = 0;
-+						// check for augmentation length
-+						if ( cieInfo->fdesHaveAugmentationData ) {
-+							uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
-+							pint_t endOfAug = p + augLen;
-+							if ( cieInfo->lsdaEncoding != 0 ) {
-+								// peek at value (without indirection).  Zero means no lsda
-+								pint_t lsdaStart = p;
-+								if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) {
-+									// reset pointer and re-parse lsda address
-+									p = lsdaStart;
-+									fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
-+								}
-+							}
-+							p = endOfAug;
-+						}
-+						fdeInfo->fdeStart = currentCFI;
-+						fdeInfo->fdeLength = nextCFI - currentCFI;
-+						fdeInfo->fdeInstructions = p;
-+						fdeInfo->pcStart = pcStart;
-+						fdeInfo->pcEnd = pcStart+pcRange;
-+						//fprintf(stderr, "findFDE(pc=0x%llX) found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
-+						return true;
-+					}
-+					else {
-+						//fprintf(stderr, "findFDE(pc=0x%llX) not found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
-+						// pc is not in begin/range, skip this FDE
-+					}
-+				}
-+				else {
-+					// malformed CIE, now augmentation describing pc range encoding
-+					//fprintf(stderr, "malformed CIE\n");
-+				}
-+			}
-+			else {
-+				// malformed FDE.  CIE is bad
-+				//fprintf(stderr, "malformed FDE, cieStart=0x%llX, ehSectionStart=0x%llX, ehSectionEnd=0x%llX\n",
-+				//	(uint64_t)cieStart, (uint64_t)ehSectionStart, (uint64_t)ehSectionEnd);
-+			}
-+			p = nextCFI;
-+		}
-+	}
-+	//fprintf(stderr, "findFDE(pc=0x%llX) not found\n",(uint64_t)pc);
-+	return false;
-+}
-+
-+
-+
-+///
-+/// Extract info from a CIE
-+///  
-+template <typename A>
-+const char* CFI_Parser<A>::parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo)
-+{
-+	//fprintf(stderr, "parseCIE(0x%llX)\n", (long long)cie);
-+	cieInfo->pointerEncoding = 0;
-+	cieInfo->lsdaEncoding = 0;
-+	cieInfo->personalityEncoding = 0;
-+	cieInfo->personalityOffsetInCIE = 0;
-+	cieInfo->personality = 0;
-+	cieInfo->codeAlignFactor = 0;
-+	cieInfo->dataAlignFactor = 0;
-+	cieInfo->isSignalFrame = false;
-+	cieInfo->fdesHaveAugmentationData = false;
-+	cieInfo->cieStart = cie;
-+	pint_t p = cie;
-+	uint64_t cieLength = addressSpace.get32(p);
-+	p += 4;
-+	pint_t cieContentEnd = p + cieLength;
-+	if ( cieLength == 0xffffffff ) {
-+		// 0xffffffff means length is really next 8 bytes
-+		cieLength = addressSpace.get64(p);
-+		p += 8;
-+		cieContentEnd = p + cieLength;
-+	}
-+	if ( cieLength == 0 ) 
-+		return NULL;	
-+	// CIE ID is always 0
-+	if ( addressSpace.get32(p) != 0 ) 
-+		return "CIE ID is not zero";
-+	p += 4;
-+	// Version is always 1 or 3
-+	uint8_t version = addressSpace.get8(p);
-+	if ( (version != 1) && (version != 3) )
-+		return "CIE version is not 1 or 3";
-+	++p;
-+	// save start of augmentation string and find end
-+	pint_t strStart = p;
-+	while ( addressSpace.get8(p) != 0 )
-+		++p;
-+	++p;
-+	// parse code aligment factor
-+	cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd);
-+	// parse data alignment factor
-+	cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
-+	// parse return address register
-+	addressSpace.getULEB128(p, cieContentEnd);
-+	// parse augmentation data based on augmentation string
-+	const char* result = NULL;
-+	if ( addressSpace.get8(strStart) == 'z' ) {
-+		// parse augmentation data length 
-+		addressSpace.getULEB128(p, cieContentEnd);
-+		for (pint_t s=strStart; addressSpace.get8(s) != '\0'; ++s) {
-+			switch ( addressSpace.get8(s) ) {
-+				case 'z':
-+					cieInfo->fdesHaveAugmentationData = true;
-+					break;
-+				case 'P':
-+					cieInfo->personalityEncoding = addressSpace.get8(p);
-+					++p;
-+					cieInfo->personalityOffsetInCIE = p-cie;
-+					cieInfo->personality = addressSpace.getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
-+					break;
-+				case 'L':
-+					cieInfo->lsdaEncoding = addressSpace.get8(p);
-+					++p;
-+					break;
-+				case 'R':
-+					cieInfo->pointerEncoding = addressSpace.get8(p);
-+					++p;
-+					break;
-+				case 'S':
-+					cieInfo->isSignalFrame = true;
-+					break;
-+				default:
-+					// ignore unknown letters
-+					break;
-+			}
-+		}
-+	}
-+	cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
-+	cieInfo->cieInstructions = p;
-+	return result;
-+}
-+
-+
-+template <typename A>
-+uint32_t CFI_Parser<A>::getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength)
-+{
-+	uint32_t count = 0;
-+	const pint_t ehSectionEnd = ehSectionStart + sectionLength;
-+	for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
-+		uint64_t cfiLength = addressSpace.get32(p);
-+		p += 4;
-+		if ( cfiLength == 0xffffffff ) {
-+			// 0xffffffff means length is really next 8 bytes
-+			cfiLength = addressSpace.get64(p);
-+			p += 8;
-+		}
-+		if ( cfiLength == 0 ) 
-+			return count;	// end marker
-+		++count;
-+		p += cfiLength;
-+	}
-+	return count;
-+}
-+
-+
-+
-+template <typename A>
-+const char* CFI_Parser<A>::getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
-+								  std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies)
-+{
-+	const pint_t ehSectionEnd = ehSectionStart + sectionLength;
-+	for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
-+		pint_t currentCFI = p;
-+		uint64_t cfiLength = addressSpace.get32(p);
-+		p += 4;
-+		if ( cfiLength == 0xffffffff ) {
-+			// 0xffffffff means length is really next 8 bytes
-+			cfiLength = addressSpace.get64(p);
-+			p += 8;
-+		}
-+		if ( cfiLength == 0 ) 
-+			return NULL;	// end marker
-+		uint32_t id = addressSpace.get32(p);
-+		if ( id == 0 ) {
-+			// is CIE
-+			CIE_Info cieInfo;
-+			const char* err = parseCIE(addressSpace, currentCFI, &cieInfo);
-+			if ( err != NULL ) 
-+				return err;
-+			CIE_Atom_Info entry;
-+			entry.cieAddress = currentCFI;
-+			entry.personality.address = cieInfo.personality;
-+			entry.personality.offsetInFDE = cieInfo.personalityOffsetInCIE;
-+			entry.personality.encodingOfAddress = cieInfo.personalityEncoding;
-+			cies.push_back(entry);
-+			p += cfiLength;
-+		}
-+		else {
-+			// is FDE
-+			FDE_Atom_Info entry;
-+			entry.fdeAddress = currentCFI;
-+			entry.function.address = 0;
-+			entry.cie.address = 0;
-+			entry.lsda.address = 0;
-+			pint_t nextCFI = p + cfiLength;
-+			uint32_t ciePointer = addressSpace.get32(p);
-+			pint_t cieStart = p-ciePointer;
-+			// validate pointer to CIE is within section
-+			if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) )
-+				return "FDE points to CIE outside __eh_frame section";
-+			CIE_Info cieInfo;
-+			const char* err = parseCIE(addressSpace, cieStart, &cieInfo);
-+			if ( err != NULL ) 
-+				return err;
-+			entry.cie.address = cieStart;
-+			entry.cie.offsetInFDE = p-currentCFI;
-+			entry.cie.encodingOfAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
-+			p += 4;
-+			// parse pc begin and range
-+			pint_t offsetOfFunctionAddress = p-currentCFI;
-+			pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding);
-+			pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F);
-+			//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
-+			// test if pc is within the function this FDE covers
-+			entry.function.address = pcStart;
-+			entry.function.offsetInFDE = offsetOfFunctionAddress;
-+			entry.function.encodingOfAddress = cieInfo.pointerEncoding;
-+			// skip over augmentation length
-+			if ( cieInfo.fdesHaveAugmentationData ) {
-+				uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
-+				pint_t endOfAug = p + augLen;
-+				if ( (cieInfo.lsdaEncoding != 0) && (addressSpace.getP(p) != 0) ) {
-+					pint_t offsetOfLSDAAddress = p-currentCFI;
-+					entry.lsda.address = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding);
-+					entry.lsda.offsetInFDE = offsetOfLSDAAddress;
-+					entry.lsda.encodingOfAddress = cieInfo.lsdaEncoding;
-+				}
-+				p = endOfAug;
-+			}
-+			fdes.push_back(entry);
-+			p = nextCFI;
-+		}
-+	}
-+	return NULL; // success
-+}
-+
-+	
-+
-+///
-+/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
-+///  
-+template <typename A>
-+bool CFI_Parser<A>::parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results)
-+{
-+	// clear results
-+	bzero(results, sizeof(PrologInfo));
-+	PrologInfoStackEntry* rememberStack = NULL;
-+
-+	// parse CIE then FDE instructions
-+	return parseInstructions(addressSpace, cieInfo.cieInstructions, cieInfo.cieStart+cieInfo.cieLength, 
-+						cieInfo, (pint_t)(-1), rememberStack, results)
-+	    && parseInstructions(addressSpace, fdeInfo.fdeInstructions, fdeInfo.fdeStart+fdeInfo.fdeLength, 
-+							cieInfo, upToPC-fdeInfo.pcStart, rememberStack, results);
-+}
-+
-+
-+///
-+/// "run" the dwarf instructions
-+///  
-+template <typename A>
-+bool CFI_Parser<A>::parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo,
-+									pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results)
-+{
-+	const bool logDwarf = false;
-+	pint_t p = instructions;
-+	uint32_t codeOffset = 0;
-+	PrologInfo initialState = *results;
-+	if ( logDwarf ) fprintf(stderr, "parseInstructions(instructions=0x%0llX)\n", (uint64_t)instructionsEnd);
-+	
-+	// see Dwarf Spec, section 6.4.2 for details on unwind opcodes
-+	while ( (p < instructionsEnd) && (codeOffset < pcoffset) ) {
-+		uint64_t reg;
-+		uint64_t reg2;
-+		int64_t offset;
-+		uint64_t length;
-+		uint8_t opcode = addressSpace.get8(p);
-+		uint8_t operand;
-+		PrologInfoStackEntry* entry;
-+		++p;
-+		switch (opcode) {
-+			case DW_CFA_nop:
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_nop\n");
-+				break;
-+			case DW_CFA_set_loc:
-+				codeOffset = addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_set_loc\n");
-+				break;
-+			case DW_CFA_advance_loc1:
-+				codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
-+				p += 1;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc1: new offset=%u\n", codeOffset);
-+				break;
-+			case DW_CFA_advance_loc2:
-+				codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
-+				p += 2;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc2: new offset=%u\n", codeOffset);
-+				break;
-+			case DW_CFA_advance_loc4:
-+				codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
-+				p += 4;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc4: new offset=%u\n", codeOffset);
-+				break;
-+			case DW_CFA_offset_extended:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				if ( results->savedRegisters[reg].location != kRegisterUnused ) 
-+					results->registerSavedMoreThanOnce = true;
-+				results->savedRegisters[reg].location = kRegisterInCFA;
-+				results->savedRegisters[reg].value = offset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg, offset);
-+				break;
-+			case DW_CFA_restore_extended:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);;
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				results->savedRegisters[reg] = initialState.savedRegisters[reg];
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg);
-+				break;
-+			case DW_CFA_undefined:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				results->savedRegisters[reg].location = kRegisterUnused;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg);
-+				break;
-+			case DW_CFA_same_value:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				// <rdar://problem/8456377> DW_CFA_same_value unsupported
-+				// "same value" means register was stored in frame, but its current
-+				// value has not changed, so no need to restore from frame.
-+				// We model this as if the register was never saved.
-+				results->savedRegisters[reg].location = kRegisterUnused;
-+				// set flag to disable conversion to compact unwind
-+				results->sameValueUsed = true;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg);
-+				break;
-+			case DW_CFA_register:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				reg2 = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				if ( reg2 > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
-+					return false;
-+				}
-+				results->savedRegisters[reg].location = kRegisterInRegister;
-+				results->savedRegisters[reg].value = reg2;
-+				// set flag to disable conversion to compact unwind
-+				results->registersInOtherRegisters = true;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2);
-+				break;
-+			case DW_CFA_remember_state:
-+				// avoid operator new, because that would be an upward dependency
-+				entry = (PrologInfoStackEntry*)malloc(sizeof(PrologInfoStackEntry));
-+				if ( entry != NULL ) {
-+					entry->next = rememberStack;
-+					entry->info = *results;
-+					rememberStack = entry;
-+				}
-+				else {
-+					return false;
-+				}
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_remember_state\n");
-+				break;
-+			case DW_CFA_restore_state:
-+				if ( rememberStack != NULL ) {
-+					PrologInfoStackEntry* top = rememberStack;
-+					*results = top->info;
-+					rememberStack = top->next;
-+					free((char*)top);
-+				}
-+				else {
-+					return false;
-+				}
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_state\n");
-+				break;
-+			case DW_CFA_def_cfa:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				offset = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				results->cfaRegister = reg;
-+				results->cfaRegisterOffset = offset;
-+				if ( offset > 0x80000000 ) 
-+					results->cfaOffsetWasNegative = true;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset);
-+				break;
-+			case DW_CFA_def_cfa_register:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				results->cfaRegister = reg;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg);
-+				break;
-+			case DW_CFA_def_cfa_offset:
-+				results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd);
-+				results->codeOffsetAtStackDecrement = codeOffset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n", results->cfaRegisterOffset);
-+				break;
-+			case DW_CFA_def_cfa_expression:
-+				results->cfaRegister = 0;
-+				results->cfaExpression = p;
-+				length = addressSpace.getULEB128(p, instructionsEnd);
-+				p += length;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n", 
-+													results->cfaExpression, length);
-+				break;
-+			case DW_CFA_expression:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_expression dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				results->savedRegisters[reg].location = kRegisterAtExpression;
-+				results->savedRegisters[reg].value = p;
-+				length = addressSpace.getULEB128(p, instructionsEnd);
-+				p += length;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n", 
-+													reg, results->savedRegisters[reg].value, length);
-+				break;
-+			case DW_CFA_offset_extended_sf:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+				if ( results->savedRegisters[reg].location != kRegisterUnused ) 
-+					results->registerSavedMoreThanOnce = true;
-+				results->savedRegisters[reg].location = kRegisterInCFA;
-+				results->savedRegisters[reg].value = offset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n", reg, offset);
-+				break;
-+			case DW_CFA_def_cfa_sf:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				results->cfaRegister = reg;
-+				results->cfaRegisterOffset = offset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg, offset);
-+				break;
-+			case DW_CFA_def_cfa_offset_sf:
-+				results->cfaRegisterOffset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+				results->codeOffsetAtStackDecrement = codeOffset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n", results->cfaRegisterOffset);
-+				break;
-+			case DW_CFA_val_offset:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+				results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
-+				results->savedRegisters[reg].value = offset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg, offset);
-+				break;
-+			case DW_CFA_val_offset_sf:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+				results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
-+				results->savedRegisters[reg].value = offset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg, offset);
-+				break;
-+			case DW_CFA_val_expression:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				results->savedRegisters[reg].location = kRegisterIsExpression;
-+				results->savedRegisters[reg].value = p;
-+				length = addressSpace.getULEB128(p, instructionsEnd);
-+				p += length;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n", 
-+													reg, results->savedRegisters[reg].value, length);
-+				break;
-+			case DW_CFA_GNU_args_size:
-+				offset = addressSpace.getULEB128(p, instructionsEnd);
-+				results->spExtraArgSize = offset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", offset);
-+				break;
-+			case DW_CFA_GNU_negative_offset_extended:
-+				reg = addressSpace.getULEB128(p, instructionsEnd);
-+				if ( reg > kMaxRegisterNumber ) {
-+					fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf unwind, reg too big\n");
-+					return false;
-+				}
-+				offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+				if ( results->savedRegisters[reg].location != kRegisterUnused ) 
-+					results->registerSavedMoreThanOnce = true;
-+				results->savedRegisters[reg].location = kRegisterInCFA;
-+				results->savedRegisters[reg].value = -offset;
-+				if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset);
-+				break;
-+			default:
-+				operand = opcode & 0x3F;
-+				switch ( opcode & 0xC0 ) {
-+					case DW_CFA_offset:
-+						reg = operand;
-+						offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
-+						if ( results->savedRegisters[reg].location != kRegisterUnused ) {
-+							// look for idiom of PC saved twice in CIE to mean disable compact unwind encoding
-+							if ( (pcoffset == (pint_t)(-1)) 
-+								&& (results->savedRegisters[reg].location == kRegisterInCFA) 
-+								&& (results->savedRegisters[reg].value == offset)  )
-+								results->registerSavedTwiceInCIE = reg;
-+							else
-+								results->registerSavedMoreThanOnce = true;
-+						}
-+						results->savedRegisters[reg].location = kRegisterInCFA;
-+						results->savedRegisters[reg].value = offset;
-+						if ( logDwarf ) fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand, offset);
-+						break;
-+					case DW_CFA_advance_loc:
-+						codeOffset += operand * cieInfo.codeAlignFactor;
-+						if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc: new offset=%u\n", codeOffset);
-+						break;
-+					case DW_CFA_restore:
-+						// <rdar://problem/7503075> Python crashes when handling an exception thrown by an obj-c object
-+						// libffi uses DW_CFA_restore in the middle of some custom dwarf, so it is not a good epilog flag
-+						//return true; // gcc-4.5 starts the epilog with this
-+						reg = operand;
-+						results->savedRegisters[reg] = initialState.savedRegisters[reg];
-+						if ( logDwarf ) fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg);
-+						break;
-+					default: 
-+						if ( logDwarf ) fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
-+						return false;
-+				}
-+		}
-+	}
-+
-+	return true;
-+}
-+
-+
-+} // namespace libunwind 
-+
-+
-+#endif // __DWARF_PARSER_HPP__
-+
-+
-+
-+
-diff --git a/src/ld/parsers/libunwind/InternalMacros.h b/src/ld/parsers/libunwind/InternalMacros.h
-new file mode 100644
-index 0000000..25c1631
---- /dev/null
-+++ src/ld/parsers/libunwind/InternalMacros.h
-@@ -0,0 +1,105 @@
-+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
-+ *
-+ * Copyright (c) 2008 Apple Inc. All rights reserved.
-+ *
-+ * @APPLE_LICENSE_HEADER_START@
-+ *
-+ * This file contains Original Code and/or Modifications of Original Code
-+ * as defined in and that are subject to the Apple Public Source License
-+ * Version 2.0 (the 'License'). You may not use this file except in
-+ * compliance with the License. Please obtain a copy of the License at
-+ * http://www.opensource.apple.com/apsl/ and read it before using this
-+ * file.
-+ *
-+ * The Original Code and all software distributed under the License are
-+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-+ * Please see the License for the specific language governing rights and
-+ * limitations under the License.
-+ *
-+ * @APPLE_LICENSE_HEADER_END@
-+ */
-+ 
-+
-+
-+#ifndef INTERNAL_MACROS_H
-+#define INTERNAL_MACROS_H
-+
-+#include <assert.h>
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+	extern void __assert_rtn(const char *, const char *, int, const char *) __attribute__((noreturn));
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#define UNW_STEP_SUCCESS 1
-+#define UNW_STEP_END     0
-+
-+
-+struct v128 { unsigned int vec[4]; };
-+
-+
-+#define EXPORT __attribute__((visibility("default"))) 
-+
-+#define COMPILE_TIME_ASSERT( expr )    \
-+		extern int compile_time_assert_failed[ ( expr ) ? 1 : -1 ] __attribute__( ( unused ) );
-+
-+#define ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg) 
-+
-+#if NDEBUG
-+	#define DEBUG_MESSAGE(msg, ...)  
-+	#define DEBUG_PRINT_API(msg, ...)
-+	#define DEBUG_PRINT_UNWINDING_TEST 0
-+	#define DEBUG_PRINT_UNWINDING(msg, ...)
-+	#define DEBUG_LOG_NON_ZERO(x) x;
-+	#define INITIALIZE_DEBUG_PRINT_API
-+	#define INITIALIZE_DEBUG_PRINT_UNWINDING
-+#else
-+	#define DEBUG_MESSAGE(msg, ...)  fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
-+	#ifdef __cplusplus
-+		extern "C" {
-+	#endif
-+		extern  bool logAPIs();
-+		extern  bool logUnwinding();
-+	#ifdef __cplusplus
-+		}
-+	#endif
-+	#define DEBUG_LOG_NON_ZERO(x) { int _err = x; if ( _err != 0 ) fprintf(stderr, "libuwind: " #x "=%d in %s", _err, __FUNCTION__); }
-+	#define DEBUG_PRINT_API(msg, ...) do { if ( logAPIs() ) fprintf(stderr,  msg, __VA_ARGS__); } while(0)
-+	#define DEBUG_PRINT_UNWINDING(msg, ...) do { if ( logUnwinding() ) fprintf(stderr,  msg, __VA_ARGS__); } while(0)
-+	#define DEBUG_PRINT_UNWINDING_TEST logUnwinding()
-+	#define INITIALIZE_DEBUG_PRINT_API bool logAPIs() { static bool log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); return log; }
-+	#define INITIALIZE_DEBUG_PRINT_UNWINDING bool logUnwinding() { static bool log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); return log; }
-+#endif
-+
-+
-+// note hack for <rdar://problem/6175741>
-+// Once libgcc_s.dylib vectors to libSystem, then we can remove the $ld$hide$os10.6$ lines
-+#if __ppc__
-+	#define NOT_HERE_BEFORE_10_6(sym) \
-+		extern const char sym##_tmp3 __asm("$ld$hide$os10.3$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \
-+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
-+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; 
-+	#define NEVER_HERE(sym) \
-+		extern const char sym##_tmp3 __asm("$ld$hide$os10.3$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \
-+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
-+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
-+		extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
-+#else
-+	#define NOT_HERE_BEFORE_10_6(sym) \
-+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
-+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; 
-+	#define NEVER_HERE(sym) \
-+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
-+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
-+		extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
-+#endif
-+
-+
-+
-+#endif // INTERNAL_MACROS_H
-diff --git a/src/ld/parsers/libunwind/Registers.hpp b/src/ld/parsers/libunwind/Registers.hpp
-new file mode 100644
-index 0000000..7d39fd7
---- /dev/null
-+++ src/ld/parsers/libunwind/Registers.hpp
-@@ -0,0 +1,1050 @@
-+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
-+ *
-+ * Copyright (c) 2007-2009 Apple Inc. All rights reserved.
-+ *
-+ * @APPLE_LICENSE_HEADER_START@
-+ *
-+ * This file contains Original Code and/or Modifications of Original Code
-+ * as defined in and that are subject to the Apple Public Source License
-+ * Version 2.0 (the 'License'). You may not use this file except in
-+ * compliance with the License. Please obtain a copy of the License at
-+ * http://www.opensource.apple.com/apsl/ and read it before using this
-+ * file.
-+ *
-+ * The Original Code and all software distributed under the License are
-+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-+ * Please see the License for the specific language governing rights and
-+ * limitations under the License.
-+ *
-+ * @APPLE_LICENSE_HEADER_END@
-+ */
-+ 
-+//
-+//	C++ interface to lower levels of libuwind 
-+//
-+
-+#ifndef __REGISTERS_HPP__
-+#define __REGISTERS_HPP__
-+
-+#include <stdint.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <dlfcn.h>
-+#include <mach-o/loader.h>
-+#include <mach-o/getsect.h>
-+#include <mach/i386/thread_status.h>
-+
-+#include "libunwind.h"
-+#include "InternalMacros.h"
-+
-+namespace libunwind {
-+
-+
-+///
-+/// Registers_x86 holds the register state of a thread in a 32-bit intel process.  
-+///
-+class Registers_x86
-+{
-+public:	
-+					Registers_x86();
-+					Registers_x86(const void* registers);
-+
-+	bool			validRegister(int num) const;
-+	uint32_t		getRegister(int num) const;
-+	void			setRegister(int num, uint32_t value);
-+	bool			validFloatRegister(int num) const { return false; }
-+	double			getFloatRegister(int num) const;
-+	void			setFloatRegister(int num, double value); 
-+	bool			validVectorRegister(int num) const { return false; }
-+	v128			getVectorRegister(int num) const;
-+	void			setVectorRegister(int num, v128 value);
-+	const char*		getRegisterName(int num);
-+	void			jumpto();
-+	
-+	uint32_t		getSP() const			{ return fRegisters.__esp; }
-+	void			setSP(uint32_t value)	{ fRegisters.__esp = value; }
-+	uint32_t		getIP()	const			{ return fRegisters.__eip; }
-+	void			setIP(uint32_t value)	{ fRegisters.__eip = value; }
-+	uint32_t		getEBP() const			{ return fRegisters.__ebp; }
-+	void			setEBP(uint32_t value)	{ fRegisters.__ebp = value; }
-+	uint32_t		getEBX() const			{ return fRegisters.__ebx; }
-+	void			setEBX(uint32_t value)	{ fRegisters.__ebx = value; }
-+	uint32_t		getECX() const			{ return fRegisters.__ecx; }
-+	void			setECX(uint32_t value)	{ fRegisters.__ecx = value; }
-+	uint32_t		getEDX() const			{ return fRegisters.__edx; }
-+	void			setEDX(uint32_t value)	{ fRegisters.__edx = value; }
-+	uint32_t		getESI() const			{ return fRegisters.__esi; }
-+	void			setESI(uint32_t value)	{ fRegisters.__esi = value; }
-+	uint32_t		getEDI() const			{ return fRegisters.__edi; }
-+	void			setEDI(uint32_t value)	{ fRegisters.__edi = value; }
-+	
-+private:
-+	i386_thread_state_t  fRegisters;
-+};
-+
-+inline Registers_x86::Registers_x86(const void* registers)
-+{
-+	COMPILE_TIME_ASSERT( sizeof(Registers_x86) < sizeof(unw_context_t) );
-+	fRegisters = *((i386_thread_state_t*)registers); 
-+}
-+
-+inline Registers_x86::Registers_x86()
-+{
-+	bzero(&fRegisters, sizeof(fRegisters)); 
-+}
-+
-+
-+inline bool Registers_x86::validRegister(int regNum) const
-+{
-+	if ( regNum == UNW_REG_IP )
-+		return true;
-+	if ( regNum == UNW_REG_SP )
-+		return true;
-+	if ( regNum < 0 )
-+		return false;
-+	if ( regNum > 7 )
-+		return false;
-+	return true;
-+}
-+
-+inline uint32_t Registers_x86::getRegister(int regNum) const
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			return fRegisters.__eip;
-+		case UNW_REG_SP:
-+			return fRegisters.__esp;
-+		case UNW_X86_EAX:
-+			return fRegisters.__eax;
-+		case UNW_X86_ECX:
-+			return fRegisters.__ecx;
-+		case UNW_X86_EDX:
-+			return fRegisters.__edx;
-+		case UNW_X86_EBX:
-+			return fRegisters.__ebx;
-+		case UNW_X86_EBP:
-+			return fRegisters.__ebp;
-+		case UNW_X86_ESP:
-+			return fRegisters.__esp;
-+		case UNW_X86_ESI:
-+			return fRegisters.__esi;
-+		case UNW_X86_EDI:
-+			return fRegisters.__edi;
-+	}
-+	ABORT("unsupported x86 register");
-+}
-+
-+inline void Registers_x86::setRegister(int regNum, uint32_t value)
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			fRegisters.__eip = value;
-+			return;
-+		case UNW_REG_SP:
-+			fRegisters.__esp = value;
-+			return;
-+		case UNW_X86_EAX:
-+			fRegisters.__eax = value;
-+			return;
-+		case UNW_X86_ECX:
-+			fRegisters.__ecx = value;
-+			return;
-+		case UNW_X86_EDX:
-+			fRegisters.__edx = value;
-+			return;
-+		case UNW_X86_EBX:
-+			fRegisters.__ebx = value;
-+			return;
-+		case UNW_X86_EBP:
-+			fRegisters.__ebp = value;
-+			return;
-+		case UNW_X86_ESP:
-+			fRegisters.__esp = value;
-+			return;
-+		case UNW_X86_ESI:
-+			fRegisters.__esi = value;
-+			return;
-+		case UNW_X86_EDI:
-+			fRegisters.__edi = value;
-+			return;
-+	}
-+	ABORT("unsupported x86 register");
-+}
-+
-+inline const char* Registers_x86::getRegisterName(int regNum)
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			return "ip";
-+		case UNW_REG_SP:
-+			return "esp";
-+		case UNW_X86_EAX:
-+			return "eax";
-+		case UNW_X86_ECX:
-+			return "ecx";
-+		case UNW_X86_EDX:
-+			return "edx";
-+		case UNW_X86_EBX:
-+			return "ebx";
-+		case UNW_X86_EBP:
-+			return "ebp";
-+		case UNW_X86_ESP:
-+			return "esp";
-+		case UNW_X86_ESI:
-+			return "esi";
-+		case UNW_X86_EDI:
-+			return "edi";
-+		default:
-+			return "unknown register";
-+	}
-+}
-+
-+inline double Registers_x86::getFloatRegister(int num) const
-+{
-+	ABORT("no x86 float registers");
-+}
-+
-+inline void Registers_x86::setFloatRegister(int num, double value)
-+{
-+	ABORT("no x86 float registers");
-+}
-+
-+inline v128 Registers_x86::getVectorRegister(int num) const
-+{
-+	ABORT("no x86 vector registers");
-+}
-+
-+inline void Registers_x86::setVectorRegister(int num, v128 value)
-+{
-+	ABORT("no x86 vector registers");
-+}
-+
-+
-+
-+
-+///
-+/// Registers_x86_64  holds the register state of a thread in a 64-bit intel process.  
-+///
-+class Registers_x86_64
-+{
-+public:	
-+					Registers_x86_64();
-+					Registers_x86_64(const void* registers); 
-+
-+	bool			validRegister(int num) const;
-+	uint64_t		getRegister(int num) const;
-+	void			setRegister(int num, uint64_t value);
-+	bool			validFloatRegister(int num) const{ return false; }
-+	double			getFloatRegister(int num) const;
-+	void			setFloatRegister(int num, double value);
-+	bool			validVectorRegister(int num) const { return false; }
-+	v128			getVectorRegister(int num) const;
-+	void			setVectorRegister(int num, v128 value);
-+	const char*		getRegisterName(int num);
-+	void			jumpto();
-+	uint64_t		getSP()	const			{ return fRegisters.__rsp; }
-+	void			setSP(uint64_t value)	{ fRegisters.__rsp = value; }
-+	uint64_t		getIP()	const			{ return fRegisters.__rip; }
-+	void			setIP(uint64_t value)	{ fRegisters.__rip = value; }
-+	uint64_t		getRBP() const			{ return fRegisters.__rbp; }
-+	void			setRBP(uint64_t value)	{ fRegisters.__rbp = value; }
-+	uint64_t		getRBX() const			{ return fRegisters.__rbx; }
-+	void			setRBX(uint64_t value)	{ fRegisters.__rbx = value; }
-+	uint64_t		getR12() const			{ return fRegisters.__r12; }
-+	void			setR12(uint64_t value)	{ fRegisters.__r12 = value; }
-+	uint64_t		getR13() const			{ return fRegisters.__r13; }
-+	void			setR13(uint64_t value)	{ fRegisters.__r13 = value; }
-+	uint64_t		getR14() const			{ return fRegisters.__r14; }
-+	void			setR14(uint64_t value)	{ fRegisters.__r14 = value; }
-+	uint64_t		getR15() const			{ return fRegisters.__r15; }
-+	void			setR15(uint64_t value)	{ fRegisters.__r15 = value; }
-+private:
-+	x86_thread_state64_t fRegisters;
-+};
-+
-+inline Registers_x86_64::Registers_x86_64(const void* registers)
-+{
-+	COMPILE_TIME_ASSERT( sizeof(Registers_x86_64) < sizeof(unw_context_t) );
-+	fRegisters = *((x86_thread_state64_t*)registers); 
-+}
-+
-+inline Registers_x86_64::Registers_x86_64()
-+{
-+	bzero(&fRegisters, sizeof(fRegisters)); 
-+}
-+
-+
-+inline bool Registers_x86_64::validRegister(int regNum) const
-+{
-+	if ( regNum == UNW_REG_IP )
-+		return true;
-+	if ( regNum == UNW_REG_SP )
-+		return true;
-+	if ( regNum < 0 )
-+		return false;
-+	if ( regNum > 15 )
-+		return false;
-+	return true;
-+}
-+
-+inline uint64_t Registers_x86_64::getRegister(int regNum) const
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			return fRegisters.__rip;
-+		case UNW_REG_SP:
-+			return fRegisters.__rsp;
-+		case UNW_X86_64_RAX:
-+			return fRegisters.__rax;
-+		case UNW_X86_64_RDX:
-+			return fRegisters.__rdx;
-+		case UNW_X86_64_RCX:
-+			return fRegisters.__rcx;
-+		case UNW_X86_64_RBX:
-+			return fRegisters.__rbx;
-+		case UNW_X86_64_RSI:
-+			return fRegisters.__rsi;
-+		case UNW_X86_64_RDI:
-+			return fRegisters.__rdi;
-+		case UNW_X86_64_RBP:
-+			return fRegisters.__rbp;
-+		case UNW_X86_64_RSP:
-+			return fRegisters.__rsp;
-+		case UNW_X86_64_R8:
-+			return fRegisters.__r8;
-+		case UNW_X86_64_R9:
-+			return fRegisters.__r9;
-+		case UNW_X86_64_R10:
-+			return fRegisters.__r10;
-+		case UNW_X86_64_R11:
-+			return fRegisters.__r11;
-+		case UNW_X86_64_R12:
-+			return fRegisters.__r12;
-+		case UNW_X86_64_R13:
-+			return fRegisters.__r13;
-+		case UNW_X86_64_R14:
-+			return fRegisters.__r14;
-+		case UNW_X86_64_R15:
-+			return fRegisters.__r15;
-+	}
-+	ABORT("unsupported x86_64 register");
-+}
-+
-+inline void Registers_x86_64::setRegister(int regNum, uint64_t value)
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			fRegisters.__rip = value;
-+			return;
-+		case UNW_REG_SP:
-+			fRegisters.__rsp = value;
-+			return;
-+		case UNW_X86_64_RAX:
-+			fRegisters.__rax = value;
-+			return;
-+		case UNW_X86_64_RDX:
-+			fRegisters.__rdx = value;
-+			return;
-+		case UNW_X86_64_RCX:
-+			fRegisters.__rcx = value;
-+			return;
-+		case UNW_X86_64_RBX:
-+			fRegisters.__rbx = value;
-+			return;
-+		case UNW_X86_64_RSI:
-+			fRegisters.__rsi = value;
-+			return;
-+		case UNW_X86_64_RDI:
-+			fRegisters.__rdi = value;
-+			return;
-+		case UNW_X86_64_RBP:
-+			fRegisters.__rbp = value;
-+			return;
-+		case UNW_X86_64_RSP:
-+			fRegisters.__rsp = value;
-+			return;
-+		case UNW_X86_64_R8:
-+			fRegisters.__r8 = value;
-+			return;
-+		case UNW_X86_64_R9:
-+			fRegisters.__r9 = value;
-+			return;
-+		case UNW_X86_64_R10:
-+			fRegisters.__r10 = value;
-+			return;
-+		case UNW_X86_64_R11:
-+			fRegisters.__r11 = value;
-+			return;
-+		case UNW_X86_64_R12:
-+			fRegisters.__r12 = value;
-+			return;
-+		case UNW_X86_64_R13:
-+			fRegisters.__r13 = value;
-+			return;
-+		case UNW_X86_64_R14:
-+			fRegisters.__r14 = value;
-+			return;
-+		case UNW_X86_64_R15:
-+			fRegisters.__r15 = value;
-+			return;
-+	}
-+	ABORT("unsupported x86_64 register");
-+}
-+
-+inline const char* Registers_x86_64::getRegisterName(int regNum)
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			return "rip";
-+		case UNW_REG_SP:
-+			return "rsp";
-+		case UNW_X86_64_RAX:
-+			return "rax";
-+		case UNW_X86_64_RDX:
-+			return "rdx";
-+		case UNW_X86_64_RCX:
-+			return "rcx";
-+		case UNW_X86_64_RBX:
-+			return "rbx";
-+		case UNW_X86_64_RSI:
-+			return "rsi";
-+		case UNW_X86_64_RDI:
-+			return "rdi";
-+		case UNW_X86_64_RBP:
-+			return "rbp";
-+		case UNW_X86_64_RSP:
-+			return "rsp";
-+		case UNW_X86_64_R8:
-+			return "r8";
-+		case UNW_X86_64_R9:
-+			return "r9";
-+		case UNW_X86_64_R10:
-+			return "r10";
-+		case UNW_X86_64_R11:
-+			return "r11";
-+		case UNW_X86_64_R12:
-+			return "r12";
-+		case UNW_X86_64_R13:
-+			return "r13";
-+		case UNW_X86_64_R14:
-+			return "r14";
-+		case UNW_X86_64_R15:
-+			return "r15";
-+		default:
-+			return "unknown register";
-+	}
-+}
-+
-+double Registers_x86_64::getFloatRegister(int num) const
-+{
-+	ABORT("no x86_64 float registers");
-+}
-+
-+void Registers_x86_64::setFloatRegister(int num, double value)
-+{
-+	ABORT("no x86_64 float registers");
-+}
-+
-+inline v128 Registers_x86_64::getVectorRegister(int num) const
-+{
-+	ABORT("no x86_64 vector registers");
-+}
-+
-+inline void Registers_x86_64::setVectorRegister(int num, v128 value)
-+{
-+	ABORT("no x86_64 vector registers");
-+}
-+
-+
-+///
-+/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC process.  
-+///
-+class Registers_ppc
-+{
-+public:	
-+					Registers_ppc();
-+					Registers_ppc(const void* registers);
-+
-+	bool			validRegister(int num) const;
-+	uint32_t		getRegister(int num) const;
-+	void			setRegister(int num, uint32_t value);
-+	bool			validFloatRegister(int num) const;
-+	double			getFloatRegister(int num) const;
-+	void			setFloatRegister(int num, double value);
-+	bool			validVectorRegister(int num) const;
-+	v128			getVectorRegister(int num) const;
-+	void			setVectorRegister(int num, v128 value);
-+	void			jumpto();
-+	const char*		getRegisterName(int num);
-+	uint64_t		getSP() const			{ return fRegisters.__r1; }
-+	void			setSP(uint64_t value)	{ fRegisters.__r1 = value; }
-+	uint64_t		getIP() const			{ return fRegisters.__srr0; }
-+	void			setIP(uint64_t value)	{ fRegisters.__srr0 = value; }
-+private:
-+	struct ppc_thread_state_t
-+	{
-+		unsigned int __srr0;	/* Instruction address register (PC) */
-+		unsigned int __srr1;	/* Machine state register (supervisor) */
-+		unsigned int __r0;
-+		unsigned int __r1;
-+		unsigned int __r2;
-+		unsigned int __r3;
-+		unsigned int __r4;
-+		unsigned int __r5;
-+		unsigned int __r6;
-+		unsigned int __r7;
-+		unsigned int __r8;
-+		unsigned int __r9;
-+		unsigned int __r10;
-+		unsigned int __r11;
-+		unsigned int __r12;
-+		unsigned int __r13;
-+		unsigned int __r14;
-+		unsigned int __r15;
-+		unsigned int __r16;
-+		unsigned int __r17;
-+		unsigned int __r18;
-+		unsigned int __r19;
-+		unsigned int __r20;
-+		unsigned int __r21;
-+		unsigned int __r22;
-+		unsigned int __r23;
-+		unsigned int __r24;
-+		unsigned int __r25;
-+		unsigned int __r26;
-+		unsigned int __r27;
-+		unsigned int __r28;
-+		unsigned int __r29;
-+		unsigned int __r30;
-+		unsigned int __r31;
-+		unsigned int __cr;	/* Condition register */
-+		unsigned int __xer;	/* User's integer exception register */
-+		unsigned int __lr;	/* Link register */
-+		unsigned int __ctr;	/* Count register */
-+		unsigned int __mq;	/* MQ register (601 only) */
-+		unsigned int __vrsave;	/* Vector Save Register */
-+	};
-+	
-+	struct ppc_float_state_t
-+	{
-+		double  __fpregs[32];
-+
-+		unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
-+		unsigned int __fpscr;	/* floating point status register */
-+	};
-+
-+	ppc_thread_state_t	fRegisters;
-+	ppc_float_state_t	fFloatRegisters;
-+	v128				fVectorRegisters[32];	// offset 424 
-+};
-+
-+
-+
-+inline Registers_ppc::Registers_ppc(const void* registers) 
-+{
-+	COMPILE_TIME_ASSERT( sizeof(Registers_ppc) < sizeof(unw_context_t) );
-+	fRegisters = *((ppc_thread_state_t*)registers); 
-+	fFloatRegisters = *((ppc_float_state_t*)((char*)registers+160));
-+	memcpy(fVectorRegisters, ((char*)registers+424), sizeof(fVectorRegisters));
-+}
-+
-+inline Registers_ppc::Registers_ppc() 
-+{ 
-+	bzero(&fRegisters, sizeof(fRegisters)); 
-+	bzero(&fFloatRegisters, sizeof(fFloatRegisters)); 
-+	bzero(&fVectorRegisters, sizeof(fVectorRegisters)); 
-+}
-+
-+
-+inline bool Registers_ppc::validRegister(int regNum) const
-+{
-+	if ( regNum == UNW_REG_IP )
-+		return true;
-+	if ( regNum == UNW_REG_SP )
-+		return true;
-+	if ( regNum == UNW_PPC_VRSAVE )
-+		return true;
-+	if ( regNum < 0 )
-+		return false;
-+	if ( regNum <= UNW_PPC_R31 )
-+		return true;
-+	if ( regNum == UNW_PPC_MQ )
-+		return true;
-+	if ( regNum == UNW_PPC_LR )
-+		return true;
-+	if ( regNum == UNW_PPC_CTR )
-+		return true;
-+	if ( (UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7) )
-+		return true;
-+	return false;
-+}
-+
-+
-+inline uint32_t Registers_ppc::getRegister(int regNum) const
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			return fRegisters.__srr0;
-+		case UNW_REG_SP:
-+			return fRegisters.__r1;
-+		case UNW_PPC_R0:
-+			return fRegisters.__r0;
-+		case UNW_PPC_R1:
-+			return fRegisters.__r1;
-+		case UNW_PPC_R2:
-+			return fRegisters.__r2;
-+		case UNW_PPC_R3:
-+			return fRegisters.__r3;
-+		case UNW_PPC_R4:
-+			return fRegisters.__r4;
-+		case UNW_PPC_R5:
-+			return fRegisters.__r5;
-+		case UNW_PPC_R6:
-+			return fRegisters.__r6;
-+		case UNW_PPC_R7:
-+			return fRegisters.__r7;
-+		case UNW_PPC_R8:
-+			return fRegisters.__r8;
-+		case UNW_PPC_R9:
-+			return fRegisters.__r9;
-+		case UNW_PPC_R10:
-+			return fRegisters.__r10;
-+		case UNW_PPC_R11:
-+			return fRegisters.__r11;
-+		case UNW_PPC_R12:
-+			return fRegisters.__r12;
-+		case UNW_PPC_R13:
-+			return fRegisters.__r13;
-+		case UNW_PPC_R14:
-+			return fRegisters.__r14;
-+		case UNW_PPC_R15:
-+			return fRegisters.__r15;
-+		case UNW_PPC_R16:
-+			return fRegisters.__r16;
-+		case UNW_PPC_R17:
-+			return fRegisters.__r17;
-+		case UNW_PPC_R18:
-+			return fRegisters.__r18;
-+		case UNW_PPC_R19:
-+			return fRegisters.__r19;
-+		case UNW_PPC_R20:
-+			return fRegisters.__r20;
-+		case UNW_PPC_R21:
-+			return fRegisters.__r21;
-+		case UNW_PPC_R22:
-+			return fRegisters.__r22;
-+		case UNW_PPC_R23:
-+			return fRegisters.__r23;
-+		case UNW_PPC_R24:
-+			return fRegisters.__r24;
-+		case UNW_PPC_R25:
-+			return fRegisters.__r25;
-+		case UNW_PPC_R26:
-+			return fRegisters.__r26;
-+		case UNW_PPC_R27:
-+			return fRegisters.__r27;
-+		case UNW_PPC_R28:
-+			return fRegisters.__r28;
-+		case UNW_PPC_R29:
-+			return fRegisters.__r29;
-+		case UNW_PPC_R30:
-+			return fRegisters.__r30;
-+		case UNW_PPC_R31:
-+			return fRegisters.__r31;
-+		case UNW_PPC_LR:
-+			return fRegisters.__lr;
-+		case UNW_PPC_CR0:
-+			return (fRegisters.__cr & 0xF0000000);
-+		case UNW_PPC_CR1:
-+			return (fRegisters.__cr & 0x0F000000);
-+		case UNW_PPC_CR2:
-+			return (fRegisters.__cr & 0x00F00000);
-+		case UNW_PPC_CR3:
-+			return (fRegisters.__cr & 0x000F0000);
-+		case UNW_PPC_CR4:
-+			return (fRegisters.__cr & 0x0000F000);
-+		case UNW_PPC_CR5:
-+			return (fRegisters.__cr & 0x00000F00);
-+		case UNW_PPC_CR6:
-+			return (fRegisters.__cr & 0x000000F0);
-+		case UNW_PPC_CR7:
-+			return (fRegisters.__cr & 0x0000000F);
-+		case UNW_PPC_VRSAVE:
-+			return fRegisters.__vrsave;
-+	}
-+	ABORT("unsupported ppc register");
-+}
-+
-+
-+inline void Registers_ppc::setRegister(int regNum, uint32_t value)
-+{
-+	//fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);	
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			fRegisters.__srr0 = value;
-+			return;
-+		case UNW_REG_SP:
-+			fRegisters.__r1 = value;
-+			return;
-+		case UNW_PPC_R0:
-+			fRegisters.__r0 = value;
-+			return;
-+		case UNW_PPC_R1:
-+			fRegisters.__r1 = value;
-+			return;
-+		case UNW_PPC_R2:
-+			fRegisters.__r2 = value;
-+			return;
-+		case UNW_PPC_R3:
-+			fRegisters.__r3 = value;
-+			return;
-+		case UNW_PPC_R4:
-+			fRegisters.__r4 = value;
-+			return;
-+		case UNW_PPC_R5:
-+			fRegisters.__r5 = value;
-+			return;
-+		case UNW_PPC_R6:
-+			fRegisters.__r6 = value;
-+			return;
-+		case UNW_PPC_R7:
-+			fRegisters.__r7 = value;
-+			return;
-+		case UNW_PPC_R8:
-+			fRegisters.__r8 = value;
-+			return;
-+		case UNW_PPC_R9:
-+			fRegisters.__r9 = value;
-+			return;
-+		case UNW_PPC_R10:
-+			fRegisters.__r10 = value;
-+			return;
-+		case UNW_PPC_R11:
-+			fRegisters.__r11 = value;
-+			return;
-+		case UNW_PPC_R12:
-+			fRegisters.__r12 = value;
-+			return;
-+		case UNW_PPC_R13:
-+			fRegisters.__r13 = value;
-+			return;
-+		case UNW_PPC_R14:
-+			fRegisters.__r14 = value;
-+			return;
-+		case UNW_PPC_R15:
-+			fRegisters.__r15 = value;
-+			return;
-+		case UNW_PPC_R16:
-+			fRegisters.__r16 = value;
-+			return;
-+		case UNW_PPC_R17:
-+			fRegisters.__r17 = value;
-+			return;
-+		case UNW_PPC_R18:
-+			fRegisters.__r18 = value;
-+			return;
-+		case UNW_PPC_R19:
-+			fRegisters.__r19 = value;
-+			return;
-+		case UNW_PPC_R20:
-+			fRegisters.__r20 = value;
-+			return;
-+		case UNW_PPC_R21:
-+			fRegisters.__r21 = value;
-+			return;
-+		case UNW_PPC_R22:
-+			fRegisters.__r22 = value;
-+			return;
-+		case UNW_PPC_R23:
-+			fRegisters.__r23 = value;
-+			return;
-+		case UNW_PPC_R24:
-+			fRegisters.__r24 = value;
-+			return;
-+		case UNW_PPC_R25:
-+			fRegisters.__r25 = value;
-+			return;
-+		case UNW_PPC_R26:
-+			fRegisters.__r26 = value;
-+			return;
-+		case UNW_PPC_R27:
-+			fRegisters.__r27 = value;
-+			return;
-+		case UNW_PPC_R28:
-+			fRegisters.__r28 = value;
-+			return;
-+		case UNW_PPC_R29:
-+			fRegisters.__r29 = value;
-+			return;
-+		case UNW_PPC_R30:
-+			fRegisters.__r30 = value;
-+			return;
-+		case UNW_PPC_R31:
-+			fRegisters.__r31 = value;
-+			return;
-+		case UNW_PPC_MQ:
-+			fRegisters.__mq = value;
-+			return;
-+		case UNW_PPC_LR:
-+			fRegisters.__lr = value;
-+			return;
-+		case UNW_PPC_CTR:
-+			fRegisters.__ctr = value;
-+			return;
-+		case UNW_PPC_CR0:
-+			fRegisters.__cr &= 0x0FFFFFFF;
-+			fRegisters.__cr |= (value & 0xF0000000);
-+			return;
-+		case UNW_PPC_CR1:
-+			fRegisters.__cr &= 0xF0FFFFFF;
-+			fRegisters.__cr |= (value & 0x0F000000);
-+			return;
-+		case UNW_PPC_CR2:
-+			fRegisters.__cr &= 0xFF0FFFFF;
-+			fRegisters.__cr |= (value & 0x00F00000);
-+			return;
-+		case UNW_PPC_CR3:
-+			fRegisters.__cr &= 0xFFF0FFFF;
-+			fRegisters.__cr |= (value & 0x000F0000);
-+			return;
-+		case UNW_PPC_CR4:
-+			fRegisters.__cr &= 0xFFFF0FFF;
-+			fRegisters.__cr |= (value & 0x0000F000);
-+			return;
-+		case UNW_PPC_CR5:
-+			fRegisters.__cr &= 0xFFFFF0FF;
-+			fRegisters.__cr |= (value & 0x00000F00);
-+			return;
-+		case UNW_PPC_CR6:
-+			fRegisters.__cr &= 0xFFFFFF0F;
-+			fRegisters.__cr |= (value & 0x000000F0);
-+			return;
-+		case UNW_PPC_CR7:
-+			fRegisters.__cr &= 0xFFFFFFF0;
-+			fRegisters.__cr |= (value & 0x0000000F);
-+			return;
-+		case UNW_PPC_VRSAVE:
-+			fRegisters.__vrsave = value;
-+			return;
-+			// not saved
-+			return;
-+		case UNW_PPC_XER:
-+			fRegisters.__xer = value;
-+			return;
-+		case UNW_PPC_AP:
-+		case UNW_PPC_VSCR:
-+		case UNW_PPC_SPEFSCR:
-+			// not saved
-+			return;
-+	}
-+	ABORT("unsupported ppc register");
-+}
-+
-+inline bool Registers_ppc::validFloatRegister(int regNum) const
-+{
-+	if ( regNum < UNW_PPC_F0 )
-+		return false;
-+	if ( regNum > UNW_PPC_F31 )
-+		return false;
-+	return true;
-+}
-+
-+inline double Registers_ppc::getFloatRegister(int regNum) const
-+{
-+	assert(validFloatRegister(regNum));
-+	return fFloatRegisters.__fpregs[regNum-UNW_PPC_F0];
-+}
-+
-+inline void Registers_ppc::setFloatRegister(int regNum, double value)
-+{
-+	//fprintf(stderr, "Registers_ppc::setFloatRegister(%d, %g))\n", regNum, value);
-+	assert(validFloatRegister(regNum));
-+	fFloatRegisters.__fpregs[regNum-UNW_PPC_F0] = value;
-+}
-+
-+
-+inline bool Registers_ppc::validVectorRegister(int regNum) const
-+{
-+	if ( regNum < UNW_PPC_V0 )
-+		return false;
-+	if ( regNum > UNW_PPC_V31 )
-+		return false;
-+	return true;
-+}
-+
-+v128 Registers_ppc::getVectorRegister(int regNum) const
-+{
-+	assert(validVectorRegister(regNum));
-+	v128 result = fVectorRegisters[regNum-UNW_PPC_V0];
-+	//fprintf(stderr, "Registers_ppc::getVectorRegister(this=%p, %d) => <0x%08X, 0x%08X, 0x%08X, 0x%08X> \n", 
-+	//		this, regNum, result.vec[0], result.vec[1], result.vec[2], result.vec[3]);
-+	return result;
-+}
-+
-+void Registers_ppc::setVectorRegister(int regNum, v128 value) 
-+{
-+	assert(validVectorRegister(regNum));
-+	//fprintf(stderr, "Registers_ppc::setVectorRegister(this=%p, %d) <0x%08X, 0x%08X, 0x%08X, 0x%08X> => <0x%08X, 0x%08X, 0x%08X, 0x%08X> \n", 
-+	//		this, regNum, fVectorRegisters[regNum-UNW_PPC_V0].vec[0], fVectorRegisters[regNum-UNW_PPC_V0].vec[1], fVectorRegisters[regNum-UNW_PPC_V0].vec[2], 
-+	//			fVectorRegisters[regNum-UNW_PPC_V0].vec[3], value.vec[0], value.vec[1], value.vec[2], value.vec[3]);
-+	fVectorRegisters[regNum-UNW_PPC_V0] = value;
-+}
-+
-+
-+inline const char* Registers_ppc::getRegisterName(int regNum)
-+{
-+	switch ( regNum ) {
-+		case UNW_REG_IP:
-+			return "ip";
-+		case UNW_REG_SP:
-+			return "sp";
-+		case UNW_PPC_R0:
-+			return "r0";
-+		case UNW_PPC_R1:
-+			return "r1";
-+		case UNW_PPC_R2:
-+			return "r2";
-+		case UNW_PPC_R3:
-+			return "r3";
-+		case UNW_PPC_R4:
-+			return "r4";
-+		case UNW_PPC_R5:
-+			return "r5";
-+		case UNW_PPC_R6:
-+			return "r6";
-+		case UNW_PPC_R7:
-+			return "r7";
-+		case UNW_PPC_R8:
-+			return "r8";
-+		case UNW_PPC_R9:
-+			return "r9";
-+		case UNW_PPC_R10:
-+			return "r10";
-+		case UNW_PPC_R11:
-+			return "r11";
-+		case UNW_PPC_R12:
-+			return "r12";
-+		case UNW_PPC_R13:
-+			return "r13";
-+		case UNW_PPC_R14:
-+			return "r14";
-+		case UNW_PPC_R15:
-+			return "r15";
-+		case UNW_PPC_R16:
-+			return "r16";
-+		case UNW_PPC_R17:
-+			return "r17";
-+		case UNW_PPC_R18:
-+			return "r18";
-+		case UNW_PPC_R19:
-+			return "r19";
-+		case UNW_PPC_R20:
-+			return "r20";
-+		case UNW_PPC_R21:
-+			return "r21";
-+		case UNW_PPC_R22:
-+			return "r22";
-+		case UNW_PPC_R23:
-+			return "r23";
-+		case UNW_PPC_R24:
-+			return "r24";
-+		case UNW_PPC_R25:
-+			return "r25";
-+		case UNW_PPC_R26:
-+			return "r26";
-+		case UNW_PPC_R27:
-+			return "r27";
-+		case UNW_PPC_R28:
-+			return "r28";
-+		case UNW_PPC_R29:
-+			return "r29";
-+		case UNW_PPC_R30:
-+			return "r30";
-+		case UNW_PPC_R31:
-+			return "r31";
-+		case UNW_PPC_F0:
-+			return "fp0";
-+		case UNW_PPC_F1:
-+			return "fp1";
-+		case UNW_PPC_F2:
-+			return "fp2";
-+		case UNW_PPC_F3:
-+			return "fp3";
-+		case UNW_PPC_F4:
-+			return "fp4";
-+		case UNW_PPC_F5:
-+			return "fp5";
-+		case UNW_PPC_F6:
-+			return "fp6";
-+		case UNW_PPC_F7:
-+			return "fp7";
-+		case UNW_PPC_F8:
-+			return "fp8";
-+		case UNW_PPC_F9:
-+			return "fp9";
-+		case UNW_PPC_F10:
-+			return "fp10";
-+		case UNW_PPC_F11:
-+			return "fp11";
-+		case UNW_PPC_F12:
-+			return "fp12";
-+		case UNW_PPC_F13:
-+			return "fp13";
-+		case UNW_PPC_F14:
-+			return "fp14";
-+		case UNW_PPC_F15:
-+			return "fp15";
-+		case UNW_PPC_F16:
-+			return "fp16";
-+		case UNW_PPC_F17:
-+			return "fp17";
-+		case UNW_PPC_F18:
-+			return "fp18";
-+		case UNW_PPC_F19:
-+			return "fp19";
-+		case UNW_PPC_F20:
-+			return "fp20";
-+		case UNW_PPC_F21:
-+			return "fp21";
-+		case UNW_PPC_F22:
-+			return "fp22";
-+		case UNW_PPC_F23:
-+			return "fp23";
-+		case UNW_PPC_F24:
-+			return "fp24";
-+		case UNW_PPC_F25:
-+			return "fp25";
-+		case UNW_PPC_F26:
-+			return "fp26";
-+		case UNW_PPC_F27:
-+			return "fp27";
-+		case UNW_PPC_F28:
-+			return "fp28";
-+		case UNW_PPC_F29:
-+			return "fp29";
-+		case UNW_PPC_F30:
-+			return "fp30";
-+		case UNW_PPC_F31:
-+			return "fp31";
-+		case UNW_PPC_LR:
-+			return "lr";
-+		default:
-+			return "unknown register";
-+	}
-+
-+
-+}
-+
-+
-+} // namespace libunwind 
-+
-+
-+
-+#endif // __REGISTERS_HPP__
-+
-+
-+
-+
--- 
-2.2.1
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20150213/86aabea3/attachment-0001.html>


More information about the macports-changes mailing list