aboutsummaryrefslogtreecommitdiffstats
path: root/get_stack_direction.c
diff options
context:
space:
mode:
Diffstat (limited to 'get_stack_direction.c')
-rw-r--r--get_stack_direction.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/get_stack_direction.c b/get_stack_direction.c
new file mode 100644
index 0000000..2f639da
--- /dev/null
+++ b/get_stack_direction.c
@@ -0,0 +1,62 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+#ifdef SUPPORTED
+# undef SUPPORTED
+#endif
+
+
+#if defined(__GNUC__)
+# define SUPPORTED
+
+__attribute__((__noinline__))
+static void *
+get_callee_frame_address(void)
+{
+ return __builtin_frame_address(0);
+}
+
+
+__attribute__((__noinline__))
+static int
+get_stack_direction(void)
+{
+ void *callerptr, *calleeptr;
+ uintptr_t caller, callee;
+ callerptr = __builtin_frame_address(0);
+ calleeptr = get_callee_frame_address();
+ caller = (uintptr_t)callerptr;
+ callee = (uintptr_t)calleeptr;
+ return callee > caller ? +1 : callee < caller ? -1 : 0;
+}
+
+#endif
+
+
+int
+libsimple_get_stack_direction(void)
+{
+#ifdef SUPPORTED
+ int r = get_stack_direction();
+ if (!r)
+ errno = ENOTSUP;
+ return r;
+#else
+ errno = ENOTSUP;
+ return 0;
+#endif
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void)
+{
+ return 0;
+}
+
+#endif