From: Paul Floyd Date: Mon, 6 Jun 2022 13:18:29 +0000 (+0200) Subject: Use a different way to tell where the syscall handler was interrupted on FreeBSD... X-Git-Tag: VALGRIND_3_20_0~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cc2d94d93fa5350355b8cedb0d6b5309fcc588c;p=thirdparty%2Fvalgrind.git Use a different way to tell where the syscall handler was interrupted on FreeBSD and macOS I was using a global variable. This would be set to '1' just before calling the function to save cflags and cleared just after, then using the variable to fill in the 'outside_rnage_ condition in VG_(fixup_guest_state_after_syscall_interrupted) Even though I haven't experienced any isseus with that, the comments just before do_syscall_for_client made me want to try an alternative. This code is very ugly and won't please the language lawyers. Functions aren't guaranteed to have an address and there is no guarantee that the binary layout will reflect the source layout. Sadly C doesn't have something like "sizeof(*function)" to give the size of a function in bytes. The next best that I could manage was to use dummy 'marker' functions just after the ones I want the end address of and then use the address of 'marker - 1' I did think of one other way to do this. That would be to generate a C file containing the function sizes. This would require 1. "put_flag_size.c" would depend on the VEX guest_(x86|amd64)_helpers object files 2. Extract the sizes, for instance echo -n "const size_t x86_put_eflag_c_size = 0x" > put_flag_size.c nm -F sysv libvex_x86_freebsd_a-guest_x86_helpers.o | awk -F\| '/LibVEX_GuestX86_put_eflag_c/{print $5}' >> put_flag_size.c echo ";" >> put_flag_size.c That seems fairly difficult to do in automake and I'm not sure if it would be robust. --- diff --git a/VEX/priv/guest_amd64_helpers.c b/VEX/priv/guest_amd64_helpers.c index ba71c1b62f..abd2a1e370 100644 --- a/VEX/priv/guest_amd64_helpers.c +++ b/VEX/priv/guest_amd64_helpers.c @@ -768,6 +768,25 @@ 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. */ @@ -994,6 +1013,15 @@ 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. ---*/ diff --git a/VEX/priv/guest_x86_helpers.c b/VEX/priv/guest_x86_helpers.c index c0a4d33edc..7b229cb795 100644 --- a/VEX/priv/guest_x86_helpers.c +++ b/VEX/priv/guest_x86_helpers.c @@ -567,6 +567,20 @@ 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. */ @@ -790,6 +804,15 @@ 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. ---*/ diff --git a/VEX/pub/libvex_guest_amd64.h b/VEX/pub/libvex_guest_amd64.h index 1518ba304c..864b54b04e 100644 --- a/VEX/pub/libvex_guest_amd64.h +++ b/VEX/pub/libvex_guest_amd64.h @@ -203,6 +203,13 @@ void LibVEX_GuestAMD64_put_rflag_c ( ULong new_carry_flag, /*MOD*/VexGuestAMD64State* vex_state ); +#if defined(VGO_freebsd) || defined(VGO_darwin) +void _______VVVVVVVV_after_GuestAMD64_put_rflag_c_VVVVVVVV_______ (void); +extern Addr addr_amd64g_calculate_rflags_all_WRK; +extern Addr addr________VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______; +#endif + + /* Do FXSAVE from the supplied VexGuestAMD64tate structure and store the result at the given address which represents a buffer of at least 416 bytes. */ diff --git a/VEX/pub/libvex_guest_x86.h b/VEX/pub/libvex_guest_x86.h index fabafe113c..53f72acb8c 100644 --- a/VEX/pub/libvex_guest_x86.h +++ b/VEX/pub/libvex_guest_x86.h @@ -292,6 +292,12 @@ 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. */ diff --git a/coregrind/m_syswrap/syscall-amd64-darwin.S b/coregrind/m_syswrap/syscall-amd64-darwin.S index 8a970fa088..ed93a851eb 100644 --- a/coregrind/m_syswrap/syscall-amd64-darwin.S +++ b/coregrind/m_syswrap/syscall-amd64-darwin.S @@ -248,11 +248,6 @@ ML_(blksys_complete_UNIX): .quad MK_L_SCCLASS_N(UNIX,3) ML_(blksys_committed_UNIX): .quad MK_L_SCCLASS_N(UNIX,4) ML_(blksys_finished_UNIX): .quad MK_L_SCCLASS_N(UNIX,5) -.data -globl ML_(blksys_saving_cflag) -ML_(blksys_saving_cflag): .quad 0 -.previous - #endif // defined(VGP_amd64_darwin) /* Let the linker know we don't need an executable stack */ diff --git a/coregrind/m_syswrap/syscall-amd64-freebsd.S b/coregrind/m_syswrap/syscall-amd64-freebsd.S index 55d53f0b76..8f084c3e19 100644 --- a/coregrind/m_syswrap/syscall-amd64-freebsd.S +++ b/coregrind/m_syswrap/syscall-amd64-freebsd.S @@ -153,9 +153,7 @@ ML_(do_syscall_for_client_WRK): movq %rax, %rdi /* arg1 = new flag */ movq %r11, %rsi /* arg2 = vex state */ addq $24, %rsp /* remove syscall parameters */ - movq $0x1, ML_(blksys_saving_cflag) call LibVEX_GuestAMD64_put_rflag_c - movq $0x0, ML_(blksys_saving_cflag) 4: /* Re-block signals. If eip is in [4,5), then the syscall is complete and we needn't worry about it. */ @@ -208,12 +206,6 @@ ML_(blksys_committed): .quad 4b ML_(blksys_finished): .quad 5b .previous - .data - .globl ML_(blksys_saving_cflag) - ML_(blksys_saving_cflag): .quad 0 - .previous - - #endif /* defined(VGP_amd64_freebsd) */ /* Let the linker know we don't need an executable stack */ diff --git a/coregrind/m_syswrap/syscall-x86-darwin.S b/coregrind/m_syswrap/syscall-x86-darwin.S index cbeadc52f8..9032422685 100644 --- a/coregrind/m_syswrap/syscall-x86-darwin.S +++ b/coregrind/m_syswrap/syscall-x86-darwin.S @@ -246,10 +246,6 @@ ML_(blksys_complete_UNIX): .long MK_L_SCCLASS_N(UNIX,3) ML_(blksys_committed_UNIX): .long MK_L_SCCLASS_N(UNIX,4) ML_(blksys_finished_UNIX): .long MK_L_SCCLASS_N(UNIX,5) -.data -.globl ML_(blksys_saving_cflag) -ML_(blksys_saving_cflag): .long 0 -.previous #endif // defined(VGP_x86_darwin) /* Let the linker know we don't need an executable stack */ diff --git a/coregrind/m_syswrap/syscall-x86-freebsd.S b/coregrind/m_syswrap/syscall-x86-freebsd.S index 523d3d2e0d..1faa74c4d6 100644 --- a/coregrind/m_syswrap/syscall-x86-freebsd.S +++ b/coregrind/m_syswrap/syscall-x86-freebsd.S @@ -143,9 +143,7 @@ ML_(do_syscall_for_client_WRK): movl $0, 0(%esp) movb 12(%esp), %al movb %al, 0(%esp) - movl $0x1, ML_(blksys_saving_cflag) call LibVEX_GuestX86_put_eflag_c - movl $0x0, ML_(blksys_saving_cflag) addl $12, %esp 4: /* Re-block signals. If eip is in [4,5), then the syscall is @@ -193,11 +191,6 @@ ML_(blksys_committed): .long 4b ML_(blksys_finished): .long 5b .previous - .data - .globl ML_(blksys_saving_cflag) - ML_(blksys_saving_cflag): .long 0 - .previous - #endif // defined(VGP_x86_freebsd) /* Let the linker know we don't need an executable stack */ diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index 5824a1dbea..5077a7da73 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -2569,9 +2569,6 @@ void VG_(post_syscall) (ThreadId tid) extern const Addr ML_(blksys_complete); extern const Addr ML_(blksys_committed); extern const Addr ML_(blksys_finished); -#if defined(VGO_freebsd) - extern const Addr ML_(blksys_saving_cflag); -#endif #elif defined(VGO_darwin) /* Darwin requires extra uglyness */ extern const Addr ML_(blksys_setup_MACH); @@ -2589,7 +2586,6 @@ void VG_(post_syscall) (ThreadId tid) extern const Addr ML_(blksys_complete_UNIX); extern const Addr ML_(blksys_committed_UNIX); extern const Addr ML_(blksys_finished_UNIX); - extern const Addr ML_(blksys_saving_cflag); #elif defined(VGO_solaris) extern const Addr ML_(blksys_setup); extern const Addr ML_(blksys_complete); @@ -3123,7 +3119,35 @@ VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid, #if defined(VGO_freebsd) || defined(VGO_darwin) if (outside_range) { - if (ML_(blksys_saving_cflag)) + /* 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 { outside_range = False; in_complete_to_committed = True;