]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
FreeBSD and macOS: change detection of when carry flag is being set
authorPaul Floyd <pjfloyd@wanadoo.fr>
Mon, 4 Mar 2024 20:09:16 +0000 (21:09 +0100)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Mon, 4 Mar 2024 20:55:32 +0000 (21:55 +0100)
FreeBSD and macOS syscalls both have two return registers and
use the carry flag for the status. So syscall for client
needs to set the carry flag in the VexGuestArchState. That's
a bit much to do all in asm so we call VEX funtions.

But that doesn't play well with interrupts. There are labels
in ML_(do_syscall_for_client_WRK) so that we can work out
what to do if we get interrupted there. But there are no asm
labels in the VEX functions. Getting the address of the start
of the extern function is easy. There's no way in C to get
the length, and getting the address for the static helpers
is also messy.

I did bodge a solution whereby I put a dummy function in the
source file and scientifically crossed my fingers and hoped
that the compiler would lay out the object file in the same
way. And it did, at least for amd64 FreeBSD amd64 Darwin and
x86 FreeBSD (I don't have easy access to Darwin with working
x86).

Still, it's UB.

I recently tried the same thing for arm64 FreeBSD. And there
the functions are all over the shop in the object file.

So, time to do something a bit cleaner. I've removed all of
the hacky dummy functions and put a flag in the guest vex
state. For both amd64 and x86 there were spare padding
UInts that I've used. Arm64 won't be so lucky when I get there,
no spare padding words.

VEX/auxprogs/genoffsets.c
VEX/priv/guest_amd64_helpers.c
VEX/priv/guest_x86_helpers.c
VEX/pub/libvex_guest_amd64.h
VEX/pub/libvex_guest_x86.h
coregrind/m_syswrap/syscall-amd64-darwin.S
coregrind/m_syswrap/syscall-amd64-freebsd.S
coregrind/m_syswrap/syscall-x86-darwin.S
coregrind/m_syswrap/syscall-x86-freebsd.S
coregrind/m_syswrap/syswrap-main.c

index 54376dc90f7d980aa1cc62ecd1c2e11cb4aecef5..81cf77e417ea5c70a6296d92c6ebd02630064256 100644 (file)
@@ -97,6 +97,7 @@ void foo ( void )
    GENOFFSET(X86,x86,FS);
    GENOFFSET(X86,x86,GS);
    GENOFFSET(X86,x86,SS);
+   GENOFFSET(X86,x86,SETC);
 
    // amd64
    GENOFFSET(AMD64,amd64,RAX);
@@ -116,6 +117,7 @@ void foo ( void )
    GENOFFSET(AMD64,amd64,R14);
    GENOFFSET(AMD64,amd64,R15);
    GENOFFSET(AMD64,amd64,RIP);
+   GENOFFSET(AMD64,amd64,SETC);
 
    // ppc32
    GENOFFSET(PPC32,ppc32,GPR0);
index 42ec80e0369a82e1487b77377eaf090414c0aa4e..adb5c7287e5ed6ed51b77369955d6acea2158eb4 100644 (file)
@@ -768,26 +768,6 @@ ULong amd64g_calculate_rflags_all_WRK ( ULong cc_op,
    }
 }
 
-#if defined(VGO_freebsd) || defined(VGO_darwin)
-
-/* This dummy function is just used to have an address just after
-   amd64g_calculate_rflags_all_WRK */
-
-static
-void _______VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______ (void)
-{
-}
-
-/* Export addresses of amd64g_calculate_rflags_all_WRK and
-   _______VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______
-   Used in syswrap-main.c / VG_(post_syscall) in the case where
-   the above function was interrupted and we need to work out
-   what needs to be done for the resumption */
-
-Addr addr_amd64g_calculate_rflags_all_WRK = (Addr)amd64g_calculate_rflags_all_WRK;
-Addr addr________VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______ = (Addr)_______VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______;
-#endif
-
 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
 /* Calculate all the 6 flags from the supplied thunk parameters. */
 ULong amd64g_calculate_rflags_all ( ULong cc_op, 
@@ -1013,16 +993,6 @@ LibVEX_GuestAMD64_put_rflag_c ( ULong new_carry_flag,
    vex_state->guest_CC_NDEP = 0;
 }
 
-#if defined(VGO_freebsd) || defined(VGO_darwin)
-/* Used in syswrap-main.c / VG_(post_syscall) in the case where
-   the above function was interrupted and we need to work out
-   what needs to be done for the resumption. These functions
-   are extern so no need for 'addr' global variables */
-void _______VVVVVVVV_after_GuestAMD64_put_rflag_c_VVVVVVVV_______ (void)
-{
-}
-#endif
-
 /*---------------------------------------------------------------*/
 /*--- %rflags translation-time function specialisers.         ---*/
 /*--- These help iropt specialise calls the above run-time    ---*/
@@ -4816,6 +4786,8 @@ void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
 
    vex_state->guest_EMNOTE = EmNote_NONE;
 
+   vex_state->guest_SETC = 0;
+
    /* These should not ever be either read or written, but we
       initialise them anyway. */
    vex_state->guest_CMSTART = 0;
index 0c0c1ad2c86535eb5b09eb9738ed3e47176a6dbd..7743c63a4746792745fcd0e3944629fa75940743 100644 (file)
@@ -567,21 +567,6 @@ UInt x86g_calculate_eflags_all_WRK ( UInt cc_op,
    }
 }
 
