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:
parent
27db01d803
commit
019808c95c
@ -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. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user