]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Prevent GCC from doing some alignment-unsafe optimizations on SPARC.
authorGuy Harris <[email protected]>
Sun, 15 Aug 2010 00:31:04 +0000 (17:31 -0700)
committerGuy Harris <[email protected]>
Sun, 15 Aug 2010 00:32:21 +0000 (17:32 -0700)
At least some versions of GCC will, on SPARC, generate code for

if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) {

where bp is a pointer to a struct bootp, that loads the first 4-byte
word in that structure, masks out the field in that structure that's not
being compared, and compares against a word with the appropriate values
in the other fields.  That won't work, because there's no guarantee that
bp points to a value aligned on a 4-byte boundary.

Declaring "struct bootp" to be packed appears to keep at least GCC 4.2.4
from performing that optimization; we define an "UNALIGNED" tag to apply
to structures to prevent that optimization, and apply that tag to the
structures in bootp.h.  (We'll apply it to other structures as we
discover the need for it.)

bootp.h
interface.h

diff --git a/bootp.h b/bootp.h
index 65ca3766c713c181d762d821c88482126564652c..b1b81dce908434b1d1ba95b5ab9837a46582d809 100644 (file)
--- a/bootp.h
+++ b/bootp.h
@@ -37,7 +37,7 @@ struct bootp {
        u_int8_t        bp_sname[64];   /* server host name */
        u_int8_t        bp_file[128];   /* boot file name */
        u_int8_t        bp_vend[64];    /* vendor-specific area */
-};
+} UNALIGNED;
 
 /*
  * UDP port numbers, server and client.
@@ -217,7 +217,7 @@ struct cmu_vend {
        struct in_addr  v_ins1, v_ins2; /* IEN-116 name servers */
        struct in_addr  v_ts1, v_ts2;   /* Time servers */
        u_int8_t        v_unused[24];   /* currently unused */
-};
+} UNALIGNED;
 
 
 /* v_flags values */
index 58ccbfce2525f2d64ed44311e481ddb593c531c9..06f1ffe3d8e867648a268f2e6d9cd3e21766be6a 100644 (file)
 #define __attribute__(x)
 #endif
 
+/*
+ * Used to declare a structure unaligned, so that the C compiler,
+ * if necessary, generates code that doesn't assume alignment.
+ * This is required because there is no guarantee that the packet
+ * data we get from libpcap/WinPcap is properly aligned.
+ *
+ * This assumes that, for all compilers that support __attribute__:
+ *
+ *     1) they support __attribute__((packed));
+ *
+ *     2) for all instruction set architectures requiring strict
+ *        alignment, declaring a structure with that attribute
+ *        causes the compiler to generate code that handles
+ *        misaligned 2-byte, 4-byte, and 8-byte integral
+ *        quantities.
+ *
+ * It does not (yet) handle compilers where you can get the compiler
+ * to generate code of that sort by some other means.
+ *
+ * This is required in order to, for example, keep the compiler from
+ * generating, for
+ *
+ *     if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) {
+ *
+ * in print-bootp.c, code that loads the first 4-byte word of a
+ * "struct bootp", masking out the bp_hops field, and comparing the result
+ * against 0x01010600.
+ *
+ * Note: this also requires that padding be put into the structure,
+ * at least for compilers where it's implemented as __attribute__((packed)).
+ */
+#define UNALIGNED      __attribute__((packed))
+
 /* snprintf et al */
 
 #include <stdarg.h>