diff options
author | Guy Harris <guy@alum.mit.edu> | 2017-10-16 01:39:10 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2017-10-16 01:39:10 -0700 |
commit | 2b9bfa05b690f71d08243a8089d6feacbe52b2d2 (patch) | |
tree | 442322da7c5af5ec3041d4821be7265025fecab9 | |
parent | fdd0467bcd46ea0d472111adedd21f43d6d4d15e (diff) | |
download | tcpdump-2b9bfa05b690f71d08243a8089d6feacbe52b2d2.tar.gz |
Check for unaligned memory access support at compile time.
Don't test at configure time; that doesn't work when cross-compiling and
may be a pain to do with CMake.
-rw-r--r-- | aclocal.m4 | 100 | ||||
-rw-r--r-- | config.h.in | 3 | ||||
-rwxr-xr-x | configure | 95 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | extract.h | 85 | ||||
-rw-r--r-- | netdissect.h | 32 | ||||
-rw-r--r-- | util-print.c | 35 |
7 files changed, 102 insertions, 250 deletions
@@ -799,106 +799,6 @@ AC_DEFUN(AC_LBL_CHECK_64BIT_FORMAT, ]) dnl -dnl Checks to see if unaligned memory accesses fail -dnl -dnl usage: -dnl -dnl AC_LBL_UNALIGNED_ACCESS -dnl -dnl results: -dnl -dnl LBL_ALIGN (DEFINED) -dnl -AC_DEFUN(AC_LBL_UNALIGNED_ACCESS, - [AC_MSG_CHECKING(if unaligned accesses fail) - AC_CACHE_VAL(ac_cv_lbl_unaligned_fail, - [case "$host_cpu" in - - # - # These are CPU types where: - # - # the CPU faults on an unaligned access, but at least some - # OSes that support that CPU catch the fault and simulate - # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) - - # the simulation is slow, so we don't want to use it; - # - # the CPU, I infer (from the old - # - # XXX: should also check that they don't do weird things (like on arm) - # - # comment) doesn't fault on unaligned accesses, but doesn't - # do a normal unaligned fetch, either (e.g., presumably, ARM); - # - # for whatever reason, the test program doesn't work - # (this has been claimed to be the case for several of those - # CPUs - I don't know what the problem is; the problem - # was reported as "the test program dumps core" for SuperH, - # but that's what the test program is *supposed* to do - - # it dumps core before it writes anything, so the test - # for an empty output file should find an empty output - # file and conclude that unaligned accesses don't work). - # - # This run-time test won't work if you're cross-compiling, so - # in order to support cross-compiling for a particular CPU, - # we have to wire in the list of CPU types anyway, as far as - # I know, so perhaps we should just have a set of CPUs on - # which we know it doesn't work, a set of CPUs on which we - # know it does work, and have the script just fail on other - # cpu types and update it when such a failure occurs. - # - alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1) - ac_cv_lbl_unaligned_fail=yes - ;; - - *) - cat >conftest.c <<EOF -# include <sys/types.h> -# include <sys/wait.h> -# include <stdio.h> - unsigned char a[[5]] = { 1, 2, 3, 4, 5 }; - main() { - unsigned int i; - pid_t pid; - int status; - /* avoid "core dumped" message */ - pid = fork(); - if (pid < 0) - exit(2); - if (pid > 0) { - /* parent */ - pid = waitpid(pid, &status, 0); - if (pid < 0) - exit(3); - exit(!WIFEXITED(status)); - } - /* child */ - i = *(unsigned int *)&a[[1]]; - printf("%d\n", i); - exit(0); - } -EOF - ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \ - conftest.c $LIBS >/dev/null 2>&1 - if test ! -x conftest ; then - dnl failed to compile for some reason - ac_cv_lbl_unaligned_fail=yes - else - ./conftest >conftest.out - if test ! -s conftest.out ; then - ac_cv_lbl_unaligned_fail=yes - else - ac_cv_lbl_unaligned_fail=no - fi - fi - rm -f -r conftest* core core.conftest - ;; - esac]) - AC_MSG_RESULT($ac_cv_lbl_unaligned_fail) - if test $ac_cv_lbl_unaligned_fail = yes ; then - AC_DEFINE(LBL_ALIGN,1,[if unaligned access fails]) - fi]) - -dnl dnl If the file .devel exists: dnl Add some warning flags if the compiler supports them dnl If an os prototype include exists, symlink os-proto.h to it diff --git a/config.h.in b/config.h.in index 487364dc..6d695afa 100644 --- a/config.h.in +++ b/config.h.in @@ -247,9 +247,6 @@ /* define if your compiler has __attribute__ */ #undef HAVE___ATTRIBUTE__ -/* if unaligned access fails */ -#undef LBL_ALIGN - /* Define to 1 if netinet/ether.h declares `ether_ntohost' */ #undef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST @@ -7332,101 +7332,6 @@ $as_echo "$as_me: WARNING: can't find $name" >&2;} fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5 -$as_echo_n "checking if unaligned accesses fail... " >&6; } - if ${ac_cv_lbl_unaligned_fail+:} false; then : - $as_echo_n "(cached) " >&6 -else - case "$host_cpu" in - - # - # These are CPU types where: - # - # the CPU faults on an unaligned access, but at least some - # OSes that support that CPU catch the fault and simulate - # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) - - # the simulation is slow, so we don't want to use it; - # - # the CPU, I infer (from the old - # - # XXX: should also check that they don't do weird things (like on arm) - # - # comment) doesn't fault on unaligned accesses, but doesn't - # do a normal unaligned fetch, either (e.g., presumably, ARM); - # - # for whatever reason, the test program doesn't work - # (this has been claimed to be the case for several of those - # CPUs - I don't know what the problem is; the problem - # was reported as "the test program dumps core" for SuperH, - # but that's what the test program is *supposed* to do - - # it dumps core before it writes anything, so the test - # for an empty output file should find an empty output - # file and conclude that unaligned accesses don't work). - # - # This run-time test won't work if you're cross-compiling, so - # in order to support cross-compiling for a particular CPU, - # we have to wire in the list of CPU types anyway, as far as - # I know, so perhaps we should just have a set of CPUs on - # which we know it doesn't work, a set of CPUs on which we - # know it does work, and have the script just fail on other - # cpu types and update it when such a failure occurs. - # - alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1) - ac_cv_lbl_unaligned_fail=yes - ;; - - *) - cat >conftest.c <<EOF -# include <sys/types.h> -# include <sys/wait.h> -# include <stdio.h> - unsigned char a[5] = { 1, 2, 3, 4, 5 }; - main() { - unsigned int i; - pid_t pid; - int status; - /* avoid "core dumped" message */ - pid = fork(); - if (pid < 0) - exit(2); - if (pid > 0) { - /* parent */ - pid = waitpid(pid, &status, 0); - if (pid < 0) - exit(3); - exit(!WIFEXITED(status)); - } - /* child */ - i = *(unsigned int *)&a[1]; - printf("%d\n", i); - exit(0); - } -EOF - ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \ - conftest.c $LIBS >/dev/null 2>&1 - if test ! -x conftest ; then - ac_cv_lbl_unaligned_fail=yes - else - ./conftest >conftest.out - if test ! -s conftest.out ; then - ac_cv_lbl_unaligned_fail=yes - else - ac_cv_lbl_unaligned_fail=no - fi - fi - rm -f -r conftest* core core.conftest - ;; - esac -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_unaligned_fail" >&5 -$as_echo "$ac_cv_lbl_unaligned_fail" >&6; } - if test $ac_cv_lbl_unaligned_fail = yes ; then - -$as_echo "#define LBL_ALIGN 1" >>confdefs.h - - fi - # Check for OpenSSL/libressl libcrypto { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use OpenSSL/libressl libcrypto" >&5 $as_echo_n "checking whether to use OpenSSL/libressl libcrypto... " >&6; } diff --git a/configure.in b/configure.in index 654d973a..ef0e8f4f 100644 --- a/configure.in +++ b/configure.in @@ -815,8 +815,6 @@ AC_CHECK_TOOL([AR], [ar]) AC_LBL_DEVEL(V_CCOPT) -AC_LBL_UNALIGNED_ACCESS - # Check for OpenSSL/libressl libcrypto AC_MSG_CHECKING(whether to use OpenSSL/libressl libcrypto) # Specify location for both includes and libraries. @@ -62,19 +62,54 @@ #define UNALIGNED_OK #endif -#ifdef LBL_ALIGN +#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \ + (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \ + (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \ + (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \ + (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) /* - * The processor doesn't natively handle unaligned loads. + * The processor natively handles unaligned loads, so we can just + * cast the pointer and fetch through it. + * + * XXX - are those all the x86 tests we need? + * XXX - do we need to worry about ARMv1 through ARMv5, which didn't + * support unaligned loads, and, if so, do we need to worry about all + * of them, or just some of them, e.g. ARMv5? + * XXX - are those the only 68k tests we need not to generated + * unaligned accesses if the target is the 68000 or 68010? + * XXX - are there any tests we don't need, because some definitions are for + * compilers that also predefine the GCC symbols? + * XXX - do we need to test for both 32-bit and 64-bit versions of those + * architectures in all cases? */ -#if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \ +static inline uint16_t UNALIGNED_OK +EXTRACT_16BITS(const void *p) +{ + return ((uint16_t)ntohs(*(const uint16_t *)(p))); +} + +static inline uint32_t UNALIGNED_OK +EXTRACT_32BITS(const void *p) +{ + return ((uint32_t)ntohl(*(const uint32_t *)(p))); +} + +static inline uint64_t UNALIGNED_OK +EXTRACT_64BITS(const void *p) +{ + return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | + ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0)); + +} +#elif defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \ (defined(__alpha) || defined(__alpha__) || \ defined(__mips) || defined(__mips__)) - /* -* This is a GCC-compatible compiler and we have __attribute__, which - * we assume that mean we have __attribute__((packed)), and this is - * MIPS or Alpha, which has instructions that can help when doing - * unaligned loads. + * This is MIPS or Alpha, which don't natively handle unaligned loads, + * but which have instructions that can help when doing unaligned + * loads, and this is a GCC-compatible compiler and we have __attribute__, + * which we assume that mean we have __attribute__((packed)), which + * we can use to convince the compiler to generate those instructions. * * Declare packed structures containing a uint16_t and a uint32_t, * cast the pointer to point to one of those, and fetch through it; @@ -146,10 +181,10 @@ EXTRACT_64BITS(const void *p) return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0)); } - -#else /* have to do it a byte at a time */ +#else /* - * This isn't a GCC-compatible compiler, we don't have __attribute__, + * This architecture doesn't natively support unaligned loads, and either + * this isn't a GCC-compatible compiler, we don't have __attribute__, * or we do but we don't know of any better way with this instruction * set to do unaligned loads, so do unaligned loads of big-endian * quantities the hard way - fetch the bytes one at a time and @@ -172,33 +207,7 @@ EXTRACT_64BITS(const void *p) ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \ ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \ ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0))) -#endif /* must special-case unaligned accesses */ -#else /* LBL_ALIGN */ -/* - * The processor natively handles unaligned loads, so we can just - * cast the pointer and fetch through it. - */ -static inline uint16_t UNALIGNED_OK -EXTRACT_16BITS(const void *p) -{ - return ((uint16_t)ntohs(*(const uint16_t *)(p))); -} - -static inline uint32_t UNALIGNED_OK -EXTRACT_32BITS(const void *p) -{ - return ((uint32_t)ntohl(*(const uint32_t *)(p))); -} - -static inline uint64_t UNALIGNED_OK -EXTRACT_64BITS(const void *p) -{ - return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | - ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0)); - -} - -#endif /* LBL_ALIGN */ +#endif /* unaligned access checks */ #define EXTRACT_24BITS(p) \ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \ diff --git a/netdissect.h b/netdissect.h index e8d1f3c2..90bc8050 100644 --- a/netdissect.h +++ b/netdissect.h @@ -340,7 +340,30 @@ extern void txtproto_print(netdissect_options *, const u_char *, u_int, extern void safeputchar(netdissect_options *, const u_char); extern void safeputs(netdissect_options *, const u_char *, const u_int); -#ifdef LBL_ALIGN +#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \ + (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \ + (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \ + (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \ + (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \ + defined(__vax__) +/* + * The procesor natively handles unaligned loads, so just use memcpy() + * and memcmp(), to enable those optimizations. + * + * XXX - are those all the x86 tests we need? + * XXX - do we need to worry about ARMv1 through ARMv5, which didn't + * support unaligned loads, and, if so, do we need to worry about all + * of them, or just some of them, e.g. ARMv5? + * XXX - are those the only 68k tests we need not to generated + * unaligned accesses if the target is the 68000 or 68010? + * XXX - are there any tests we don't need, because some definitions are for + * compilers that also predefine the GCC symbols? + * XXX - do we need to test for both 32-bit and 64-bit versions of those + * architectures in all cases? + */ +#define UNALIGNED_MEMCPY(p, q, l) memcpy((p), (q), (l)) +#define UNALIGNED_MEMCMP(p, q, l) memcmp((p), (q), (l)) +#else /* * The processor doesn't natively handle unaligned loads, * and the compiler might "helpfully" optimize memcpy() @@ -356,13 +379,6 @@ extern void unaligned_memcpy(void *, const void *, size_t); extern int unaligned_memcmp(const void *, const void *, size_t); #define UNALIGNED_MEMCPY(p, q, l) unaligned_memcpy((p), (q), (l)) #define UNALIGNED_MEMCMP(p, q, l) unaligned_memcmp((p), (q), (l)) -#else -/* - * The procesor natively handles unaligned loads, so just use memcpy() - * and memcmp(), to enable those optimizations. - */ -#define UNALIGNED_MEMCPY(p, q, l) memcpy((p), (q), (l)) -#define UNALIGNED_MEMCMP(p, q, l) memcmp((p), (q), (l)) #endif #define PLURAL_SUFFIX(n) \ diff --git a/util-print.c b/util-print.c index 25ea1386..892e07a7 100644 --- a/util-print.c +++ b/util-print.c @@ -946,11 +946,38 @@ safeputchar(netdissect_options *ndo, ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c)); } -#ifdef LBL_ALIGN +#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \ + (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \ + (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \ + (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \ + (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \ + defined(__vax__) /* - * Some compilers try to optimize memcpy(), using the alignment constraint - * on the argument pointer type. by using this function, we try to avoid the - * optimization. + * The procesor natively handles unaligned loads, so just use memcpy() + * and memcmp(), to enable those optimizations. + * + * XXX - are those all the x86 tests we need? + * XXX - do we need to worry about ARMv1 through ARMv5, which didn't + * support unaligned loads, and, if so, do we need to worry about all + * of them, or just some of them, e.g. ARMv5? + * XXX - are those the only 68k tests we need not to generated + * unaligned accesses if the target is the 68000 or 68010? + * XXX - are there any tests we don't need, because some definitions are for + * compilers that also predefine the GCC symbols? + * XXX - do we need to test for both 32-bit and 64-bit versions of those + * architectures in all cases? + */ +#else +/* + * The processor doesn't natively handle unaligned loads, + * and the compiler might "helpfully" optimize memcpy() + * and memcmp(), when handed pointers that would normally + * be properly aligned, into sequences that assume proper + * alignment. + * + * Do copies and compares of possibly-unaligned data by + * calling routines that wrap memcpy() and memcmp(), to + * prevent that optimization. */ void unaligned_memcpy(void *p, const void *q, size_t l) |