// Exception handling and frame unwind runtime interface routines.
// Copyright (C) 2011-2021 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(ref const(ubyte)* p)
{
    _uleb128_t result = 0;
    uint shift = 0;

    while (1)
    {
        ubyte b = *p++;
        result |= cast(_uleb128_t)(b & 0x7F) << shift;
        if ((b & 0x80) == 0)
            break;
        shift += 7;
    }

    return result;
}

// Similar, but read a signed leb128 value.
_sleb128_t read_sleb128(ref const(ubyte)* p)
{
    _sleb128_t result = 0;
    uint shift = 0;
    ubyte b = void;

    while (1)
    {
        b = *p++;
        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);

    return result;
}

// Similar, but read an unaligned value of type T.
pragma(inline, true)
private T read_unaligned(T)(ref const(ubyte)* p)
{
    version (X86)         enum hasUnalignedLoads = true;
    else version (X86_64) enum hasUnalignedLoads = true;
    else                  enum hasUnalignedLoads = false;

    static if (hasUnalignedLoads)
    {
        T result = *cast(T*)p;
    }
    else
    {
        import core.stdc.string : memcpy;
        T result = void;
        memcpy(&result, p, T.sizeof);
    }
    p += T.sizeof;
    return result;
}

// Load an encoded value from memory at P.  The function returns the
// encoded value.  P is 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,
                                         ref const(ubyte)* p)
{
    auto psave = p;
    _Unwind_Internal_Ptr result;

    if (encoding == DW_EH_PE_aligned)
    {
        _Unwind_Internal_Ptr a = cast(_Unwind_Internal_Ptr)p;
        a = cast(_Unwind_Internal_Ptr)((a + (void*).sizeof - 1) & - (void*).sizeof);
        result = *cast(_Unwind_Internal_Ptr*)a;
        p = 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(p);
                break;

            case DW_EH_PE_sleb128:
                result = cast(_Unwind_Internal_Ptr)read_sleb128(p);
                break;

            case DW_EH_PE_udata2:
                result = cast(_Unwind_Internal_Ptr)read_unaligned!ushort(p);
                break;
            case DW_EH_PE_udata4:
                result = cast(_Unwind_Internal_Ptr)read_unaligned!uint(p);
                break;
            case DW_EH_PE_udata8:
                result = cast(_Unwind_Internal_Ptr)read_unaligned!ulong(p);
                break;

            case DW_EH_PE_sdata2:
                result = cast(_Unwind_Internal_Ptr)read_unaligned!short(p);
                break;
            case DW_EH_PE_sdata4:
                result = cast(_Unwind_Internal_Ptr)read_unaligned!int(p);
                break;
            case DW_EH_PE_sdata8:
                result = cast(_Unwind_Internal_Ptr)read_unaligned!long(p);
                break;

            case DW_EH_PE_absptr:
                result = cast(_Unwind_Internal_Ptr)read_unaligned!(size_t)(p);
                break;

            default:
                __builtin_abort();
        }

        if (result != 0)
        {
            result += ((encoding & 0x70) == DW_EH_PE_pcrel
                       ? cast(_Unwind_Internal_Ptr)psave : base);
            if (encoding & DW_EH_PE_indirect)
                result = *cast(_Unwind_Internal_Ptr*)result;
        }
    }

    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,
                               ref const(ubyte)* p)
{
    auto base = base_of_encoded_value(encoding, context);
    return read_encoded_value_with_base(encoding, base, p);
}
