summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac8
-rw-r--r--src/x86_64/Gstep.c27
2 files changed, 31 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 9a4c887d..f535c86c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,10 +34,10 @@ esac
dnl Checks for header files.
AC_HEADER_STDC
-AC_CHECK_HEADERS(asm/ptrace_offsets.h asm/ptrace.h endian.h sys/endian.h sys/param.h \
- execinfo.h ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h \
- sys/procfs.h sys/ptrace.h sys/syscall.h byteswap.h elf.h sys/elf.h \
- link.h sys/link.h)
+AC_CHECK_HEADERS(asm/ptrace_offsets.h asm/ptrace.h asm/vsyscall.h endian.h sys/endian.h \
+ sys/param.h execinfo.h ia64intrin.h sys/uc_access.h unistd.h signal.h \
+ sys/types.h sys/procfs.h sys/ptrace.h sys/syscall.h byteswap.h elf.h \
+ sys/elf.h link.h sys/link.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c
index 4216d188..1dc440e3 100644
--- a/src/x86_64/Gstep.c
+++ b/src/x86_64/Gstep.c
@@ -25,6 +25,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+#ifdef HAVE_ASM_VSYSCALL_H
+#include <asm/vsyscall.h>
+#endif
+
#include "libunwind_i.h"
#include "unwind_i.h"
#include <signal.h>
@@ -53,6 +57,20 @@ is_plt_entry (struct dwarf_cursor *c)
return ret;
}
+static int
+is_vsyscall (struct dwarf_cursor *c)
+{
+#if defined(VSYSCALL_START) && defined(VSYSCALL_END)
+ return c->ip >= VSYSCALL_START && c->ip < VSYSCALL_END;
+#elif defined(VSYSCALL_ADDR)
+ /* Linux 3.16 removes `VSYSCALL_START` and `VSYSCALL_END`. Assume
+ a single page is mapped for vsyscalls. */
+ return c->ip >= VSYSCALL_ADDR && c->ip < VSYSCALL_ADDR + sysconf(_SC_PAGESIZE);
+#else
+ return 0;
+#endif
+}
+
int
unw_step (unw_cursor_t *cursor)
{
@@ -141,6 +159,15 @@ unw_step (unw_cursor_t *cursor)
c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0);
c->dwarf.cfa += 8;
}
+ else if (is_vsyscall (&c->dwarf))
+ {
+ Debug (2, "in vsyscall region\n");
+ c->frame_info.cfa_reg_offset = 8;
+ c->frame_info.cfa_reg_rsp = -1;
+ c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED;
+ c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0);
+ c->dwarf.cfa += 8;
+ }
else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
{
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)