libphobos: Fix SIGBUS in read_encoded_value_with_base on sparc-sun-solaris (PR98584)
Instead of unsafe pointer dereferencing, use memcpy() to read encoded values from memory. The function `read_encoded_value' has been updated to accept a ref parameter, this simplifies handling of the pointer to memory needing to be read. libphobos/ChangeLog: PR d/98584 * libdruntime/gcc/deh.d (scanLSDA): Update calls to read_uleb128 and read_encoded_value. (actionTableLookup): Update calls to read_sleb128 and read_encoded_value_with_base. * libdruntime/gcc/unwind/pe.d (read_uleb128): Update signature. (read_sleb128): Update signature. (read_unaligned): New function. (read_encoded_value_with_base): Update signature. Call read_unaligned instead of unsafe pointer dereferencing. (read_encoded_value): Update signature.
This commit is contained in:
parent
6e81e015d9
commit
30b11d8d1b
@ -547,7 +547,7 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
|
||||
_Unwind_Ptr LPStart = 0;
|
||||
|
||||
if (LPStartEncoding != DW_EH_PE_omit)
|
||||
LPStart = read_encoded_value(context, LPStartEncoding, &p);
|
||||
LPStart = read_encoded_value(context, LPStartEncoding, p);
|
||||
else
|
||||
LPStart = Start;
|
||||
|
||||
@ -563,14 +563,14 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
|
||||
// hardcoded OS-specific format.
|
||||
TTypeEncoding = _TTYPE_ENCODING;
|
||||
}
|
||||
auto TTbase = read_uleb128(&p);
|
||||
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);
|
||||
auto CSTableSize = read_uleb128(p);
|
||||
const(ubyte)* actionTable = p + CSTableSize;
|
||||
|
||||
auto TTypeBase = base_of_encoded_value(TTypeEncoding, context);
|
||||
@ -608,8 +608,8 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
|
||||
_uleb128_t CSLandingPad, CSAction;
|
||||
do
|
||||
{
|
||||
CSLandingPad = read_uleb128(&p);
|
||||
CSAction = read_uleb128(&p);
|
||||
CSLandingPad = read_uleb128(p);
|
||||
CSAction = read_uleb128(p);
|
||||
}
|
||||
while (--ip);
|
||||
|
||||
@ -626,10 +626,10 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
|
||||
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);
|
||||
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)
|
||||
@ -703,9 +703,9 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
|
||||
while (1)
|
||||
{
|
||||
auto ap = actionRecord;
|
||||
auto ARFilter = read_sleb128(&ap);
|
||||
auto ARFilter = read_sleb128(ap);
|
||||
auto apn = ap;
|
||||
auto ARDisp = read_sleb128(&ap);
|
||||
auto ARDisp = read_sleb128(ap);
|
||||
|
||||
if (ARFilter == 0)
|
||||
{
|
||||
@ -725,7 +725,7 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
|
||||
// the ClassInfo is stored.
|
||||
const(ubyte)* tp = TType - ARFilter * encodedSize;
|
||||
|
||||
auto entry = read_encoded_value_with_base(TTypeEncoding, TTypeBase, &tp);
|
||||
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
|
||||
|
@ -103,40 +103,37 @@ _Unwind_Ptr base_of_encoded_value(ubyte encoding, _Unwind_Context* context)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// Read an unsigned leb128 value from P, *P is incremented past the value.
|
||||
// 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)
|
||||
_uleb128_t read_uleb128(ref const(ubyte)* p)
|
||||
{
|
||||
auto q = *p;
|
||||
_uleb128_t result = 0;
|
||||
uint shift = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
ubyte b = *q++;
|
||||
ubyte b = *p++;
|
||||
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)
|
||||
_sleb128_t read_sleb128(ref const(ubyte)* p)
|
||||
{
|
||||
auto q = *p;
|
||||
_sleb128_t result = 0;
|
||||
uint shift = 0;
|
||||
ubyte b = void;
|
||||
|
||||
while (1)
|
||||
{
|
||||
b = *q++;
|
||||
b = *p++;
|
||||
result |= cast(_sleb128_t)(b & 0x7F) << shift;
|
||||
shift += 7;
|
||||
if ((b & 0x80) == 0)
|
||||
@ -147,69 +144,82 @@ _sleb128_t read_sleb128(const(ubyte)** p)
|
||||
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
|
||||
// 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,
|
||||
const(ubyte)** p)
|
||||
ref const(ubyte)* p)
|
||||
{
|
||||
auto q = *p;
|
||||
auto psave = p;
|
||||
_Unwind_Internal_Ptr result;
|
||||
|
||||
if (encoding == DW_EH_PE_aligned)
|
||||
{
|
||||
_Unwind_Internal_Ptr a = cast(_Unwind_Internal_Ptr)q;
|
||||
_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;
|
||||
q = cast(ubyte*) cast(_Unwind_Internal_Ptr)(a + (void*).sizeof);
|
||||
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(&q);
|
||||
result = cast(_Unwind_Internal_Ptr)read_uleb128(p);
|
||||
break;
|
||||
|
||||
case DW_EH_PE_sleb128:
|
||||
result = cast(_Unwind_Internal_Ptr)read_sleb128(&q);
|
||||
result = cast(_Unwind_Internal_Ptr)read_sleb128(p);
|
||||
break;
|
||||
|
||||
case DW_EH_PE_udata2:
|
||||
result = cast(_Unwind_Internal_Ptr) *cast(ushort*)q;
|
||||
q += 2;
|
||||
result = cast(_Unwind_Internal_Ptr)read_unaligned!ushort(p);
|
||||
break;
|
||||
case DW_EH_PE_udata4:
|
||||
result = cast(_Unwind_Internal_Ptr) *cast(uint*)q;
|
||||
q += 4;
|
||||
result = cast(_Unwind_Internal_Ptr)read_unaligned!uint(p);
|
||||
break;
|
||||
case DW_EH_PE_udata8:
|
||||
result = cast(_Unwind_Internal_Ptr) *cast(ulong*)q;
|
||||
q += 8;
|
||||
result = cast(_Unwind_Internal_Ptr)read_unaligned!ulong(p);
|
||||
break;
|
||||
|
||||
case DW_EH_PE_sdata2:
|
||||
result = cast(_Unwind_Internal_Ptr) *cast(short*)q;
|
||||
q += 2;
|
||||
result = cast(_Unwind_Internal_Ptr)read_unaligned!short(p);
|
||||
break;
|
||||
case DW_EH_PE_sdata4:
|
||||
result = cast(_Unwind_Internal_Ptr) *cast(int*)q;
|
||||
q += 4;
|
||||
result = cast(_Unwind_Internal_Ptr)read_unaligned!int(p);
|
||||
break;
|
||||
case DW_EH_PE_sdata8:
|
||||
result = cast(_Unwind_Internal_Ptr) *cast(long*)q;
|
||||
q += 8;
|
||||
result = cast(_Unwind_Internal_Ptr)read_unaligned!long(p);
|
||||
break;
|
||||
|
||||
case DW_EH_PE_absptr:
|
||||
if (size_t.sizeof == 8)
|
||||
goto case DW_EH_PE_udata8;
|
||||
else
|
||||
goto case DW_EH_PE_udata4;
|
||||
result = cast(_Unwind_Internal_Ptr)read_unaligned!(size_t)(p);
|
||||
break;
|
||||
|
||||
default:
|
||||
__builtin_abort();
|
||||
@ -218,20 +228,19 @@ _Unwind_Ptr read_encoded_value_with_base(ubyte encoding, _Unwind_Ptr base,
|
||||
if (result != 0)
|
||||
{
|
||||
result += ((encoding & 0x70) == DW_EH_PE_pcrel
|
||||
? cast(_Unwind_Internal_Ptr)*p : base);
|
||||
? cast(_Unwind_Internal_Ptr)psave : 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)
|
||||
ref const(ubyte)* p)
|
||||
{
|
||||
auto base = base_of_encoded_value(encoding, context);
|
||||
return read_encoded_value_with_base(encoding, base, p);
|
||||
|
Loading…
Reference in New Issue
Block a user