libgo: fix for unaligned read in go-unwind.c's read_encoded_value()
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 4 May 2018 14:29:05 +0000 (14:29 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 4 May 2018 14:29:05 +0000 (14:29 +0000)
    Change code to work properly reading unaligned data on architectures
    that don't support unaliged reads. This fixes a regression (broke
    Solaris/sparc) introduced in https://golang.org/cl/90235.

    Reviewed-on: https://go-review.googlesource.com/111296

From-SVN: r259935

gcc/go/gofrontend/MERGE
libgo/runtime/go-unwind.c

index d299f23d675aaa6e530adbab79e08c2093861738..02bf62520cbc2bcd6b6dfce835a306b18a336102 100644 (file)
@@ -1,4 +1,4 @@
-30e2033a91fc08be9351d26737599a1fa6486017
+0c9b7a1ca4c6308345ea2a276cf820ff52513592
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 536a619d2987fc08d80fc54a93b21d78cf493915..a059acbc22aa01c1b35637b4b71fa6a3b090e798 100644 (file)
@@ -197,10 +197,6 @@ read_sleb128 (const uint8_t *p, _sleb128_t *val)
 
 #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)
@@ -221,17 +217,53 @@ read_encoded_value (struct _Unwind_Context *context, uint8_t encoding,
       switch (encoding & 0x0f)
         {
           case DW_EH_PE_sdata2:
+            {
+              int16_t result;
+              __builtin_memcpy (&result, p, sizeof(int16_t));
+              decoded = result;
+              p += sizeof(int16_t);
+              break;
+            }
           case DW_EH_PE_udata2:
-            COPY_AND_ADVANCE (decoded, p, uint16_t);
-            break;
+            {
+              uint16_t result;
+              __builtin_memcpy (&result, p, sizeof(uint16_t));
+              decoded = result;
+              p += sizeof(uint16_t);
+              break;
+            }
           case DW_EH_PE_sdata4:
+            {
+              int32_t result;
+              __builtin_memcpy (&result, p, sizeof(int32_t));
+              decoded = result;
+              p += sizeof(int32_t);
+              break;
+            }
           case DW_EH_PE_udata4:
-            COPY_AND_ADVANCE (decoded, p, uint32_t);
-            break;
+            {
+              uint32_t result;
+              __builtin_memcpy (&result, p, sizeof(uint32_t));
+              decoded = result;
+              p += sizeof(uint32_t);
+              break;
+            }
           case DW_EH_PE_sdata8:
+            {
+              int64_t result;
+              __builtin_memcpy (&result, p, sizeof(int64_t));
+              decoded = result;
+              p += sizeof(int64_t);
+              break;
+            }
           case DW_EH_PE_udata8:
-            COPY_AND_ADVANCE (decoded, p, uint64_t);
-            break;
+            {
+              uint64_t result;
+              __builtin_memcpy (&result, p, sizeof(uint64_t));
+              decoded = result;
+              p += sizeof(uint64_t);
+              break;
+            }
           case DW_EH_PE_uleb128:
             {
               _uleb128_t value;
@@ -247,7 +279,7 @@ read_encoded_value (struct _Unwind_Context *context, uint8_t encoding,
               break;
             }
           case DW_EH_PE_absptr:
-            decoded = (_Unwind_Internal_Ptr)(*(const void *const *)p);
+            __builtin_memcpy (&decoded, (const void *)p, sizeof(const void*));
             p += sizeof(void *);
             break;
           default: