Auto-generate header of struct offsets/sizes
Code written in assembly needs to be told the offsets of struct members.
Currently these are hardcoded and static_assert-ed at compile time,
requiring manual updates every time struct declarations change.
This patch adds a mechanism for auto-generating a header with these
constants.
It uses a "hack" similar to other projects, e.g. Linux, where the
integer constant is used as an immediate in an inline assembly block.
The file is compiled and the constant extracted by a script which
generates the header file. For easy grep-ing, the constant is compiled
into a '.ascii' string, surrounded by magic strings, and extracted using
the 'strings' binutils tool.
To guarantee correctness, the same source file is compiled again as part
of the Hafnium binary but this time the declarations are converted to
static_asserts which check the values.
Fix: 120137356
Test: ./kokoru/ubuntu/build.sh
Change-Id: I551126519675e73cb01b4beb4ff9b1200b9b3de7
diff --git a/inc/hf/offset_size_header.h b/inc/hf/offset_size_header.h
new file mode 100644
index 0000000..7d96950
--- /dev/null
+++ b/inc/hf/offset_size_header.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This header file is intended for use by files compiled with the
+ * 'offset_size_header' build rule. See overview in 'offset_size_header.gni'.
+ */
+
+#pragma once
+
+#if (defined GENERATE_BINARY) && (defined VERIFY_HEADER)
+#error Only one action can be specified
+
+#elif defined GENERATE_BINARY
+
+/**
+ * File being compiled to generate binaries with definitions of constants.
+ */
+
+/**
+ * Emit a function with an embedded string in the format:
+ * <HAFNIUM_DEFINE name #value />
+ * These will be recognized by a script that generates the header file.
+ */
+#define DEFINE(sym, val) \
+ void gen_header__##sym(void) \
+ { \
+ __asm__ volatile( \
+ "\n" \
+ ".ascii \"\\n<HAFNIUM_DEFINE " #sym \
+ " %0 />\\n\"\n" \
+ ".align 8\n" /* Align epilogue */ \
+ : \
+ : "i"(val)); \
+ }
+
+#define DEFINE_SIZEOF(sym, type) DEFINE(sym, sizeof(type))
+#define DEFINE_OFFSETOF(sym, type, field) DEFINE(sym, offsetof(type, field))
+
+#elif defined VERIFY_HEADER
+
+/**
+ * File being compiled as part of the main build to check the values in
+ * the auto-generated header file (included using a command-line flag).
+ */
+
+#include "hf/static_assert.h"
+
+#define DEFINE_SIZEOF(sym, type) \
+ void gen_header__##sym(void) \
+ { \
+ static_assert(sizeof(type) == sym, \
+ "Generated struct size mismatch"); \
+ }
+
+#define DEFINE_OFFSETOF(sym, type, field) \
+ void gen_header__##sym(void) \
+ { \
+ static_assert(offsetof(type, field) == sym, \
+ "Generated struct offset mismatch"); \
+ }
+
+#else
+#error No action specified
+#endif