diff mbox

[v2,11/13] D: GCC builtins and runtime support.

Message ID CABOHX+eJuu0QSJBpdHjLQTsvv_Dnqkp340jTa+oCHpM6930ZZA@mail.gmail.com
State New
Headers show

Commit Message

Iain Buclaw June 24, 2017, 5:53 p.m. UTC
On 28 May 2017 at 23:17, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
> This patch adds GCC builtins and runtime support for GDC compiled code.
>
>   - module __entrypoint defines the C main function.  Its contents are
> parsed and compiled in during compilation, but only if needed.
>   - module gcc.atomic is a deprecated module that defines templated
> __sync builtins.  It's original user, core.atomic, now uses the GCC
> __atomic builtins.
>   - module gcc.attribute exposes GDC-specific attributes.
>   - module gcc.backtrace implements backtrace support for GDC.
>   - module gcc.builtins exposes GCC builtins to D code.
>   - module gcc.config exposes things determined at configure time to D code.
>   - module gcc.deh implements D unwind EH.
>   - module gcc.libbacktrace defines C bindings to libbacktrace.
>   - module gcc.unwind defines C bindings to libgcc unwind library.
>   - libgphobos.spec contains a list of libraries to link in that are
> dependencies of D runtime and/or the Phobos standard library.  It is
> used by the GDC driver.
>
> ---

Added GCC Runtime Library Exception to gcc modules as requested.

Regards
Iain.

---

Comments

Jeff Law Sept. 11, 2017, 4:40 p.m. UTC | #1
On 06/24/2017 11:53 AM, Iain Buclaw wrote:
> On 28 May 2017 at 23:17, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>> This patch adds GCC builtins and runtime support for GDC compiled code.
>>
>>   - module __entrypoint defines the C main function.  Its contents are
>> parsed and compiled in during compilation, but only if needed.
>>   - module gcc.atomic is a deprecated module that defines templated
>> __sync builtins.  It's original user, core.atomic, now uses the GCC
>> __atomic builtins.
>>   - module gcc.attribute exposes GDC-specific attributes.
>>   - module gcc.backtrace implements backtrace support for GDC.
>>   - module gcc.builtins exposes GCC builtins to D code.
>>   - module gcc.config exposes things determined at configure time to D code.
>>   - module gcc.deh implements D unwind EH.
>>   - module gcc.libbacktrace defines C bindings to libbacktrace.
>>   - module gcc.unwind defines C bindings to libgcc unwind library.
>>   - libgphobos.spec contains a list of libraries to link in that are
>> dependencies of D runtime and/or the Phobos standard library.  It is
>> used by the GDC driver.
>>
>> ---
> Added GCC Runtime Library Exception to gcc modules as requested.
Nothing particularly concerning here now that the license is fixed.
Based on my reading, this is all code that the FSF will own, so we don't
have to worry about alternate upstreams, license exceptions, etc which
makes things so much easier.

You may need to bump the copyright dates.

jeff
Iain Buclaw Sept. 11, 2017, 6:04 p.m. UTC | #2
On 11 September 2017 at 18:40, Jeff Law <law@redhat.com> wrote:
> On 06/24/2017 11:53 AM, Iain Buclaw wrote:
>> On 28 May 2017 at 23:17, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>>> This patch adds GCC builtins and runtime support for GDC compiled code.
>>>
>>>   - module __entrypoint defines the C main function.  Its contents are
>>> parsed and compiled in during compilation, but only if needed.
>>>   - module gcc.atomic is a deprecated module that defines templated
>>> __sync builtins.  It's original user, core.atomic, now uses the GCC
>>> __atomic builtins.
>>>   - module gcc.attribute exposes GDC-specific attributes.
>>>   - module gcc.backtrace implements backtrace support for GDC.
>>>   - module gcc.builtins exposes GCC builtins to D code.
>>>   - module gcc.config exposes things determined at configure time to D code.
>>>   - module gcc.deh implements D unwind EH.
>>>   - module gcc.libbacktrace defines C bindings to libbacktrace.
>>>   - module gcc.unwind defines C bindings to libgcc unwind library.
>>>   - libgphobos.spec contains a list of libraries to link in that are
>>> dependencies of D runtime and/or the Phobos standard library.  It is
>>> used by the GDC driver.
>>>
>>> ---
>> Added GCC Runtime Library Exception to gcc modules as requested.
> Nothing particularly concerning here now that the license is fixed.
> Based on my reading, this is all code that the FSF will own, so we don't
> have to worry about alternate upstreams, license exceptions, etc which
> makes things so much easier.
>
> You may need to bump the copyright dates.
>

I thought I bumped all copyright dates in v2 of the patch.  I will check again.

However, I will prep a v3 of the patch, as it has been some time since
June - I have made no changes to any of these files anyway.

Iain
Jakub Jelinek Sept. 11, 2017, 6:19 p.m. UTC | #3
On Mon, Sep 11, 2017 at 08:04:02PM +0200, Iain Buclaw wrote:
> > You may need to bump the copyright dates.
> >
> 
> I thought I bumped all copyright dates in v2 of the patch.  I will check again.

Regarding copyright dates, after everything is committed, we should also
adjust
contrib/update-copyright.py
so that it is able to update the copyright on the D source files where we
want to bump them.

	Jakub
Jeff Law Sept. 12, 2017, 5:12 p.m. UTC | #4
On 09/11/2017 12:04 PM, Iain Buclaw wrote:
> On 11 September 2017 at 18:40, Jeff Law <law@redhat.com> wrote:
>> On 06/24/2017 11:53 AM, Iain Buclaw wrote:
>>> On 28 May 2017 at 23:17, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>>>> This patch adds GCC builtins and runtime support for GDC compiled code.
>>>>
>>>>   - module __entrypoint defines the C main function.  Its contents are
>>>> parsed and compiled in during compilation, but only if needed.
>>>>   - module gcc.atomic is a deprecated module that defines templated
>>>> __sync builtins.  It's original user, core.atomic, now uses the GCC
>>>> __atomic builtins.
>>>>   - module gcc.attribute exposes GDC-specific attributes.
>>>>   - module gcc.backtrace implements backtrace support for GDC.
>>>>   - module gcc.builtins exposes GCC builtins to D code.
>>>>   - module gcc.config exposes things determined at configure time to D code.
>>>>   - module gcc.deh implements D unwind EH.
>>>>   - module gcc.libbacktrace defines C bindings to libbacktrace.
>>>>   - module gcc.unwind defines C bindings to libgcc unwind library.
>>>>   - libgphobos.spec contains a list of libraries to link in that are
>>>> dependencies of D runtime and/or the Phobos standard library.  It is
>>>> used by the GDC driver.
>>>>
>>>> ---
>>> Added GCC Runtime Library Exception to gcc modules as requested.
>> Nothing particularly concerning here now that the license is fixed.
>> Based on my reading, this is all code that the FSF will own, so we don't
>> have to worry about alternate upstreams, license exceptions, etc which
>> makes things so much easier.
>>
>> You may need to bump the copyright dates.
>>
> 
> I thought I bumped all copyright dates in v2 of the patch.  I will check again.
> 
> However, I will prep a v3 of the patch, as it has been some time since
> June - I have made no changes to any of these files anyway.
I may have been looking at the V1 patch -- my email client didnt' thread
any of the D submission well and I was working from a coffee shop
yesterday afternoon.  If it's fixed in the V2, then sorry for the noise.


jeff
diff mbox

Patch

