Fix calculation of zero offset.

gcc emits `.zero 8` for 8 bytes of zero rather than `.xword 0`. This
corrects the faulty logic that was trying to handle that before.

This also adds logic to check that the calculated offsets are correct
when doing a build to catch error like this in future.

Change-Id: Ic4fbb958e71b1ee1c025458ee5d2b241f989803d
diff --git a/Makefile b/Makefile
index fdcfd6c..888e823 100644
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,7 @@
   TGT := $(patsubst %.c,%.o,$(OUT)/$(patsubst src/%,%,$(1)))
   GLOBAL_OBJS += $$(TGT)
   REMAIN_SRCS := $$(filter-out $(1),$$(REMAIN_SRCS))
-$$(TGT): $(ROOT_DIR)$(1) | $$(dir $$(TGT))
+$$(TGT): $(ROOT_DIR)$(1) $(GLOBAL_OFFSETS) | $$(dir $$(TGT))
 	$$(info CC $(ROOT_DIR)$1)
 	@$(CC) $(COPTS) $(DEP_GEN) -c $(ROOT_DIR)$(1) -o $$@
 endef
@@ -100,10 +100,11 @@
   GLOBAL_OFFSETS += $$(TGT)
 $$(TGT): $(ROOT_DIR)$(1) | $$(dir $$(TGT))
 	$$(info GENOFFSET $(ROOT_DIR)$1)
-	@$(CC) $(COPTS) $(DEP_GEN) -MT $$@ -S -c $(ROOT_DIR)$(1) -o - | \
+	@$(CC) -DGEN_OFFSETS $(COPTS) $(DEP_GEN) -MT $$@ -S -c $(ROOT_DIR)$(1) -o - | \
 		grep ^DEFINE_OFFSET -A1 | \
 		grep -v ^--$ | \
 		sed 's/^DEFINE_OFFSET__\([^:]*\):/#define \1 \\/' | \
+		sed 's/\.zero.*/0/' | \
 		sed 's/\.[^\t][^\t]*//' > $$@
 endef
 
@@ -170,7 +171,7 @@
 	@find $(ROOT_DIR)inc/ -name *.c -o -name *.h | xargs clang-format -style file -i
 
 # see .clang-tidy
-tidy:
+tidy: $(GLOBAL_OFFSETS)
 	@find $(ROOT_DIR)src/ -name *.c -exec clang-tidy {} -fix -- -target $(TARGET) $(COPTS) \;
 
 -include $(patsubst %,%.d,$(GLOBAL_OBJS),$(GLOBAL_OFFSETS))
diff --git a/inc/decl_offsets.h b/inc/decl_offsets.h
index fbcff34..ede3ad7 100644
--- a/inc/decl_offsets.h
+++ b/inc/decl_offsets.h
@@ -1,9 +1,35 @@
 #ifndef _DECL_OFFSETS_H
 #define _DECL_OFFSETS_H
 
+#ifdef GEN_OFFSETS
+
+/* When generating offsets, create constants which can be extracted from the
+ * generated assembly. */
+
 #define DECL(name, type, field) \
 	const size_t DEFINE_OFFSET__##name = offsetof(type, field)
 
 #define DECL_SIZE(name, type) const size_t DEFINE_OFFSET__name = sizeof(type)
 
+#else /* GEN_OFFSETS */
+
+/* When not generating offsets, validate that the extracted values are as
+ * expected. */
+
+#include <assert.h>
+
+#define DECL(name, type, field) DECL_1(#name, name, offsetof(type, field))
+#define DECL_1(name, actual, expected)                       \
+	static_assert((actual) == (expected),                \
+		      "Offset " name " should be " #expected \
+		      " and not " #actual)
+
+#define DECL_SIZE(name, type) DECL_SIZE_1(#name, name, sizeof(type))
+#define DECL_SIZE_1(name, actual, expected)                 \
+	static_assert((actual) == (expected),               \
+		      "Size " #name " should be " #expected \
+		      " and not" #actual)
+
+#endif /* GEN_OFFSETS */
+
 #endif /* _DECL_OFFSETS_H */
diff --git a/src/arch/aarch64/offsets.c b/src/arch/aarch64/offsets.c
index 8c49fed..8e7e9df 100644
--- a/src/arch/aarch64/offsets.c
+++ b/src/arch/aarch64/offsets.c
@@ -1,3 +1,7 @@
+#ifndef GEN_OFFSETS
+#include "offsets.h"
+#endif /* GEN_OFFSETS */
+
 #include "cpu.h"
 #include "decl_offsets.h"
 
diff --git a/src/arch/aarch64/rules.mk b/src/arch/aarch64/rules.mk
index 4abf817..a006751 100644
--- a/src/arch/aarch64/rules.mk
+++ b/src/arch/aarch64/rules.mk
@@ -2,6 +2,7 @@
 SRCS += exceptions.S
 SRCS += handler.c
 SRCS += mm.c
+SRCS += offsets.c
 SRCS += params.c
 
 OFFSET_SRCS += offsets.c