#define HA_HAVE_CRYPT_R
#endif
+/* some backtrace() implementations are broken or incomplete, in this case we
+ * can replace them. We must not do it all the time as some are more accurate
+ * than ours.
+ */
+#ifdef USE_BACKTRACE
+#if defined(__aarch64__)
+/* on aarch64 at least from gcc-4.7.4 to 7.4.1 we only get a single entry, which
+ * is pointless. Ours works though it misses the faulty function itself,
+ * probably due to an alternate stack for the signal handler which does not
+ * create a new frame hence doesn't store the caller's return address.
+ */
+#else
+#define HA_HAVE_WORKING_BACKTRACE
+#endif
+#endif
+
#endif /* _COMMON_COMPAT_H */
/*
#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>
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)
{
*/
-#ifdef USE_BACKTRACE
-#define _GNU_SOURCE
-#include <execinfo.h>
-#endif
-
#include <fcntl.h>
#include <signal.h>
#include <time.h>
void *addr;
int dump = 0;
- nptrs = backtrace(callers, sizeof(callers)/sizeof(*callers));
+ nptrs = my_backtrace(callers, sizeof(callers)/sizeof(*callers));
/* The call backtrace_symbols_fd(callers, nptrs, STDOUT_FILENO)
would produce similar output to the following: */
* ready in memory for later use.
*/
void *callers[1];
- backtrace(callers, sizeof(callers)/sizeof(*callers));
+ my_backtrace(callers, sizeof(callers)/sizeof(*callers));
#endif
sa.sa_handler = NULL;
sa.sa_sigaction = debug_handler;