MINOR: debug: improve backtrace() on aarch64 and possibly other systems

It happens that on aarch64 backtrace() only returns one entry (tested
with gcc 4.7.4, 5.5.0 and 7.4.1). Probably that it refrains from unwinding
the stack due to the risk of hitting a bad pointer. Here we can use
may_access() to know when it's safe, so we can actually unwind the stack
without taking risks. It happens that the faulting function (the one
just after the signal handler) is not listed here, very likely because
the signal handler uses a special stack and did not create a new frame.

So this patch creates a new my_backtrace() function in standard.h that
either calls backtrace() or does its own unrolling. The choice depends
on HA_HAVE_WORKING_BACKTRACE which is set in compat.h based on the build
target.
diff --git a/include/common/standard.h b/include/common/standard.h
index b278f08..a780833 100644
--- a/include/common/standard.h
+++ b/include/common/standard.h
@@ -22,6 +22,11 @@
 #ifndef _COMMON_STANDARD_H
 #define _COMMON_STANDARD_H
 
+#ifdef USE_BACKTRACE
+#define _GNU_SOURCE
+#include <execinfo.h>
+#endif
+
 #include <limits.h>
 #include <string.h>
 #include <stdio.h>
@@ -1487,6 +1492,31 @@
 int may_access(const void *ptr);
 void *resolve_sym_name(struct buffer *buf, const char *pfx, void *addr);
 
+#if defined(USE_BACKTRACE)
+/* Note that this may result in opening libgcc() on first call, so it may need
+ * to have been called once before chrooting.
+ */
+static forceinline int my_backtrace(void **buffer, int max)
+{
+#ifdef HA_HAVE_WORKING_BACKTRACE
+	return backtrace(buffer, max);
+#else
+	const struct frame {
+		const struct frame *next;
+		void *ra;
+	} *frame;
+	int count;
+
+	frame = __builtin_frame_address(0);
+	for (count = 0; count < max && may_access(frame) && may_access(frame->ra);) {
+		buffer[count++] = frame->ra;
+		frame = frame->next;
+	}
+	return count;
+#endif
+}
+#endif
+
 /* same as realloc() except that ptr is also freed upon failure */
 static inline void *my_realloc2(void *ptr, size_t size)
 {