diff --git a/libphobos/libdruntime/__entrypoint.di b/libphobos/libdruntime/__entrypoint.di
new file mode 100644
index 00000000000..d04fe5d0889
--- /dev/null
+++ b/libphobos/libdruntime/__entrypoint.di
@@ -0,0 +1,56 @@ 
+/* GDC -- D front-end for GCC
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.
+*/
+
+/* This module provides the C main() function supplied by the user's program.  */
+
+module __entrypoint;
+
+extern(C):
+
+/* The D main() function supplied by the user's program
+
+   It always has `_Dmain` symbol name and uses C calling convention.
+   But D frontend returns its type as `extern(D)` because of Issue 9028.
+   As we need to deal with actual calling convention we have to mark it
+   as `extern(C)` and use its symbol name.
+*/
+
+int _Dmain(char[][] args);
+int _d_run_main(int argc, char **argv, void* mainFunc);
+
+/* Substitutes for the C main() function.  Just calls into d_run_main with
+   the default main function.  Applications are free to implement their own
+   main function and call the _d_run_main function themselves with any main
+   function.
+*/
+
+int main(int argc, char **argv)
+{
+    return _d_run_main(argc, argv, &_Dmain);
+}
+
+/* This is apparently needed on Solaris because the C tool chain seems to
+   expect the main function to be called _main.  It needs both not just one!
+*/
+
+version (Solaris)
+int _main(int argc, char** argv)
+{
+    return main(argc, argv);
+}
+
diff --git a/libphobos/libdruntime/gcc/attribute.d b/libphobos/libdruntime/gcc/attribute.d
new file mode 100644
index 00000000000..2498c27e7cc
--- /dev/null
+++ b/libphobos/libdruntime/gcc/attribute.d
@@ -0,0 +1,33 @@ 
+// GNU D Compiler attribute support declarations.
+// Copyright (C) 2013-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.attribute;
+
+private struct Attribute(A...)
+{
+    A args;
+}
+
+auto attribute(A...)(A args) if(A.length > 0 && is(A[0] == string))
+{
+    return Attribute!A(args);
+}
diff --git a/libphobos/libdruntime/gcc/backtrace.d b/libphobos/libdruntime/gcc/backtrace.d
new file mode 100644
index 00000000000..c24a53a42fb
--- /dev/null
+++ b/libphobos/libdruntime/gcc/backtrace.d
@@ -0,0 +1,575 @@ 
+// GNU D Compiler routines for stack backtrace support.
+// Copyright (C) 2013-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.backtrace;
+
+import gcc.libbacktrace;
+
+
+version( Posix )
+{
+    // NOTE: The first 5 frames with the current implementation are
+    //       inside core.runtime and the object code, so eliminate
+    //       these for readability.  The alternative would be to
+    //       exclude the first N frames that are in a list of
+    //       mangled function names.
+    static enum FIRSTFRAME = 5;
+}
+else
+{
+    // NOTE: On Windows, the number of frames to exclude is based on
+    //       whether the exception is user or system-generated, so
+    //       it may be necessary to exclude a list of function names
+    //       instead.
+    static enum FIRSTFRAME = 0;
+}
+
+static if(BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC)
+{
+    import core.stdc.stdint, core.stdc.string, core.stdc.stdio;
+    enum MAXFRAMES = 128;
+
+    extern(C) int simpleCallback(void* data, uintptr_t pc)
+    {
+        auto context = cast(LibBacktrace)data;
+
+        if(context.numPCs == MAXFRAMES)
+            return 1;
+
+        context.pcs[context.numPCs++] = pc;
+        return 0;
+    }
+
+    /*
+     * Used for backtrace_create_state and backtrace_simple
+     */
+    extern(C) void simpleErrorCallback(void* data, const(char)* msg, int errnum)
+    {
+        if(data) //context is not available in backtrace_create_state
+        {
+            auto context = cast(LibBacktrace)data;
+            strncpy(context.errorBuf.ptr, msg, context.errorBuf.length - 1);
+            context.error = errnum;
+        }
+    }
+
+    /*
+     * Used for backtrace_pcinfo
+     */
+    extern(C) int pcinfoCallback(void* data, uintptr_t pc, const(char)* filename,
+        int lineno, const(char)* func)
+    {
+        auto context = cast(SymbolCallbackInfo*)data;
+
+        //Try to get the function name via backtrace_syminfo
+        if(func is null)
+        {
+            SymbolCallbackInfo2 info;
+            info.base = context;
+            info.filename = filename;
+            info.lineno = lineno;
+            if(backtrace_syminfo(context.state, pc, &syminfoCallback2, null, &info) != 0)
+            {
+                return context.retval;
+            }
+        }
+
+        auto sym = SymbolOrError(0, SymbolInfo(func, filename, lineno, cast(void*)pc));
+        context.retval = context.applyCB(context.num, sym);
+        context.num++;
+
+        return context.retval;
+    }
+
+    /*
+     * Used for backtrace_pcinfo and backtrace_syminfo
+     */
+    extern(C) void pcinfoErrorCallback(void* data, const(char)* msg, int errnum)
+    {
+        auto context = cast(SymbolCallbackInfo*)data;
+
+        if(errnum == -1)
+        {
+            context.noInfo = true;
+            return;
+        }
+
+        SymbolOrError symError;
+        symError.errnum = errnum;
+        symError.msg = msg;
+
+        size_t i = 0;
+        context.retval = context.applyCB(i, symError);
+    }
+
+    /*
+     * Used for backtrace_syminfo (in opApply)
+     */
+    extern(C) void syminfoCallback(void* data, uintptr_t pc,
+        const(char)* symname, uintptr_t symval)
+    {
+        auto context = cast(SymbolCallbackInfo*)data;
+
+        auto sym = SymbolOrError(0, SymbolInfo(symname, null, 0, cast(void*)pc));
+        context.retval = context.applyCB(context.num, sym);
+
+        context.num++;
+    }
+
+    /*
+     * This callback is used if backtrace_syminfo is called from the pcinfoCallback
+     * callback. It merges it's information with the information from pcinfoCallback.
+     */
+    extern(C) void syminfoCallback2(void* data, uintptr_t pc,
+        const(char)* symname, uintptr_t symval)
+    {
+        auto context = cast(SymbolCallbackInfo2*)data;
+
+        auto sym = SymbolOrError(0, SymbolInfo(symname, context.filename, context.lineno,
+            cast(void*)pc));
+        context.base.retval = context.base.applyCB(context.base.num, sym);
+
+        context.base.num++;
+    }
+
+    /*
+     * The callback type used with the opApply overload which returns a SymbolOrError
+     */
+    private alias scope int delegate(ref size_t, ref SymbolOrError) ApplyCallback;
+
+    /*
+     * Passed to syminfoCallback, pcinfoCallback and pcinfoErrorCallback
+     */
+    struct SymbolCallbackInfo
+    {
+        bool noInfo = false;       //True if debug info / symbol table is not available
+        size_t num = 0;            //Counter for opApply
+        int retval;                //Value returned by applyCB
+        backtrace_state* state;
+
+        //info.fileName / funcName / errmsg may become invalid after this delegate returned
+        ApplyCallback applyCB;
+
+        void reset()
+        {
+            noInfo = false;
+            num = 0;
+        }
+    }
+
+    /*
+     * Passed to the syminfoCallback2 callback. That function merges it's
+     * funcName with this information and updates base as all other callbacks do.
+     */
+    struct SymbolCallbackInfo2
+    {
+        SymbolCallbackInfo* base;
+        const(char)* filename;
+        int lineno;
+    }
+
+    /*
+     * Contains a valid symbol or an error message if errnum is != 0.
+     */
+    struct SymbolOrError
+    {
+        int errnum; // == 0: No error
+        union
+        {
+            SymbolInfo symbol;
+            const(char)* msg;
+        }
+    }
+
+    //FIXME: state is never freed as libbacktrace doesn't provide a free function...
+    public class LibBacktrace : Throwable.TraceInfo
+    {
+        enum MaxAlignment = (void*).alignof;
+
+        static void initLibBacktrace()
+        {
+            if(!initialized)
+            {
+                state = backtrace_create_state(null, false, &simpleErrorCallback, null);
+                initialized = true;
+            }
+        }
+
+        this(int firstFrame = FIRSTFRAME)
+        {
+            _firstFrame = firstFrame;
+
+            initLibBacktrace();
+
+            if(state)
+            {
+                backtrace_simple(state, _firstFrame, &simpleCallback,
+                    &simpleErrorCallback, cast(void*)this);
+            }
+        }
+
+        override int opApply( scope int delegate(ref const(char[])) dg ) const
+        {
+            return opApply( (ref size_t, ref const(char[]) buf)
+                            {
+                                return dg( buf );
+                            } );
+        }
+
+        override int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const
+        {
+            return opApply( (ref size_t i, ref SymbolOrError sym)
+                {
+                    char[512] buffer = '\0';
+                    char[] msg;
+                    if(sym.errnum != 0)
+                    {
+                        auto retval = snprintf(buffer.ptr, buffer.length,
+                            "libbacktrace error: '%s' errno: %d", sym.msg, sym.errnum);
+
+                        if(retval >= buffer.length)
+                            msg = buffer[0 .. $-1]; //Ignore zero terminator
+                        else if(retval > 0)
+                            msg = buffer[0 .. retval];
+                    }
+                    else
+                    {
+                        msg = formatLine(sym.symbol, buffer);
+                    }
+
+                    return dg(i, msg);
+                } );
+        }
+
+        int opApply(ApplyCallback dg) const
+        {
+            //If backtrace_simple produced an error report it and exit
+            if(!state || error != 0)
+            {
+                size_t pos = 0;
+                SymbolOrError symError;
+                symError.errnum = error;
+                symError.msg = errorBuf.ptr;
+
+                return dg(pos, symError);
+            }
+
+            SymbolCallbackInfo cinfo;
+            cinfo.applyCB = dg;
+            cinfo.state = cast(backtrace_state*)state;
+
+            //Try using debug info first
+            foreach(i, pc; pcs[0 .. numPCs])
+            {
+                //FIXME: We may violate const guarantees here...
+                if(backtrace_pcinfo(cast(backtrace_state*)state, pc, &pcinfoCallback,
+                    &pcinfoErrorCallback, &cinfo) != 0)
+                {
+                    break; //User delegate requested abort or no debug info at all
+                }
+            }
+
+            //If no error or other error which has already been reported via callback
+            if(!cinfo.noInfo)
+                return cinfo.retval;
+
+            //Try using symbol table
+            cinfo.reset();
+            foreach(pc; pcs[0 .. numPCs])
+            {
+                if(backtrace_syminfo(cast(backtrace_state*)state, pc, &syminfoCallback,
+                    &pcinfoErrorCallback, &cinfo) == 0)
+                {
+                    break;
+                }
+            }
+
+            if(!cinfo.noInfo)
+                return cinfo.retval;
+
+            //No symbol table
+            foreach(i, pc; pcs[0 .. numPCs])
+            {
+                auto sym = SymbolOrError(0, SymbolInfo(null, null, 0, cast(void*)pc));
+                if(auto ret = dg(i, sym) != 0)
+                    return ret;
+            }
+
+            return 0;
+        }
+
+        override string toString() const
+        {
+            string buf;
+            foreach(i, const(char[]) line; this )
+                buf ~= i ? "\n" ~ line : line;
+            return buf;
+        }
+
+    private:
+        static backtrace_state* state = null;
+        static bool initialized       = false;
+        size_t                  numPCs = 0;
+        uintptr_t[MAXFRAMES]    pcs;
+
+        int                   error = 0;
+        int                   _firstFrame = 0;
+        char[128]             errorBuf;
+    }
+}
+else
+{
+    /*
+     * Our fallback backtrace implementation using libgcc's unwind
+     * and backtrace support. In theory libbacktrace should be available
+     * everywhere where this code works. We keep it anyway till libbacktrace
+     * is well-tested.
+     */
+    public class UnwindBacktrace : Throwable.TraceInfo
+    {
+        this(int firstFrame = FIRSTFRAME)
+        {
+            _firstFrame = firstFrame;
+            _callstack = getBacktrace();
+            _framelist = getBacktraceSymbols(_callstack);
+        }
+
+        override int opApply( scope int delegate(ref const(char[])) dg ) const
+        {
+            return opApply( (ref size_t, ref const(char[]) buf)
+                            {
+                                return dg( buf );
+                            } );
+        }
+
+        override int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const
+        {
+            int ret = 0;
+            char[512] fixbuf = '\0';
+
+            for( int i = _firstFrame; i < _framelist.entries; ++i )
+            {
+                auto pos = cast(size_t)(i - _firstFrame);
+                auto buf = formatLine(_framelist.symbols[i], fixbuf);
+                ret = dg( pos, buf );
+                if( ret )
+                    break;
+            }
+            return ret;
+        }
+
+        override string toString() const
+        {
+            string buf;
+            foreach( i, line; this )
+                buf ~= i ? "\n" ~ line : line;
+            return buf;
+        }
+
+    private:
+        BTSymbolData     _framelist;
+        UnwindBacktraceData _callstack;
+        int              _firstFrame = 0;
+    }
+
+    // Implementation details
+    private:
+        import gcc.unwind;
+
+        static enum MAXFRAMES = 128;
+
+        struct UnwindBacktraceData
+        {
+            void*[MAXFRAMES] callstack;
+            int numframes = 0;
+        }
+
+        struct BTSymbolData
+        {
+            size_t entries;
+            SymbolInfo[MAXFRAMES] symbols;
+        }
+
+        static extern (C) _Unwind_Reason_Code unwindCB(_Unwind_Context *ctx, void *d)
+        {
+            UnwindBacktraceData* bt = cast(UnwindBacktraceData*)d;
+            if(bt.numframes >= MAXFRAMES)
+                return _URC_NO_REASON;
+
+            bt.callstack[bt.numframes] = cast(void*)_Unwind_GetIP(ctx);
+            bt.numframes++;
+            return _URC_NO_REASON;
+        }
+
+        UnwindBacktraceData getBacktrace()
+        {
+            UnwindBacktraceData stackframe;
+            _Unwind_Backtrace(&unwindCB, &stackframe);
+            return stackframe;
+        }
+
+        BTSymbolData getBacktraceSymbols(UnwindBacktraceData data)
+        {
+            BTSymbolData symData;
+
+            for(auto i = 0; i < data.numframes; i++)
+            {
+                static if(HAVE_DLADDR)
+                {
+                    Dl_info funcInfo;
+
+                    if(data.callstack[i] !is null && dladdr(data.callstack[i], &funcInfo) != 0)
+                    {
+                        symData.symbols[symData.entries].funcName = funcInfo.dli_sname;
+
+                        symData.symbols[symData.entries].address = data.callstack[i];
+                        symData.entries++;
+                    }
+                    else
+                    {
+                        symData.symbols[symData.entries].address = data.callstack[i];
+                        symData.entries++;
+                    }
+                }
+                else
+                {
+                    symData.symbols[symData.entries].address = data.callstack[i];
+                    symData.entries++;
+                }
+            }
+
+            return symData;
+        }
+}
+
+/*
+ * Struct representing a symbol (function) in the backtrace
+ */
+struct SymbolInfo
+{
+    const(char)* funcName, fileName;
+    size_t line;
+    const(void)* address;
+}
+
+/*
+ * Format one output line for symbol sym.
+ * Returns a slice of fixbuf.
+ */
+char[] formatLine(const SymbolInfo sym, ref char[512] fixbuf)
+{
+    import core.demangle, core.stdc.config;
+    import core.stdc.stdio : snprintf, printf;
+    import core.stdc.string : strlen;
+
+    int ret;
+
+    ret = snprintf(fixbuf.ptr, fixbuf.sizeof, "0x%lx ", cast(c_ulong)sym.address);
+    if(ret >= fixbuf.sizeof)
+        return fixbuf[0 .. $-1]; //Ignore zero terminator
+
+    if(sym.funcName is null)
+    {
+        if(!(fixbuf.sizeof - ret > 3))
+            return fixbuf[0 .. ret];
+
+        fixbuf[ret] = fixbuf[ret+1] = fixbuf[ret+2] = '?';
+        ret += 3;
+    }
+    else
+    {
+        auto demangled = demangle(sym.funcName[0 .. strlen(sym.funcName)],
+            fixbuf[ret .. $-1]);
+
+        ret += demangled.length;
+        if(ret + 1 >= fixbuf.sizeof)
+            return fixbuf[0 .. $-1]; //Ignore zero terminator
+    }
+
+    ret += snprintf(fixbuf.ptr + ret, fixbuf.sizeof - ret, "\n\t%s:%d",
+        sym.fileName is null ? "???" : sym.fileName,
+        sym.line);
+
+    if(ret >= fixbuf.sizeof)
+        return fixbuf[0 .. $-1]; //Ignore zero terminator
+    else
+        return fixbuf[0 .. ret];
+}
+
+
+unittest
+{
+    char[512] sbuf = '\0';
+    char[] result;
+    string longString;
+    for(size_t i = 0; i < 60; i++)
+        longString ~= "abcdefghij";
+    longString ~= '\0';
+
+    auto symbol = SymbolInfo(null, null, 0, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo(longString.ptr, null, 0, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo("func", "test.d", 0, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo("func", longString.ptr, 0, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo(longString.ptr, "test.d", 0, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo(longString.ptr, longString.ptr, 0, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo("func", "test.d", 1000, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo(null, (longString[0..500] ~ '\0').ptr, 100000000, null);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo("func", "test.d", 0, cast(void*)0x100000);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo("func", null, 0, cast(void*)0x100000);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo(null, "test.d", 0, cast(void*)0x100000);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+
+    symbol = SymbolInfo(longString.ptr, "test.d", 0, cast(void*)0x100000);
+    result = formatLine(symbol, sbuf);
+    assert(result.length < 512 && result.ptr[result.length] == '\0' && sbuf[$-1] == '\0');
+}
diff --git a/libphobos/libdruntime/gcc/builtins.d b/libphobos/libdruntime/gcc/builtins.d
new file mode 100644
index 00000000000..e4e0bf3481f
--- /dev/null
+++ b/libphobos/libdruntime/gcc/builtins.d
@@ -0,0 +1,44 @@ 
+/* GNU D Compiler bindings for built-in functions and types.
+   Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/**
+  Declarations are automatically created by the compiler.  All
+  declarations start with "__builtin_". Refer to _builtins.def in the
+  GCC source for a list of functions.  Not all of the functions are
+  supported.
+
+  In addition to built-in functions, the following types are defined.
+
+  $(TABLE
+  $(TR $(TD ___builtin_va_list)      $(TD The target's va_list type ))
+  $(TR $(TD ___builtin_clong  )      $(TD The D equivalent of the target's
+                                       C "long" type ))
+  $(TR $(TD ___builtin_culong )      $(TD The D equivalent of the target's
+                                       C "unsigned long" type ))
+  $(TR $(TD ___builtin_machine_int ) $(TD Signed word-sized integer ))
+  $(TR $(TD ___builtin_machine_uint) $(TD Unsigned word-sized integer ))
+  $(TR $(TD ___builtin_pointer_int ) $(TD Signed pointer-sized integer ))
+  $(TR $(TD ___builtin_pointer_uint) $(TD Unsigned pointer-sized integer ))
+  )
+ */
+
+module gcc.builtins;
diff --git a/libphobos/libdruntime/gcc/config.d.in b/libphobos/libdruntime/gcc/config.d.in
new file mode 100644
index 00000000000..05013c09c47
--- /dev/null
+++ b/libphobos/libdruntime/gcc/config.d.in
@@ -0,0 +1,42 @@ 
+// GNU D Compiler configure constants.
+// Copyright (C) 2015-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.config;
+
+// Does platform define __ARM_EABI_UNWINDER__
+enum GNU_ARM_EABI_Unwinder = @DCFG_ARM_EABI_UNWINDER@;
+
+// Map from thread model to thread interface.
+enum ThreadModel
+{
+    Single,
+    Posix,
+    Win32,
+}
+
+enum ThreadModel GNU_Thread_Model = ThreadModel.@DCFG_THREAD_MODEL@;
+
+// Whether the linker provides __start_minfo and __stop_minfo symbols
+enum Minfo_Bracketing = @DCFG_MINFO_BRACKETING@;
+
+// Do we have libatomic available
+enum HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@;
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
new file mode 100644
index 00000000000..4630504f58a
--- /dev/null
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -0,0 +1,964 @@ 
+// GNU D Compiler exception personality routines.
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// This code is based on the libstdc++ exception handling routines.
+
+module gcc.deh;
+
+import gcc.unwind;
+import gcc.unwind.pe;
+import gcc.builtins;
+import gcc.config;
+
+extern(C)
+{
+    int _d_isbaseof(ClassInfo, ClassInfo);
+    void _d_createTrace(Object, void*);
+
+    // Not used in GDC but declaration required by rt/sections.d
+    struct FuncTable
+    {
+    }
+}
+
+/**
+ * Declare all known and handled exception classes.
+ * D exceptions -- "GNUCD\0\0\0".
+ * C++ exceptions -- "GNUCC++\0"
+ * C++ dependent exceptions -- "GNUCC++\x01"
+ */
+static if (GNU_ARM_EABI_Unwinder)
+{
+    enum _Unwind_Exception_Class gdcExceptionClass = "GNUCD\0\0\0";
+    enum _Unwind_Exception_Class gxxExceptionClass = "GNUCC++\0";
+    enum _Unwind_Exception_Class gxxDependentExceptionClass = "GNUCC++\x01";
+}
+else
+{
+    enum _Unwind_Exception_Class gdcExceptionClass =
+        (cast(_Unwind_Exception_Class)'G' << 56) |
+        (cast(_Unwind_Exception_Class)'N' << 48) |
+        (cast(_Unwind_Exception_Class)'U' << 40) |
+        (cast(_Unwind_Exception_Class)'C' << 32) |
+        (cast(_Unwind_Exception_Class)'D' << 24);
+
+    enum _Unwind_Exception_Class gxxExceptionClass =
+        (cast(_Unwind_Exception_Class)'G' << 56) |
+        (cast(_Unwind_Exception_Class)'N' << 48) |
+        (cast(_Unwind_Exception_Class)'U' << 40) |
+        (cast(_Unwind_Exception_Class)'C' << 32) |
+        (cast(_Unwind_Exception_Class)'C' << 24) |
+        (cast(_Unwind_Exception_Class)'+' << 16) |
+        (cast(_Unwind_Exception_Class)'+' <<  8) |
+        (cast(_Unwind_Exception_Class)0 <<  0);
+
+    enum _Unwind_Exception_Class gxxDependentExceptionClass =
+        gxxExceptionClass + 1;
+}
+
+/**
+ * Checks for GDC exception class.
+ */
+bool isGdcExceptionClass(_Unwind_Exception_Class c) @nogc
+{
+    static if (GNU_ARM_EABI_Unwinder)
+    {
+        return c[0] == gdcExceptionClass[0]
+            && c[1] == gdcExceptionClass[1]
+            && c[2] == gdcExceptionClass[2]
+            && c[3] == gdcExceptionClass[3]
+            && c[4] == gdcExceptionClass[4]
+            && c[5] == gdcExceptionClass[5]
+            && c[6] == gdcExceptionClass[6]
+            && c[7] == gdcExceptionClass[7];
+    }
+    else
+    {
+        return c == gdcExceptionClass;
+    }
+}
+
+/**
+ * Checks for any C++ exception class.
+ */
+bool isGxxExceptionClass(_Unwind_Exception_Class c) @nogc
+{
+    static if (GNU_ARM_EABI_Unwinder)
+    {
+        return c[0] == gxxExceptionClass[0]
+            && c[1] == gxxExceptionClass[1]
+            && c[2] == gxxExceptionClass[2]
+            && c[3] == gxxExceptionClass[3]
+            && c[4] == gxxExceptionClass[4]
+            && c[5] == gxxExceptionClass[5]
+            && c[6] == gxxExceptionClass[6]
+            && (c[7] == gxxExceptionClass[7]
+                || c[7] == gxxDependentExceptionClass[7]);
+    }
+    else
+    {
+        return c == gxxExceptionClass
+            || c == gxxDependentExceptionClass;
+    }
+}
+
+/**
+ * Checks for primary or dependent, but not that it is a C++ exception.
+ */
+bool isDependentException(_Unwind_Exception_Class c) @nogc
+{
+    static if (GNU_ARM_EABI_Unwinder)
+        return (c[7] == '\x01');
+    else
+        return (c & 1);
+}
+
+/**
+ * A D exception object consists of a header, which is a wrapper
+ * around an unwind object header with additional D specific
+ * information, prefixed by the exception object itself.
+ */
+struct ExceptionHeader
+{
+    // Because of a lack of __aligned__ style attribute, our object
+    // and the unwind object are the first two fields.
+    static if (Throwable.alignof < _Unwind_Exception.alignof)
+        ubyte[_Unwind_Exception.alignof - Throwable.alignof] pad;
+
+    // The object being thrown.  The compiled code expects this to
+    // be immediately before the generic exception header.
+    Throwable object;
+
+    // The generic exception header.
+    _Unwind_Exception unwindHeader;
+
+    static assert(unwindHeader.offsetof - object.offsetof == object.sizeof);
+
+    // Cache handler details between Phase 1 and Phase 2.
+    static if (GNU_ARM_EABI_Unwinder)
+    {
+        // Nothing here yet.
+    }
+    else
+    {
+        // Which catch was found.
+        int handler;
+
+        // Language Specific Data Area for function enclosing the handler.
+        const(ubyte)* languageSpecificData;
+
+        // Pointer to catch code.
+        _Unwind_Ptr landingPad;
+    }
+
+    // Stack other thrown exceptions in current thread through here.
+    ExceptionHeader* next;
+
+    // Thread local stack of chained exceptions.
+    static ExceptionHeader* stack;
+
+    // Pre-allocate storage for 1 instance per thread.
+    // Use calloc/free for multiple exceptions in flight.
+    static ExceptionHeader ehstorage;
+
+    /**
+     * Allocate and initialize an ExceptionHeader.
+     */
+    static ExceptionHeader* create(Throwable o) @nogc
+    {
+        auto eh = &ehstorage;
+
+        // Check exception object in use.
+        if (eh.object)
+        {
+            eh = cast(ExceptionHeader*) __builtin_calloc(ExceptionHeader.sizeof, 1);
+            // Out of memory while throwing - not much else can be done.
+            if (!eh)
+                terminate(__LINE__);
+        }
+        eh.object = o;
+
+        eh.unwindHeader.exception_class = gdcExceptionClass;
+
+        return eh;
+    }
+
+    /**
+     * Free ExceptionHeader that was created by create().
+     */
+    static void free(ExceptionHeader* eh) @nogc
+    {
+        *eh = ExceptionHeader.init;
+        if (eh != &ehstorage)
+            __builtin_free(eh);
+    }
+
+    /**
+     * Push this onto stack of chained exceptions.
+     */
+    void push() @nogc
+    {
+        next = stack;
+        stack = &this;
+    }
+
+    /**
+     * Pop and return top of chained exception stack.
+     */
+    static ExceptionHeader* pop() @nogc
+    {
+        auto eh = stack;
+        stack = eh.next;
+        return eh;
+    }
+
+    /**
+     * Save stage1 handler information in the exception object.
+     */
+    static void save(_Unwind_Exception* unwindHeader,
+                     _Unwind_Context* context, int handler,
+                     const(ubyte)* lsda, _Unwind_Ptr landingPad) @nogc
+    {
+        static if (GNU_ARM_EABI_Unwinder)
+        {
+            unwindHeader.barrier_cache.sp = _Unwind_GetGR(context, UNWIND_STACK_REG);
+            unwindHeader.barrier_cache.bitpattern[1] = cast(_uw)handler;
+            unwindHeader.barrier_cache.bitpattern[2] = cast(_uw)lsda;
+            unwindHeader.barrier_cache.bitpattern[3] = cast(_uw)landingPad;
+        }
+        else
+        {
+            ExceptionHeader* eh = toExceptionHeader(unwindHeader);
+            eh.handler = handler;
+            eh.languageSpecificData = lsda;
+            eh.landingPad = landingPad;
+        }
+    }
+
+    /**
+     * Restore the catch handler data saved during phase1.
+     */
+    static void restore(_Unwind_Exception* unwindHeader, out int handler,
+                        out const(ubyte)* lsda, out _Unwind_Ptr landingPad) @nogc
+    {
+        static if (GNU_ARM_EABI_Unwinder)
+        {
+            handler = cast(int)unwindHeader.barrier_cache.bitpattern[1];
+            lsda = cast(ubyte*)unwindHeader.barrier_cache.bitpattern[2];
+            landingPad = cast(_Unwind_Ptr)unwindHeader.barrier_cache.bitpattern[3];
+        }
+        else
+        {
+            ExceptionHeader* eh = toExceptionHeader(unwindHeader);
+            handler = eh.handler;
+            lsda = eh.languageSpecificData;
+            landingPad = cast(_Unwind_Ptr)eh.landingPad;
+        }
+    }
+
+    /**
+     * Look at the chain of inflight exceptions and pick the class type that'll
+     * be looked for in catch clauses.
+     */
+    static getClassInfo(_Unwind_Exception* unwindHeader) @nogc
+    {
+        ExceptionHeader* eh = toExceptionHeader(unwindHeader);
+        // The first thrown Exception at the top of the stack takes precedence
+        // over others that are inflight, unless an Error was thrown, in which
+        // case, we search for error handlers instead.
+        Throwable ehobject = eh.object;
+        for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
+        {
+            Error e = cast(Error)ehobject;
+            if (e is null || (cast(Error)ehn.object) !is null)
+                ehobject = ehn.object;
+        }
+        return ehobject.classinfo;
+    }
+
+    /**
+     * Convert from pointer to unwindHeader to pointer to ExceptionHeader
+     * that it is embedded inside of.
+     */
+    static ExceptionHeader* toExceptionHeader(_Unwind_Exception* exc) @nogc
+    {
+        return cast(ExceptionHeader*)(cast(void*)exc - ExceptionHeader.unwindHeader.offsetof);
+    }
+}
+
+/**
+ * Map to C++ std::type_info's virtual functions from D,
+ * being careful to not require linking with libstdc++.
+ * So it is given a different name.
+ */
+extern(C++) interface CxxTypeInfo
+{
+    void dtor1();
+    void dtor2();
+    bool __is_pointer_p() const;
+    bool __is_function_p() const;
+    bool __do_catch(const CxxTypeInfo, void**, uint) const;
+    bool __do_upcast(const void*, void**) const;
+}
+
+/**
+ * Structure of a C++ exception, represented as a C structure.
+ * See unwind-cxx.h for the full definition.
+ */
+struct CxaExceptionHeader
+{
+    union
+    {
+        CxxTypeInfo exceptionType;
+        void* primaryException;
+    }
+    void function(void*) exceptionDestructor;
+    void function() unexpectedHandler;
+    void function() terminateHandler;
+    CxaExceptionHeader* nextException;
+    int handlerCount;
+
+    static if (GNU_ARM_EABI_Unwinder)
+    {
+        CxaExceptionHeader* nextPropagatingException;
+        int propagationCount;
+    }
+    else
+    {
+        int handlerSwitchValue;
+        const(ubyte)* actionRecord;
+        const(ubyte)* languageSpecificData;
+        _Unwind_Ptr catchTemp;
+        void* adjustedPtr;
+    }
+
+    _Unwind_Exception unwindHeader;
+
+    /**
+     * There's no saving between phases, so only cache pointer.
+     * __cxa_begin_catch expects this to be set.
+     */
+    static void save(_Unwind_Exception* unwindHeader, void* thrownPtr) @nogc
+    {
+        static if (GNU_ARM_EABI_Unwinder)
+            unwindHeader.barrier_cache.bitpattern[0] = cast(_uw) thrownPtr;
+        else
+        {
+            auto eh = toExceptionHeader(unwindHeader);
+            eh.adjustedPtr = thrownPtr;
+        }
+    }
+
+    /**
+     * Get pointer to the thrown object if the thrown object type behind the
+     * exception is implicitly convertible to the catch type.
+     */
+    static void* getAdjustedPtr(_Unwind_Exception* exc, CxxTypeInfo catchType)
+    {
+        void* thrownPtr;
+
+        // A dependent C++ exceptions is just a wrapper around the unwind header.
+        // A primary C++ exception has the thrown object located immediately after it.
+        if (isDependentException(exc.exception_class))
+            thrownPtr = toExceptionHeader(exc).primaryException;
+        else
+            thrownPtr = cast(void*)(exc + 1);
+
+        // Pointer types need to adjust the actual pointer, not the pointer that is
+        // the exception object.  This also has the effect of passing pointer types
+        // "by value" through the __cxa_begin_catch return value.
+        const throw_type = (cast(CxaExceptionHeader*)thrownPtr - 1).exceptionType;
+
+        if (throw_type.__is_pointer_p())
+            thrownPtr = *cast(void**)thrownPtr;
+
+        // Pointer adjustment may be necessary due to multiple inheritance
+        if (catchType is throw_type
+            || catchType.__do_catch(throw_type, &thrownPtr, 1))
+            return thrownPtr;
+
+        return null;
+    }
+
+    /**
+     * Convert from pointer to unwindHeader to pointer to CxaExceptionHeader
+     * that it is embedded inside of.
+     */
+    static CxaExceptionHeader* toExceptionHeader(_Unwind_Exception* exc) @nogc
+    {
+        return cast(CxaExceptionHeader*)(exc + 1) - 1;
+    }
+}
+
+/**
+ * Replaces std::terminate and terminating with a specific handler
+ */
+private void terminate(uint line) @nogc
+{
+    __builtin_printf("deh(%u) fatal error\n", line);
+    __builtin_trap();
+}
+
+/**
+ * Called when fibers switch contexts.
+ */
+extern(C) void* _d_eh_swapContext(void* newContext) nothrow
+{
+    auto old = ExceptionHeader.stack;
+    ExceptionHeader.stack = cast(ExceptionHeader*)newContext;
+    return old;
+}
+
+/**
+ * Called before starting a catch.  Returns the exception object.
+ */
+extern(C) void* __gdc_begin_catch(_Unwind_Exception* unwindHeader)
+{
+    ExceptionHeader* header = ExceptionHeader.toExceptionHeader(unwindHeader);
+
+    void* objectp = cast(void*)header.object;
+
+    // Something went wrong when stacking up chained headers...
+    if (header != ExceptionHeader.pop())
+        terminate(__LINE__);
+
+    // Handling for this exception is complete.
+    _Unwind_DeleteException(&header.unwindHeader);
+
+    return objectp;
+}
+
+/**
+ * Perform a throw, D style. Throw will unwind through this call,
+ * so there better not be any handlers or exception thrown here.
+ */
+extern(C) void _d_throw(Throwable object)
+{
+    // If possible, avoid always allocating new memory for exception headers.
+    ExceptionHeader *eh = ExceptionHeader.create(object);
+
+    // Add to thrown exception stack.
+    eh.push();
+
+    // Called by unwinder when exception object needs destruction by other than our code.
+    extern(C) void exception_cleanup(_Unwind_Reason_Code code, _Unwind_Exception* exc)
+    {
+        // If we haven't been caught by a foreign handler, then this is
+        // some sort of unwind error.  In that case just die immediately.
+        // _Unwind_DeleteException in the HP-UX IA64 libunwind library
+        //  returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
+        // like the GCC _Unwind_DeleteException function does.
+        if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
+            terminate(__LINE__);
+
+        auto eh = ExceptionHeader.toExceptionHeader(exc);
+        ExceptionHeader.free(eh);
+    }
+
+    eh.unwindHeader.exception_cleanup = &exception_cleanup;
+
+    // Runtime now expects us to do this first before unwinding.
+    _d_createTrace(eh.object, null);
+
+    // We're happy with setjmp/longjmp exceptions or region-based
+    // exception handlers: entry points are provided here for both.
+    _Unwind_Reason_Code r = void;
+
+    version (GNU_SjLj_Exceptions)
+        r = _Unwind_SjLj_RaiseException(&eh.unwindHeader);
+    else
+        r = _Unwind_RaiseException(&eh.unwindHeader);
+
+    // If code == _URC_END_OF_STACK, then we reached top of stack without finding
+    // a handler for the exception.  Since each thread is run in a try/catch,
+    // this oughtn't happen.  If code is something else, we encountered some sort
+    // of heinous lossage from which we could not recover.  As is the way of such
+    // things, almost certainly we will have crashed before now, rather than
+    // actually being able to diagnose the problem.
+    if (r == _URC_END_OF_STACK)
+        __builtin_printf("uncaught exception\n");
+
+    terminate(__LINE__);
+}
+
+
+/**
+ * Read and extract information from the LSDA (.gcc_except_table section).
+ */
+_Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class exceptionClass,
+                             _Unwind_Action actions, _Unwind_Exception* unwindHeader,
+                             _Unwind_Context* context,
+                             out _Unwind_Ptr landingPad, out int handler)
+{
+    // If no LSDA, then there are no handlers or cleanups.
+    if (lsda is null)
+        return CONTINUE_UNWINDING(unwindHeader, context);
+
+    // Parse the LSDA header
+    auto p = lsda;
+
+    auto Start = (context ? _Unwind_GetRegionStart(context) : 0);
+
+    // Find @LPStart, the base to which landing pad offsets are relative.
+    ubyte LPStartEncoding = *p++;
+    _Unwind_Ptr LPStart = 0;
+
+    if (LPStartEncoding != DW_EH_PE_omit)
+        LPStart = read_encoded_value(context, LPStartEncoding, &p);
+    else
+        LPStart = Start;
+
+    // Find @TType, the base of the handler and exception spec type data.
+    ubyte TTypeEncoding = *p++;
+    const(ubyte)* TType = null;
+
+    if (TTypeEncoding != DW_EH_PE_omit)
+    {
+        static if (__traits(compiles, _TTYPE_ENCODING))
+        {
+            // Older ARM EABI toolchains set this value incorrectly, so use a
+            // hardcoded OS-specific format.
+            TTypeEncoding = _TTYPE_ENCODING;
+        }
+        auto TTbase = read_uleb128(&p);
+        TType = p + TTbase;
+    }
+
+    // The encoding and length of the call-site table; the action table
+    // immediately follows.
+    ubyte CSEncoding = *p++;
+    auto CSTableSize = read_uleb128(&p);
+    const(ubyte)* actionTable = p + CSTableSize;
+
+    auto TTypeBase = base_of_encoded_value(TTypeEncoding, context);
+
+    // Get instruction pointer (ip) at start of instruction that threw.
+    version (CRuntime_Glibc)
+    {
+        int ip_before_insn;
+        auto ip = _Unwind_GetIPInfo(context, &ip_before_insn);
+        if (!ip_before_insn)
+            --ip;
+    }
+    else
+    {
+        auto ip = _Unwind_GetIP(context);
+        --ip;
+    }
+
+    bool saw_cleanup = false;
+    bool saw_handler = false;
+    const(ubyte)* actionRecord = null;
+
+    version (GNU_SjLj_Exceptions)
+    {
+        // The given "IP" is an index into the call-site table, with two
+        // exceptions -- -1 means no-action, and 0 means terminate.
+        // But since we're using uleb128 values, we've not got random
+        // access to the array.
+        if (cast(int) ip <= 0)
+        {
+            return _URC_CONTINUE_UNWIND;
+        }
+        else
+        {
+            _uleb128_t CSLandingPad, CSAction;
+            do
+            {
+                CSLandingPad = read_uleb128(&p);
+                CSAction = read_uleb128(&p);
+            }
+            while (--ip);
+
+            // Can never have null landing pad for sjlj -- that would have
+            // been indicated by a -1 call site index.
+            landingPad = CSLandingPad + 1;
+            if (CSAction)
+                actionRecord = actionTable + CSAction - 1;
+        }
+    }
+    else
+    {
+        // Search the call-site table for the action associated with this IP.
+        while (p < actionTable)
+        {
+            // Note that all call-site encodings are "absolute" displacements.
+            auto CSStart = read_encoded_value(null, CSEncoding, &p);
+            auto CSLen = read_encoded_value(null, CSEncoding, &p);
+            auto CSLandingPad = read_encoded_value(null, CSEncoding, &p);
+            auto CSAction = read_uleb128(&p);
+
+            // The table is sorted, so if we've passed the ip, stop.
+            if (ip < Start + CSStart)
+                p = actionTable;
+            else if (ip < Start + CSStart + CSLen)
+            {
+                if (CSLandingPad)
+                    landingPad = LPStart + CSLandingPad;
+                if (CSAction)
+                    actionRecord = actionTable + CSAction - 1;
+                break;
+            }
+        }
+    }
+
+    if (landingPad == 0)
+    {
+        // IP is present, but has a null landing pad.
+        // No cleanups or handlers to be run.
+    }
+    else if (actionRecord is null)
+    {
+        // If ip is present, has a non-null landing pad, and a null
+        // action table offset, then there are only cleanups present.
+        // Cleanups use a zero switch value, as set above.
+        saw_cleanup = true;
+    }
+    else
+    {
+        // Otherwise we have a catch handler or exception specification.
+        handler = actionTableLookup(actions, unwindHeader, actionRecord,
+                                    exceptionClass, TTypeBase,
+                                    TType, TTypeEncoding,
+                                    saw_handler, saw_cleanup);
+    }
+
+    // IP is not in table.  No associated cleanups.
+    if (!saw_handler && !saw_cleanup)
+        return CONTINUE_UNWINDING(unwindHeader, context);
+
+    if (actions & _UA_SEARCH_PHASE)
+    {
+        if (!saw_handler)
+            return CONTINUE_UNWINDING(unwindHeader, context);
+
+        // For domestic exceptions, we cache data from phase 1 for phase 2.
+        if (isGdcExceptionClass(exceptionClass))
+            ExceptionHeader.save(unwindHeader, context, handler, lsda, landingPad);
+
+        return _URC_HANDLER_FOUND;
+    }
+
+    return 0;
+}
+
+/**
+ * Look up and return the handler index of the classType in Action Table.
+ */
+int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
+                      const(ubyte)* actionRecord, _Unwind_Exception_Class exceptionClass,
+                      _Unwind_Ptr TTypeBase, const(ubyte)* TType,
+                      ubyte TTypeEncoding,
+                      out bool saw_handler, out bool saw_cleanup)
+{
+    ClassInfo thrownType;
+    if (isGdcExceptionClass(exceptionClass))
+    {
+        thrownType = ExceptionHeader.getClassInfo(unwindHeader);
+    }
+
+    while (1)
+    {
+        auto ap = actionRecord;
+        auto ARFilter = read_sleb128(&ap);
+        auto apn = ap;
+        auto ARDisp = read_sleb128(&ap);
+
+        if (ARFilter == 0)
+        {
+            // Zero filter values are cleanups.
+            saw_cleanup = true;
+        }
+        else if (actions & _UA_FORCE_UNWIND)
+        {
+            // During forced unwinding, we only run cleanups.
+        }
+        else if (ARFilter > 0)
+        {
+            // Positive filter values are handlers.
+            auto encodedSize = size_of_encoded_value(TTypeEncoding);
+
+            // ARFilter is the negative index from TType, which is where
+            // the ClassInfo is stored.
+            const(ubyte)* tp = TType - ARFilter * encodedSize;
+
+            auto entry = read_encoded_value_with_base(TTypeEncoding, TTypeBase, &tp);
+            ClassInfo ci = cast(ClassInfo)cast(void*)(entry);
+
+            // D does not have catch-all handlers, and so the following
+            // assumes that we will never handle a null value.
+            assert(ci !is null);
+
+            if (ci.classinfo is __cpp_type_info_ptr.classinfo
+                && isGxxExceptionClass(exceptionClass))
+            {
+                // catchType is the catch clause type_info.
+                auto catchType = cast(CxxTypeInfo)((cast(__cpp_type_info_ptr)cast(void*)ci).ptr);
+                auto thrownPtr = CxaExceptionHeader.getAdjustedPtr(unwindHeader, catchType);
+
+                if (thrownPtr !is null)
+                {
+                    if (actions & _UA_SEARCH_PHASE)
+                        CxaExceptionHeader.save(unwindHeader, thrownPtr);
+                    saw_handler = true;
+                    return cast(int)ARFilter;
+                }
+            }
+            else if (isGdcExceptionClass(exceptionClass)
+                     && _d_isbaseof(thrownType, ci))
+            {
+                saw_handler = true;
+                return cast(int)ARFilter;
+            }
+            else
+            {
+                // ??? What to do about other GNU language exceptions.
+            }
+        }
+        else
+        {
+            // Negative filter values are exception specifications,
+            // which D does not use.
+            break;
+        }
+
+        if (ARDisp == 0)
+            break;
+        actionRecord = apn + ARDisp;
+    }
+
+    return 0;
+}
+
+/**
+ * Called when the personality function has found neither a cleanup or handler.
+ * To support ARM EABI personality routines, that must also unwind the stack.
+ */
+_Unwind_Reason_Code CONTINUE_UNWINDING(_Unwind_Exception* unwindHeader, _Unwind_Context* context)
+{
+    static if (GNU_ARM_EABI_Unwinder)
+    {
+        if (__gnu_unwind_frame(unwindHeader, context) != _URC_OK)
+            return _URC_FAILURE;
+    }
+    return _URC_CONTINUE_UNWIND;
+}
+
+/**
+ * Using a different personality function name causes link failures
+ * when trying to mix code using different exception handling models.
+ */
+version (GNU_SEH_Exceptions)
+{
+    enum PERSONALITY_FUNCTION = "__gdc_personality_imp";
+
+    extern(C) EXCEPTION_DISPOSITION __gdc_personality_seh0(void* ms_exc, void* this_frame,
+                                                           void* ms_orig_context, void* ms_disp)
+    {
+        return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context,
+                                     ms_disp, &__gdc_personality_imp);
+    }
+}
+else version (GNU_SjLj_Exceptions)
+{
+    enum PERSONALITY_FUNCTION = "__gdc_personality_sj0";
+
+    private int __builtin_eh_return_data_regno(int x) { return x; }
+}
+else
+{
+    enum PERSONALITY_FUNCTION = "__gdc_personality_v0";
+}
+
+/**
+ * The "personality" function, specific to each language.
+ */
+static if (GNU_ARM_EABI_Unwinder)
+{
+    pragma(mangle, PERSONALITY_FUNCTION)
+    extern(C) _Unwind_Reason_Code gdc_personality(_Unwind_State state,
+                                                  _Unwind_Exception* unwindHeader,
+                                                  _Unwind_Context* context)
+    {
+        _Unwind_Action actions;
+
+        switch (state & _US_ACTION_MASK)
+        {
+            case _US_VIRTUAL_UNWIND_FRAME:
+                // If the unwind state pattern is (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND)
+                // then we don't need to search for any handler as it is not a real exception.
+                // Just unwind the stack.
+                if (state & _US_FORCE_UNWIND)
+                    return CONTINUE_UNWINDING(unwindHeader, context);
+                actions = _UA_SEARCH_PHASE;
+                break;
+
+            case _US_UNWIND_FRAME_STARTING:
+                actions = _UA_CLEANUP_PHASE;
+                if (!(state & _US_FORCE_UNWIND)
+                    && unwindHeader.barrier_cache.sp == _Unwind_GetGR(context, UNWIND_STACK_REG))
+                    actions |= _UA_HANDLER_FRAME;
+                break;
+
+            case _US_UNWIND_FRAME_RESUME:
+                return CONTINUE_UNWINDING(unwindHeader, context);
+
+            default:
+                __builtin_abort();
+        }
+        actions |= state & _US_FORCE_UNWIND;
+
+        // The dwarf unwinder assumes the context structure holds things like
+        // the function and LSDA pointers.  The ARM implementation caches these
+        // in the exception header (UCB).  To avoid rewriting everything we make
+        // the virtual IP register point at the UCB.
+        _Unwind_SetGR(context, UNWIND_POINTER_REG, cast(_Unwind_Ptr)unwindHeader);
+
+        return __gdc_personality(actions, unwindHeader.exception_class,
+                                 unwindHeader, context);
+    }
+}
+else
+{
+    pragma(mangle, PERSONALITY_FUNCTION)
+    extern(C) _Unwind_Reason_Code gdc_personality(int iversion,
+                                                  _Unwind_Action actions,
+                                                  _Unwind_Exception_Class exceptionClass,
+                                                  _Unwind_Exception* unwindHeader,
+                                                  _Unwind_Context* context)
+    {
+        // Interface version check.
+        if (iversion != 1)
+            return _URC_FATAL_PHASE1_ERROR;
+
+        return __gdc_personality(actions, exceptionClass, unwindHeader, context);
+    }
+}
+
+private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
+                                              _Unwind_Exception_Class exceptionClass,
+                                              _Unwind_Exception* unwindHeader,
+                                              _Unwind_Context* context)
+{
+    const(ubyte)* lsda;
+    _Unwind_Ptr landingPad;
+    int handler;
+
+    // Shortcut for phase 2 found handler for domestic exception.
+    if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
+        && isGdcExceptionClass(exceptionClass))
+    {
+        ExceptionHeader.restore(unwindHeader, handler, lsda, landingPad);
+        // Shouldn't have cached a null landing pad in phase 1.
+        if (landingPad == 0)
+            terminate(__LINE__);
+    }
+    else
+    {
+        lsda = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
+
+        auto result = scanLSDA(lsda, exceptionClass, actions, unwindHeader,
+                               context, landingPad, handler);
+
+        // Positive on handler found in phase 1, continue unwinding, or failure.
+        if (result)
+            return result;
+    }
+
+    // Unexpected negative handler, call terminate directly.
+    if (handler < 0)
+        terminate(__LINE__);
+
+    // We can't use any of the deh routines with foreign exceptions,
+    // because they all expect unwindHeader to be an ExceptionHeader.
+    if (isGdcExceptionClass(exceptionClass))
+    {
+        // If there are any in-flight exceptions being thrown, chain our
+        // current object onto the end of the prevous object.
+        ExceptionHeader* eh = ExceptionHeader.toExceptionHeader(unwindHeader);
+        auto currentLsd = lsda;
+        bool bypassed = false;
+
+        while (eh.next)
+        {
+            ExceptionHeader* ehn = eh.next;
+            const(ubyte)* nextLsd;
+            _Unwind_Ptr nextLandingPad;
+            int nextHandler;
+
+            ExceptionHeader.restore(&ehn.unwindHeader, nextHandler, nextLsd, nextLandingPad);
+
+            Error e = cast(Error)eh.object;
+            if (e !is null && !cast(Error)ehn.object)
+            {
+                // We found an Error, bypass the exception chain.
+                currentLsd = nextLsd;
+                eh = ehn;
+                bypassed = true;
+                continue;
+            }
+
+            // Don't combine when the exceptions are from different functions.
+            if (currentLsd != nextLsd)
+                break;
+
+            // Add our object onto the end of the existing chain.
+            Throwable n = ehn.object;
+            while (n.next)
+                n = n.next;
+            n.next = eh.object;
+
+            // Replace our exception object with in-flight one
+            eh.object = ehn.object;
+            if (nextHandler != handler && !bypassed)
+            {
+                handler = nextHandler;
+                ExceptionHeader.save(unwindHeader, context, handler,
+                                     lsda, landingPad);
+            }
+
+            // Exceptions chained, can now throw away the previous header.
+            eh.next = ehn.next;
+            _Unwind_DeleteException(&ehn.unwindHeader);
+        }
+
+        if (bypassed)
+        {
+            eh = ExceptionHeader.toExceptionHeader(unwindHeader);
+            Error e = cast(Error)eh.object;
+            auto ehn = eh.next;
+            e.bypassedException = ehn.object;
+            eh.next = ehn.next;
+            _Unwind_DeleteException(&ehn.unwindHeader);
+        }
+    }
+
+    // Set up registers and jump to cleanup or handler.
+    // For targets with pointers smaller than the word size, we must extend the
+    // pointer, and this extension is target dependent.
+    _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
+                  cast(_Unwind_Ptr)unwindHeader);
+    _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), handler);
+    _Unwind_SetIP(context, landingPad);
+
+    return _URC_INSTALL_CONTEXT;
+}
diff --git a/libphobos/libdruntime/gcc/libbacktrace.d.in b/libphobos/libdruntime/gcc/libbacktrace.d.in
new file mode 100644
index 00000000000..5bb01374731
--- /dev/null
+++ b/libphobos/libdruntime/gcc/libbacktrace.d.in
@@ -0,0 +1,91 @@ 
+// GNU D Compiler bindings for the stack backtrace functions.
+// Copyright (C) 2013-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.libbacktrace;
+
+/*
+ * This is not part of libbacktrace, it's used for the temporary gdc fallback
+ * implementation. To avoid adding another autoconf module it's defined here
+ */
+
+enum HAVE_DLADDR = @HAVE_DLADDR@;
+static if (HAVE_DLADDR)
+{
+    extern(C):
+        int dladdr(void *addr, Dl_info *info);
+        struct Dl_info
+        {
+            const (char*) dli_fname;
+            void*         dli_fbase;
+            const (char*) dli_sname;
+            void*         dli_saddr;
+        }
+}
+
+/*
+ * Part of backtrace-supported.h: These are platform specific variables.
+ * They are obtained via the configure script
+ */
+
+enum BACKTRACE_SUPPORTED = @BACKTRACE_SUPPORTED@;
+enum BACKTRACE_USES_MALLOC = @BACKTRACE_USES_MALLOC@;
+enum BACKTRACE_SUPPORTS_THREADS = @BACKTRACE_SUPPORTS_THREADS@;
+
+/*
+ * libbacktrace.h
+ */
+
+static if(BACKTRACE_SUPPORTED)
+{
+    import core.stdc.stddef, core.stdc.stdio, core.stdc.stdint;
+
+    extern(C):
+        struct backtrace_state {}
+
+        alias extern(C) void function(void* data,
+            const(char)* msg, int errnum) backtrace_error_callback;
+
+        backtrace_state* backtrace_create_state( const(char)* filename, int threaded,
+            backtrace_error_callback error_callback, void* data) nothrow;
+
+        alias extern(C) int function(void* data, uintptr_t pc,
+            const(char)* filename, int lineno, const(char)* func) backtrace_full_callback;
+
+        int backtrace_full(backtrace_state* state, int skip, backtrace_full_callback callback,
+            backtrace_error_callback error_callback, void* data) nothrow;
+
+        alias extern(C) int function(void* data, uintptr_t pc) backtrace_simple_callback;
+
+        int backtrace_simple(backtrace_state* state, int skip, backtrace_simple_callback callback,
+            backtrace_error_callback error_callback, void* data) nothrow;
+
+        void backtrace_print(backtrace_state* state, int skip, FILE* file) nothrow;
+
+        int backtrace_pcinfo(backtrace_state* state, uintptr_t pc, backtrace_full_callback callback,
+            backtrace_error_callback error_callback,    void* data) nothrow;
+
+        alias extern(C) void function(void* data, uintptr_t pc,
+            const(char)* symname, uintptr_t symval) backtrace_syminfo_callback;
+
+        int backtrace_syminfo(backtrace_state *state, uintptr_t pc, backtrace_syminfo_callback callback,
+            backtrace_error_callback error_callback, void* data) nothrow;
+}
diff --git a/libphobos/libdruntime/gcc/unwind/arm.d b/libphobos/libdruntime/gcc/unwind/arm.d
new file mode 100644
index 00000000000..34b845a5cbc
--- /dev/null
+++ b/libphobos/libdruntime/gcc/unwind/arm.d
@@ -0,0 +1,71 @@ 
+// Exception handling and frame unwind runtime interface routines.
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// extern(C) interface for the ARM EABI unwinder library.
+// This corresponds to unwind-arm.h
+
+module gcc.unwind.arm;
+
+import gcc.config;
+
+version(ARM):
+static if (GNU_ARM_EABI_Unwinder):
+
+public import gcc.unwind.arm_common;
+import gcc.unwind.pe;
+
+extern (C):
+@nogc:
+
+enum int UNWIND_STACK_REG = 13;
+// Use IP as a scratch register within the personality routine.
+enum int UNWIND_POINTER_REG = 12;
+
+version (linux)
+    enum _TTYPE_ENCODING = (DW_EH_PE_pcrel | DW_EH_PE_indirect);
+else version (NetBSD)
+    enum _TTYPE_ENCODING = (DW_EH_PE_pcrel | DW_EH_PE_indirect);
+else version (FreeBSD)
+    enum _TTYPE_ENCODING = (DW_EH_PE_pcrel | DW_EH_PE_indirect);
+else version (Symbian)
+    enum _TTYPE_ENCODING = (DW_EH_PE_absptr);
+else version (uClinux)
+    enum _TTYPE_ENCODING = (DW_EH_PE_absptr);
+else
+    enum _TTYPE_ENCODING = (DW_EH_PE_pcrel);
+
+// Return the address of the instruction, not the actual IP value.
+_Unwind_Word _Unwind_GetIP(_Unwind_Context* context)
+{
+    return _Unwind_GetGR(context, 15) & ~ cast(_Unwind_Word) 1;
+}
+
+void _Unwind_SetIP(_Unwind_Context* context, _Unwind_Word val)
+{
+    return _Unwind_SetGR(context, 15, val | (_Unwind_GetGR(context, 15) & 1));
+}
+
+_Unwind_Word _Unwind_GetIPInfo(_Unwind_Context* context, int* ip_before_insn)
+{
+    *ip_before_insn = 0;
+    return _Unwind_GetIP(context);
+}
diff --git a/libphobos/libdruntime/gcc/unwind/arm_common.d b/libphobos/libdruntime/gcc/unwind/arm_common.d
new file mode 100644
index 00000000000..9adc0f33f27
--- /dev/null
+++ b/libphobos/libdruntime/gcc/unwind/arm_common.d
@@ -0,0 +1,244 @@ 
+// Exception handling and frame unwind runtime interface routines.
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// extern(C) interface for the ARM EABI and C6X unwinders.
+// This corresponds to unwind-arm-common.h
+
+module gcc.unwind.arm_common;
+
+import gcc.config;
+
+static if (GNU_ARM_EABI_Unwinder):
+
+import gcc.builtins;
+
+extern (C):
+
+// Placed outside @nogc in order to not constrain what the callback does.
+// ??? Does this really need to be extern(C) alias?
+extern(C) alias _Unwind_Exception_Cleanup_Fn
+    = void function(_Unwind_Reason_Code, _Unwind_Exception*);
+
+extern(C) alias personality_routine
+    = _Unwind_Reason_Code function(_Unwind_State,
+                                   _Unwind_Control_Block*,
+                                   _Unwind_Context*);
+
+extern(C) alias _Unwind_Stop_Fn
+    =_Unwind_Reason_Code function(int, _Unwind_Action,
+                                  _Unwind_Exception_Class,
+                                  _Unwind_Control_Block*,
+                                  _Unwind_Context*, void*);
+
+extern(C) alias _Unwind_Trace_Fn
+    = _Unwind_Reason_Code function(_Unwind_Context*, void*);
+
+@nogc:
+
+alias _Unwind_Word = __builtin_machine_uint;
+alias _Unwind_Sword = __builtin_machine_int;
+alias _Unwind_Ptr = __builtin_pointer_uint;
+alias _Unwind_Internal_Ptr =__builtin_pointer_uint;
+alias _uw = _Unwind_Word;
+alias _uw64 = ulong;
+alias _uw16 = ushort;
+alias _uw8 = ubyte;
+
+alias _Unwind_Reason_Code = uint;
+enum : _Unwind_Reason_Code
+{
+    _URC_OK = 0,        // operation completed successfully
+    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+    _URC_END_OF_STACK = 5,
+    _URC_HANDLER_FOUND = 6,
+    _URC_INSTALL_CONTEXT = 7,
+    _URC_CONTINUE_UNWIND = 8,
+    _URC_FAILURE = 9    // unspecified failure of some kind
+}
+
+alias _Unwind_State = int;
+enum : _Unwind_State
+{
+    _US_VIRTUAL_UNWIND_FRAME = 0,
+    _US_UNWIND_FRAME_STARTING = 1,
+    _US_UNWIND_FRAME_RESUME = 2,
+    _US_ACTION_MASK = 3,
+    _US_FORCE_UNWIND = 8,
+    _US_END_OF_STACK = 16
+}
+
+// Provided only for for compatibility with existing code.
+alias _Unwind_Action = int;
+enum : _Unwind_Action
+{
+    _UA_SEARCH_PHASE = 1,
+    _UA_CLEANUP_PHASE = 2,
+    _UA_HANDLER_FRAME = 4,
+    _UA_FORCE_UNWIND = 8,
+    _UA_END_OF_STACK = 16,
+    _URC_NO_REASON = _URC_OK
+}
+
+struct _Unwind_Context;
+alias _Unwind_EHT_Header = _uw;
+
+struct _Unwind_Control_Block
+{
+    _Unwind_Exception_Class exception_class = '\0';
+    _Unwind_Exception_Cleanup_Fn exception_cleanup;
+    // Unwinder cache, private fields for the unwinder's use
+    struct _unwinder_cache
+    {
+        _uw reserved1;  // Forced unwind stop fn, 0 if not forced
+        _uw reserved2;  // Personality routine address
+        _uw reserved3;  // Saved callsite address
+        _uw reserved4;  // Forced unwind stop arg
+        _uw reserved5;
+    }
+    _unwinder_cache unwinder_cache;
+    // Propagation barrier cache (valid after phase 1):
+    struct _barrier_cache
+    {
+        _uw sp;
+        _uw[5] bitpattern;
+    }
+    _barrier_cache barrier_cache;
+    // Cleanup cache (preserved over cleanup):
+    struct _cleanup_cache
+    {
+        _uw[4] bitpattern;
+    }
+    _cleanup_cache cleanup_cache;
+    // Pr cache (for pr's benefit):
+    struct _pr_cache
+    {
+        _uw fnstart;                // function start address */
+        _Unwind_EHT_Header* ehtp;   // pointer to EHT entry header word
+        _uw additional;             // additional data
+        _uw reserved1;
+    }
+    _pr_cache pr_cache;
+    long[0] _force_alignment;       // Force alignment to 8-byte boundary
+}
+
+// Virtual Register Set
+alias _Unwind_VRS_RegClass = int;
+enum : _Unwind_VRS_RegClass
+{
+    _UVRSC_CORE = 0,    // integer register
+    _UVRSC_VFP = 1,     // vfp
+    _UVRSC_FPA = 2,     // fpa
+    _UVRSC_WMMXD = 3,   // Intel WMMX data register
+    _UVRSC_WMMXC = 4    // Intel WMMX control register
+}
+
+alias _Unwind_VRS_DataRepresentation = int;
+enum : _Unwind_VRS_DataRepresentation
+{
+    _UVRSD_UINT32 = 0,
+    _UVRSD_VFPX = 1,
+    _UVRSD_FPAX = 2,
+    _UVRSD_UINT64 = 3,
+    _UVRSD_FLOAT = 4,
+    _UVRSD_DOUBLE = 5
+}
+
+alias _Unwind_VRS_Result = int;
+enum : _Unwind_VRS_Result
+{
+    _UVRSR_OK = 0,
+    _UVRSR_NOT_IMPLEMENTED = 1,
+    _UVRSR_FAILED = 2
+}
+
+// Frame unwinding state.
+struct __gnu_unwind_state
+{
+    _uw data;           // The current word (bytes packed msb first).
+    _uw* next;          // Pointer to the next word of data.
+    _uw8 bytes_left;    // The number of bytes left in this word.
+    _uw8 words_left;    // The number of words pointed to by ptr.
+}
+
+_Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context*, _Unwind_VRS_RegClass,
+                                   _uw, _Unwind_VRS_DataRepresentation,
+                                   void*);
+
+_Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context*, _Unwind_VRS_RegClass,
+                                   _uw, _Unwind_VRS_DataRepresentation,
+                                   void*);
+
+_Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context*, _Unwind_VRS_RegClass,
+                                   _uw, _Unwind_VRS_DataRepresentation);
+
+
+// Support functions for the PR.
+alias _Unwind_Exception = _Unwind_Control_Block;
+alias _Unwind_Exception_Class = char[8];
+
+void* _Unwind_GetLanguageSpecificData(_Unwind_Context*);
+_Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*);
+
+_Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*);
+// This should never be used.
+_Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*);
+
+// Interface functions:
+_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block*);
+void _Unwind_Resume(_Unwind_Control_Block*);
+_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Control_Block*);
+
+_Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Control_Block*,
+                                         _Unwind_Stop_Fn, void*);
+
+// @@@ Use unwind data to perform a stack backtrace.  The trace callback
+// is called for every stack frame in the call chain, but no cleanup
+// actions are performed.
+_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
+
+_Unwind_Word _Unwind_GetCFA(_Unwind_Context*);
+void _Unwind_Complete(_Unwind_Control_Block*);
+void _Unwind_DeleteException(_Unwind_Exception*);
+
+_Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Control_Block*,
+                                       _Unwind_Context*);
+_Unwind_Reason_Code __gnu_unwind_execute(_Unwind_Context*,
+                                         __gnu_unwind_state*);
+
+_Unwind_Word _Unwind_GetGR(_Unwind_Context* context, int regno)
+{
+    _uw val;
+    _Unwind_VRS_Get(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+    return val;
+}
+
+void _Unwind_SetGR(_Unwind_Context* context, int regno, _Unwind_Word val)
+{
+    _Unwind_VRS_Set(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+}
+
+// leb128 type numbers have a potentially unlimited size.
+// The target of the following definitions of _sleb128_t and _uleb128_t
+// is to have efficient data types large enough to hold the leb128 type
+// numbers used in the unwind code.
+alias _sleb128_t = __builtin_clong;
+alias _uleb128_t = __builtin_culong;
diff --git a/libphobos/libdruntime/gcc/unwind/c6x.d b/libphobos/libdruntime/gcc/unwind/c6x.d
new file mode 100644
index 00000000000..490bcb2f78c
--- /dev/null
+++ b/libphobos/libdruntime/gcc/unwind/c6x.d
@@ -0,0 +1,52 @@ 
+// Exception handling and frame unwind runtime interface routines.
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// extern(C) interface for the C6X EABI unwinder library.
+// This corresponds to unwind-c6x.h
+
+module gcc.unwind.c6x;
+
+import gcc.config;
+
+version (TIC6X):
+static if (GNU_ARM_EABI_Unwinder):
+
+// Not really the ARM EABI, but pretty close.
+public import gcc.unwind.arm_common;
+
+extern (C):
+@nogc:
+
+enum int UNWIND_STACK_REG = 31;
+// Use A0 as a scratch register within the personality routine.
+enum int UNWIND_POINTER_REG = 0;
+
+_Unwind_Word _Unwind_GetIP(_Unwind_Context* context)
+{
+    return _Unwind_GetGR(context, 33);
+}
+
+void _Unwind_SetIP(_Unwind_Context* context, _Unwind_Word val)
+{
+    return _Unwind_SetGR(context, 33, val);
+}
+
+_Unwind_Word _Unwind_GetIPInfo(_Unwind_Context* context, int* ip_before_insn)
+{
+    *ip_before_insn = 0;
+    return _Unwind_GetIP(context);
+}
diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d
new file mode 100644
index 00000000000..2d8549414bb
--- /dev/null
+++ b/libphobos/libdruntime/gcc/unwind/generic.d
@@ -0,0 +1,274 @@ 
+// Exception handling and frame unwind runtime interface routines.
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// extern(C) interface for the generic unwinder library.
+// This corresponds to unwind-generic.h
+
+module gcc.unwind.generic;
+
+import gcc.config;
+
+static if (!GNU_ARM_EABI_Unwinder):
+
+import gcc.builtins;
+
+// This is derived from the C++ ABI for IA-64.  Where we diverge
+// for cross-architecture compatibility are noted with "@@@".
+
+extern (C):
+
+// Placed outside @nogc in order to not constrain what the callback does.
+// ??? Does this really need to be extern(C) alias?
+
+extern(C) alias _Unwind_Exception_Cleanup_Fn
+    = void function(_Unwind_Reason_Code, _Unwind_Exception*);
+
+extern(C) alias _Unwind_Stop_Fn
+    = _Unwind_Reason_Code function(int, _Unwind_Action,
+                                   _Unwind_Exception_Class,
+                                   _Unwind_Exception*,
+                                   _Unwind_Context*, void*);
+
+extern(C) alias _Unwind_Trace_Fn
+    = _Unwind_Reason_Code function(_Unwind_Context*, void*);
+
+// The personality routine is the function in the C++ (or other language)
+// runtime library which serves as an interface between the system unwind
+// library and language-specific exception handling semantics.  It is
+// specific to the code fragment described by an unwind info block, and
+// it is always referenced via the pointer in the unwind info block, and
+// hence it has no ABI-specified name.
+
+// Note that this implies that two different C++ implementations can
+// use different names, and have different contents in the language
+// specific data area.  Moreover, that the language specific data
+// area contains no version info because name of the function invoked
+// provides more effective versioning by detecting at link time the
+// lack of code to handle the different data format.
+
+extern(C) alias _Unwind_Personality_Fn
+    = _Unwind_Reason_Code function(int, _Unwind_Action,
+                                   _Unwind_Exception_Class,
+                                   _Unwind_Exception*,
+                                   _Unwind_Context*);
+
+@nogc:
+
+// Level 1: Base ABI
+
+// @@@ The IA-64 ABI uses uint64 throughout.
+// Most places this is inefficient for 32-bit and smaller machines.
+alias _Unwind_Word = __builtin_unwind_uint;
+alias _Unwind_Sword = __builtin_unwind_int;
+version (IA64)
+{
+    version (HPUX)
+        alias _Unwind_Ptr = __builtin_machine_uint;
+    else
+        alias _Unwind_Ptr = __builtin_pointer_uint;
+}
+else
+{
+    alias _Unwind_Ptr = __builtin_pointer_uint;
+}
+alias _Unwind_Internal_Ptr = __builtin_pointer_uint;
+
+// @@@ The IA-64 ABI uses a 64-bit word to identify the producer and
+// consumer of an exception.  We'll go along with this for now even on
+// 32-bit machines.  We'll need to provide some other option for
+// 16-bit machines and for machines with > 8 bits per byte.
+alias _Unwind_Exception_Class = ulong;
+
+// The unwind interface uses reason codes in several contexts to
+// identify the reasons for failures or other actions.
+alias _Unwind_Reason_Code = uint;
+enum : _Unwind_Reason_Code
+{
+    _URC_NO_REASON = 0,
+    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+    _URC_FATAL_PHASE2_ERROR = 2,
+    _URC_FATAL_PHASE1_ERROR = 3,
+    _URC_NORMAL_STOP = 4,
+    _URC_END_OF_STACK = 5,
+    _URC_HANDLER_FOUND = 6,
+    _URC_INSTALL_CONTEXT = 7,
+    _URC_CONTINUE_UNWIND = 8
+}
+
+// The unwind interface uses a pointer to an exception header object
+// as its representation of an exception being thrown. In general, the
+// full representation of an exception object is language- and
+// implementation-specific, but it will be prefixed by a header
+// understood by the unwind interface.
+
+// @@@ The IA-64 ABI says that this structure must be double-word aligned.
+// Taking that literally does not make much sense generically.  Instead we
+// provide the maximum alignment required by any type for the machine.
+struct _Unwind_Exception
+{
+    _Unwind_Exception_Class exception_class;
+    _Unwind_Exception_Cleanup_Fn exception_cleanup;
+    _Unwind_Word private_1;
+    _Unwind_Word private_2;
+}
+
+// The ACTIONS argument to the personality routine is a bitwise OR of one
+// or more of the following constants.
+alias _Unwind_Action = int;
+enum : _Unwind_Action
+{
+    _UA_SEARCH_PHASE = 1,
+    _UA_CLEANUP_PHASE = 2,
+    _UA_HANDLER_FRAME = 4,
+    _UA_FORCE_UNWIND = 8,
+    _UA_END_OF_STACK = 16
+}
+
+// This is an opaque type used to refer to a system-specific data
+// structure used by the system unwinder. This context is created and
+// destroyed by the system, and passed to the personality routine
+// during unwinding.
+struct _Unwind_Context;
+
+// Raise an exception, passing along the given exception object.
+_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
+
+// Raise an exception for forced unwinding.
+_Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*);
+
+// Helper to invoke the exception_cleanup routine.
+void _Unwind_DeleteException(_Unwind_Exception*);
+
+// Resume propagation of an existing exception.  This is used after
+// e.g. executing cleanup code, and not to implement rethrowing.
+void _Unwind_Resume(_Unwind_Exception*);
+
+// @@@ Resume propagation of an FORCE_UNWIND exception, or to rethrow
+// a normal exception that was handled.
+_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception*);
+
+// @@@ Use unwind data to perform a stack backtrace.  The trace callback
+// is called for every stack frame in the call chain, but no cleanup
+// actions are performed.
+_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
+
+// These functions are used for communicating information about the unwind
+// context (i.e. the unwind descriptors and the user register state) between
+// the unwind library and the personality routine and landing pad.  Only
+// selected registers may be manipulated.
+
+_Unwind_Word _Unwind_GetGR(_Unwind_Context*, int);
+void _Unwind_SetGR(_Unwind_Context*, int, _Unwind_Word);
+
+_Unwind_Ptr _Unwind_GetIP(_Unwind_Context*);
+_Unwind_Ptr _Unwind_GetIPInfo(_Unwind_Context*, int*);
+void _Unwind_SetIP(_Unwind_Context*, _Unwind_Ptr);
+
+// @@@ Retrieve the CFA of the given context.
+_Unwind_Word _Unwind_GetCFA(_Unwind_Context*);
+
+void* _Unwind_GetLanguageSpecificData(_Unwind_Context*);
+
+_Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*);
+
+
+// @@@ The following alternate entry points are for setjmp/longjmp
+// based unwinding.
+
+struct SjLj_Function_Context;
+extern void _Unwind_SjLj_Register(SjLj_Function_Context*);
+extern void _Unwind_SjLj_Unregister(SjLj_Function_Context*);
+
+_Unwind_Reason_Code _Unwind_SjLj_RaiseException(_Unwind_Exception*);
+_Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*);
+void _Unwind_SjLj_Resume(_Unwind_Exception*);
+_Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception*);
+
+// @@@ The following provide access to the base addresses for text
+// and data-relative addressing in the LDSA.  In order to stay link
+// compatible with the standard ABI for IA-64, we inline these.
+
+version (IA64)
+{
+    _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context* _C)
+    {
+        // The GP is stored in R1.
+        return _Unwind_GetGR(_C, 1);
+    }
+
+    _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*)
+    {
+        __builtin_abort();
+        return 0;
+    }
+
+    // @@@ Retrieve the Backing Store Pointer of the given context.
+    _Unwind_Word _Unwind_GetBSP(_Unwind_Context*);
+}
+else
+{
+    _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*);
+    _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*);
+}
+
+// @@@ Given an address, return the entry point of the function that
+// contains it.
+extern void* _Unwind_FindEnclosingFunction(void* pc);
+
+
+// leb128 type numbers have a potentially unlimited size.
+// The target of the following definitions of _sleb128_t and _uleb128_t
+// is to have efficient data types large enough to hold the leb128 type
+// numbers used in the unwind code.
+// Mostly these types will simply be defined to long and unsigned long
+// except when a unsigned long data type on the target machine is not
+// capable of storing a pointer.
+
+static if (__builtin_clong.sizeof >= (void*).sizeof)
+{
+    alias _sleb128_t = __builtin_clong;
+    alias _uleb128_t = __builtin_culong;
+}
+else static if (long.sizeof >= (void*).sizeof)
+{
+    alias _sleb128_t = long;
+    alias _uleb128_t = ulong;
+}
+else
+{
+    static assert(false, "What type shall we use for _sleb128_t?");
+}
+
+version (GNU_SEH_Exceptions)
+{
+    // We're lazy, exact definition in MinGW/winnt.h
+    enum EXCEPTION_DISPOSITION
+    {
+        ExceptionContinueExecution,
+        ExceptionContinueSearch,
+        ExceptionNestedException,
+        ExceptionCollidedUnwind
+    }
+
+    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*,
+                                                          _Unwind_Personality_Fn);
+}
diff --git a/libphobos/libdruntime/gcc/unwind/package.d b/libphobos/libdruntime/gcc/unwind/package.d
new file mode 100644
index 00000000000..2b9107c3624
--- /dev/null
+++ b/libphobos/libdruntime/gcc/unwind/package.d
@@ -0,0 +1,37 @@ 
+// Exception handling and frame unwind runtime interface routines.
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.unwind;
+
+import gcc.config;
+
+static if (GNU_ARM_EABI_Unwinder)
+{
+    version (ARM)
+        public import gcc.unwind.arm;
+    else version (TIC6X)
+        public import gcc.unwind.c6x;
+    else
+        static assert(false, "Unsupported target for ARM_EABI_UNWINDER");
+}
+else
+    public import gcc.unwind.generic;
diff --git a/libphobos/libdruntime/gcc/unwind/pe.d b/libphobos/libdruntime/gcc/unwind/pe.d
new file mode 100644
index 00000000000..a26c447c59a
--- /dev/null
+++ b/libphobos/libdruntime/gcc/unwind/pe.d
@@ -0,0 +1,238 @@ 
+// Exception handling and frame unwind runtime interface routines.
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// extern(C) interface for the GNU/GCC pointer encoding library.
+// This corresponds to unwind-pe.h
+
+module gcc.unwind.pe;
+
+import gcc.unwind;
+import gcc.builtins;
+
+@nogc:
+
+// Pointer encodings, from dwarf2.h.
+enum
+{
+    DW_EH_PE_absptr   = 0x00,
+    DW_EH_PE_omit     = 0xff,
+
+    DW_EH_PE_uleb128  = 0x01,
+    DW_EH_PE_udata2   = 0x02,
+    DW_EH_PE_udata4   = 0x03,
+    DW_EH_PE_udata8   = 0x04,
+    DW_EH_PE_sleb128  = 0x09,
+    DW_EH_PE_sdata2   = 0x0A,
+    DW_EH_PE_sdata4   = 0x0B,
+    DW_EH_PE_sdata8   = 0x0C,
+    DW_EH_PE_signed   = 0x08,
+
+    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
+}
+
+// Given an encoding, return the number of bytes the format occupies.
+// This is only defined for fixed-size encodings, and so does not
+// include leb128.
+uint size_of_encoded_value(ubyte encoding)
+{
+    if (encoding == DW_EH_PE_omit)
+        return 0;
+
+    final switch (encoding & 0x07)
+    {
+        case DW_EH_PE_absptr:
+            return (void*).sizeof;
+        case DW_EH_PE_udata2:
+            return 2;
+        case DW_EH_PE_udata4:
+            return 4;
+        case DW_EH_PE_udata8:
+            return 8;
+    }
+    assert(0);
+}
+
+// Given an encoding and an _Unwind_Context, return the base to which
+// the encoding is relative.  This base may then be passed to
+// read_encoded_value_with_base for use when the _Unwind_Context is
+// not available.
+_Unwind_Ptr base_of_encoded_value(ubyte encoding, _Unwind_Context* context)
+{
+    if (encoding == DW_EH_PE_omit)
+        return cast(_Unwind_Ptr) 0;
+
+    final switch (encoding & 0x70)
+    {
+        case DW_EH_PE_absptr:
+        case DW_EH_PE_pcrel:
+        case DW_EH_PE_aligned:
+            return cast(_Unwind_Ptr) 0;
+
+        case DW_EH_PE_textrel:
+            return _Unwind_GetTextRelBase(context);
+        case DW_EH_PE_datarel:
+            return _Unwind_GetDataRelBase(context);
+        case DW_EH_PE_funcrel:
+            return _Unwind_GetRegionStart(context);
+    }
+    assert(0);
+}
+
+// Read an unsigned leb128 value from P, *P is incremented past the value.
+// We assume that a word is large enough to hold any value so encoded;
+// if it is smaller than a pointer on some target, pointers should not be
+// leb128 encoded on that target.
+_uleb128_t read_uleb128(const(ubyte)** p)
+{
+    auto q = *p;
+    _uleb128_t result = 0;
+    uint shift = 0;
+
+    while (1)
+    {
+        ubyte b = *q++;
+        result |= cast(_uleb128_t)(b & 0x7F) << shift;
+        if ((b & 0x80) == 0)
+            break;
+        shift += 7;
+    }
+
+    *p = q;
+    return result;
+}
+
+// Similar, but read a signed leb128 value.
+_sleb128_t read_sleb128(const(ubyte)** p)
+{
+    auto q = *p;
+    _sleb128_t result = 0;
+    uint shift = 0;
+    ubyte b = void;
+
+    while (1)
+    {
+        b = *q++;
+        result |= cast(_sleb128_t)(b & 0x7F) << shift;
+        shift += 7;
+        if ((b & 0x80) == 0)
+            break;
+    }
+
+    // Sign-extend a negative value.
+    if (shift < result.sizeof * 8 && (b & 0x40))
+        result |= -(cast(_sleb128_t)1 << shift);
+
+    *p = q;
+    return result;
+}
+
+// Load an encoded value from memory at P.  The value is returned in VAL;
+// The function returns P incremented past the value.  BASE is as given
+// by base_of_encoded_value for this encoding in the appropriate context.
+_Unwind_Ptr read_encoded_value_with_base(ubyte encoding, _Unwind_Ptr base,
+                                         const(ubyte)** p)
+{
+    auto q = *p;
+    _Unwind_Internal_Ptr result;
+
+    if (encoding == DW_EH_PE_aligned)
+    {
+        _Unwind_Internal_Ptr a = cast(_Unwind_Internal_Ptr)q;
+        a = cast(_Unwind_Internal_Ptr)((a + (void*).sizeof - 1) & - (void*).sizeof);
+        result = *cast(_Unwind_Internal_Ptr*)a;
+        q = cast(ubyte*) cast(_Unwind_Internal_Ptr)(a + (void*).sizeof);
+    }
+    else
+    {
+        switch (encoding & 0x0f)
+        {
+            case DW_EH_PE_uleb128:
+                result = cast(_Unwind_Internal_Ptr)read_uleb128(&q);
+                break;
+
+            case DW_EH_PE_sleb128:
+                result = cast(_Unwind_Internal_Ptr)read_sleb128(&q);
+                break;
+
+            case DW_EH_PE_udata2:
+                result = cast(_Unwind_Internal_Ptr) *cast(ushort*)q;
+                q += 2;
+                break;
+            case DW_EH_PE_udata4:
+                result = cast(_Unwind_Internal_Ptr) *cast(uint*)q;
+                q += 4;
+                break;
+            case DW_EH_PE_udata8:
+                result = cast(_Unwind_Internal_Ptr) *cast(ulong*)q;
+                q += 8;
+                break;
+
+            case DW_EH_PE_sdata2:
+                result = cast(_Unwind_Internal_Ptr) *cast(short*)q;
+                q += 2;
+                break;
+            case DW_EH_PE_sdata4:
+                result = cast(_Unwind_Internal_Ptr) *cast(int*)q;
+                q += 4;
+                break;
+            case DW_EH_PE_sdata8:
+                result = cast(_Unwind_Internal_Ptr) *cast(long*)q;
+                q += 8;
+                break;
+
+            case DW_EH_PE_absptr:
+                if (size_t.sizeof == 8)
+                    goto case DW_EH_PE_udata8;
+                else
+                    goto case DW_EH_PE_udata4;
+
+            default:
+                __builtin_abort();
+        }
+
+        if (result != 0)
+        {
+            result += ((encoding & 0x70) == DW_EH_PE_pcrel
+                       ? cast(_Unwind_Internal_Ptr)*p : base);
+            if (encoding & DW_EH_PE_indirect)
+                result = *cast(_Unwind_Internal_Ptr*)result;
+        }
+    }
+
+    *p = q;
+    return result;
+}
+
+// Like read_encoded_value_with_base, but get the base from the context
+// rather than providing it directly.
+_Unwind_Ptr read_encoded_value(_Unwind_Context* context, ubyte encoding,
+                               const(ubyte)** p)
+{
+    auto base = base_of_encoded_value(encoding, context);
+    return read_encoded_value_with_base(encoding, base, p);
+}
diff --git a/libphobos/src/libgphobos.spec.in b/libphobos/src/libgphobos.spec.in
new file mode 100644
index 00000000000..a11ec3ea192
--- /dev/null
+++ b/libphobos/src/libgphobos.spec.in
@@ -0,0 +1,8 @@ 
+#
+# This spec file is read by gdc when linking.
+# It is used to specify the libraries we need to link in, in the right
+# order.
+#
+
+%rename lib liborig_gdc_renamed
+*lib: %(liborig_gdc_renamed) @SPEC_PHOBOS_DEPS@