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


On Mon, Aug 29, 2016 at 7:08 PM, Avi Kivity <[email protected] <mailto:[email protected]>> 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 <[email protected]
        <mailto:[email protected]>>
        ---
          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 [email protected]
    <mailto:osv-dev%[email protected]>.
    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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to