syscall.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "sandbox/linux/seccomp-bpf/syscall.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <asm/unistd.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/basictypes.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sandbox { 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) asm( // We need to be able to tell the kernel exactly where we made a 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // system call. The C++ compiler likes to sometimes clone or 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // inline code, which would inadvertently end up duplicating 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the entry point. 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // "gcc" can suppress code duplication with suitable function 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // attributes, but "clang" doesn't have this ability. 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The "clang" developer mailing list suggested that the correct 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and portable solution is a file-scope assembly block. 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // N.B. We do mark our code as a proper function so that backtraces 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // work correctly. But we make absolutely no attempt to use the 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ABI's calling conventions for passing arguments. We will only 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ever be called from assembly code and thus can pick more 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // suitable calling conventions. 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__i386__) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".text\n" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".align 16, 0x90\n" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".type SyscallAsm, @function\n" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SyscallAsm:.cfi_startproc\n" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if "%eax" is negative. If so, do not attempt to make a 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // system call. Instead, compute the return address that is visible 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to the kernel after we execute "int $0x80". This address can be 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // used as a marker that BPF code inspects. 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "test %eax, %eax\n" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "jge 1f\n" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Always, make sure that our code is position-independent, or 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // address space randomization might not work on i386. This means, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we can't use "lea", but instead have to rely on "call/pop". 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "call 0f; .cfi_adjust_cfa_offset 4\n" 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "0:pop %eax; .cfi_adjust_cfa_offset -4\n" 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "addl $2f-0b, %eax\n" 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ret\n" 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Save register that we don't want to clobber. On i386, we need to 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // save relatively aggressively, as there are a couple or registers 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that are used internally (e.g. %ebx for position-independent 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // code, and %ebp for the frame pointer), and as we need to keep at 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // least a few registers available for the register allocator. 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "1:push %esi; .cfi_adjust_cfa_offset 4\n" 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "push %edi; .cfi_adjust_cfa_offset 4\n" 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "push %ebx; .cfi_adjust_cfa_offset 4\n" 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "push %ebp; .cfi_adjust_cfa_offset 4\n" 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy entries from the array holding the arguments into the 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // correct CPU registers. 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movl 0(%edi), %ebx\n" 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movl 4(%edi), %ecx\n" 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movl 8(%edi), %edx\n" 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movl 12(%edi), %esi\n" 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movl 20(%edi), %ebp\n" 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movl 16(%edi), %edi\n" 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Enter the kernel. 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "int $0x80\n" 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is our "magic" return address that the BPF filter sees. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "2:" 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Restore any clobbered registers that we didn't declare to the 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // compiler. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "pop %ebp; .cfi_adjust_cfa_offset -4\n" 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "pop %ebx; .cfi_adjust_cfa_offset -4\n" 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "pop %edi; .cfi_adjust_cfa_offset -4\n" 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "pop %esi; .cfi_adjust_cfa_offset -4\n" 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ret\n" 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_endproc\n" 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "9:.size SyscallAsm, 9b-SyscallAsm\n" 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(__x86_64__) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".text\n" 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".align 16, 0x90\n" 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".type SyscallAsm, @function\n" 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SyscallAsm:.cfi_startproc\n" 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if "%rax" is negative. If so, do not attempt to make a 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // system call. Instead, compute the return address that is visible 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to the kernel after we execute "syscall". This address can be 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // used as a marker that BPF code inspects. 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "test %rax, %rax\n" 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "jge 1f\n" 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Always make sure that our code is position-independent, or the 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // linker will throw a hissy fit on x86-64. 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "call 0f; .cfi_adjust_cfa_offset 8\n" 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "0:pop %rax; .cfi_adjust_cfa_offset -8\n" 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "addq $2f-0b, %rax\n" 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ret\n" 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We declared all clobbered registers to the compiler. On x86-64, 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // there really isn't much of a problem with register pressure. So, 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we can go ahead and directly copy the entries from the arguments 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // array into the appropriate CPU registers. 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "1:movq 0(%r12), %rdi\n" 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movq 8(%r12), %rsi\n" 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movq 16(%r12), %rdx\n" 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movq 24(%r12), %r10\n" 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movq 32(%r12), %r8\n" 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "movq 40(%r12), %r9\n" 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Enter the kernel. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "syscall\n" 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is our "magic" return address that the BPF filter sees. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "2:ret\n" 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_endproc\n" 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "9:.size SyscallAsm, 9b-SyscallAsm\n" 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(__arm__) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Throughout this file, we use the same mode (ARM vs. thumb) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that the C++ compiler uses. This means, when transfering control 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from C++ to assembly code, we do not need to switch modes (e.g. 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // by using the "bx" instruction). It also means that our assembly 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // code should not be invoked directly from code that lives in 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // other compilation units, as we don't bother implementing thumb 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // interworking. That's OK, as we don't make any of the assembly 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // symbols public. They are all local to this file. 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".text\n" 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".align 2\n" 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".type SyscallAsm, %function\n" 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__thumb__) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".thumb_func\n" 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".arm\n" 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SyscallAsm:.fnstart\n" 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "@ args = 0, pretend = 0, frame = 8\n" 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "@ frame_needed = 1, uses_anonymous_args = 0\n" 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__thumb__) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_startproc\n" 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "push {r7, lr}\n" 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_offset 14, -4\n" 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_offset 7, -8\n" 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "mov r7, sp\n" 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_def_cfa_register 7\n" 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_def_cfa_offset 8\n" 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "stmfd sp!, {fp, lr}\n" 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "add fp, sp, #4\n" 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if "r0" is negative. If so, do not attempt to make a 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // system call. Instead, compute the return address that is visible 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to the kernel after we execute "swi 0". This address can be 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // used as a marker that BPF code inspects. 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "cmp r0, #0\n" 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "bge 1f\n" 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ldr r0, =2f\n" 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "b 2f\n" 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We declared (almost) all clobbered registers to the compiler. On 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ARM there is no particular register pressure. So, we can go 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ahead and directly copy the entries from the arguments array 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // into the appropriate CPU registers. 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "1:ldr r5, [r6, #20]\n" 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ldr r4, [r6, #16]\n" 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ldr r3, [r6, #12]\n" 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ldr r2, [r6, #8]\n" 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ldr r1, [r6, #4]\n" 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "mov r7, r0\n" 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ldr r0, [r6, #0]\n" 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Enter the kernel 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "swi 0\n" 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Restore the frame pointer. Also restore the program counter from 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the link register; this makes us return to the caller. 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__thumb__) 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "2:pop {r7, pc}\n" 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".cfi_endproc\n" 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "2:ldmfd sp!, {fp, pc}\n" 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".fnend\n" 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "9:.size SyscallAsm, 9b-SyscallAsm\n" 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ); // asm 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)intptr_t SandboxSyscall(int nr, 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intptr_t p0, intptr_t p1, intptr_t p2, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intptr_t p3, intptr_t p4, intptr_t p5) { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We rely on "intptr_t" to be the exact size as a "void *". This is 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // typically true, but just in case, we add a check. The language 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // specification allows platforms some leeway in cases, where 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // "sizeof(void *)" is not the same as "sizeof(void (*)())". We expect 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that this would only be an issue for IA64, which we are currently not 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // planning on supporting. And it is even possible that this would work 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // on IA64, but for lack of actual hardware, I cannot test. 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) COMPILE_ASSERT(sizeof(void *) == sizeof(intptr_t), 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pointer_types_and_intptr_must_be_exactly_the_same_size); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const intptr_t args[6] = { p0, p1, p2, p3, p4, p5 }; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invoke our file-scope assembly code. The constraints have been picked 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // carefully to match what the rest of the assembly code expects in input, 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // output, and clobbered registers. 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__i386__) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intptr_t ret = nr; 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) asm volatile( 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "call SyscallAsm\n" 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // N.B. These are not the calling conventions normally used by the ABI. 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : "=a"(ret) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : "0"(ret), "D"(args) 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : "cc", "esp", "memory", "ecx", "edx"); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(__x86_64__) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intptr_t ret = nr; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) register const intptr_t *data __asm__("r12") = args; 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) asm volatile( 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "lea -128(%%rsp), %%rsp\n" // Avoid red zone. 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "call SyscallAsm\n" 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "lea 128(%%rsp), %%rsp\n" 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // N.B. These are not the calling conventions normally used by the ABI. 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : "=a"(ret) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : "0"(ret), "r"(data) 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : "cc", "rsp", "memory", 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "rcx", "rdi", "rsi", "rdx", "r8", "r9", "r10", "r11"); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(__arm__) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intptr_t ret; 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) register intptr_t inout __asm__("r0") = nr; 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) register const intptr_t *data __asm__("r6") = args; 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) asm volatile( 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "bl SyscallAsm\n" 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // N.B. These are not the calling conventions normally used by the ABI. 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : "=r"(inout) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : "0"(inout), "r"(data) 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : "cc", "lr", "memory", "r1", "r2", "r3", "r4", "r5" 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(__arm__) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In thumb mode, we cannot use "r7" as a general purpose register, as 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it is our frame pointer. We have to manually manage and preserve it. 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In ARM mode, we have a dedicated frame pointer register and "r7" is 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // thus available as a general purpose register. We don't preserve it, 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // but instead mark it as clobbered. 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) , "r7" 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = inout; 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) errno = ENOSYS; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intptr_t ret = -1; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace sandbox 244