From: Nadav Har'El <n...@scylladb.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master
syscall: fix CFI information for debugging with GDB
GDB uses DWARF CFI meta-instructions to know how to backtrace through
function call frames, and which registers get saved where.
This patch fixes the CFI instructions in the syscall_entry() assembly
code. After this patch, if we are in system call code we can backtrack
through the syscall_entry() - for example:
5 0x000000000059c10b in syscall_wrapper (number=186) at linux.cc:332
6 0x0000000000480245 in syscall_entry () at arch/x64/entry.S:238
7 0x0000100000c00bce in main (argc=1, argv=<optimized out>)
at /home/nyh/osv/tests/tst-syscall.cc:49
8 0x000000000063526e in osv::application::run_main
(this=0xffffa00003079910,
path="tests/tst-syscall.so", argc=1, argv=0xffffa00001f88170)
at core/app.cc:338
Note how syscall_entry() looks like a normal function - it no longer
pretends to be a "signal frame". In particular, we no longer need to
obey a specific layout of the registers saved on the stack, so I took
this opportunity to remove some of the useless things we saved (like rax,
which will be overwritten by a return value anyway) or saved multiple times
(rcx, rsp).
Signed-off-by: Nadav Har'El <n...@scylladb.com>
Message-Id: <1472503638-5362-2-git-send-email-...@scylladb.com>
---
diff --git a/arch/x64/entry.S b/arch/x64/entry.S
--- a/arch/x64/entry.S
+++ b/arch/x64/entry.S
@@ -164,78 +164,52 @@ call_signal_handler_thunk:
syscall_entry:
.type syscall_entry, @function
.cfi_startproc simple
+ .cfi_undefined rcx # was overwritten with rip by the syscall
instruction
+ .cfi_undefined r11 # was overwritten with rflags by the syscall
instruction
+ .cfi_register rip, rcx # rcx took previous rip value
+ .cfi_register rflags, r11 # r11 took previous rflags value
# There is no ring transition and rflags are left unchanged.
# Skip the "red zone" allowed by the AMD64 ABI (the caller used a
# SYSCALL instruction and doesn't know he called a function):
subq $128, %rsp
-
- # Skip the "red zone" allowed by the AMD64 ABI (the caller used a
- # SYSCALL instruction and doesn't know he called a function):
- subq $128, %rsp
+ .cfi_def_cfa %rsp, 0
# We need to save and restore the caller's %rbp anyway, so let's also
# set it up properly for old-style frame-pointer backtracing to work
# (e.g., backtrace_safe()). Also need to push the return address before
# the rbp to get a normal frame. Our return address is in rcx.
- pushq %rcx
- pushq %rbp
+ pushq_cfi %rcx
+ .cfi_rel_offset %rip, 0
+ pushq_cfi %rbp
movq %rsp, %rbp
+ .cfi_rel_offset %rsp, 0
#
# From
http://stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-on-x86-64:
# "User-level applications use as integer registers for passing the
sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface
uses %rdi, %rsi, %rdx, %r10, %r8 and %r9"
# FIXME: fpu
- # build the stack frame by hand
- pushq %rsp
- subq $8, %rsp # rip was saved in rcx by the syscall instruction
- pushq %rax
- pushq %rbx
- pushq %rcx # contains rip before syscall instruction
- pushq %rdx
- pushq %rsi
- pushq %rdi
- pushq %r8
- pushq %r9
- pushq %r10
- pushq %r11 # contains rflags before syscall instruction
- pushq %r12
- pushq %r13
- pushq %r14
- pushq %r15
-
- # stack contains a signal_frame
- .cfi_signal_frame
- .cfi_def_cfa %rsp, 0
- .cfi_register rip,rcx # rcx took previous rip value
- .cfi_register rflags,r11 # r11 took previous rflags value
- .cfi_undefined rcx # was overwritten with rip by the syscall instruction
- .cfi_undefined r11 # was overwritten with rflags by the syscall
instruction
- .cfi_offset %r15, 0x00
- .cfi_offset %r14, 0x08
- .cfi_offset %r13, 0x10
- .cfi_offset %r12, 0x18
- .cfi_offset %r11, 0x20
- .cfi_offset %r10, 0x28
- .cfi_offset %r9, 0x30
- .cfi_offset %r8, 0x38
- .cfi_offset %rbp, 0x40
- .cfi_offset %rdi, 0x48
- .cfi_offset %rsi, 0x50
- .cfi_offset %rdx, 0x58
- .cfi_offset %rcx, 0x60
- .cfi_offset %rbx, 0x68
- .cfi_offset %rax, 0x70
- .cfi_offset %rip, 0x80
- .cfi_offset %rsp, 0x98
+ pushq_cfi %rbx
+ pushq_cfi %rdx
+ pushq_cfi %rsi
+ pushq_cfi %rdi
+ pushq_cfi %r8
+ pushq_cfi %r9
+ pushq_cfi %r10
+ pushq_cfi %r11 # contains rflags before syscall instruction
+ .cfi_rel_offset %rflags, 0
+ pushq_cfi %r12
+ pushq_cfi %r13
+ pushq_cfi %r14
+ pushq_cfi %r15
# The kernel interface use r10 as fourth argument while the user
interface use rcx
# so overwrite rcx with r10
movq %r10, %rcx
# prepare function call parameter: r9 is on the stack since it's the
seventh param
# because we shift existing params by one to make room for syscall
number
- pushq %r9
+ pushq_cfi %r9
movq %r8, %r9
movq %rcx, %r8
movq %rdx, %rcx
@@ -258,34 +232,33 @@ syscall_entry:
# restore it from 8(%rsp).
pushq %rsp
pushq (%rsp)
+ .cfi_adjust_cfa_offset 16
andq $-0x10, %rsp
+ .cfi_rel_offset %rsp, 8
callq syscall_wrapper
movq 8(%rsp), %rsp
+ .cfi_adjust_cfa_offset -16
- popq %r9
+ popq_cfi %r9
# in Linux user and kernel return value are in rax so we have nothing
to do for return values
- popq %r15
- popq %r14
- popq %r13
- popq %r12
- popq %r11
- popq %r10
- popq %r9
- popq %r8
- popq %rdi
- popq %rsi
- popq %rdx
- popq %rcx
- popq %rbx
- addq $8, %rsp # skip rax emplacement (return value is in rax)
- addq $8, %rsp # rip emplacement (rip cannot be popped)
- popq %rsp
+ popq_cfi %r15
+ popq_cfi %r14
+ popq_cfi %r13
+ popq_cfi %r12
+ popq_cfi %r11
+ popq_cfi %r10
+ popq_cfi %r9
+ popq_cfi %r8
+ popq_cfi %rdi
+ popq_cfi %rsi
+ popq_cfi %rdx
+ popq_cfi %rbx
- popq %rbp
- popq %rcx
+ popq_cfi %rbp
+ popq_cfi %rcx
addq $128, %rsp # undo red-zone skip
--
You received this message because you are subscribed to the Google Groups "OSv
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.