On 08/29/2016 08:10 PM, Benoît Canet wrote:


On Mon, Aug 29, 2016 at 7:08 PM, Avi Kivity <a...@scylladb.com <mailto:a...@scylladb.com>> wrote:



    On 08/29/2016 07:49 PM, Nadav Har'El wrote:

        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 or
        saved multiple times.

        Signed-off-by: Nadav Har'El <n...@scylladb.com
        <mailto:n...@scylladb.com>>
        ---
          arch/x64/entry.S | 104
        +++++++++++++++++++++----------------------------------
          1 file changed, 40 insertions(+), 64 deletions(-)

        diff --git a/arch/x64/entry.S b/arch/x64/entry.S
        index e265a30..e3be0bc 100644
        --- a/arch/x64/entry.S
        +++ b/arch/x64/entry.S
        @@ -164,66 +164,43 @@ call_signal_handler_thunk:
          syscall_entry:
              .type syscall_entry, @function
              .cfi_startproc simple


    Probably, we need to remove simple here, likely it sets up
    incorrect references.

        +    .cfi_undefined rcx # was overwritten with rip by the
        syscall instruction


    Not .cfi_register1 %rip, %rcx?  So if we trap here, we know who
    the caller is.


From what I understand Nadav does it by hand later when pushing.

He does, but when you debug between this point and the push, you will have a broken stack trace.



        +    .cfi_undefined r11 # was overwritten with rflags by the
        syscall instruction
              # 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
        +    .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
        
<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 %rax
        +    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
        @@ -231,7 +208,7 @@ syscall_entry:
                # 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
        @@ -254,34 +231,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
    <mailto:osv-dev%2bunsubscr...@googlegroups.com>.
    For more options, visit https://groups.google.com/d/optout
    <https://groups.google.com/d/optout>.



--
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.

Reply via email to