-#if defined(VGO_freebsd) || defined(VGO_darwin)
-
-/* see guest_amd64_helpers.c
-   Used in syswrap-main.c / VG_(post_syscall) for signal
-   resumption */
-
-static void _______VVVVVVVV_after_x86g_calculate_eflags_all_WRK_VVVVVVVV_______ (void)
-{
-}
-
-Addr addr_x86g_calculate_eflags_all_WRK = (Addr)x86g_calculate_eflags_all_WRK;
-Addr addr________VVVVVVVV_x86g_calculate_eflags_all_WRK_VVVVVVVV_______ = (Addr)_______VVVVVVVV_after_x86g_calculate_eflags_all_WRK_VVVVVVVV_______;
-#endif
-
-
 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
 /* Calculate all the 6 flags from the supplied thunk parameters. */
 UInt x86g_calculate_eflags_all ( UInt cc_op, 
@@ -804,16 +789,6 @@ LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag,
    vex_state->guest_CC_NDEP = 0;
 }
 
-#if defined(VGO_freebsd) || defined(VGO_darwin)
-
-/* Used in syswrap-main.c / VG_(post_syscall) for signal resumption */
-
-void _______VVVVVVVV_after_LibVEX_GuestX86_put_eflag_c_VVVVVVVV_______ (void)
-{
-}
-#endif
-
-
 /*---------------------------------------------------------------*/
 /*--- %eflags translation-time function specialisers.         ---*/
 /*--- These help iropt specialise calls the above run-time    ---*/
@@ -2943,9 +2918,10 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
    vex_state->guest_SC_CLASS = 0;
    vex_state->guest_IP_AT_SYSCALL = 0;
 
+   vex_state->guest_SETC = 0;
+
    vex_state->padding1 = 0;
    vex_state->padding2 = 0;
-   vex_state->padding3 = 0;
 }
 
 
index 864b54b04ecc162b5a8bdccfc36ac02558526319..c0520d2f6dd00c40366628f3a6f3e5fb32d0efd2 100644 (file)
@@ -131,7 +131,10 @@ typedef
 
       /* Emulation notes */
       UInt  guest_EMNOTE;
-      UInt  pad2;
+      /* Used by Darwin and FreeBSD when setting the carry flag from
+       * ML_(do_syscall_for_client_WRK). Needed to determine how
+       * to restart interrupted syscalls. */
+      UInt guest_SETC;
 
       /* Translation-invalidation area description.  Not used on amd64
          (there is no invalidate-icache insn), but needed so as to
index 53f72acb8cf01b6bc127703f699fa519c1d099a0..50de8d37983bd0d07970deee6a0f9cd17cf6bdde 100644 (file)
@@ -219,10 +219,11 @@ typedef
          been interrupted by a signal. */
       UInt guest_IP_AT_SYSCALL;
 
+      UInt guest_SETC;
+
       /* Padding to make it have an 16-aligned size */
       UInt padding1;
       UInt padding2;
-      UInt padding3;
    }
    VexGuestX86State;
 
@@ -292,12 +293,6 @@ void
 LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag,
                               /*MOD*/VexGuestX86State* vex_state );
 
-#if defined(VGO_freebsd) || defined(VGO_darwin)
-extern void _______VVVVVVVV_after_LibVEX_GuestX86_put_eflag_c_VVVVVVVV_______ (void);
-extern Addr addr_x86g_calculate_eflags_all_WRK;
-extern Addr addr________VVVVVVVV_x86g_calculate_eflags_all_WRK_VVVVVVVV_______;
-#endif
-
 /* Do x87 save from the supplied VexGuestX86State structure and store the
    result at the given address which represents a buffer of at least 108
    bytes. */
index ed93a851ebfabded3ff5fae2503f41a9efc4009e..5c68d0c4d0471e62ab26b895768fe5ad40de61de 100644 (file)
@@ -153,7 +153,10 @@ L_$0_3:    /* In the range [3, 4), the syscall result is in %rax,
        movq    %rax, %rdi      /* arg1 = new flag */
        movq    %r11, %rsi      /* arg2 = vex state */
        addq    $$24, %rsp      /* remove syscall parameters */
