summaryrefslogtreecommitdiff
path: root/extract.h
diff options
context:
space:
mode:
Diffstat (limited to 'extract.h')
-rw-r--r--extract.h49
1 files changed, 41 insertions, 8 deletions
diff --git a/extract.h b/extract.h
index 23623c28..2ea4ca80 100644
--- a/extract.h
+++ b/extract.h
@@ -20,8 +20,41 @@
*/
/*
- * Macros to extract possibly-unaligned big-endian integral values.
+ * Inline functions or macros to extract possibly-unaligned big-endian
+ * integral values.
*/
+#include "funcattrs.h"
+
+/*
+ * If we have versions of GCC or Clang that support an __attribute__
+ * to say "if we're building with unsigned behavior sanitization,
+ * don't complain about undefined behavior in this function", we
+ * label these functions with that attribute - we *know* it's undefined
+ * in the C standard, but we *also* know it does what we want with
+ * the ISA we're targeting and the compiler we're using.
+ *
+ * For GCC 4.9.0 and later, we use __attribute__((no_sanitize_undefined));
+ * pre-5.0 GCC doesn't have __has_attribute, and I'm not sure whether
+ * GCC or Clang first had __attribute__((no_sanitize(XXX)).
+ *
+ * For Clang, we check for __attribute__((no_sanitize(XXX)) with
+ * __has_attribute, as there are versions of Clang that support
+ * __attribute__((no_sanitize("undefined")) but don't support
+ * __attribute__((no_sanitize_undefined)).
+ *
+ * We define this here, rather than in funcattrs.h, because we
+ * only want it used here, we don't want it to be broadly used.
+ * (Any printer will get this defined, but this should at least
+ * make it harder for people to find.)
+ */
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409)
+#define UNALIGNED_OK __attribute__((no_sanitize_undefined))
+#elif __has_attribute(no_sanitize)
+#define UNALIGNED_OK __attribute__((no_sanitize("undefined")))
+#else
+#define UNALIGNED_OK
+#endif
+
#ifdef LBL_ALIGN
/*
* The processor doesn't natively handle unaligned loads.
@@ -31,7 +64,7 @@
defined(__mips) || defined(__mips__))
/*
- * This is a GCC-compatible compiler and we have __attribute__, which
+* 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.
@@ -88,19 +121,19 @@ typedef struct {
uint32_t val;
} __attribute__((packed)) unaligned_uint32_t;
-static inline uint16_t
+UNALIGNED_OK static inline uint16_t
EXTRACT_16BITS(const void *p)
{
return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
}
-static inline uint32_t
+UNALIGNED_OK static inline uint32_t
EXTRACT_32BITS(const void *p)
{
return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
}
-static inline uint64_t
+UNALIGNED_OK static inline uint64_t
EXTRACT_64BITS(const void *p)
{
return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 |
@@ -138,19 +171,19 @@ EXTRACT_64BITS(const void *p)
* The processor natively handles unaligned loads, so we can just
* cast the pointer and fetch through it.
*/
-static inline uint16_t
+static inline uint16_t UNALIGNED_OK
EXTRACT_16BITS(const void *p)
{
return ((uint16_t)ntohs(*(const uint16_t *)(p)));
}
-static inline uint32_t
+static inline uint32_t UNALIGNED_OK
EXTRACT_32BITS(const void *p)
{
return ((uint32_t)ntohl(*(const uint32_t *)(p)));
}
-static inline uint64_t
+static inline uint64_t UNALIGNED_OK
EXTRACT_64BITS(const void *p)
{
return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |