[binutils-gdb] PR 33721 load/store of misaligned address

Alan Modra amodra@sourceware.org
Tue Dec 16 21:31:23 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=44e7622937280a0a7c679949fc313d6ffc710701

commit 44e7622937280a0a7c679949fc313d6ffc710701
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Dec 17 08:00:24 2025 +1030

    PR 33721 load/store of misaligned address
    
    This fixes PR33721 by a common technique of declaring a packed struct
    to access unaligned integer fields.  (See eg. linux kernel
    include/vdso/unaligned.h)  I've tidied the PR29856 fix for a similar
    bug too (not that there was anything wrong with that fix).
    
            PR 33721
            PR 29856
            * sframe.c (flip_fre_start_address): Use a packed struct to
            access 2-byte and 4-byte unaligned fields.  Make addr a void*.
            (sframe_decode_fre_start_address): Similarly, and remove
            unnecessary casts.  Always set *fre_start_addr.

Diff:
---
 libsframe/sframe.c | 38 +++++++++++++++-----------------------
 1 file changed, 15 insertions(+), 23 deletions(-)

diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index 0dcc782b1f6..3a02a76a2a9 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -311,17 +311,17 @@ sframe_header_sanity_check_p (const sframe_header *hp)
 /* Flip the start address pointed to by FP.  */
 
 static void
-flip_fre_start_address (char *addr, uint32_t fre_type)
+flip_fre_start_address (void *addr, uint32_t fre_type)
 {
   if (fre_type == SFRAME_FRE_TYPE_ADDR2)
     {
-      uint16_t *start_addr = (uint16_t *)addr;
-      swap_thing (*start_addr);
+      struct { uint16_t x; } ATTRIBUTE_PACKED *p = addr;
+      swap_thing (p->x);
     }
   else if (fre_type == SFRAME_FRE_TYPE_ADDR4)
     {
-      uint32_t *start_addr = (uint32_t *)addr;
-      swap_thing (*start_addr);
+      struct { uint32_t x; } ATTRIBUTE_PACKED *p = addr;
+      swap_thing (p->x);
     }
 }
 
@@ -938,42 +938,34 @@ sframe_frame_row_entry_copy (sframe_frame_row_entry *dst,
    Returns 0 on success, SFRAME_ERR otherwise.  */
 
 static int
-sframe_decode_fre_start_address (const char *fre_buf,
+sframe_decode_fre_start_address (const void *fre_buf,
 				 uint32_t *fre_start_addr,
 				 uint32_t fre_type)
 {
   uint32_t saddr = 0;
   int err = 0;
-  size_t addr_size = 0;
-
-  addr_size = sframe_fre_start_addr_size (fre_type);
 
   if (fre_type == SFRAME_FRE_TYPE_ADDR1)
     {
-      uint8_t *uc = (uint8_t *)fre_buf;
-      saddr = (uint32_t)*uc;
+      const uint8_t *uc = fre_buf;
+      saddr = *uc;
     }
   else if (fre_type == SFRAME_FRE_TYPE_ADDR2)
     {
-      uint16_t *ust = (uint16_t *)fre_buf;
-      /* SFrame is an unaligned on-disk format.  Using memcpy helps avoid the
-	 use of undesirable unaligned loads.  See PR libsframe/29856.  */
-      uint16_t tmp = 0;
-      memcpy (&tmp, ust, addr_size);
-      saddr = (uint32_t)tmp;
+      /* SFrame is an unaligned on-disk format.  See PR libsframe/29856.  */
+      const struct { uint16_t x; } ATTRIBUTE_PACKED *p = fre_buf;
+      saddr = p->x;
     }
   else if (fre_type == SFRAME_FRE_TYPE_ADDR4)
     {
-      uint32_t *uit = (uint32_t *)fre_buf;
-      uint32_t tmp = 0;
-      memcpy (&tmp, uit, addr_size);
-      saddr = (uint32_t)tmp;
+      const struct { uint32_t x; } ATTRIBUTE_PACKED *p = fre_buf;
+      saddr = p->x;
     }
   else
-    return sframe_set_errno (&err, SFRAME_ERR_INVAL);
+    sframe_set_errno (&err, SFRAME_ERR_INVAL);
 
   *fre_start_addr = saddr;
-  return 0;
+  return err;
 }
 
 /* Decode a frame row entry FRE which starts at location FRE_BUF.  The function


More information about the Binutils-cvs mailing list