[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