Hi Fangrui, On Tue, 8 Aug 2023 18:39:58 -0700, Fangrui Song via dmidecode-devel wrote: > Currently ALIGNMENT_WORKAROUND is only defined for __ia64__ and __arm__. > However, -fsanitize=alignment (part of UndefinedBehaviorSanitizer) will > give errors for other architectures like x86, e.g. > > dmidecode.c:4941:7: runtime error: load of misaligned address 0x5629323b5f05 > for type 'const u32', which requires 4 byt > e alignment > 0x5629323b5f05: note: pointer points here > 13 0f 01 03 00 00 40 00 ff ff 0f 20 00 02 01 00 00 14 13 00 40 00 00 00 > 00 ff ff 2f 00 00 70 00 > ^ > > Let's just use memcpy to perform unaligned memory accesses. Modern > compilers are able to optimize memcpy. > > For x86-64 builds using GCC or Clang, the old assembly seems to prefer > 2 32-bit mov while the new assembly prefers 64-bit mov with shr with 32. > For aarch64 builds using GCC or Clang, the output sizes do not change. > > Signed-off-by: Fangrui Song <mask...@google.com> > --- > Makefile | 1 - > config.h | 5 ----- > types.h | 47 ++++++++++++++++++++++------------------------- > 3 files changed, 22 insertions(+), 31 deletions(-) > > diff --git a/Makefile b/Makefile > index 7aa729d..3e83805 100644 > --- a/Makefile > +++ b/Makefile > @@ -25,7 +25,6 @@ CFLAGS += -W -Wall -Wshadow -Wstrict-prototypes > -Wpointer-arith -Wcast-qual \ > CFLAGS += -D_FILE_OFFSET_BITS=64 > > #CFLAGS += -DBIGENDIAN > -#CFLAGS += -DALIGNMENT_WORKAROUND > > # Pass linker flags here (can be set from environment too) > LDFLAGS ?= > diff --git a/config.h b/config.h > index 0a1af7d..416d4a6 100644 > --- a/config.h > +++ b/config.h > @@ -21,11 +21,6 @@ > #define USE_MMAP > #endif > > -/* Use memory alignment workaround or not */ > -#if defined(__ia64__) || defined(__arm__) > -#define ALIGNMENT_WORKAROUND > -#endif > - > /* Avoid unaligned memcpy on /dev/mem */ > #ifdef __aarch64__ > #define USE_SLOW_MEMCPY > diff --git a/types.h b/types.h > index 51c32d7..80a3605 100644 > --- a/types.h > +++ b/types.h > @@ -1,6 +1,8 @@ > #ifndef TYPES_H > #define TYPES_H > > +#include <string.h> > + > #include "config.h" > > typedef unsigned char u8; > @@ -12,10 +14,6 @@ typedef unsigned int u32; > * You may use the following defines to adjust the type definitions > * depending on the architecture: > * - Define BIGENDIAN on big-endian systems. > - * - Define ALIGNMENT_WORKAROUND if your system doesn't support > - * non-aligned memory access. In this case, we use a slower, but safer, > - * memory access method. This should be done automatically in config.h > - * for architectures which need it. > */ > > #ifdef BIGENDIAN > @@ -30,30 +28,29 @@ typedef struct { > } u64; > #endif > > -#if defined(ALIGNMENT_WORKAROUND) || defined(BIGENDIAN) > -static inline u64 U64(u32 low, u32 high) > -{ > - u64 self; > - > - self.l = low; > - self.h = high; > - > - return self; > -} > -#endif > - > /* > * Per SMBIOS v2.8.0 and later, all structures assume a little-endian > * ordering convention. > */ > -#if defined(ALIGNMENT_WORKAROUND) || defined(BIGENDIAN) > -#define WORD(x) (u16)((x)[0] + ((x)[1] << 8)) > -#define DWORD(x) (u32)((x)[0] + ((x)[1] << 8) + ((x)[2] << 16) + ((x)[3] << > 24)) > -#define QWORD(x) (U64(DWORD(x), DWORD(x + 4))) > -#else /* ALIGNMENT_WORKAROUND || BIGENDIAN */ > -#define WORD(x) (u16)(*(const u16 *)(x)) > -#define DWORD(x) (u32)(*(const u32 *)(x)) > -#define QWORD(x) (*(const u64 *)(x)) > -#endif /* ALIGNMENT_WORKAROUND || BIGENDIAN */ > +static inline u16 WORD(void *x) > +{ > + u16 ret; > + memcpy(&ret, x, sizeof(ret)); > + return ret; > +} > + > +static inline u32 DWORD(void *x) > +{ > + u32 ret; > + memcpy(&ret, x, sizeof(ret)); > + return ret; > +} > + > +static inline u64 QWORD(void *x) > +{ > + u64 ret; > + memcpy(&ret, x, sizeof(ret)); > + return ret; > +}
I can't see how this would work on big-endian systems. > > #endif I just gave a try to your patch on my system (openSUSE Leap 15.4, gcc 7.5.0, x86-64) and it results in pages and pages of warnings such as: dmidecode.c: In function ‘dmi_base_board_handles’: dmidecode.c:592:31: warning: passing argument 1 of ‘WORD’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] pr_list_item("0x%04X", WORD(p + sizeof(u16) * i)); ^ In file included from dmidecode.c:81:0: types.h:35:19: note: expected ‘void *’ but argument is of type ‘const u8 * {aka const unsigned char *}’ static inline u16 WORD(void *x) ^~~~ I can't possibly commit a change which generates build warnings, sorry. -- Jean Delvare SUSE L3 Support