+        movl    $$1, OFFSET_amd64_SETC(%r11)
        call    _LibVEX_GuestAMD64_put_rflag_c
+        movq   -16(%rbp), %r11
+        movl    $$0, OFFSET_amd64_SETC(%r11)
 .else
        addq    $$24, %rsp      /* remove syscall parameters*/
 .endif
index 8f084c3e1989b85b82f570d497a8f549496d9d25..d1516b106505573ad2788d21dc3a6baa764175ab 100644 (file)
@@ -153,7 +153,10 @@ ML_(do_syscall_for_client_WRK):
    movq  %rax, %rdi      /* arg1 = new flag */
    movq  %r11, %rsi      /* arg2 = vex state */
    addq  $24, %rsp       /* remove syscall parameters */
+   movl  $1, OFFSET_amd64_SETC(%r11)
    call  LibVEX_GuestAMD64_put_rflag_c
+   movq  -16(%rbp), %r11 /* r11 = VexGuestAMD64State * */
+   movl  $0, OFFSET_amd64_SETC(%r11)
 
 4: /* Re-block signals.  If eip is in [4,5), then the syscall
       is complete and we needn't worry about it. */
index 903242268501060da090b830596fda21ca23ddc9..d92ecf15e097b6eab25ad6e48d9295950ebc69d8 100644 (file)
@@ -156,7 +156,10 @@ L_$0_3:    /* In the range [3, 4), the syscall result is in %eax and %edx and C,
        movl    $$0, 0(%esp)
        movb    12(%esp), %al
        movb    %al, 0(%esp)
+        movl    $$1, OFFSET_x86_SETC(%ecx)
        call    _LibVEX_GuestX86_put_eflag_c
+        movl   12(%ebp), %ecx
+        movl    $$0, OFFSET_x86_SETC(%ecx)
        addl    $$12, %esp
 .endif
 
index 1faa74c4d67d9a05738237670767b612b164e546..4ddba2d340aa377b14d593498687d93e764ac56d 100644 (file)
@@ -143,7 +143,10 @@ ML_(do_syscall_for_client_WRK):
    movl  $0, 0(%esp)
    movb  12(%esp), %al
    movb  %al, 0(%esp)
+   movl  $1, OFFSET_x86_SETC(%ecx)
    call  LibVEX_GuestX86_put_eflag_c
+   movl  12(%ebp), %ecx
+   movl  $0, OFFSET_x86_SETC(%ecx)
    addl  $12, %esp
 
 4: /* Re-block signals.  If eip is in [4,5), then the syscall is
index 91a1f7e53e6ee06cf811ce03459961bc97d46d6a..20d02c7fa5210b3234916bccb88a37ec914e6c41 100644 (file)
@@ -3120,35 +3120,7 @@ VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid,
 #if defined(VGO_freebsd) || defined(VGO_darwin)
   if (outside_range)
   {
-     /* This is not guaranteed to work since the compiler / link editor
-        could lay out the binary functions in a different order to
-        the source file. However, it seems to work. */
-
-#if defined (VGA_amd64)
-
-     vg_assert((Addr)_______VVVVVVVV_after_GuestAMD64_put_rflag_c_VVVVVVVV_______ >
-               (Addr)LibVEX_GuestAMD64_put_rflag_c );
-
-     vg_assert(addr________VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______ >
-               addr_amd64g_calculate_rflags_all_WRK);
-
-     if ((ip >= (Addr)LibVEX_GuestAMD64_put_rflag_c &&
-          ip <  (Addr)_______VVVVVVVV_after_GuestAMD64_put_rflag_c_VVVVVVVV_______) ||
-         (ip >= addr_amd64g_calculate_rflags_all_WRK &&
-         ip < addr________VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______))
-#else
-
-     vg_assert((Addr)_______VVVVVVVV_after_LibVEX_GuestX86_put_eflag_c_VVVVVVVV_______ >
-               (Addr)LibVEX_GuestX86_put_eflag_c);
-     vg_assert(addr________VVVVVVVV_x86g_calculate_eflags_all_WRK_VVVVVVVV_______>
-              addr_x86g_calculate_eflags_all_WRK);
-
-     if ((ip >= (Addr)LibVEX_GuestX86_put_eflag_c &&
-         ip <  (Addr)_______VVVVVVVV_after_LibVEX_GuestX86_put_eflag_c_VVVVVVVV_______) ||
-         (ip >= addr_x86g_calculate_eflags_all_WRK &&
-          ip < addr________VVVVVVVV_x86g_calculate_eflags_all_WRK_VVVVVVVV_______))
-#endif
+     if (th_regs->vex.guest_SETC)
      {
         outside_range = False;
         in_complete_to_committed = True;