summaryrefslogtreecommitdiff
path: root/tools/objtool/tests/generic/fixtures/ubsan_noise.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/objtool/tests/generic/fixtures/ubsan_noise.c')
-rw-r--r--tools/objtool/tests/generic/fixtures/ubsan_noise.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/tools/objtool/tests/generic/fixtures/ubsan_noise.c b/tools/objtool/tests/generic/fixtures/ubsan_noise.c
new file mode 100644
index 000000000000..bf5999254163
--- /dev/null
+++ b/tools/objtool/tests/generic/fixtures/ubsan_noise.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * A translation unit built with UBSAN, where only one of two functions is
+ * patched.
+ *
+ * Every instrumented operation gets a per-callsite metadata object in an
+ * anonymous data section -- .data..Lubsan_data and .data..Lubsan_type from
+ * GCC, .data..L__unnamed_ from Clang -- and a call to a __ubsan_handle_*
+ * routine. The names are compiler-generated and carry no meaning across a
+ * rebuild, so klp diff has to treat those sections as uncorrelated rather than
+ * pairing them up by name.
+ *
+ * untouched() is byte-identical in both builds and exists to catch the false
+ * positive: if the metadata were correlated by name, its shifts would look
+ * changed and it would be dragged into the patch.
+ *
+ * The shifts are what draw the instrumentation. A bounds check would do as
+ * well but neither compiler emits one for an index it can prove in range.
+ */
+
+static const char __modinfo[]
+ __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
+
+int shift_by(int v, int n);
+
+int untouched(int v, int n)
+{
+ int s = 0;
+
+ s += v << (n & 31);
+ s += v << ((n + 1) & 31);
+ s += shift_by(v, n);
+
+ return s;
+}
+
+int touched(int v, int n)
+{
+ int s = 0;
+
+ s += v << (n & 31);
+#ifdef PATCHED
+ s += v << ((n + 3) & 31);
+#else
+ s += v << ((n + 2) & 31);
+#endif
+
+ return s;
+}