summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--backends/ChangeLog6
-rw-r--r--backends/Makefile.am2
-rw-r--r--backends/aarch64_init.c1
-rw-r--r--backends/aarch64_unwind.c83
-rw-r--r--tests/ChangeLog10
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/backtrace-subr.sh2
-rw-r--r--tests/backtrace.aarch64.fp.core.bz2bin0 -> 8437 bytes
-rw-r--r--tests/backtrace.aarch64.fp.exec.bz2bin0 -> 394972 bytes
-rw-r--r--tests/backtrace.c12
-rwxr-xr-xtests/run-backtrace-fp-core-aarch64.sh28
11 files changed, 145 insertions, 2 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 8b1c4f52..1ac5bab3 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -6,6 +6,12 @@
2017-02-09 Ulf Hermann <[email protected]>
+ * aarch64_unwind.c: New file
+ * Makefile.am (aarch64_SRCS): Add aarch64_unwind.c
+ * aarch64_init.c (aarch64_init): Hook aarch64_unwind
+
+2017-02-09 Ulf Hermann <[email protected]>
+
* x86_64_unwind.c: New file
* Makefile.am (x86_64_SRCS): Add x86_64_unwind.c
* x86_64_init.c (x86_64_init): Hook x86_64_unwind
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 22eb6ac6..ff80a82c 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -80,7 +80,7 @@ am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
aarch64_SRCS = aarch64_init.c aarch64_regs.c aarch64_symbol.c \
aarch64_corenote.c aarch64_retval.c aarch64_cfi.c \
- aarch64_initreg.c
+ aarch64_initreg.c aarch64_unwind.c
libebl_aarch64_pic_a_SOURCES = $(aarch64_SRCS)
am_libebl_aarch64_pic_a_OBJECTS = $(aarch64_SRCS:.c=.os)
diff --git a/backends/aarch64_init.c b/backends/aarch64_init.c
index 6395f117..08664943 100644
--- a/backends/aarch64_init.c
+++ b/backends/aarch64_init.c
@@ -63,6 +63,7 @@ aarch64_init (Elf *elf __attribute__ ((unused)),
+ ALT_FRAME_RETURN_COLUMN (used when LR isn't used) = 97 DWARF regs. */
eh->frame_nregs = 97;
HOOK (eh, set_initial_registers_tid);
+ HOOK (eh, unwind);
return MODVERSION;
}
diff --git a/backends/aarch64_unwind.c b/backends/aarch64_unwind.c
new file mode 100644
index 00000000..e0a7e96e
--- /dev/null
+++ b/backends/aarch64_unwind.c
@@ -0,0 +1,83 @@
+/* Get previous frame state for an existing frame state.
+ Copyright (C) 2016 The Qt Company Ltd.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND aarch64_
+#define FP_REG 29
+#define LR_REG 30
+#define SP_REG 31
+#define FP_OFFSET 0
+#define LR_OFFSET 8
+#define SP_OFFSET 16
+
+#include "libebl_CPU.h"
+
+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */
+
+bool
+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
+ ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+ ebl_pid_memory_read_t *readfunc, void *arg,
+ bool *signal_framep __attribute__ ((unused)))
+{
+ Dwarf_Word fp, lr, sp;
+
+ if (!getfunc(LR_REG, 1, &lr, arg))
+ return false;
+
+ if (lr == 0 || !setfunc(-1, 1, &lr, arg))
+ return false;
+
+ if (!getfunc(FP_REG, 1, &fp, arg))
+ fp = 0;
+
+ if (!getfunc(SP_REG, 1, &sp, arg))
+ sp = 0;
+
+ Dwarf_Word newLr, newFp, newSp;
+
+ if (!readfunc(fp + LR_OFFSET, &newLr, arg))
+ newLr = 0;
+
+ if (!readfunc(fp + FP_OFFSET, &newFp, arg))
+ newFp = 0;
+
+ newSp = fp + SP_OFFSET;
+
+ // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
+ setfunc(LR_REG, 1, &newLr, arg);
+ setfunc(FP_REG, 1, &newFp, arg);
+ setfunc(SP_REG, 1, &newSp, arg);
+
+ // If the fp is invalid, we might still have a valid lr.
+ // But if the fp is valid, then the stack should be moving in the right direction.
+ return fp == 0 || newSp > sp;
+}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 81b5f7a2..5b0d486e 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,13 @@
+2017-02-13 Ulf Hermann <[email protected]>
+ Mark Wielaard <[email protected]>
+
+ * Makefile.am: Add test for unwinding with frame pointers on aarch64
+ * backtrace.aarch64.fp.core.bz2: New file
+ * backtrace.aarch64.fp.exec.bz2: New file
+ * run-backtrace-fp-core-aarch64.sh: New file
+ * backtrace-subr.sh (check_err): Allow Invalid register.
+ * backtrace.c (callback_verify): Allow duplicate_sigusr2 frames.
+
2017-04-06 Mark Wielaard <[email protected]>
* run-backtrace-fp-core-i386.sh: New test.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2c82bfd8..3a12fe3a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -116,6 +116,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-backtrace-native-biarch.sh run-backtrace-native-core.sh \
run-backtrace-native-core-biarch.sh run-backtrace-core-x86_64.sh \
run-backtrace-fp-core-x86_64.sh \
+ run-backtrace-fp-core-aarch64.sh \
run-backtrace-core-x32.sh \
run-backtrace-core-i386.sh run-backtrace-fp-core-i386.sh \
run-backtrace-core-ppc.sh \
@@ -297,6 +298,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-backtrace-core-x86_64.sh run-backtrace-core-i386.sh \
run-backtrace-fp-core-x86_64.sh \
run-backtrace-core-x32.sh \
+ run-backtrace-fp-core-aarch64.sh \
+ backtrace.aarch64.fp.core.bz2 backtrace.aarch64.fp.exec.bz2 \
backtrace-subr.sh backtrace.i386.core.bz2 backtrace.i386.exec.bz2 \
run-backtrace-fp-core-i386.sh \
backtrace.i386.fp.core.bz2 backtrace.i386.fp.exec.bz2 \
diff --git a/tests/backtrace-subr.sh b/tests/backtrace-subr.sh
index a303e32c..9731c43a 100644
--- a/tests/backtrace-subr.sh
+++ b/tests/backtrace-subr.sh
@@ -59,7 +59,7 @@ check_backtracegen()
# Ignore it here as it is a bug of OS, not a bug of elfutils.
check_err()
{
- if [ $(egrep -v <$1 'dwfl_thread_getframes: (No DWARF information found|no matching address range|address out of range)$' \
+ if [ $(egrep -v <$1 'dwfl_thread_getframes: (No DWARF information found|no matching address range|address out of range|Invalid register)$' \
| wc -c) \
-eq 0 ]
then
diff --git a/tests/backtrace.aarch64.fp.core.bz2 b/tests/backtrace.aarch64.fp.core.bz2
new file mode 100644
index 00000000..ff867881
--- /dev/null
+++ b/tests/backtrace.aarch64.fp.core.bz2
Binary files differ
diff --git a/tests/backtrace.aarch64.fp.exec.bz2 b/tests/backtrace.aarch64.fp.exec.bz2
new file mode 100644
index 00000000..9d06db1e
--- /dev/null
+++ b/tests/backtrace.aarch64.fp.exec.bz2
Binary files differ
diff --git a/tests/backtrace.c b/tests/backtrace.c
index 1ff6353c..21abe8af 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -90,6 +90,10 @@ callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
return;
}
Dwfl_Module *mod;
+ /* See case 4. Special case to help out simple frame pointer unwinders. */
+ static bool duplicate_sigusr2 = false;
+ if (duplicate_sigusr2)
+ frameno--;
static bool reduce_frameno = false;
if (reduce_frameno)
frameno--;
@@ -125,6 +129,14 @@ callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
}
/* FALLTHRU */
case 4:
+ /* Some simple frame unwinders get this wrong and think sigusr2
+ is calling itself again. Allow it and just pretend there is
+ an extra sigusr2 frame. */
+ if (symname != NULL && strcmp (symname, "sigusr2") == 0)
+ {
+ duplicate_sigusr2 = true;
+ break;
+ }
assert (symname != NULL && strcmp (symname, "stdarg") == 0);
break;
case 5:
diff --git a/tests/run-backtrace-fp-core-aarch64.sh b/tests/run-backtrace-fp-core-aarch64.sh
new file mode 100755
index 00000000..fda88d37
--- /dev/null
+++ b/tests/run-backtrace-fp-core-aarch64.sh
@@ -0,0 +1,28 @@
+#! /bin/bash
+# Copyright (C) 2017 The Qt Company
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# The binary is generated by compiling with eh_frame CFI, but with frame
+# pointers.
+#
+# gcc -static -O2 -fno-omit-frame-pointer -fno-asynchronous-unwind-tables \
+# -D_GNU_SOURCE -pthread -o tests/backtrace.aarch64.fp.exec -I. -Ilib \
+# tests/backtrace-child.c
+# The core is generated by calling the binary with --gencore
+
+check_core aarch64.fp