diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2016-03-15 19:29:25 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2016-03-17 09:25:38 +0000 |
commit | 17ad3b57d613fede17a01b6cdd2d894850364f81 (patch) | |
tree | 6db562f557acb145d85e1a90eeeedb79c83bf5f1 /3rdparty/elfutils | |
parent | eb8cb4749e8b30a4bc25f2c2adeeabc8481fab4b (diff) |
Add frame pointer unwinding for aarch64
Change-Id: I43f184deba97ed57cc7efbfbda9432cfd8d99664
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to '3rdparty/elfutils')
-rw-r--r-- | 3rdparty/elfutils/backends/aarch64/aarch64.pro | 3 | ||||
-rw-r--r-- | 3rdparty/elfutils/backends/aarch64_init.c | 1 | ||||
-rw-r--r-- | 3rdparty/elfutils/backends/aarch64_unwind.c | 78 |
3 files changed, 81 insertions, 1 deletions
diff --git a/3rdparty/elfutils/backends/aarch64/aarch64.pro b/3rdparty/elfutils/backends/aarch64/aarch64.pro index 5489b1d..a53be98 100644 --- a/3rdparty/elfutils/backends/aarch64/aarch64.pro +++ b/3rdparty/elfutils/backends/aarch64/aarch64.pro @@ -8,7 +8,8 @@ SOURCES += \ ../aarch64_initreg.c \ ../aarch64_regs.c \ ../aarch64_retval.c \ - ../aarch64_symbol.c + ../aarch64_symbol.c \ + ../aarch64_unwind.c HEADERS += \ ../aarch64_reloc.def diff --git a/3rdparty/elfutils/backends/aarch64_init.c b/3rdparty/elfutils/backends/aarch64_init.c index b0fd17a..8a96f73 100644 --- a/3rdparty/elfutils/backends/aarch64_init.c +++ b/3rdparty/elfutils/backends/aarch64_init.c @@ -64,6 +64,7 @@ aarch64_init (elf, machine, eh, ehlen) + 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/3rdparty/elfutils/backends/aarch64_unwind.c b/3rdparty/elfutils/backends/aarch64_unwind.c new file mode 100644 index 0000000..5560c58 --- /dev/null +++ b/3rdparty/elfutils/backends/aarch64_unwind.c @@ -0,0 +1,78 @@ +/* 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 + +#include <stdlib.h> +#include <assert.h> + +#define BACKEND aarch64_ +#include "libebl_CPU.h" +#include <stdio.h> + +/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */ + +bool +aarch64_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) +{ + const int fpReg = 29; + const int lrReg = 30; + const int spReg = 31; + + Dwarf_Word fp; + if (!getfunc(fpReg, 1, &fp, arg) || fp == 0) + return false; + + Dwarf_Word lr; + if (!getfunc(lrReg, 1, &lr, arg)) + return false; + + Dwarf_Word newFp, newLr; + if (!readfunc(fp, &newFp, arg)) + return false; + fp += 8; + if (!readfunc(fp, &newLr, arg)) + return false; + + fp += 8; + if (!setfunc(spReg, 1, &fp, arg)) + return false; + if (!setfunc(fpReg, 1, &newFp, arg)) + return false; + if (!setfunc(-1, 1, &newLr, arg)) + return false; + if (!setfunc(lrReg, 1, &newLr, arg)) + return false; + + *signal_framep = false; + return true; +} |