From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id 11AB93858028; Tue, 20 Apr 2021 00:28:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 11AB93858028 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc r11-8254] libphobos: Fix SIGBUS in read_encoded_value_with_base on sparc-sun-solaris (PR98584) X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/master X-Git-Oldrev: 6e81e015d91568fc3df3939623ae999e0681a0fc X-Git-Newrev: 30b11d8d1be9c683f1517472c47a3cb69df02c4f Message-Id: <20210420002833.11AB93858028@sourceware.org> Date: Tue, 20 Apr 2021 00:28:33 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Apr 2021 00:28:33 -0000 https://gcc.gnu.org/g:30b11d8d1be9c683f1517472c47a3cb69df02c4f commit r11-8254-g30b11d8d1be9c683f1517472c47a3cb69df02c4f Author: Iain Buclaw Date: Tue Apr 20 02:09:51 2021 +0200 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. Diff: --- libphobos/libdruntime/gcc/deh.d | 24 +++++------ libphobos/libdruntime/gcc/unwind/pe.d | 81 +++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 48 deletions(-) diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d index 712f5d7bc9d..eb83751c59d 100644 --- a/libphobos/libdruntime/gcc/deh.d +++ b/libphobos/libdruntime/gcc/deh.d @@ -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 diff --git a/libphobos/libdruntime/gcc/unwind/pe.d b/libphobos/libdruntime/gcc/unwind/pe.d index 361ec12490f..b9b05cbc8f6 100644 --- a/libphobos/libdruntime/gcc/unwind/pe.d +++ b/libphobos/libdruntime/gcc/unwind/pe.d @@ -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);