<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[132916] distfiles</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="https://trac.macports.org/changeset/132916">132916</a></dd>
<dt>Author</dt> <dd>jeremyhu@macports.org</dd>
<dt>Date</dt> <dd>2015-02-13 00:53:30 -0800 (Fri, 13 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Move large ld64 patch to distfiles</pre>

<h3>Added Paths</h3>
<ul>
<li>distfiles/ld64/</li>
<li><a href="#distfilesld64ld6497standalonelibunwindheaderspatch">distfiles/ld64/ld64-97-standalone-libunwind-headers.patch</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="distfilesld64ld6497standalonelibunwindheaderspatch"></a>
<div class="addfile"><h4>Added: distfiles/ld64/ld64-97-standalone-libunwind-headers.patch (0 => 132916)</h4>
<pre class="diff"><span>
<span class="info">--- distfiles/ld64/ld64-97-standalone-libunwind-headers.patch                                (rev 0)
+++ distfiles/ld64/ld64-97-standalone-libunwind-headers.patch        2015-02-13 08:53:30 UTC (rev 132916)
</span><span class="lines">@@ -0,0 +1,4438 @@
</span><ins>+From ce433767d79be40375b69dd3139d04978401df3d Mon Sep 17 00:00:00 2001
+From: Nick Kledzik &lt;kledzik@apple.com&gt;
+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 &quot;dwarf2.h&quot;
+ #include &quot;debugline.h&quot;

+-#include &lt;libunwind/DwarfInstructions.hpp&gt;
+-#include &lt;libunwind/AddressSpace.hpp&gt;
+-#include &lt;libunwind/Registers.hpp&gt;
++#include &quot;libunwind/DwarfInstructions.hpp&quot;
++#include &quot;libunwind/AddressSpace.hpp&quot;
++#include &quot;libunwind/Registers.hpp&quot;

+ //
+ //
+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 &lt;stdint.h&gt;
++#include &lt;stdio.h&gt;
++#include &lt;stdlib.h&gt;
++#include &lt;dlfcn.h&gt;
++#include &lt;mach-o/loader.h&gt;
++#include &lt;mach-o/getsect.h&gt;
++#include &lt;mach-o/dyld_priv.h&gt;
++#include &lt;mach/i386/thread_status.h&gt;
++#include &lt;Availability.h&gt;
++
++#include &quot;FileAbstraction.hpp&quot;
++#include &quot;libunwind.h&quot;
++#include &quot;InternalMacros.h&quot;
++#include &quot;dwarf2.h&quot;
++
++
++#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 (&quot;__DATA,__dyld&quot;))) = { 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(&quot;__dyld_find_unwind_sections&quot;, (void**)&amp;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&amp; addr, pint_t end);
++        static int64_t                getSLEB128(pint_t&amp; addr, pint_t end);
++        
++                pint_t                        getEncodedP(pint_t&amp; 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&amp; mh, pint_t&amp; dwarfStart, pint_t&amp; dwarfLen, pint_t&amp; 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&amp; 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(&quot;truncated uleb128 expression&quot;);
++
++                b = *p &amp; 0x7f;
++
++                if (bit &gt;= 64 || b &lt;&lt; bit &gt;&gt; bit != b) {
++                        ABORT(&quot;malformed uleb128 expression&quot;);
++                }
++                else {
++                        result |= b &lt;&lt; bit;
++                        bit += 7;
++                }
++        } while ( *p++ &gt;= 0x80 );
++        addr = (pint_t)p;
++        return result;
++}
++
++/* Read a SLEB128 into a 64-bit word.  */
++inline int64_t
++LocalAddressSpace::getSLEB128(pint_t&amp; 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 &amp; 0x7f) &lt;&lt; bit);
++                bit += 7;
++        } while (byte &amp; 0x80);
++        // sign extend negative numbers
++        if ( (byte &amp; 0x40) != 0 )
++                result |= (-1LL) &lt;&lt; bit;
++        addr = (pint_t)p;
++        return result;
++}
++
++LocalAddressSpace::pint_t
++LocalAddressSpace::getEncodedP(pint_t&amp; 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 &amp; 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(&quot;unknown pointer encoding&quot;);
++        }
++        
++        // then add relative offset
++        switch ( encoding &amp; 0x70 ) {
++                case DW_EH_PE_absptr:
++                        // do nothing
++                        break;
++                case DW_EH_PE_pcrel:
++                        result += startAddr;
++                        break;
++                case DW_EH_PE_textrel:
++                        ABORT(&quot;DW_EH_PE_textrel pointer encoding not supported&quot;);
++                        break;
++                case DW_EH_PE_datarel:
++                        ABORT(&quot;DW_EH_PE_datarel pointer encoding not supported&quot;);
++                        break;
++                case DW_EH_PE_funcrel:
++                        ABORT(&quot;DW_EH_PE_funcrel pointer encoding not supported&quot;);
++                        break;
++                case DW_EH_PE_aligned:
++                        ABORT(&quot;DW_EH_PE_aligned pointer encoding not supported&quot;);
++                        break;
++                default:
++                        ABORT(&quot;unknown pointer encoding&quot;);
++                        break;
++        }
++        
++        if ( encoding &amp; DW_EH_PE_indirect )
++                result = getP(result);
++        
++        return result;
++}
++
++
++inline bool LocalAddressSpace::findUnwindSections(pint_t addr, pint_t&amp; mh, pint_t&amp; dwarfStart, pint_t&amp; dwarfLen, pint_t&amp; compactStart)
++{
++        dyld_unwind_sections info;
++        if ( _dyld_find_unwind_sections((void*)addr, &amp;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, &amp;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 &lt;typename P&gt;
++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&amp; addr, pint_t end);
++                int64_t                        getSLEB128(pint_t&amp; addr, pint_t end);
++                pint_t                        getEncodedP(pint_t&amp; 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&amp; info);
++private:
++                void*                        localCopy(pint_t addr);
++
++
++                task_t                        fTask;
++};
++
++
++template &lt;typename P&gt;
++uint8_t OtherAddressSpace&lt;P&gt;::get8(pint_t addr)
++{
++        return *((uint8_t*)localCopy(addr));
++}
++
++template &lt;typename P&gt;
++uint16_t OtherAddressSpace&lt;P&gt;::get16(pint_t addr)
++{
++        return P::E::get16(*(uint16_t*)localCopy(addr));
++}
++
++template &lt;typename P&gt;
++uint32_t OtherAddressSpace&lt;P&gt;::get32(pint_t addr)
++{
++        return P::E::get32(*(uint32_t*)localCopy(addr));
++}
++
++template &lt;typename P&gt;
++uint64_t OtherAddressSpace&lt;P&gt;::get64(pint_t addr)
++{
++        return P::E::get64(*(uint64_t*)localCopy(addr));
++}
++
++template &lt;typename P&gt;
++typename P::uint_t OtherAddressSpace&lt;P&gt;::getP(pint_t addr)
++{
++        return P::getP(*(uint64_t*)localCopy(addr));
++}
++
++template &lt;typename P&gt;
++uint64_t OtherAddressSpace&lt;P&gt;::getULEB128(pint_t&amp; 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 &lt;typename P&gt;
++int64_t OtherAddressSpace&lt;P&gt;::getSLEB128(pint_t&amp; 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 &lt;typename P&gt;
++void* OtherAddressSpace&lt;P&gt;::localCopy(pint_t addr)
++{
++        // FIX ME
++}
++
++template &lt;typename P&gt;
++bool OtherAddressSpace&lt;P&gt;::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&lt;Pointer32&lt;LittleEndian&gt; &gt;                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&lt;Pointer64&lt;LittleEndian&gt; &gt;                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&lt;Pointer32&lt;BigEndian&gt; &gt;                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 &lt;stdint.h&gt;
++#include &lt;stdio.h&gt;
++#include &lt;stdlib.h&gt;
++
++#include &lt;algorithm&gt;
++#include &lt;vector&gt;
++
++#include &lt;libunwind.h&gt;
++#include &lt;mach-o/compact_unwind_encoding.h&gt;
++
++#include &quot;dwarf2.h&quot;
++#include &quot;AddressSpace.hpp&quot;
++#include &quot;Registers.hpp&quot;
++#include &quot;DwarfParser.hpp&quot;
++#include &quot;InternalMacros.h&quot;
++//#include &quot;CompactUnwinder.hpp&quot;
++
++#define EXTRACT_BITS(value, mask) \
++        ( (value &gt;&gt; __builtin_ctz(mask)) &amp; (((1 &lt;&lt; __builtin_popcount(mask)))-1) )
++
++#define CFI_INVALID_ADDRESS ((pint_t)(-1))
++
++namespace libunwind {
++
++///
++/// Used by linker when parsing __eh_frame section
++///  
++template &lt;typename A&gt;
++struct CFI_Reference {
++        typedef typename A::pint_t                pint_t;        
++        uint8_t                encodingOfTargetAddress;
++        uint32_t        offsetInCFI;
++        pint_t                targetAddress;
++};
++template &lt;typename A&gt;
++struct CFI_Atom_Info {
++        typedef typename A::pint_t                pint_t;        
++        pint_t                        address;
++        uint32_t                size;
++        bool                        isCIE;
++        union {
++                struct {
++                        CFI_Reference&lt;A&gt;        function;
++                        CFI_Reference&lt;A&gt;        cie;
++                        CFI_Reference&lt;A&gt;        lsda;
++                        uint32_t                compactUnwindInfo;
++                }                        fdeInfo;
++                struct {
++                        CFI_Reference&lt;A&gt;        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 &lt;typename A, typename R&gt;
++class DwarfInstructions
++{
++public:
++        typedef typename A::pint_t                pint_t;        
++        typedef typename A::sint_t                sint_t;        
++
++        static const char* parseCFIs(A&amp; addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
++                                                CFI_Atom_Info&lt;A&gt;* infos, uint32_t infosCount, void* ref, WarnFunc warn);
++
++
++        static compact_unwind_encoding_t createCompactEncodingFromFDE(A&amp; addressSpace, pint_t fdeStart, 
++                                                                                                                                pint_t* lsda, pint_t* personality,
++                                                                                                                                char warningBuffer[1024]);
++
++        static int stepWithDwarf(A&amp; addressSpace, pint_t pc, pint_t fdeStart, R&amp; registers);
++                                                                                
++private:
++
++        enum {
++                DW_X86_64_RET_ADDR = 16
++        };
++
++        enum {
++                DW_X86_RET_ADDR = 8
++        };
++
++        static pint_t evaluateExpression(pint_t expression, A&amp; addressSpace, const R&amp; registers, pint_t initialStackValue);
++        static pint_t getSavedRegister(A&amp; addressSpace, const R&amp; registers, pint_t cfa, 
++                                                                                const typename CFI_Parser&lt;A&gt;::RegisterLocation&amp; savedReg);
++        static double getSavedFloatRegister(A&amp; addressSpace, const R&amp; registers, pint_t cfa, 
++                                                                                const typename CFI_Parser&lt;A&gt;::RegisterLocation&amp; savedReg);
++        static v128 getSavedVectorRegister(A&amp; addressSpace, const R&amp; registers, pint_t cfa, 
++                                                                                const typename CFI_Parser&lt;A&gt;::RegisterLocation&amp; savedReg);
++                                                                                
++        // x86 specific variants
++        static int    lastRestoreReg(const Registers_x86&amp;);
++        static bool   isReturnAddressRegister(int regNum, const Registers_x86&amp;);
++        static pint_t getCFA(A&amp; addressSpace, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog, const Registers_x86&amp;);
++
++        static uint32_t getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool&amp; failure);
++        static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86&amp;);
++        static compact_unwind_encoding_t createCompactEncodingFromProlog(A&amp; addressSpace, pint_t funcAddr,
++                                                                                                const Registers_x86&amp;, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog,
++                                                                                                char warningBuffer[1024]);
++
++        // x86_64 specific variants
++        static int    lastRestoreReg(const Registers_x86_64&amp;);
++        static bool   isReturnAddressRegister(int regNum, const Registers_x86_64&amp;);
++        static pint_t getCFA(A&amp; addressSpace, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog, const Registers_x86_64&amp;);
++
++        static uint32_t getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool&amp; failure);
++        static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86_64&amp;);
++        static compact_unwind_encoding_t createCompactEncodingFromProlog(A&amp; addressSpace, pint_t funcAddr,
++                                                                                                const Registers_x86_64&amp;, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog,
++                                                                                                char warningBuffer[1024]);
++        
++        // ppc specific variants
++        static int    lastRestoreReg(const Registers_ppc&amp;);
++        static bool   isReturnAddressRegister(int regNum, const Registers_ppc&amp;);
++        static pint_t getCFA(A&amp; addressSpace, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog, const Registers_ppc&amp;);
++        static compact_unwind_encoding_t encodeToUseDwarf(const Registers_ppc&amp;);
++        static compact_unwind_encoding_t createCompactEncodingFromProlog(A&amp; addressSpace, pint_t funcAddr,
++                                                                                                const Registers_ppc&amp;, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog,
++                                                                                                char warningBuffer[1024]);
++};
++
++
++                                                                                        
++
++template &lt;typename A, typename R&gt;
++const char* DwarfInstructions&lt;A,R&gt;::parseCFIs(A&amp; addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
++                                                                                                CFI_Atom_Info&lt;A&gt;* infos, uint32_t infosCount, void* ref, WarnFunc warn)
++{
++        typename CFI_Parser&lt;A&gt;::CIE_Info cieInfo;
++        CFI_Atom_Info&lt;A&gt;* entry = infos;
++        CFI_Atom_Info&lt;A&gt;* end = &amp;infos[infosCount];
++        const pint_t ehSectionEnd = ehSectionStart + sectionLength;
++        for (pint_t p=ehSectionStart; p &lt; 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 &gt;= end )
++                        return &quot;too little space allocated for parseCFIs&quot;;
++                pint_t nextCFI = p + cfiLength;
++                uint32_t id = addressSpace.get32(p);
++                if ( id == 0 ) {
++                        // is CIE
++                        const char* err = CFI_Parser&lt;A&gt;::parseCIE(addressSpace, currentCFI, &amp;cieInfo);
++                        if ( err != NULL ) 
++                                return err;
++                        entry-&gt;address = currentCFI;
++                        entry-&gt;size = nextCFI - currentCFI;
++                        entry-&gt;isCIE = true;
++                        entry-&gt;u.cieInfo.personality.targetAddress = cieInfo.personality;
++                        entry-&gt;u.cieInfo.personality.offsetInCFI = cieInfo.personalityOffsetInCIE;
++                        entry-&gt;u.cieInfo.personality.encodingOfTargetAddress = cieInfo.personalityEncoding;
++                        ++entry;
++                }
++                else {
++                        // is FDE
++                        entry-&gt;address = currentCFI;
++                        entry-&gt;size = nextCFI - currentCFI;
++                        entry-&gt;isCIE = false;
++                        entry-&gt;u.fdeInfo.function.targetAddress = CFI_INVALID_ADDRESS;
++                        entry-&gt;u.fdeInfo.cie.targetAddress = CFI_INVALID_ADDRESS;
++                        entry-&gt;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 &lt; ehSectionStart) || (cieStart &gt; ehSectionEnd) )
++                                return &quot;FDE points to CIE outside __eh_frame section&quot;;
++                        // optimize usual case where cie is same for all FDEs
++                        if ( cieStart != cieInfo.cieStart ) {
++                                const char* err = CFI_Parser&lt;A&gt;::parseCIE(addressSpace, cieStart, &amp;cieInfo);
++                                if ( err != NULL ) 
++                                        return err;
++                        }
++                        entry-&gt;u.fdeInfo.cie.targetAddress = cieStart;
++                        entry-&gt;u.fdeInfo.cie.offsetInCFI = p-currentCFI;
++                        entry-&gt;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 &amp; 0x0F);
++                        //fprintf(stderr, &quot;FDE with pcRange [0x%08llX, 0x%08llX)\n&quot;,(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
++                        // test if pc is within the function this FDE covers
++                        entry-&gt;u.fdeInfo.function.targetAddress = pcStart;
++                        entry-&gt;u.fdeInfo.function.offsetInCFI = offsetOfFunctionAddress;
++                        entry-&gt;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 &amp; 0x0F) != 0 ) {
++                                                // reset pointer and re-parse lsda address
++                                                p = lsdaStart;
++                                                pint_t offsetOfLSDAAddress = p-currentCFI;
++                                                entry-&gt;u.fdeInfo.lsda.targetAddress = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding);
++                                                entry-&gt;u.fdeInfo.lsda.offsetInCFI = offsetOfLSDAAddress;
++                                                entry-&gt;u.fdeInfo.lsda.encodingOfTargetAddress = cieInfo.lsdaEncoding;
++                                        }
++                                }
++                                p = endOfAug;
++                        }
++                        // compute compact unwind encoding
++                        typename CFI_Parser&lt;A&gt;::FDE_Info fdeInfo;
++                        fdeInfo.fdeStart = currentCFI;
++                        fdeInfo.fdeLength = nextCFI - currentCFI;
++                        fdeInfo.fdeInstructions = p;
++                        fdeInfo.pcStart = pcStart;
++                        fdeInfo.pcEnd = pcStart +  pcRange;
++                        fdeInfo.lsda = entry-&gt;u.fdeInfo.lsda.targetAddress;
++                        typename CFI_Parser&lt;A&gt;::PrologInfo prolog;
++                        R dummy; // for proper selection of architecture specific functions
++                        if ( CFI_Parser&lt;A&gt;::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &amp;prolog) ) {
++                                char warningBuffer[1024];
++                                entry-&gt;u.fdeInfo.compactUnwindInfo = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer);
++                                if ( fdeInfo.lsda != CFI_INVALID_ADDRESS ) 
++                                        entry-&gt;u.fdeInfo.compactUnwindInfo |= UNWIND_HAS_LSDA;
++                                if ( warningBuffer[0] != '\0' )
++                                        warn(ref, fdeInfo.pcStart, warningBuffer);
++                        }
++                        else {
++                                warn(ref, CFI_INVALID_ADDRESS, &quot;dwarf unwind instructions could not be parsed&quot;);
++                                entry-&gt;u.fdeInfo.compactUnwindInfo = encodeToUseDwarf(dummy);
++                        }
++                        ++entry;
++                }
++                p = nextCFI;
++        }
++        if ( entry != end )
++                return &quot;wrong entry count for parseCFIs&quot;;
++        return NULL; // success
++}
++
++
++
++
++template &lt;typename A, typename R&gt;
++compact_unwind_encoding_t DwarfInstructions&lt;A,R&gt;::createCompactEncodingFromFDE(A&amp; addressSpace, pint_t fdeStart, 
++                                                                                                                                                pint_t* lsda, pint_t* personality,
++                                                                                                                                                char warningBuffer[1024])
++{
++        typename CFI_Parser&lt;A&gt;::FDE_Info fdeInfo;
++        typename CFI_Parser&lt;A&gt;::CIE_Info cieInfo;
++        R dummy; // for proper selection of architecture specific functions
++        if ( CFI_Parser&lt;A&gt;::decodeFDE(addressSpace, fdeStart, &amp;fdeInfo, &amp;cieInfo) == NULL ) {
++                typename CFI_Parser&lt;A&gt;::PrologInfo prolog;
++                if ( CFI_Parser&lt;A&gt;::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &amp;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, &quot;dwarf unwind instructions could not be parsed&quot;);
++                        return encodeToUseDwarf(dummy);
++                }
++        }
++        else {
++                strcpy(warningBuffer, &quot;dwarf FDE could not be parsed&quot;);
++                return encodeToUseDwarf(dummy);
++        }
++}
++
++
++template &lt;typename A, typename R&gt;
++typename A::pint_t DwarfInstructions&lt;A,R&gt;::getSavedRegister(A&amp; addressSpace, const R&amp; registers, pint_t cfa,
++                                                                                                        const typename CFI_Parser&lt;A&gt;::RegisterLocation&amp; savedReg)
++{
++        switch ( savedReg.location ) {
++                case CFI_Parser&lt;A&gt;::kRegisterInCFA:
++                        return addressSpace.getP(cfa + savedReg.value);
++
++                case CFI_Parser&lt;A&gt;::kRegisterAtExpression:
++                        return addressSpace.getP(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
++
++                case CFI_Parser&lt;A&gt;::kRegisterIsExpression:
++                        return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
++
++                case CFI_Parser&lt;A&gt;::kRegisterInRegister:
++                        return registers.getRegister(savedReg.value);
++
++                case CFI_Parser&lt;A&gt;::kRegisterUnused:
++                case CFI_Parser&lt;A&gt;::kRegisterOffsetFromCFA:
++                        // FIX ME
++                        break;
++        }
++        ABORT(&quot;unsupported restore location for register&quot;);
++}
++
++template &lt;typename A, typename R&gt;
++double DwarfInstructions&lt;A,R&gt;::getSavedFloatRegister(A&amp; addressSpace, const R&amp; registers, pint_t cfa,
++                                                                                                        const typename CFI_Parser&lt;A&gt;::RegisterLocation&amp; savedReg)
++{
++        switch ( savedReg.location ) {
++                case CFI_Parser&lt;A&gt;::kRegisterInCFA:
++                        return addressSpace.getDouble(cfa + savedReg.value);
++
++                case CFI_Parser&lt;A&gt;::kRegisterAtExpression:
++                        return addressSpace.getDouble(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
++
++                case CFI_Parser&lt;A&gt;::kRegisterIsExpression:
++                case CFI_Parser&lt;A&gt;::kRegisterUnused:
++                case CFI_Parser&lt;A&gt;::kRegisterOffsetFromCFA:
++                case CFI_Parser&lt;A&gt;::kRegisterInRegister:
++                        // FIX ME
++                        break;
++        }
++        ABORT(&quot;unsupported restore location for float register&quot;);
++}
++
++template &lt;typename A, typename R&gt;
++v128 DwarfInstructions&lt;A,R&gt;::getSavedVectorRegister(A&amp; addressSpace, const R&amp; registers, pint_t cfa,
++                                                                                                        const typename CFI_Parser&lt;A&gt;::RegisterLocation&amp; savedReg)
++{
++        switch ( savedReg.location ) {
++                case CFI_Parser&lt;A&gt;::kRegisterInCFA:
++                        return addressSpace.getVector(cfa + savedReg.value);
++
++                case CFI_Parser&lt;A&gt;::kRegisterAtExpression:
++                        return addressSpace.getVector(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
++
++                case CFI_Parser&lt;A&gt;::kRegisterIsExpression:
++                case CFI_Parser&lt;A&gt;::kRegisterUnused:
++                case CFI_Parser&lt;A&gt;::kRegisterOffsetFromCFA:
++                case CFI_Parser&lt;A&gt;::kRegisterInRegister:
++                        // FIX ME
++                        break;
++        }
++        ABORT(&quot;unsupported restore location for vector register&quot;);
++}
++
++
++template &lt;typename A, typename R&gt;
++int DwarfInstructions&lt;A,R&gt;::stepWithDwarf(A&amp; addressSpace, pint_t pc, pint_t fdeStart, R&amp; registers)
++{
++        //fprintf(stderr, &quot;stepWithDwarf(pc=0x%0llX, fdeStart=0x%0llX)\n&quot;, (uint64_t)pc, (uint64_t)fdeStart);
++        typename CFI_Parser&lt;A&gt;::FDE_Info fdeInfo;
++        typename CFI_Parser&lt;A&gt;::CIE_Info cieInfo;
++        if ( CFI_Parser&lt;A&gt;::decodeFDE(addressSpace, fdeStart, &amp;fdeInfo, &amp;cieInfo) == NULL ) {
++                typename CFI_Parser&lt;A&gt;::PrologInfo prolog;
++                if ( CFI_Parser&lt;A&gt;::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &amp;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 &lt;= lastRestoreReg(newRegisters); ++i) {
++                                if ( prolog.savedRegisters[i].location != CFI_Parser&lt;A&gt;::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 &lt;typename A, typename R&gt;
++typename A::pint_t DwarfInstructions&lt;A,R&gt;::evaluateExpression(pint_t expression, A&amp; addressSpace, 
++                                                                                                                const R&amp; 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, &quot;evaluateExpression(): length=%llu\n&quot;, length);
++        pint_t stack[100];
++        pint_t* sp = stack;
++        *(++sp) = initialStackValue;
++        
++        while ( p &lt; expressionEnd ) {
++                if (log) {
++                        for(pint_t* t = sp; t &gt; stack; --t) {
++                                fprintf(stderr, &quot;sp[] = 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (uint64_t)value);
++                                break;
++                
++                        case DW_OP_deref:
++                                // pop stack, dereference, push result
++                                value = *sp--;
++                                *(++sp) = addressSpace.getP(value);
++                                if (log) fprintf(stderr, &quot;dereference 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (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, &quot;push 0x%llX\n&quot;, (uint64_t)value);
++                                break;
++                
++                        case DW_OP_constu:
++                                // push immediate ULEB128 value
++                                value = addressSpace.getULEB128(p, expressionEnd);
++                                *(++sp) = value;
++                                if (log) fprintf(stderr, &quot;push 0x%llX\n&quot;, (uint64_t)value);
++                                break;
++                                
++                        case DW_OP_consts:
++                                // push immediate SLEB128 value
++                                svalue = addressSpace.getSLEB128(p, expressionEnd);
++                                *(++sp) = svalue;
++                                if (log) fprintf(stderr, &quot;push 0x%llX\n&quot;, (uint64_t)svalue);
++                                break;
++                
++                        case DW_OP_dup:
++                                // push top of stack
++                                value = *sp;
++                                *(++sp) = value;
++                                if (log) fprintf(stderr, &quot;duplicate top of stack\n&quot;);
++                                break;
++                                
++                        case DW_OP_drop:
++                                // pop
++                                --sp; 
++                                if (log) fprintf(stderr, &quot;pop top of stack\n&quot;);
++                                break;
++                                
++                        case DW_OP_over:
++                                // dup second
++                                value = sp[-1];
++                                *(++sp) = value;
++                                if (log) fprintf(stderr, &quot;duplicate second in stack\n&quot;);
++                                break;
++
++                        case DW_OP_pick:
++                                // pick from
++                                reg = addressSpace.get8(p);
++                                p += 1;
++                                value = sp[-reg];
++                                *(++sp) = value;
++                                if (log) fprintf(stderr, &quot;duplicate %d in stack\n&quot;, reg);
++                                break;
++
++                        case DW_OP_swap:
++                                // swap top two
++                                value = sp[0];
++                                sp[0] = sp[-1];
++                                sp[-1] = value;
++                                if (log) fprintf(stderr, &quot;swap top of stack\n&quot;);
++                                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, &quot;rotate top three of stack\n&quot;);
++                                break;
++
++                        case DW_OP_xderef:
++                                // pop stack, dereference, push result
++                                value = *sp--;
++                                *sp = *((uint64_t*)value);
++                                if (log) fprintf(stderr, &quot;x-dereference 0x%llX\n&quot;, (uint64_t)value);
++                                break;
++                        
++                        case DW_OP_abs:
++                                svalue = *sp;
++                                if ( svalue &lt; 0 )
++                                        *sp = -svalue;
++                                if (log) fprintf(stderr, &quot;abs\n&quot;);
++                                break;
++                
++                        case DW_OP_and:
++                                value = *sp--;
++                                *sp &amp;= value;
++                                if (log) fprintf(stderr, &quot;and\n&quot;);
++                                break;
++                        
++                        case DW_OP_div:
++                                svalue = *sp--;
++                                *sp = *sp / svalue;
++                                if (log) fprintf(stderr, &quot;div\n&quot;);
++                                break;
++                        
++                        case DW_OP_minus:
++                                svalue = *sp--;
++                                *sp = *sp - svalue;
++                                if (log) fprintf(stderr, &quot;minus\n&quot;);
++                                break;
++
++                        case DW_OP_mod:
++                                svalue = *sp--;
++                                *sp = *sp % svalue;
++                                if (log) fprintf(stderr, &quot;module\n&quot;);
++                                break;
++
++                        case DW_OP_mul:
++                                svalue = *sp--;
++                                *sp = *sp * svalue;
++                                if (log) fprintf(stderr, &quot;mul\n&quot;);
++                                break;
++
++                        case DW_OP_neg:
++                                *sp =  0 - *sp;
++                                if (log) fprintf(stderr, &quot;neg\n&quot;);
++                                break;
++
++                        case DW_OP_not:
++                                svalue = *sp;
++                                *sp =  ~svalue;
++                                if (log) fprintf(stderr, &quot;not\n&quot;);
++                                break;
++
++                        case DW_OP_or:
++                                value = *sp--;
++                                *sp |= value;
++                                if (log) fprintf(stderr, &quot;or\n&quot;);
++                                break;
++
++                        case DW_OP_plus:
++                                value = *sp--;
++                                *sp += value;
++                                if (log) fprintf(stderr, &quot;plus\n&quot;);
++                                break;
++
++                        case DW_OP_plus_uconst:
++                                // pop stack, add uelb128 constant, push result
++                                *sp += addressSpace.getULEB128(p, expressionEnd);
++                                if (log) fprintf(stderr, &quot;add constant\n&quot;);
++                                break;
++                
++                        case DW_OP_shl:
++                                value = *sp--;
++                                *sp = *sp &lt;&lt; value;
++                                if (log) fprintf(stderr, &quot;shift left\n&quot;);
++                                break;
++                        
++                        case DW_OP_shr:
++                                value = *sp--;
++                                *sp = *sp &gt;&gt; value;
++                                if (log) fprintf(stderr, &quot;shift left\n&quot;);
++                                break;
++                                
++                        case DW_OP_shra:
++                                value = *sp--;
++                                svalue = *sp;
++                                *sp = svalue &gt;&gt; value;
++                                if (log) fprintf(stderr, &quot;shift left arithmetric\n&quot;);
++                                break;
++                        
++                        case DW_OP_xor:
++                                value = *sp--;
++                                *sp ^= value;
++                                if (log) fprintf(stderr, &quot;xor\n&quot;);
++                                break;
++
++                        case DW_OP_skip:
++                                svalue = (int16_t)addressSpace.get16(p);
++                                p += 2;
++                                p += svalue;
++                                if (log) fprintf(stderr, &quot;skip %lld\n&quot;, (uint64_t)svalue);
++                                break;
++                        
++                        case DW_OP_bra:
++                                svalue = (int16_t)addressSpace.get16(p);
++                                p += 2;
++                                if ( *sp-- )
++                                        p += svalue;
++                                if (log) fprintf(stderr, &quot;bra %lld\n&quot;, (uint64_t)svalue);
++                                break;
++                        
++                        case DW_OP_eq:
++                                value = *sp--;
++                                *sp = (*sp == value);
++                                if (log) fprintf(stderr, &quot;eq\n&quot;);
++                                break;
++                        
++                        case DW_OP_ge:
++                                value = *sp--;
++                                *sp = (*sp &gt;= value);
++                                if (log) fprintf(stderr, &quot;ge\n&quot;);
++                                break;
++                                
++                        case DW_OP_gt:
++                                value = *sp--;
++                                *sp = (*sp &gt; value);
++                                if (log) fprintf(stderr, &quot;gt\n&quot;);
++                                break;
++                                
++                        case DW_OP_le:
++                                value = *sp--;
++                                *sp = (*sp &lt;= value);
++                                if (log) fprintf(stderr, &quot;le\n&quot;);
++                                break;
++                                
++                        case DW_OP_lt:
++                                value = *sp--;
++                                *sp = (*sp &lt; value);
++                                if (log) fprintf(stderr, &quot;lt\n&quot;);
++                                break;
++                                
++                        case DW_OP_ne:
++                                value = *sp--;
++                                *sp = (*sp != value);
++                                if (log) fprintf(stderr, &quot;ne\n&quot;);
++                                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, &quot;push literal 0x%llX\n&quot;, (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, &quot;push reg %d\n&quot;, reg);
++                                break;
++                
++                        case DW_OP_regx:
++                                reg = addressSpace.getULEB128(p, expressionEnd);
++                                *(++sp) = registers.getRegister(reg);
++                                if (log) fprintf(stderr, &quot;push reg %d + 0x%llX\n&quot;, 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, &quot;push reg %d + 0x%llX\n&quot;, 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, &quot;push reg %d + 0x%llX\n&quot;, reg, (uint64_t)svalue);
++                                break;
++                        
++                        case DW_OP_fbreg:
++                                ABORT(&quot;DW_OP_fbreg not implemented&quot;);
++                                break;
++                                
++                        case DW_OP_piece:
++                                ABORT(&quot;DW_OP_piece not implemented&quot;);
++                                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(&quot;DW_OP_deref_size with bad size&quot;);
++                                }
++                                *(++sp) = value;
++                                if (log) fprintf(stderr, &quot;sized dereference 0x%llX\n&quot;, (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(&quot;dwarf opcode not implemented&quot;);
++                }
++        
++        }
++        if (log) fprintf(stderr, &quot;expression evaluates to 0x%llX\n&quot;, (uint64_t)*sp);
++        return *sp;
++}
++
++
++
++//
++//        x86_64 specific functions
++//
++
++template &lt;typename A, typename R&gt;
++int DwarfInstructions&lt;A,R&gt;::lastRestoreReg(const Registers_x86_64&amp;) 
++{
++        COMPILE_TIME_ASSERT( (int)CFI_Parser&lt;A&gt;::kMaxRegisterNumber &gt; (int)DW_X86_64_RET_ADDR );
++        return DW_X86_64_RET_ADDR; 
++}
++
++template &lt;typename A, typename R&gt;
++bool DwarfInstructions&lt;A,R&gt;::isReturnAddressRegister(int regNum, const Registers_x86_64&amp;) 
++{
++        return (regNum == DW_X86_64_RET_ADDR); 
++}
++
++template &lt;typename A, typename R&gt;
++typename A::pint_t DwarfInstructions&lt;A,R&gt;::getCFA(A&amp; addressSpace, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog, 
++                                                                                const Registers_x86_64&amp; 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(&quot;getCFA(): unknown location for x86_64 cfa&quot;);
++}
++
++
++
++template &lt;typename A, typename R&gt;
++compact_unwind_encoding_t DwarfInstructions&lt;A,R&gt;::encodeToUseDwarf(const Registers_x86_64&amp;) 
++{
++        return UNWIND_X86_64_MODE_DWARF;
++}
++
++template &lt;typename A, typename R&gt;
++compact_unwind_encoding_t DwarfInstructions&lt;A,R&gt;::encodeToUseDwarf(const Registers_x86&amp;) 
++{
++        return UNWIND_X86_MODE_DWARF;
++}
++
++
++
++template &lt;typename A, typename R&gt;
++uint32_t DwarfInstructions&lt;A,R&gt;::getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool&amp; failure)
++{
++        if ( (regOffsetFromBaseOffset &lt; 0) || (regOffsetFromBaseOffset &gt; 32) ) {
++                failure = true;
++                return 0;
++        }
++        unsigned int slotIndex = regOffsetFromBaseOffset/8;
++        
++        switch ( reg ) {
++                case UNW_X86_64_RBX:
++                        return UNWIND_X86_64_REG_RBX &lt;&lt; (slotIndex*3);
++                case UNW_X86_64_R12:
++                        return UNWIND_X86_64_REG_R12 &lt;&lt; (slotIndex*3);
++                case UNW_X86_64_R13:
++                        return UNWIND_X86_64_REG_R13 &lt;&lt; (slotIndex*3);
++                case UNW_X86_64_R14:
++                        return UNWIND_X86_64_REG_R14 &lt;&lt; (slotIndex*3);
++                case UNW_X86_64_R15:
++                        return UNWIND_X86_64_REG_R15 &lt;&lt; (slotIndex*3);
++        }
++        
++        // invalid register
++        failure = true;
++        return 0;
++}
++
++
++
++template &lt;typename A, typename R&gt;
++compact_unwind_encoding_t DwarfInstructions&lt;A,R&gt;::createCompactEncodingFromProlog(A&amp; addressSpace, pint_t funcAddr,
++                                                                                                const Registers_x86_64&amp; r, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; 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, &quot;register saved more than once (might be shrink wrap)&quot;);
++                return UNWIND_X86_64_MODE_DWARF;
++        }
++        if ( prolog.cfaOffsetWasNegative ) {
++                strcpy(warningBuffer, &quot;cfa had negative offset (dwarf might contain epilog)&quot;);
++                return UNWIND_X86_64_MODE_DWARF;
++        }
++        if ( prolog.spExtraArgSize != 0 ) {
++                strcpy(warningBuffer, &quot;dwarf uses DW_CFA_GNU_args_size&quot;);
++                return UNWIND_X86_64_MODE_DWARF;
++        }
++        if ( prolog.sameValueUsed ) {
++                strcpy(warningBuffer, &quot;dwarf uses DW_CFA_same_value&quot;);
++                return UNWIND_X86_64_MODE_DWARF;
++        }
++
++        // figure out which kind of frame this function uses
++        bool standardRBPframe = ( 
++                 (prolog.cfaRegister == UNW_X86_64_RBP) 
++          &amp;&amp; (prolog.cfaRegisterOffset == 16)
++          &amp;&amp; (prolog.savedRegisters[UNW_X86_64_RBP].location == CFI_Parser&lt;A&gt;::kRegisterInCFA)
++          &amp;&amp; (prolog.savedRegisters[UNW_X86_64_RBP].value == -16) );
++        bool standardRSPframe = (prolog.cfaRegister == UNW_X86_64_RSP);
++        if ( !standardRBPframe &amp;&amp; !standardRSPframe ) {
++                // no compact encoding for this
++                strcpy(warningBuffer, &quot;does not use RBP or RSP based frame&quot;);
++                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 &lt; 64; ++i) {
++                if ( prolog.savedRegisters[i].location != CFI_Parser&lt;A&gt;::kRegisterUnused ) {
++                        if ( prolog.savedRegisters[i].location != CFI_Parser&lt;A&gt;::kRegisterInCFA ) {
++                                sprintf(warningBuffer, &quot;register %d saved somewhere other that in frame&quot;, 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, &quot;non-standard register %d being saved in prolog&quot;, 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 ) {
++                //                |              |
++                //                +--------------+   &lt;- CFA
++                //                |   ret addr   |
++                //                +--------------+
++                //                |     rbp      |
++                //                +--------------+   &lt;- rbp
++                //                ~              ~
++                //                +--------------+   
++                //                |  saved reg3  |
++                //                +--------------+   &lt;- CFA - offset+16
++                //                |  saved reg2  |
++                //                +--------------+   &lt;- CFA - offset+8
++                //                |  saved reg1  |
++                //                +--------------+   &lt;- CFA - offset
++                //                |              |
++                //                +--------------+
++                //                |              |
++                //                                                   &lt;- rsp
++                //
++                encoding = UNWIND_X86_64_MODE_RBP_FRAME;
++                
++                // find save location of farthest register from rbp
++                int furthestCfaOffset = 0;
++                if ( rbxSaved &amp; (cfaOffsetRBX &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetRBX;
++                if ( r12Saved &amp; (cfaOffsetR12 &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetR12;
++                if ( r13Saved &amp; (cfaOffsetR13 &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetR13;
++                if ( r14Saved &amp; (cfaOffsetR14 &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetR14;
++                if ( r15Saved &amp; (cfaOffsetR15 &lt; 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 &gt; 255 ) {
++                        strcpy(warningBuffer, &quot;offset of saved registers too far to encode&quot;);
++                        return UNWIND_X86_64_MODE_DWARF;
++                }
++                encoding |= (encodedOffset &lt;&lt; __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, &quot;saved registers not contiguous&quot;);
++                        return UNWIND_X86_64_MODE_DWARF;
++                }
++
++                return encoding;
++        }
++        else {
++                //                |              |
++                //                +--------------+   &lt;- CFA
++                //                |   ret addr   |
++                //                +--------------+
++                //                |  saved reg1  |
++                //                +--------------+   &lt;- CFA - 16
++                //                |  saved reg2  |
++                //                +--------------+   &lt;- CFA - 24
++                //                |  saved reg3  |
++                //                +--------------+   &lt;- CFA - 32
++                //                |  saved reg4  |
++                //                +--------------+   &lt;- CFA - 40
++                //                |  saved reg5  |
++                //                +--------------+   &lt;- CFA - 48
++                //                |  saved reg6  |
++                //                +--------------+   &lt;- CFA - 56
++                //                |              |
++                //                                                   &lt;- 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 &gt; 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, &quot;stack size is large but stack subq instruction not found&quot;);
++                                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, &quot;stack size is large but stack subq instruction not found&quot;);
++                                return UNWIND_X86_64_MODE_DWARF;
++                        }
++                        stackValue = functionContentAdjustStackIns - funcAddr;
++                        immedStackSize = false;
++                        if ( stackAdjust &gt; 7 ) {
++                                strcpy(warningBuffer, &quot;stack subq instruction is too different from dwarf stack size&quot;);
++                                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 &lt; 6;++i)
++                        registers[i] = 0;
++                if ( r15Saved ) {
++                        if ( cfaOffsetR15 &lt; -56 ) {
++                                strcpy(warningBuffer, &quot;r15 is saved too far from return address&quot;);
++                                return UNWIND_X86_64_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetR15+56)/8] = UNWIND_X86_64_REG_R15;
++                }
++                if ( r14Saved ) {
++                        if ( cfaOffsetR14 &lt; -56 ) {
++                                strcpy(warningBuffer, &quot;r14 is saved too far from return address&quot;);
++                                return UNWIND_X86_64_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetR14+56)/8] = UNWIND_X86_64_REG_R14;
++                }
++                if ( r13Saved ) {
++                        if ( cfaOffsetR13 &lt; -56 ) {
++                                strcpy(warningBuffer, &quot;r13 is saved too far from return address&quot;);
++                                return UNWIND_X86_64_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetR13+56)/8] = UNWIND_X86_64_REG_R13;
++                }
++                if ( r12Saved ) {
++                        if ( cfaOffsetR12 &lt; -56 ) {
++                                strcpy(warningBuffer, &quot;r12 is saved too far from return address&quot;);
++                                return UNWIND_X86_64_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetR12+56)/8] = UNWIND_X86_64_REG_R12;
++                }
++                if ( rbxSaved ) {
++                        if ( cfaOffsetRBX &lt; -56 ) {
++                                strcpy(warningBuffer, &quot;rbx is saved too far from return address&quot;);
++                                return UNWIND_X86_64_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetRBX+56)/8] = UNWIND_X86_64_REG_RBX;
++                }
++                if ( rbpSaved ) {
++                        if ( cfaOffsetRBP &lt; -56 ) {
++                                strcpy(warningBuffer, &quot;rbp is saved too far from return address&quot;);
++                                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 &lt; saveRegisterCount; ++i) {
++                        if ( registers[5-i] == 0 ) {
++                                strcpy(warningBuffer, &quot;registers not save contiguously in stack&quot;);
++                                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 &lt; 6; ++i) {
++                        int countless = 0;
++                        for (int j=6-saveRegisterCount; j &lt; i; ++j) {
++                                if ( registers[j] &lt; 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 &lt;&lt; __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_SIZE));
++                encoding |= (stackAdjust &lt;&lt; __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_ADJUST));
++                encoding |= (saveRegisterCount &lt;&lt; __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT));
++                encoding |= (permutationEncoding &lt;&lt; __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION));
++                return encoding;
++        }
++}
++
++
++
++
++//
++//        x86 specific functions
++//
++template &lt;typename A, typename R&gt;
++int DwarfInstructions&lt;A,R&gt;::lastRestoreReg(const Registers_x86&amp;) 
++{
++        COMPILE_TIME_ASSERT( (int)CFI_Parser&lt;A&gt;::kMaxRegisterNumber &gt; (int)DW_X86_RET_ADDR );
++        return DW_X86_RET_ADDR; 
++}
++
++template &lt;typename A, typename R&gt;
++bool DwarfInstructions&lt;A,R&gt;::isReturnAddressRegister(int regNum, const Registers_x86&amp;) 
++{
++        return (regNum == DW_X86_RET_ADDR); 
++}
++
++template &lt;typename A, typename R&gt;
++typename A::pint_t DwarfInstructions&lt;A,R&gt;::getCFA(A&amp; addressSpace, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog, 
++                                                                                const Registers_x86&amp; 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(&quot;getCFA(): unknown location for x86 cfa&quot;);
++}
++
++
++
++
++
++template &lt;typename A, typename R&gt;
++uint32_t DwarfInstructions&lt;A,R&gt;::getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool&amp; failure)
++{
++        if ( (regOffsetFromBaseOffset &lt; 0) || (regOffsetFromBaseOffset &gt; 16) ) {
++                failure = true;
++                return 0;
++        }
++        unsigned int slotIndex = regOffsetFromBaseOffset/4;
++        
++        switch ( reg ) {
++                case UNW_X86_EBX:
++                        return UNWIND_X86_REG_EBX &lt;&lt; (slotIndex*3);
++                case UNW_X86_ECX:
++                        return UNWIND_X86_REG_ECX &lt;&lt; (slotIndex*3);
++                case UNW_X86_EDX:
++                        return UNWIND_X86_REG_EDX &lt;&lt; (slotIndex*3);
++                case UNW_X86_EDI:
++                        return UNWIND_X86_REG_EDI &lt;&lt; (slotIndex*3);
++                case UNW_X86_ESI:
++                        return UNWIND_X86_REG_ESI &lt;&lt; (slotIndex*3);
++        }
++        
++        // invalid register
++        failure = true;
++        return 0;
++}
++
++template &lt;typename A, typename R&gt;
++compact_unwind_encoding_t DwarfInstructions&lt;A,R&gt;::createCompactEncodingFromProlog(A&amp; addressSpace, pint_t funcAddr,
++                                                                                                const Registers_x86&amp; r, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; 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, &quot;register saved more than once (might be shrink wrap)&quot;);
++                return UNWIND_X86_MODE_DWARF;
++        }
++        if ( prolog.spExtraArgSize != 0 ) {
++                strcpy(warningBuffer, &quot;dwarf uses DW_CFA_GNU_args_size&quot;);
++                return UNWIND_X86_MODE_DWARF;
++        }
++        if ( prolog.sameValueUsed ) {
++                strcpy(warningBuffer, &quot;dwarf uses DW_CFA_same_value&quot;);
++                return UNWIND_X86_MODE_DWARF;
++        }
++        
++        // figure out which kind of frame this function uses
++        bool standardEBPframe = ( 
++                 (prolog.cfaRegister == UNW_X86_EBP) 
++          &amp;&amp; (prolog.cfaRegisterOffset == 8)
++          &amp;&amp; (prolog.savedRegisters[UNW_X86_EBP].location == CFI_Parser&lt;A&gt;::kRegisterInCFA)
++          &amp;&amp; (prolog.savedRegisters[UNW_X86_EBP].value == -8) );
++        bool standardESPframe = (prolog.cfaRegister == UNW_X86_ESP);
++        if ( !standardEBPframe &amp;&amp; !standardESPframe ) {
++                // no compact encoding for this
++                strcpy(warningBuffer, &quot;does not use EBP or ESP based frame&quot;);
++                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 &lt; 64; ++i) {
++                if ( prolog.savedRegisters[i].location != CFI_Parser&lt;A&gt;::kRegisterUnused ) {
++                        if ( prolog.savedRegisters[i].location != CFI_Parser&lt;A&gt;::kRegisterInCFA ) {
++                                sprintf(warningBuffer, &quot;register %d saved somewhere other that in frame&quot;, 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, &quot;non-standard register %d being saved in prolog&quot;, 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 ) {
++                //                |              |
++                //                +--------------+   &lt;- CFA
++                //                |   ret addr   |
++                //                +--------------+
++                //                |     ebp      |
++                //                +--------------+   &lt;- ebp
++                //                ~              ~
++                //                +--------------+   
++                //                |  saved reg3  |
++                //                +--------------+   &lt;- CFA - offset+8
++                //                |  saved reg2  |
++                //                +--------------+   &lt;- CFA - offset+e
++                //                |  saved reg1  |
++                //                +--------------+   &lt;- CFA - offset
++                //                |              |
++                //                +--------------+
++                //                |              |
++                //                                                   &lt;- esp
++                //
++                encoding = UNWIND_X86_MODE_EBP_FRAME;
++                
++                // find save location of farthest register from ebp
++                int furthestCfaOffset = 0;
++                if ( ebxSaved &amp; (cfaOffsetEBX &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetEBX;
++                if ( ecxSaved &amp; (cfaOffsetECX &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetECX;
++                if ( edxSaved &amp; (cfaOffsetEDX &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetEDX;
++                if ( ediSaved &amp; (cfaOffsetEDI &lt; furthestCfaOffset) )
++                        furthestCfaOffset = cfaOffsetEDI;
++                if ( esiSaved &amp; (cfaOffsetESI &lt; 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 &gt; 255 ) {
++                        strcpy(warningBuffer, &quot;offset of saved registers too far to encode&quot;);
++                        return UNWIND_X86_MODE_DWARF;
++                }
++                encoding |= (encodedOffset &lt;&lt; __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, &quot;saved registers not contiguous&quot;);
++                        return UNWIND_X86_MODE_DWARF;
++                }
++
++                return encoding;
++        }
++        else {
++                //                |              |
++                //                +--------------+   &lt;- CFA
++                //                |   ret addr   |
++                //                +--------------+
++                //                |  saved reg1  |
++                //                +--------------+   &lt;- CFA - 8
++                //                |  saved reg2  |
++                //                +--------------+   &lt;- CFA - 12
++                //                |  saved reg3  |
++                //                +--------------+   &lt;- CFA - 16
++                //                |  saved reg4  |
++                //                +--------------+   &lt;- CFA - 20
++                //                |  saved reg5  |
++                //                +--------------+   &lt;- CFA - 24
++                //                |  saved reg6  |
++                //                +--------------+   &lt;- CFA - 28
++                //                |              |
++                //                                                   &lt;- 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 &gt; 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 &gt; 7 ) {
++                                strcpy(warningBuffer, &quot;stack subq instruction is too different from dwarf stack size&quot;);
++                                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 &lt; 6;++i)
++                        registers[i] = 0;
++                if ( ebxSaved ) {
++                        if ( cfaOffsetEBX &lt; -28 ) {
++                                strcpy(warningBuffer, &quot;ebx is saved too far from return address&quot;);
++                                return UNWIND_X86_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetEBX+28)/4] = UNWIND_X86_REG_EBX;
++                }
++                if ( ecxSaved ) {
++                        if ( cfaOffsetECX &lt; -28 ) {
++                                strcpy(warningBuffer, &quot;ecx is saved too far from return address&quot;);
++                                return UNWIND_X86_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetECX+28)/4] = UNWIND_X86_REG_ECX;
++                }
++                if ( edxSaved ) {
++                        if ( cfaOffsetEDX &lt; -28 ) {
++                                strcpy(warningBuffer, &quot;edx is saved too far from return address&quot;);
++                                return UNWIND_X86_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetEDX+28)/4] = UNWIND_X86_REG_EDX;
++                }
++                if ( ediSaved ) {
++                        if ( cfaOffsetEDI &lt; -28 ) {
++                                strcpy(warningBuffer, &quot;edi is saved too far from return address&quot;);
++                                return UNWIND_X86_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetEDI+28)/4] = UNWIND_X86_REG_EDI;
++                }
++                if ( esiSaved ) {
++                        if ( cfaOffsetESI &lt; -28 ) {
++                                strcpy(warningBuffer, &quot;esi is saved too far from return address&quot;);
++                                return UNWIND_X86_MODE_DWARF;
++                        }
++                        registers[(cfaOffsetESI+28)/4] = UNWIND_X86_REG_ESI;
++                }
++                if ( ebpSaved ) {
++                        if ( cfaOffsetEBP &lt; -28 ) {
++                                strcpy(warningBuffer, &quot;ebp is saved too far from return address&quot;);
++                                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 &lt; saveRegisterCount; ++i) {
++                        if ( registers[5-i] == 0 ) {
++                                strcpy(warningBuffer, &quot;registers not save contiguously in stack&quot;);
++                                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 &lt; 6; ++i) {
++                        int countless = 0;
++                        for (int j=6-saveRegisterCount; j &lt; i; ++j) {
++                                if ( registers[j] &lt; 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 &lt;&lt; __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_SIZE));
++                encoding |= (stackAdjust &lt;&lt; __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_ADJUST));
++                encoding |= (saveRegisterCount &lt;&lt; __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_COUNT));
++                encoding |= (permutationEncoding &lt;&lt; __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION));
++                return encoding;
++        }
++}
++
++
++
++
++
++
++
++//
++//        ppc specific functions
++//
++template &lt;typename A, typename R&gt;
++int DwarfInstructions&lt;A,R&gt;::lastRestoreReg(const Registers_ppc&amp;) 
++{
++        COMPILE_TIME_ASSERT( (int)CFI_Parser&lt;A&gt;::kMaxRegisterNumber &gt; (int)UNW_PPC_SPEFSCR );
++        return UNW_PPC_SPEFSCR; 
++}
++
++template &lt;typename A, typename R&gt;
++bool DwarfInstructions&lt;A,R&gt;::isReturnAddressRegister(int regNum, const Registers_ppc&amp;) 
++{
++        return (regNum == UNW_PPC_LR); 
++}
++
++template &lt;typename A, typename R&gt;
++typename A::pint_t DwarfInstructions&lt;A,R&gt;::getCFA(A&amp; addressSpace, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; prolog, 
++                                                                                const Registers_ppc&amp; 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(&quot;getCFA(): unknown location for ppc cfa&quot;);
++}
++
++
++template &lt;typename A, typename R&gt;
++compact_unwind_encoding_t DwarfInstructions&lt;A,R&gt;::encodeToUseDwarf(const Registers_ppc&amp;) 
++{
++        return UNWIND_X86_MODE_DWARF;
++}
++
++
++template &lt;typename A, typename R&gt;
++compact_unwind_encoding_t DwarfInstructions&lt;A,R&gt;::createCompactEncodingFromProlog(A&amp; addressSpace, pint_t funcAddr,
++                                                                                                const Registers_ppc&amp; r, const typename CFI_Parser&lt;A&gt;::PrologInfo&amp; 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 &lt;stdint.h&gt;
++#include &lt;stdio.h&gt;
++#include &lt;stdlib.h&gt;
++
++#include &lt;vector&gt;
++
++#include &quot;libunwind.h&quot;
++#include &quot;dwarf2.h&quot;
++
++#include &quot;AddressSpace.hpp&quot;
++
++
++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 &lt;typename A&gt;
++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 &quot;running&quot; the dwarf FDE &quot;instructions&quot;
++        ///  
++        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&amp; i)
++                                                                        : next(n), info(i) {}
++                PrologInfoStackEntry*        next;
++                PrologInfo                                info;
++        };
++
++        static bool findFDE(A&amp; addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo);
++        static const char* decodeFDE(A&amp; addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo);
++        static bool parseFDEInstructions(A&amp; addressSpace, const FDE_Info&amp; fdeInfo, const CIE_Info&amp; cieInfo, pint_t upToPC, PrologInfo* results);
++        static const char* getCFIs(A&amp; addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
++                                                                std::vector&lt;FDE_Atom_Info&gt;&amp; fdes, std::vector&lt;CIE_Atom_Info&gt;&amp; cies);
++        static uint32_t getCFICount(A&amp; addressSpace, pint_t ehSectionStart, uint32_t sectionLength);
++
++        static const char* parseCIE(A&amp; addressSpace, pint_t cie, CIE_Info* cieInfo);
++
++private:
++        static bool parseInstructions(A&amp; addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info&amp; cieInfo, 
++                                                                pint_t pcoffset, PrologInfoStackEntry*&amp; rememberStack, PrologInfo* results);
++};
++
++
++///
++/// Parse a FDE into a CIE_Info and an FDE_Info 
++///  
++template &lt;typename A&gt;
++const char* CFI_Parser&lt;A&gt;::decodeFDE(A&amp; 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 &quot;FDE has zero length&quot;;        // end marker
++        uint32_t ciePointer = addressSpace.get32(p);
++        if ( ciePointer == 0 ) 
++                return &quot;FDE is really a CIE&quot;;        // 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-&gt;pointerEncoding);
++        pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo-&gt;pointerEncoding &amp; 0x0F);
++        // parse rest of info
++        fdeInfo-&gt;lsda = 0;
++        // check for augmentation length
++        if ( cieInfo-&gt;fdesHaveAugmentationData ) {
++                uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
++                pint_t endOfAug = p + augLen;
++                if ( cieInfo-&gt;lsdaEncoding != 0 ) {
++                        // peek at value (without indirection).  Zero means no lsda
++                        pint_t lsdaStart = p;
++                        if ( addressSpace.getEncodedP(p, nextCFI, cieInfo-&gt;lsdaEncoding &amp; 0x0F) != 0 ) {
++                                // reset pointer and re-parse lsda address
++                                p = lsdaStart;
++                                fdeInfo-&gt;lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo-&gt;lsdaEncoding);
++                        }
++                }
++                p = endOfAug;
++        }
++        fdeInfo-&gt;fdeStart = fdeStart;
++        fdeInfo-&gt;fdeLength = nextCFI - fdeStart;
++        fdeInfo-&gt;fdeInstructions = p;
++        fdeInfo-&gt;pcStart = pcStart;
++        fdeInfo-&gt;pcEnd = pcStart+pcRange;
++        return NULL; // success
++}
++
++
++///
++/// Scan an eh_frame section to find an FDE for a pc
++///  
++template &lt;typename A&gt;
++bool CFI_Parser&lt;A&gt;::findFDE(A&amp; addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo)
++{
++        //fprintf(stderr, &quot;findFDE(0x%llX)\n&quot;, (long long)pc);
++        pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
++        const pint_t ehSectionEnd = p + sectionLength;
++        while ( p &lt; ehSectionEnd ) {
++                pint_t currentCFI = p;
++                //fprintf(stderr, &quot;findFDE() CFI at 0x%llX\n&quot;, (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 &lt;= cieStart) &amp;&amp; (cieStart &lt; ehSectionEnd) ) {
++                                if ( parseCIE(addressSpace, cieStart, cieInfo) == NULL ) {
++                                        p += 4;
++                                        // parse pc begin and range
++                                        pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo-&gt;pointerEncoding);
++                                        pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo-&gt;pointerEncoding &amp; 0x0F);
++                                        //fprintf(stderr, &quot;FDE with pcRange [0x%08llX, 0x%08llX)\n&quot;,(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
++                                        // test if pc is within the function this FDE covers
++                                        if ( (pcStart &lt; pc) &amp;&amp; (pc &lt;= pcStart+pcRange) ) {
++                                                // parse rest of info
++                                                fdeInfo-&gt;lsda = 0;
++                                                // check for augmentation length
++                                                if ( cieInfo-&gt;fdesHaveAugmentationData ) {
++                                                        uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
++                                                        pint_t endOfAug = p + augLen;
++                                                        if ( cieInfo-&gt;lsdaEncoding != 0 ) {
++                                                                // peek at value (without indirection).  Zero means no lsda
++                                                                pint_t lsdaStart = p;
++                                                                if ( addressSpace.getEncodedP(p, nextCFI, cieInfo-&gt;lsdaEncoding &amp; 0x0F) != 0 ) {
++                                                                        // reset pointer and re-parse lsda address
++                                                                        p = lsdaStart;
++                                                                        fdeInfo-&gt;lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo-&gt;lsdaEncoding);
++                                                                }
++                                                        }
++                                                        p = endOfAug;
++                                                }
++                                                fdeInfo-&gt;fdeStart = currentCFI;
++                                                fdeInfo-&gt;fdeLength = nextCFI - currentCFI;
++                                                fdeInfo-&gt;fdeInstructions = p;
++                                                fdeInfo-&gt;pcStart = pcStart;
++                                                fdeInfo-&gt;pcEnd = pcStart+pcRange;
++                                                //fprintf(stderr, &quot;findFDE(pc=0x%llX) found with pcRange [0x%08llX, 0x%08llX)\n&quot;,(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
++                                                return true;
++                                        }
++                                        else {
++                                                //fprintf(stderr, &quot;findFDE(pc=0x%llX) not found with pcRange [0x%08llX, 0x%08llX)\n&quot;,(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, &quot;malformed CIE\n&quot;);
++                                }
++                        }
++                        else {
++                                // malformed FDE.  CIE is bad
++                                //fprintf(stderr, &quot;malformed FDE, cieStart=0x%llX, ehSectionStart=0x%llX, ehSectionEnd=0x%llX\n&quot;,
++                                //        (uint64_t)cieStart, (uint64_t)ehSectionStart, (uint64_t)ehSectionEnd);
++                        }
++                        p = nextCFI;
++                }
++        }
++        //fprintf(stderr, &quot;findFDE(pc=0x%llX) not found\n&quot;,(uint64_t)pc);
++        return false;
++}
++
++
++
++///
++/// Extract info from a CIE
++///  
++template &lt;typename A&gt;
++const char* CFI_Parser&lt;A&gt;::parseCIE(A&amp; addressSpace, pint_t cie, CIE_Info* cieInfo)
++{
++        //fprintf(stderr, &quot;parseCIE(0x%llX)\n&quot;, (long long)cie);
++        cieInfo-&gt;pointerEncoding = 0;
++        cieInfo-&gt;lsdaEncoding = 0;
++        cieInfo-&gt;personalityEncoding = 0;
++        cieInfo-&gt;personalityOffsetInCIE = 0;
++        cieInfo-&gt;personality = 0;
++        cieInfo-&gt;codeAlignFactor = 0;
++        cieInfo-&gt;dataAlignFactor = 0;
++        cieInfo-&gt;isSignalFrame = false;
++        cieInfo-&gt;fdesHaveAugmentationData = false;
++        cieInfo-&gt;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 &quot;CIE ID is not zero&quot;;
++        p += 4;
++        // Version is always 1 or 3
++        uint8_t version = addressSpace.get8(p);
++        if ( (version != 1) &amp;&amp; (version != 3) )
++                return &quot;CIE version is not 1 or 3&quot;;
++        ++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-&gt;codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd);
++        // parse data alignment factor
++        cieInfo-&gt;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-&gt;fdesHaveAugmentationData = true;
++                                        break;
++                                case 'P':
++                                        cieInfo-&gt;personalityEncoding = addressSpace.get8(p);
++                                        ++p;
++                                        cieInfo-&gt;personalityOffsetInCIE = p-cie;
++                                        cieInfo-&gt;personality = addressSpace.getEncodedP(p, cieContentEnd, cieInfo-&gt;personalityEncoding);
++                                        break;
++                                case 'L':
++                                        cieInfo-&gt;lsdaEncoding = addressSpace.get8(p);
++                                        ++p;
++                                        break;
++                                case 'R':
++                                        cieInfo-&gt;pointerEncoding = addressSpace.get8(p);
++                                        ++p;
++                                        break;
++                                case 'S':
++                                        cieInfo-&gt;isSignalFrame = true;
++                                        break;
++                                default:
++                                        // ignore unknown letters
++                                        break;
++                        }
++                }
++        }
++        cieInfo-&gt;cieLength = cieContentEnd - cieInfo-&gt;cieStart;
++        cieInfo-&gt;cieInstructions = p;
++        return result;
++}
++
++
++template &lt;typename A&gt;
++uint32_t CFI_Parser&lt;A&gt;::getCFICount(A&amp; addressSpace, pint_t ehSectionStart, uint32_t sectionLength)
++{
++        uint32_t count = 0;
++        const pint_t ehSectionEnd = ehSectionStart + sectionLength;
++        for (pint_t p=ehSectionStart; p &lt; 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 &lt;typename A&gt;
++const char* CFI_Parser&lt;A&gt;::getCFIs(A&amp; addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
++                                                                  std::vector&lt;FDE_Atom_Info&gt;&amp; fdes, std::vector&lt;CIE_Atom_Info&gt;&amp; cies)
++{
++        const pint_t ehSectionEnd = ehSectionStart + sectionLength;
++        for (pint_t p=ehSectionStart; p &lt; 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, &amp;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 &lt; ehSectionStart) || (cieStart &gt; ehSectionEnd) )
++                                return &quot;FDE points to CIE outside __eh_frame section&quot;;
++                        CIE_Info cieInfo;
++                        const char* err = parseCIE(addressSpace, cieStart, &amp;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 &amp; 0x0F);
++                        //fprintf(stderr, &quot;FDE with pcRange [0x%08llX, 0x%08llX)\n&quot;,(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) &amp;&amp; (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
++}
++
++        
++
++///
++/// &quot;run&quot; the dwarf instructions and create the abstact PrologInfo for an FDE
++///  
++template &lt;typename A&gt;
++bool CFI_Parser&lt;A&gt;::parseFDEInstructions(A&amp; addressSpace, const FDE_Info&amp; fdeInfo, const CIE_Info&amp; 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)
++            &amp;&amp; parseInstructions(addressSpace, fdeInfo.fdeInstructions, fdeInfo.fdeStart+fdeInfo.fdeLength, 
++                                                        cieInfo, upToPC-fdeInfo.pcStart, rememberStack, results);
++}
++
++
++///
++/// &quot;run&quot; the dwarf instructions
++///  
++template &lt;typename A&gt;
++bool CFI_Parser&lt;A&gt;::parseInstructions(A&amp; addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info&amp; cieInfo,
++                                                                        pint_t pcoffset, PrologInfoStackEntry*&amp; rememberStack, PrologInfo* results)
++{
++        const bool logDwarf = false;
++        pint_t p = instructions;
++        uint32_t codeOffset = 0;
++        PrologInfo initialState = *results;
++        if ( logDwarf ) fprintf(stderr, &quot;parseInstructions(instructions=0x%0llX)\n&quot;, (uint64_t)instructionsEnd);
++        
++        // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
++        while ( (p &lt; instructionsEnd) &amp;&amp; (codeOffset &lt; 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, &quot;DW_CFA_nop\n&quot;);
++                                break;
++                        case DW_CFA_set_loc:
++                                codeOffset = addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_set_loc\n&quot;);
++                                break;
++                        case DW_CFA_advance_loc1:
++                                codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
++                                p += 1;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_advance_loc1: new offset=%u\n&quot;, codeOffset);
++                                break;
++                        case DW_CFA_advance_loc2:
++                                codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
++                                p += 2;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_advance_loc2: new offset=%u\n&quot;, codeOffset);
++                                break;
++                        case DW_CFA_advance_loc4:
++                                codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
++                                p += 4;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_advance_loc4: new offset=%u\n&quot;, codeOffset);
++                                break;
++                        case DW_CFA_offset_extended:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_offset_extended dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                if ( results-&gt;savedRegisters[reg].location != kRegisterUnused ) 
++                                        results-&gt;registerSavedMoreThanOnce = true;
++                                results-&gt;savedRegisters[reg].location = kRegisterInCFA;
++                                results-&gt;savedRegisters[reg].value = offset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_offset_extended(reg=%lld, offset=%lld)\n&quot;, reg, offset);
++                                break;
++                        case DW_CFA_restore_extended:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);;
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_restore_extended dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;savedRegisters[reg] = initialState.savedRegisters[reg];
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_restore_extended(reg=%lld)\n&quot;, reg);
++                                break;
++                        case DW_CFA_undefined:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_undefined dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;savedRegisters[reg].location = kRegisterUnused;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_undefined(reg=%lld)\n&quot;, reg);
++                                break;
++                        case DW_CFA_same_value:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_same_value dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                // &lt;rdar://problem/8456377&gt; DW_CFA_same_value unsupported
++                                // &quot;same value&quot; 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-&gt;savedRegisters[reg].location = kRegisterUnused;
++                                // set flag to disable conversion to compact unwind
++                                results-&gt;sameValueUsed = true;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_same_value(reg=%lld)\n&quot;, reg);
++                                break;
++                        case DW_CFA_register:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                reg2 = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_register dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                if ( reg2 &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_register dwarf unwind, reg2 too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;savedRegisters[reg].location = kRegisterInRegister;
++                                results-&gt;savedRegisters[reg].value = reg2;
++                                // set flag to disable conversion to compact unwind
++                                results-&gt;registersInOtherRegisters = true;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_register(reg=%lld, reg2=%lld)\n&quot;, 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-&gt;next = rememberStack;
++                                        entry-&gt;info = *results;
++                                        rememberStack = entry;
++                                }
++                                else {
++                                        return false;
++                                }
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_remember_state\n&quot;);
++                                break;
++                        case DW_CFA_restore_state:
++                                if ( rememberStack != NULL ) {
++                                        PrologInfoStackEntry* top = rememberStack;
++                                        *results = top-&gt;info;
++                                        rememberStack = top-&gt;next;
++                                        free((char*)top);
++                                }
++                                else {
++                                        return false;
++                                }
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_restore_state\n&quot;);
++                                break;
++                        case DW_CFA_def_cfa:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                offset = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_def_cfa dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;cfaRegister = reg;
++                                results-&gt;cfaRegisterOffset = offset;
++                                if ( offset &gt; 0x80000000 ) 
++                                        results-&gt;cfaOffsetWasNegative = true;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_def_cfa(reg=%lld, offset=%lld)\n&quot;, reg, offset);
++                                break;
++                        case DW_CFA_def_cfa_register:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;cfaRegister = reg;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_def_cfa_register(%lld)\n&quot;, reg);
++                                break;
++                        case DW_CFA_def_cfa_offset:
++                                results-&gt;cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd);
++                                results-&gt;codeOffsetAtStackDecrement = codeOffset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_def_cfa_offset(%d)\n&quot;, results-&gt;cfaRegisterOffset);
++                                break;
++                        case DW_CFA_def_cfa_expression:
++                                results-&gt;cfaRegister = 0;
++                                results-&gt;cfaExpression = p;
++                                length = addressSpace.getULEB128(p, instructionsEnd);
++                                p += length;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n&quot;, 
++                                                                                                        results-&gt;cfaExpression, length);
++                                break;
++                        case DW_CFA_expression:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_expression dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;savedRegisters[reg].location = kRegisterAtExpression;
++                                results-&gt;savedRegisters[reg].value = p;
++                                length = addressSpace.getULEB128(p, instructionsEnd);
++                                p += length;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n&quot;, 
++                                                                                                        reg, results-&gt;savedRegisters[reg].value, length);
++                                break;
++                        case DW_CFA_offset_extended_sf:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                if ( results-&gt;savedRegisters[reg].location != kRegisterUnused ) 
++                                        results-&gt;registerSavedMoreThanOnce = true;
++                                results-&gt;savedRegisters[reg].location = kRegisterInCFA;
++                                results-&gt;savedRegisters[reg].value = offset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n&quot;, reg, offset);
++                                break;
++                        case DW_CFA_def_cfa_sf:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;cfaRegister = reg;
++                                results-&gt;cfaRegisterOffset = offset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n&quot;, reg, offset);
++                                break;
++                        case DW_CFA_def_cfa_offset_sf:
++                                results-&gt;cfaRegisterOffset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                results-&gt;codeOffsetAtStackDecrement = codeOffset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_def_cfa_offset_sf(%d)\n&quot;, results-&gt;cfaRegisterOffset);
++                                break;
++                        case DW_CFA_val_offset:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                results-&gt;savedRegisters[reg].location = kRegisterOffsetFromCFA;
++                                results-&gt;savedRegisters[reg].value = offset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_val_offset(reg=%lld, offset=%lld\n&quot;, reg, offset);
++                                break;
++                        case DW_CFA_val_offset_sf:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                results-&gt;savedRegisters[reg].location = kRegisterOffsetFromCFA;
++                                results-&gt;savedRegisters[reg].value = offset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n&quot;, reg, offset);
++                                break;
++                        case DW_CFA_val_expression:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_val_expression dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                results-&gt;savedRegisters[reg].location = kRegisterIsExpression;
++                                results-&gt;savedRegisters[reg].value = p;
++                                length = addressSpace.getULEB128(p, instructionsEnd);
++                                p += length;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n&quot;, 
++                                                                                                        reg, results-&gt;savedRegisters[reg].value, length);
++                                break;
++                        case DW_CFA_GNU_args_size:
++                                offset = addressSpace.getULEB128(p, instructionsEnd);
++                                results-&gt;spExtraArgSize = offset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_GNU_args_size(%lld)\n&quot;, offset);
++                                break;
++                        case DW_CFA_GNU_negative_offset_extended:
++                                reg = addressSpace.getULEB128(p, instructionsEnd);
++                                if ( reg &gt; kMaxRegisterNumber ) {
++                                        fprintf(stderr, &quot;malformed DW_CFA_GNU_negative_offset_extended dwarf unwind, reg too big\n&quot;);
++                                        return false;
++                                }
++                                offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                if ( results-&gt;savedRegisters[reg].location != kRegisterUnused ) 
++                                        results-&gt;registerSavedMoreThanOnce = true;
++                                results-&gt;savedRegisters[reg].location = kRegisterInCFA;
++                                results-&gt;savedRegisters[reg].value = -offset;
++                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_GNU_negative_offset_extended(%lld)\n&quot;, offset);
++                                break;
++                        default:
++                                operand = opcode &amp; 0x3F;
++                                switch ( opcode &amp; 0xC0 ) {
++                                        case DW_CFA_offset:
++                                                reg = operand;
++                                                offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
++                                                if ( results-&gt;savedRegisters[reg].location != kRegisterUnused ) {
++                                                        // look for idiom of PC saved twice in CIE to mean disable compact unwind encoding
++                                                        if ( (pcoffset == (pint_t)(-1)) 
++                                                                &amp;&amp; (results-&gt;savedRegisters[reg].location == kRegisterInCFA) 
++                                                                &amp;&amp; (results-&gt;savedRegisters[reg].value == offset)  )
++                                                                results-&gt;registerSavedTwiceInCIE = reg;
++                                                        else
++                                                                results-&gt;registerSavedMoreThanOnce = true;
++                                                }
++                                                results-&gt;savedRegisters[reg].location = kRegisterInCFA;
++                                                results-&gt;savedRegisters[reg].value = offset;
++                                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_offset(reg=%d, offset=%lld)\n&quot;, operand, offset);
++                                                break;
++                                        case DW_CFA_advance_loc:
++                                                codeOffset += operand * cieInfo.codeAlignFactor;
++                                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_advance_loc: new offset=%u\n&quot;, codeOffset);
++                                                break;
++                                        case DW_CFA_restore:
++                                                // &lt;rdar://problem/7503075&gt; 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-&gt;savedRegisters[reg] = initialState.savedRegisters[reg];
++                                                if ( logDwarf ) fprintf(stderr, &quot;DW_CFA_restore(reg=%lld)\n&quot;, reg);
++                                                break;
++                                        default: 
++                                                if ( logDwarf ) fprintf(stderr, &quot;unknown CFA opcode 0x%02X\n&quot;, 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 &lt;assert.h&gt;
++
++#ifdef __cplusplus
++extern &quot;C&quot; {
++#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(&quot;default&quot;))) 
++
++#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, &quot;libuwind: &quot; msg, __VA_ARGS__)
++        #ifdef __cplusplus
++                extern &quot;C&quot; {
++        #endif
++                extern  bool logAPIs();
++                extern  bool logUnwinding();
++        #ifdef __cplusplus
++                }
++        #endif
++        #define DEBUG_LOG_NON_ZERO(x) { int _err = x; if ( _err != 0 ) fprintf(stderr, &quot;libuwind: &quot; #x &quot;=%d in %s&quot;, _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(&quot;LIBUNWIND_PRINT_APIS&quot;) != NULL); return log; }
++        #define INITIALIZE_DEBUG_PRINT_UNWINDING bool logUnwinding() { static bool log = (getenv(&quot;LIBUNWIND_PRINT_UNWINDING&quot;) != NULL); return log; }
++#endif
++
++
++// note hack for &lt;rdar://problem/6175741&gt;
++// 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(&quot;$ld$hide$os10.3$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp3 = 0; \
++                 extern const char sym##_tmp4 __asm(&quot;$ld$hide$os10.4$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp4 = 0; \
++                extern const char sym##_tmp5 __asm(&quot;$ld$hide$os10.5$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp5 = 0; 
++        #define NEVER_HERE(sym) \
++                extern const char sym##_tmp3 __asm(&quot;$ld$hide$os10.3$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp3 = 0; \
++                 extern const char sym##_tmp4 __asm(&quot;$ld$hide$os10.4$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp4 = 0; \
++                extern const char sym##_tmp5 __asm(&quot;$ld$hide$os10.5$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp5 = 0; \
++                extern const char sym##_tmp6 __asm(&quot;$ld$hide$os10.6$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp6 = 0;
++#else
++        #define NOT_HERE_BEFORE_10_6(sym) \
++                 extern const char sym##_tmp4 __asm(&quot;$ld$hide$os10.4$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp4 = 0; \
++                extern const char sym##_tmp5 __asm(&quot;$ld$hide$os10.5$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp5 = 0; 
++        #define NEVER_HERE(sym) \
++                 extern const char sym##_tmp4 __asm(&quot;$ld$hide$os10.4$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp4 = 0; \
++                extern const char sym##_tmp5 __asm(&quot;$ld$hide$os10.5$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) const char sym##_tmp5 = 0; \
++                extern const char sym##_tmp6 __asm(&quot;$ld$hide$os10.6$_&quot; #sym ); __attribute__((visibility(&quot;default&quot;))) 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 &lt;stdint.h&gt;
++#include &lt;stdio.h&gt;
++#include &lt;stdlib.h&gt;
++#include &lt;dlfcn.h&gt;
++#include &lt;mach-o/loader.h&gt;
++#include &lt;mach-o/getsect.h&gt;
++#include &lt;mach/i386/thread_status.h&gt;
++
++#include &quot;libunwind.h&quot;
++#include &quot;InternalMacros.h&quot;
++
++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) &lt; sizeof(unw_context_t) );
++        fRegisters = *((i386_thread_state_t*)registers); 
++}
++
++inline Registers_x86::Registers_x86()
++{
++        bzero(&amp;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 &lt; 0 )
++                return false;
++        if ( regNum &gt; 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(&quot;unsupported x86 register&quot;);
++}
++
++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(&quot;unsupported x86 register&quot;);
++}
++
++inline const char* Registers_x86::getRegisterName(int regNum)
++{
++        switch ( regNum ) {
++                case UNW_REG_IP:
++                        return &quot;ip&quot;;
++                case UNW_REG_SP:
++                        return &quot;esp&quot;;
++                case UNW_X86_EAX:
++                        return &quot;eax&quot;;
++                case UNW_X86_ECX:
++                        return &quot;ecx&quot;;
++                case UNW_X86_EDX:
++                        return &quot;edx&quot;;
++                case UNW_X86_EBX:
++                        return &quot;ebx&quot;;
++                case UNW_X86_EBP:
++                        return &quot;ebp&quot;;
++                case UNW_X86_ESP:
++                        return &quot;esp&quot;;
++                case UNW_X86_ESI:
++                        return &quot;esi&quot;;
++                case UNW_X86_EDI:
++                        return &quot;edi&quot;;
++                default:
++                        return &quot;unknown register&quot;;
++        }
++}
++
++inline double Registers_x86::getFloatRegister(int num) const
++{
++        ABORT(&quot;no x86 float registers&quot;);
++}
++
++inline void Registers_x86::setFloatRegister(int num, double value)
++{
++        ABORT(&quot;no x86 float registers&quot;);
++}
++
++inline v128 Registers_x86::getVectorRegister(int num) const
++{
++        ABORT(&quot;no x86 vector registers&quot;);
++}
++
++inline void Registers_x86::setVectorRegister(int num, v128 value)
++{
++        ABORT(&quot;no x86 vector registers&quot;);
++}
++
++
++
++
++///
++/// 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) &lt; sizeof(unw_context_t) );
++        fRegisters = *((x86_thread_state64_t*)registers); 
++}
++
++inline Registers_x86_64::Registers_x86_64()
++{
++        bzero(&amp;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 &lt; 0 )
++                return false;
++        if ( regNum &gt; 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(&quot;unsupported x86_64 register&quot;);
++}
++
++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(&quot;unsupported x86_64 register&quot;);
++}
++
++inline const char* Registers_x86_64::getRegisterName(int regNum)
++{
++        switch ( regNum ) {
++                case UNW_REG_IP:
++                        return &quot;rip&quot;;
++                case UNW_REG_SP:
++                        return &quot;rsp&quot;;
++                case UNW_X86_64_RAX:
++                        return &quot;rax&quot;;
++                case UNW_X86_64_RDX:
++                        return &quot;rdx&quot;;
++                case UNW_X86_64_RCX:
++                        return &quot;rcx&quot;;
++                case UNW_X86_64_RBX:
++                        return &quot;rbx&quot;;
++                case UNW_X86_64_RSI:
++                        return &quot;rsi&quot;;
++                case UNW_X86_64_RDI:
++                        return &quot;rdi&quot;;
++                case UNW_X86_64_RBP:
++                        return &quot;rbp&quot;;
++                case UNW_X86_64_RSP:
++                        return &quot;rsp&quot;;
++                case UNW_X86_64_R8:
++                        return &quot;r8&quot;;
++                case UNW_X86_64_R9:
++                        return &quot;r9&quot;;
++                case UNW_X86_64_R10:
++                        return &quot;r10&quot;;
++                case UNW_X86_64_R11:
++                        return &quot;r11&quot;;
++                case UNW_X86_64_R12:
++                        return &quot;r12&quot;;
++                case UNW_X86_64_R13:
++                        return &quot;r13&quot;;
++                case UNW_X86_64_R14:
++                        return &quot;r14&quot;;
++                case UNW_X86_64_R15:
++                        return &quot;r15&quot;;
++                default:
++                        return &quot;unknown register&quot;;
++        }
++}
++
++double Registers_x86_64::getFloatRegister(int num) const
++{
++        ABORT(&quot;no x86_64 float registers&quot;);
++}
++
++void Registers_x86_64::setFloatRegister(int num, double value)
++{
++        ABORT(&quot;no x86_64 float registers&quot;);
++}
++
++inline v128 Registers_x86_64::getVectorRegister(int num) const
++{
++        ABORT(&quot;no x86_64 vector registers&quot;);
++}
++
++inline void Registers_x86_64::setVectorRegister(int num, v128 value)
++{
++        ABORT(&quot;no x86_64 vector registers&quot;);
++}
++
++
++///
++/// 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) &lt; 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(&amp;fRegisters, sizeof(fRegisters)); 
++        bzero(&amp;fFloatRegisters, sizeof(fFloatRegisters)); 
++        bzero(&amp;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 &lt; 0 )
++                return false;
++        if ( regNum &lt;= 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 &lt;= regNum) &amp;&amp; (regNum &lt;= 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 &amp; 0xF0000000);
++                case UNW_PPC_CR1:
++                        return (fRegisters.__cr &amp; 0x0F000000);
++                case UNW_PPC_CR2:
++                        return (fRegisters.__cr &amp; 0x00F00000);
++                case UNW_PPC_CR3:
++                        return (fRegisters.__cr &amp; 0x000F0000);
++                case UNW_PPC_CR4:
++                        return (fRegisters.__cr &amp; 0x0000F000);
++                case UNW_PPC_CR5:
++                        return (fRegisters.__cr &amp; 0x00000F00);
++                case UNW_PPC_CR6:
++                        return (fRegisters.__cr &amp; 0x000000F0);
++                case UNW_PPC_CR7:
++                        return (fRegisters.__cr &amp; 0x0000000F);
++                case UNW_PPC_VRSAVE:
++                        return fRegisters.__vrsave;
++        }
++        ABORT(&quot;unsupported ppc register&quot;);
++}
++
++
++inline void Registers_ppc::setRegister(int regNum, uint32_t value)
++{
++        //fprintf(stderr, &quot;Registers_ppc::setRegister(%d, 0x%08X)\n&quot;, 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 &amp;= 0x0FFFFFFF;
++                        fRegisters.__cr |= (value &amp; 0xF0000000);
++                        return;
++                case UNW_PPC_CR1:
++                        fRegisters.__cr &amp;= 0xF0FFFFFF;
++                        fRegisters.__cr |= (value &amp; 0x0F000000);
++                        return;
++                case UNW_PPC_CR2:
++                        fRegisters.__cr &amp;= 0xFF0FFFFF;
++                        fRegisters.__cr |= (value &amp; 0x00F00000);
++                        return;
++                case UNW_PPC_CR3:
++                        fRegisters.__cr &amp;= 0xFFF0FFFF;
++                        fRegisters.__cr |= (value &amp; 0x000F0000);
++                        return;
++                case UNW_PPC_CR4:
++                        fRegisters.__cr &amp;= 0xFFFF0FFF;
++                        fRegisters.__cr |= (value &amp; 0x0000F000);
++                        return;
++                case UNW_PPC_CR5:
++                        fRegisters.__cr &amp;= 0xFFFFF0FF;
++                        fRegisters.__cr |= (value &amp; 0x00000F00);
++                        return;
++                case UNW_PPC_CR6:
++                        fRegisters.__cr &amp;= 0xFFFFFF0F;
++                        fRegisters.__cr |= (value &amp; 0x000000F0);
++                        return;
++                case UNW_PPC_CR7:
++                        fRegisters.__cr &amp;= 0xFFFFFFF0;
++                        fRegisters.__cr |= (value &amp; 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(&quot;unsupported ppc register&quot;);
++}
++
++inline bool Registers_ppc::validFloatRegister(int regNum) const
++{
++        if ( regNum &lt; UNW_PPC_F0 )
++                return false;
++        if ( regNum &gt; 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, &quot;Registers_ppc::setFloatRegister(%d, %g))\n&quot;, regNum, value);
++        assert(validFloatRegister(regNum));
++        fFloatRegisters.__fpregs[regNum-UNW_PPC_F0] = value;
++}
++
++
++inline bool Registers_ppc::validVectorRegister(int regNum) const
++{
++        if ( regNum &lt; UNW_PPC_V0 )
++                return false;
++        if ( regNum &gt; 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, &quot;Registers_ppc::getVectorRegister(this=%p, %d) =&gt; &lt;0x%08X, 0x%08X, 0x%08X, 0x%08X&gt; \n&quot;, 
++        //                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, &quot;Registers_ppc::setVectorRegister(this=%p, %d) &lt;0x%08X, 0x%08X, 0x%08X, 0x%08X&gt; =&gt; &lt;0x%08X, 0x%08X, 0x%08X, 0x%08X&gt; \n&quot;, 
++        //                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 &quot;ip&quot;;
++                case UNW_REG_SP:
++                        return &quot;sp&quot;;
++                case UNW_PPC_R0:
++                        return &quot;r0&quot;;
++                case UNW_PPC_R1:
++                        return &quot;r1&quot;;
++                case UNW_PPC_R2:
++                        return &quot;r2&quot;;
++                case UNW_PPC_R3:
++                        return &quot;r3&quot;;
++                case UNW_PPC_R4:
++                        return &quot;r4&quot;;
++                case UNW_PPC_R5:
++                        return &quot;r5&quot;;
++                case UNW_PPC_R6:
++                        return &quot;r6&quot;;
++                case UNW_PPC_R7:
++                        return &quot;r7&quot;;
++                case UNW_PPC_R8:
++                        return &quot;r8&quot;;
++                case UNW_PPC_R9:
++                        return &quot;r9&quot;;
++                case UNW_PPC_R10:
++                        return &quot;r10&quot;;
++                case UNW_PPC_R11:
++                        return &quot;r11&quot;;
++                case UNW_PPC_R12:
++                        return &quot;r12&quot;;
++                case UNW_PPC_R13:
++                        return &quot;r13&quot;;
++                case UNW_PPC_R14:
++                        return &quot;r14&quot;;
++                case UNW_PPC_R15:
++                        return &quot;r15&quot;;
++                case UNW_PPC_R16:
++                        return &quot;r16&quot;;
++                case UNW_PPC_R17:
++                        return &quot;r17&quot;;
++                case UNW_PPC_R18:
++                        return &quot;r18&quot;;
++                case UNW_PPC_R19:
++                        return &quot;r19&quot;;
++                case UNW_PPC_R20:
++                        return &quot;r20&quot;;
++                case UNW_PPC_R21:
++                        return &quot;r21&quot;;
++                case UNW_PPC_R22:
++                        return &quot;r22&quot;;
++                case UNW_PPC_R23:
++                        return &quot;r23&quot;;
++                case UNW_PPC_R24:
++                        return &quot;r24&quot;;
++                case UNW_PPC_R25:
++                        return &quot;r25&quot;;
++                case UNW_PPC_R26:
++                        return &quot;r26&quot;;
++                case UNW_PPC_R27:
++                        return &quot;r27&quot;;
++                case UNW_PPC_R28:
++                        return &quot;r28&quot;;
++                case UNW_PPC_R29:
++                        return &quot;r29&quot;;
++                case UNW_PPC_R30:
++                        return &quot;r30&quot;;
++                case UNW_PPC_R31:
++                        return &quot;r31&quot;;
++                case UNW_PPC_F0:
++                        return &quot;fp0&quot;;
++                case UNW_PPC_F1:
++                        return &quot;fp1&quot;;
++                case UNW_PPC_F2:
++                        return &quot;fp2&quot;;
++                case UNW_PPC_F3:
++                        return &quot;fp3&quot;;
++                case UNW_PPC_F4:
++                        return &quot;fp4&quot;;
++                case UNW_PPC_F5:
++                        return &quot;fp5&quot;;
++                case UNW_PPC_F6:
++                        return &quot;fp6&quot;;
++                case UNW_PPC_F7:
++                        return &quot;fp7&quot;;
++                case UNW_PPC_F8:
++                        return &quot;fp8&quot;;
++                case UNW_PPC_F9:
++                        return &quot;fp9&quot;;
++                case UNW_PPC_F10:
++                        return &quot;fp10&quot;;
++                case UNW_PPC_F11:
++                        return &quot;fp11&quot;;
++                case UNW_PPC_F12:
++                        return &quot;fp12&quot;;
++                case UNW_PPC_F13:
++                        return &quot;fp13&quot;;
++                case UNW_PPC_F14:
++                        return &quot;fp14&quot;;
++                case UNW_PPC_F15:
++                        return &quot;fp15&quot;;
++                case UNW_PPC_F16:
++                        return &quot;fp16&quot;;
++                case UNW_PPC_F17:
++                        return &quot;fp17&quot;;
++                case UNW_PPC_F18:
++                        return &quot;fp18&quot;;
++                case UNW_PPC_F19:
++                        return &quot;fp19&quot;;
++                case UNW_PPC_F20:
++                        return &quot;fp20&quot;;
++                case UNW_PPC_F21:
++                        return &quot;fp21&quot;;
++                case UNW_PPC_F22:
++                        return &quot;fp22&quot;;
++                case UNW_PPC_F23:
++                        return &quot;fp23&quot;;
++                case UNW_PPC_F24:
++                        return &quot;fp24&quot;;
++                case UNW_PPC_F25:
++                        return &quot;fp25&quot;;
++                case UNW_PPC_F26:
++                        return &quot;fp26&quot;;
++                case UNW_PPC_F27:
++                        return &quot;fp27&quot;;
++                case UNW_PPC_F28:
++                        return &quot;fp28&quot;;
++                case UNW_PPC_F29:
++                        return &quot;fp29&quot;;
++                case UNW_PPC_F30:
++                        return &quot;fp30&quot;;
++                case UNW_PPC_F31:
++                        return &quot;fp31&quot;;
++                case UNW_PPC_LR:
++                        return &quot;lr&quot;;
++                default:
++                        return &quot;unknown register&quot;;
++        }
++
++
++}
++
++
++} // namespace libunwind 
++
++
++
++#endif // __REGISTERS_HPP__
++
++
++
++
+-- 
+2.2.1
+
</ins></span></pre>
</div>
</div>

</body>
</html>