src/x86/unix64.S


Log

Author Commit Date CI Message
Madhavan T. Venkataraman 9ba55921 2021-03-05T10:07:30 Static tramp v5 (#624) * Static Trampolines Closure Trampoline Security Issue ================================= Currently, the trampoline code used in libffi is not statically defined in a source file (except for MACH). The trampoline is either pre-defined machine code in a data buffer. Or, it is generated at runtime. In order to execute a trampoline, it needs to be placed in a page with executable permissions. Executable data pages are attack surfaces for attackers who may try to inject their own code into the page and contrive to have it executed. The security settings in a system may prevent various tricks used in user land to write code into a page and to have it executed somehow. On such systems, libffi trampolines would not be able to run. Static Trampoline ================= To solve this problem, the trampoline code needs to be defined statically in a source file, compiled and placed in the text segment so it can be mapped and executed naturally without any tricks. However, the trampoline needs to be able to access the closure pointer at runtime. PC-relative data referencing ============================ The solution implemented in this patch set uses PC-relative data references. The trampoline is mapped in a code page. Adjacent to the code page, a data page is mapped that contains the parameters of the trampoline: - the closure pointer - pointer to the ABI handler to jump to The trampoline code uses an offset relative to its current PC to access its data. Some architectures support PC-relative data references in the ISA itself. E.g., X64 supports RIP-relative references. For others, the PC has to somehow be loaded into a general purpose register to do PC-relative data referencing. To do this, we need to define a get_pc() kind of function and call it to load the PC in a desired register. There are two cases: 1. The call instruction pushes the return address on the stack. In this case, get_pc() will extract the return address from the stack and load it in the desired register and return. 2. The call instruction stores the return address in a designated register. In this case, get_pc() will copy the return address to the desired register and return. Either way, the PC next to the call instruction is obtained. Scratch register ================ In order to do its job, the trampoline code would need to use a scratch register. Depending on the ABI, there may not be a register available for scratch. This problem needs to be solved so that all ABIs will work. The trampoline will save two values on the stack: - the closure pointer - the original value of the scratch register This is what the stack will look like: sp before trampoline ------> -------------------- | closure pointer | -------------------- | scratch register | sp after trampoline -------> -------------------- The ABI handler can do the following as needed by the ABI: - the closure pointer can be loaded in a desired register - the scratch register can be restored to its original value - the stack pointer can be restored to its original value (the value when the trampoline was invoked) To do this, I have defined prolog code for each ABI handler. The legacy trampoline jumps to the ABI handler directly. But the static trampoline defined in this patch jumps tp the prolog code which performs the above actions before jumping to the ABI handler. Trampoline Table ================ In order to reduce the trampoline memory footprint, the trampoline code would be defined as a code array in the text segment. This array would be mapped into the address space of the caller. The mapping would, therefore, contain a trampoline table. Adjacent to the trampoline table mapping, there will be a data mapping that contains a parameter table, one parameter block for each trampoline. The parameter block will contain: - a pointer to the closure - a pointer to the ABI handler The static trampoline code would finally look like this: - Make space on the stack for the closure and the scratch register by moving the stack pointer down - Store the original value of the scratch register on the stack - Using PC-relative reference, get the closure pointer - Store the closure pointer on the stack - Using PC-relative reference, get the ABI handler pointer - Jump to the ABI handler Mapping size ============ The size of the code mapping that contains the trampoline table needs to be determined on a per architecture basis. If a particular architecture supports multiple base page sizes, then the largest supported base page size needs to be chosen. E.g., we choose 16K for ARM64. Trampoline allocation and free ============================== Static trampolines are allocated in ffi_closure_alloc() and freed in ffi_closure_free(). Normally, applications use these functions. But there are some cases out there where the user of libffi allocates and manages its own closure memory. In such cases, static trampolines cannot be used. These will fall back to using legacy trampolines. The user has to make sure that the memory is executable. ffi_closure structure ===================== I did not want to make any changes to the size of the closure structure for this feature to guarantee compatibility. But the opaque static trampoline handle needs to be stored in the closure. I have defined it as follows: - char tramp[FFI_TRAMPOLINE_SIZE]; + union { + char tramp[FFI_TRAMPOLINE_SIZE]; + void *ftramp; + }; If static trampolines are used, then tramp[] is not needed to store a dynamic trampoline. That space can be reused to store the handle. Hence, the union. Architecture Support ==================== Support has been added for x64, i386, aarch64 and arm. Support for other architectures can be added very easily in the future. OS Support ========== Support has been added for Linux. Support for other OSes can be added very easily. Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com> * x86: Support for Static Trampolines - Define the arch-specific initialization function ffi_tramp_arch () that returns trampoline size information to common code. - Define the trampoline code mapping and data mapping sizes. - Define the trampoline code table statically. Define two tables, actually, one with CET and one without. - Introduce a tiny prolog for each ABI handling function. The ABI handlers addressed are: - ffi_closure_unix64 - ffi_closure_unix64_sse - ffi_closure_win64 The prolog functions are called: - ffi_closure_unix64_alt - ffi_closure_unix64_sse_alt - ffi_closure_win64_alt The legacy trampoline jumps to the ABI handler. The static trampoline jumps to the prolog function. The prolog function uses the information provided by the static trampoline, sets things up for the ABI handler and then jumps to the ABI handler. - Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to initialize static trampoline parameters. Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com> * i386: Support for Static Trampolines - Define the arch-specific initialization function ffi_tramp_arch () that returns trampoline size information to common code. - Define the trampoline code table statically. Define two tables, actually, one with CET and one without. - Define the trampoline code table statically. - Introduce a tiny prolog for each ABI handling function. The ABI handlers addressed are: - ffi_closure_i386 - ffi_closure_STDCALL - ffi_closure_REGISTER The prolog functions are called: - ffi_closure_i386_alt - ffi_closure_STDCALL_alt - ffi_closure_REGISTER_alt The legacy trampoline jumps to the ABI handler. The static trampoline jumps to the prolog function. The prolog function uses the information provided by the static trampoline, sets things up for the ABI handler and then jumps to the ABI handler. - Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to initialize static trampoline parameters. Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com> * arm64: Support for Static Trampolines - Define the arch-specific initialization function ffi_tramp_arch () that returns trampoline size information to common code. - Define the trampoline code mapping and data mapping sizes. - Define the trampoline code table statically. - Introduce a tiny prolog for each ABI handling function. The ABI handlers addressed are: - ffi_closure_SYSV - ffi_closure_SYSV_V The prolog functions are called: - ffi_closure_SYSV_alt - ffi_closure_SYSV_V_alt The legacy trampoline jumps to the ABI handler. The static trampoline jumps to the prolog function. The prolog function uses the information provided by the static trampoline, sets things up for the ABI handler and then jumps to the ABI handler. - Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to initialize static trampoline parameters. Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com> * arm: Support for Static Trampolines - Define the arch-specific initialization function ffi_tramp_arch () that returns trampoline size information to common code. - Define the trampoline code mapping and data mapping sizes. - Define the trampoline code table statically. - Introduce a tiny prolog for each ABI handling function. The ABI handlers addressed are: - ffi_closure_SYSV - ffi_closure_VFP The prolog functions are called: - ffi_closure_SYSV_alt - ffi_closure_VFP_alt The legacy trampoline jumps to the ABI handler. The static trampoline jumps to the prolog function. The prolog function uses the information provided by the static trampoline, sets things up for the ABI handler and then jumps to the ABI handler. - Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to initialize static trampoline parameters. Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
petersn c78fcf88 2020-10-27T07:02:36 Removing unnecessary instruction from ffi_call_unix64 (#588) unix64.S's `ffi_call_unix64` looks like it used to take six parameters, where the sixth said the number of SSE register arguments. However, currently the function only takes five parameters, and the number of SSE register arguments is encoded in the `struct register_args *` passed as the first parameter to `ffi_call_unix64`. This change removes an instruction that tries to use this missing sixth parameter as the number of SSE arguments. This fix should not change any behavior, nor fix any bugs, because a few instructions later the value moved from %r9d into %eax is overwritten by the correct value anyway. This change merely makes the code a tad less confusing, because currently the assembly moves from a register (r9) whose value is never set.
hjl-tools 78556561 2020-02-21T19:08:06 x86: Add indirect branch tracking support (#540) Intel Control-flow Enforcement Technology (CET): https://software.intel.com/en-us/articles/intel-sdm contains shadow stack (SHSTK) and indirect branch tracking (IBT). When CET is enabled, ELF object files must be marked with .note.gnu.property section. When Intel CET is enabled, include <cet.h> in assembly codes to mark Intel CET support. Also when IBT is enabled, all indirect branch targets must start with ENDBR instruction and notrack prefix can be used to disable IBT on indirect branch. <cet.h> defines _CET_ENDBR which can be used in assembly codes for ENDBR instruction. If <cet.h> isn't included, define _CET_ENDBR as empty so that _CET_ENDBR can be used in assembly codes. Trampoline must be enlarged to add ENDBR instruction unconditionally, which is NOP on non-CET processors. This is required regardless if libffi is enabled with CET since libffi.so will be marked in legacy bitmap, but trampoline won't. Update library version for larger FFI_TRAMPOLINE_SIZE. This fixed: https://github.com/libffi/libffi/issues/474 Tested with $ CC="gcc -Wl,-z,cet-report=error -fcf-protection" CXX="g++ -Wl,-z,cet-report=error -fcf-protection" .../configure on Linux CET machines in i686, x32 and x86-64 modes.
Jeremy Huddleston Sequoia 65da63ab 2018-06-25T04:38:58 Add compact unwind for darwin/i386 (#440) * x86: Add implementation of compact unwind for ffi_call_i386, et al. Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org> * x86: Use __text as the section name to avoid deprecated section name warnings. Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org> * darwin: Add missing regular,debug attributes for compact unwind sections Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
Jeremy Huddleston Sequoia 1d704051 2018-06-17T17:01:50 i386: Fix missing break; in case statement leading to incorrectly returned FFI_BAD_ABI (#437) * i386: Add missing break triggering dead store static analyzer checks. Register calling sequence is being reported as bad ABI instead of working as intended. Found-by: Clang Static Analysis Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org> * Mark ffi arm sysv entry points as private_extern. Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org> * x86_64: Add implementation of compact unwind for ffi_call_unix64. Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
Anthony Green b5ee3957 2018-05-05T07:41:53 Revert "Remove some symbol exports and cleanup newline warnings (#433)" This reverts commit a5a0f3cf36dfb4d64316414a872288c3170e6c1d.
Jeremy Huddleston Sequoia a5a0f3cf 2018-05-05T03:44:33 Remove some symbol exports and cleanup newline warnings (#433) * build: Ensure darwin generated sources end with a new line Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org> * build: Use .private_extern where missing to prevent exporting symbols that are not API Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
jon d15581c6 2017-12-01T00:34:30 Updating calls to ffi_closure_unix64_inner and ffi_closure_win64_inner to use PLT. Without this fix, statically linking libffi causes the linker error i.e. 'requires dynamic R_X86_64_PC32 reloc against ffi_closure_unix64_inner which may overflow at runtime; recompile with -fPIC)'
Josh Triplett eaa59755 2015-07-26T17:17:16 src/x86/win64.S: Handle name mangling and PIC Move the macros from unix64.S into a shared header asmnames.h and use them in win64.S too.
Rainer Orth f1560b7b 2015-01-16T11:31:37 x86: Solaris fixes * Solaris/x86 /bin/as doesn't support .org, so I've just disabled the uses in src/x86/{sysv, unix64}.S, as on Darwin. * Solaris/x86 needs to use EH_FRAME_FLAGS so manually and compiler generated .eh_frame sections match, otherwise libffi.so fails to link: * Solaris/x86 /bin/as has different COMDAT syntax; I've disabled it for the moment.
Iain Sandoe ae842a51 2014-11-25T11:43:40 x86: More Darwin unwind fixups EHFrame{N} IIRC is a special cue to ld64 that it should treat the unwind in the object as "special/legacy" .. [these days everything is .cfi_xxxx (except, cctools-as, as you noted)] .. without that much confusion arises with ld64's atom-isation of the eh_frame section. xxxx.eh labels are not needed for darwin ld64 >= 85.2.1 (i.e. darwin9, xcode 3.1.4) to all intents and purposes, that's all that matters now, since I think that anyone trying to build on 10.4/darwin8/xcode2.5 would have to use a later ld64 (from odcctools) for other reasons.
Richard Henderson 8fa3c9f2 2014-11-25T09:27:54 x86: Reinstate hand-written unwind info for unix64.S One more try to get default Darwin to work.
Richard Henderson 5f35e0ff 2014-11-24T16:26:50 x86: Avoid using gas local labels Which are unsupported by Darwin cctools as. Thankfully this doesn't uglify the source too much.
Richard Henderson 042b8daf 2014-11-24T11:24:02 x86: Use .balign not .align The Apple assembler defaults to power of two alignment, rather than byte alignment like everyone else. Force byte alignment by using the proper directive.
Richard Henderson 0172bc02 2014-11-24T10:42:02 x86: Disable .org for Darwin
Richard Henderson 9f112619 2014-11-22T20:02:43 x86: Best guess at update for Darwin
Richard Henderson 0e303c06 2014-11-12T03:58:58 x86: Work around clang bugs http://llvm.org/bugs/show_bug.cgi?21500 http://llvm.org/bugs/show_bug.cgi?21501 http://llvm.org/bugs/show_bug.cgi?21515
Richard Henderson 610c90bf 2014-10-28T11:21:50 x86_64: Add support for complex types
Richard Henderson 32c56831 2014-10-28T11:17:35 x86_64: Decouple return types from FFI_TYPE constants We can better support structure returns, and as prep for complex types.
Richard Henderson 2e9dc165 2014-10-27T13:41:39 x86_64: Fixups for x32
Richard Henderson 6b62fb4a 2014-10-17T11:11:58 x86-64: Support go closures Dumps all of the hand-coded unwind info for gas generated. Move jump table data into .rodata. Adjust ffi_call_unix64 to load the static chain. Split out sse portions of ffi_closure_unix64 to ffi_closure_unix64_sse rather than test cif->flags at runtime.
Anthony Green fd07c9e4 2013-02-07T18:00:36 Add cache flushing routine for sun compiler on sparc solaris 2.8
Anthony Green 35ddb69c 2013-01-08T07:53:37 Only emit DWARF unwind info when building with GCC
Anthony Green 3f5b1375 2010-07-12T14:39:18 rebase
Anthony Green c6dddbd0 2009-10-04T08:11:33 Initial commit