From: Alberto Bertogli <albertito@blitiri.com.ar>
Date: Sun, 28 Aug 2022 10:18:52 +0000 (11:18 +0100)
Subject: tests: Prevent compiler from inlining stack test functions

The tests for enable_stack() and enable_stack_by_name() depend on being
able to identify specific functions in the stack. If those functions are
inlined, they may not appear in the backtrace information and cause the
tests to fail.

For example, this happens when the test is built with
CFLAGS="-flto=auto -O2", as reported in https://bugs.debian.org/1015487.

This patch fixes the problem by telling the compiler not to inline those
specific test functions. The attribute used works at least with GCC
(tested), clang (tested), and icc (based on documentation).

The documentation is also updated to explicitly mention this, to prevent
users from getting confused due to this same problem on their own builds.
---

diff --git a/libfiu/fiu-control.h b/libfiu/fiu-control.h
index 88686cf..03aa5e0 100644
--- a/libfiu/fiu-control.h
+++ b/libfiu/fiu-control.h
@@ -73,16 +73,19 @@ int fiu_enable_external(const char *name, int failnum, void *failinfo,
  * the stack at the given position.
  *
  * This function relies on GNU extensions such as backtrace() and dladdr(), so
- * it may not be available on your platform.
+ * it may not be available on your platform. It's also quite dependent on
+ * compiler behaviour; for example, inline functions may not show up on the
+ * backtrace.
  *
- * - name: point of failure name.
- * - failnum: what will fiu_fail() return, must be != 0.
- * - failinfo: what will fiu_failinfo() return.
- * - flags: flags.
- * - func: pointer to the function.
- * - func_pos: position where we expect the function to be; use -1 for "any".
- * 	Values other than -1 are not supported at the moment, but will be in
- * 	the future.
+ * @param name Name of the point of failure to enable.
+ * @param failnum  What will fiu_fail() return, must be != 0.
+ * @param failinfo  What will fiu_failinfo() return.
+ * @param flags  Flags.
+ * @param func  Pointer to the function.
+ * @param func_pos  Position where we expect the function to be; use -1 for
+ * 		"any".  Values other than -1 are not supported at the moment,
+ * 		but will be in the future.
+ * @returns  0 if success, < 0 otherwise (e.g. backtrace() is not functional).
  */
 int fiu_enable_stack(const char *name, int failnum, void *failinfo,
 		unsigned int flags, void *func, int func_pos_in_stack);
@@ -91,7 +94,9 @@ int fiu_enable_stack(const char *name, int failnum, void *failinfo,
  * the stack at 'func_pos_in_stack'.
  *
  * This function relies on GNU extensions such as backtrace() and dladdr(), so
- * if your platform does not support them, it will always return failure.
+ * if your platform does not support them, it will always return failure. It's
+ * also quite dependent on compiler behaviour; for example, inline functions
+ * may not show up on the backtrace.
  *
  * It is exactly like fiu_enable_stack() but takes a function name, it will
  * ask the dynamic linker to find the corresponding function pointer.
@@ -104,7 +109,7 @@ int fiu_enable_stack(const char *name, int failnum, void *failinfo,
  * @param func_pos_in_stack  Position where we expect the function to be; use
  * 		-1 for "any". Values other than -1 are not supported at the
  * 		moment, but will be in the future.
- * @returns  0 if success, < 0 otherwise.
+ * @returns  0 if success, < 0 otherwise (e.g. backtrace() is not functional).
  */
 int fiu_enable_stack_by_name(const char *name, int failnum, void *failinfo,
 		unsigned int flags, const char *func_name,
diff --git a/tests/test-enable_stack.c b/tests/test-enable_stack.c
index a5d2c54..2a158ab 100644
--- a/tests/test-enable_stack.c
+++ b/tests/test-enable_stack.c
@@ -6,7 +6,7 @@
 #include <fiu.h>
 #include <fiu-control.h>
 
-int func1()
+int __attribute__ ((noinline)) func1()
 {
 	/*
 	int nptrs;
@@ -18,7 +18,7 @@ int func1()
 	return fiu_fail("fp-1") != 0;
 }
 
-int func2()
+int __attribute__ ((noinline)) func2()
 {
 	return func1();
 }
diff --git a/tests/test-enable_stack_by_name.c b/tests/test-enable_stack_by_name.c
index d769728..1d4334b 100644
--- a/tests/test-enable_stack_by_name.c
+++ b/tests/test-enable_stack_by_name.c
@@ -6,7 +6,7 @@
 #include <fiu.h>
 #include <fiu-control.h>
 
-int func1()
+int __attribute__ ((noinline)) func1()
 {
 	/*
 	int nptrs;
@@ -18,7 +18,7 @@ int func1()
 	return fiu_fail("fp-1") != 0;
 }
 
-int func2()
+int __attribute__ ((noinline)) func2()
 {
 	return func1();
 }

