libgo: break dependence on libgcc unwind-pe.h

The C portion of the Go runtime includes the header "unwind-pe.h" from
    libgcc, which contains some constants and a few small routines for
    decoding pointer values within unwind info. This patch gets rid of
    that include and instead adds a re-implementation of that
    functionality in the single file that uses it. The intent is to allow
    the C runtime portion of libgo to be built without a companion GCC
    installation.
    
    Reviewed-on: https://go-review.googlesource.com/90235

From-SVN: r259861
This commit is contained in:
Ian Lance Taylor 2018-05-02 21:53:30 +00:00
parent 27db01d803
commit 019808c95c
1 changed files with 165 additions and 2 deletions

View File

@ -10,11 +10,30 @@
#include <unistd.h>
#include "unwind.h"
#define NO_SIZE_OF_ENCODED_VALUE
#include "unwind-pe.h"
#include "runtime.h"
/* These constants are documented here:
https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/dwarfext.html
*/
#define DW_EH_PE_omit 0xff
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
#define DW_EH_PE_aligned 0x50
#define DW_EH_PE_indirect 0x80
/* The code for a Go exception. */
#ifdef __ARM_EABI_UNWINDER__
@ -109,6 +128,150 @@ throwException ()
abort ();
}
static inline _Unwind_Ptr
encoded_value_base (uint8_t encoding, struct _Unwind_Context *context)
{
if (encoding == DW_EH_PE_omit)
return 0;
switch (encoding & 0x70)
{
case DW_EH_PE_absptr:
case DW_EH_PE_pcrel:
case DW_EH_PE_aligned:
return 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);
}
abort ();
}
/* Read an unsigned leb128 value. */
static inline const uint8_t *
read_uleb128 (const uint8_t *p, _uleb128_t *val)
{
unsigned int shift = 0;
_uleb128_t result = 0;
uint8_t byte;
do
{
byte = *p++;
result |= ((_uleb128_t)byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
*val = result;
return p;
}
/* Similar, but read a signed leb128 value. */
static inline const uint8_t *
read_sleb128 (const uint8_t *p, _sleb128_t *val)
{
unsigned int shift = 0;
_uleb128_t result = 0;
uint8_t byte;
do
{
byte = *p++;
result |= ((_uleb128_t)byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
/* sign extension */
if (shift < (8 * sizeof(result)) && (byte & 0x40) != 0)
result |= (((_uleb128_t)~0) << shift);
*val = (_sleb128_t)result;
return p;
}
#define ROUND_UP_TO_PVB(x) (x + sizeof(void *) - 1) &- sizeof(void *)
#define COPY_AND_ADVANCE(dst, ptr, typ) \
(dst = *((const typ*)ptr), \
ptr += sizeof(typ))
static inline const uint8_t *
read_encoded_value (struct _Unwind_Context *context, uint8_t encoding,
const uint8_t *p, _Unwind_Ptr *val)
{
_Unwind_Ptr base = encoded_value_base (encoding, context);
_Unwind_Internal_Ptr decoded = 0;
const uint8_t *origp = p;
if (encoding == DW_EH_PE_aligned)
{
_Unwind_Internal_Ptr uip = (_Unwind_Internal_Ptr)p;
uip = ROUND_UP_TO_PVB (uip);
decoded = *(_Unwind_Internal_Ptr *)uip;
p = (const uint8_t *)(uip + sizeof(void *));
}
else
{
switch (encoding & 0x0f)
{
case DW_EH_PE_sdata2:
case DW_EH_PE_udata2:
COPY_AND_ADVANCE (decoded, p, uint16_t);
break;
case DW_EH_PE_sdata4:
case DW_EH_PE_udata4:
COPY_AND_ADVANCE (decoded, p, uint32_t);
break;
case DW_EH_PE_sdata8:
case DW_EH_PE_udata8:
COPY_AND_ADVANCE (decoded, p, uint64_t);
break;
case DW_EH_PE_uleb128:
{
_uleb128_t value;
p = read_uleb128 (p, &value);
decoded = (_Unwind_Internal_Ptr)value;
break;
}
case DW_EH_PE_sleb128:
{
_sleb128_t value;
p = read_sleb128 (p, &value);
decoded = (_Unwind_Internal_Ptr)value;
break;
}
case DW_EH_PE_absptr:
decoded = (_Unwind_Internal_Ptr)(*(const void *const *)p);
p += sizeof(void *);
break;
default:
abort ();
}
if (decoded == 0)
{
*val = decoded;
return p;
}
if ((encoding & 0x70) == DW_EH_PE_pcrel)
decoded += ((_Unwind_Internal_Ptr)origp);
else
decoded += base;
if ((encoding & DW_EH_PE_indirect) != 0)
decoded = *(_Unwind_Internal_Ptr *)decoded;
}
*val = decoded;
return p;
}
/* The rest of this code is really similar to gcc/unwind-c.c and
libjava/exception.cc. */