Last active
February 15, 2019 05:19
-
-
Save Qix-/f048052b53c67bb1596362731e178af3 to your computer and use it in GitHub Desktop.
Example of how syscall support could be added to Terra without any dependencies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.PHONY: all | |
all: bin/test-syscall | |
bin/test-syscall: test-syscall.t syscall-macos-x64.t | |
@mkdir -p bin | |
terra $< | |
.PHONY: clean | |
clean: | |
rm -rf bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Syscall wrapper for MacOS x64 | |
local errno = global(uint64) | |
local syscall = macro(function (num, ...) | |
local args = {...} | |
-- make sure all args are <= size of uint64 | |
for i=1,#args do | |
if terralib.sizeof(args[i].tree.type) > 8 then | |
error('syscall argument cannot be greater than 64 bits') | |
end | |
end | |
local arg1 = args[1] | |
local arg2 = args[2] | |
local arg3 = args[3] | |
local arg4 = args[4] | |
local arg5 = args[5] | |
local arg6 = args[6] | |
local instr = [[ | |
syscall | |
jnc 1f | |
mov %rax, $0 | |
mov $$-1, %rax | |
1: | |
]] | |
-- call appropriate stub | |
-- NOTE: there is evidence that RDX gets clobbered on MacOS. | |
-- we mark it as such here. | |
if #args == 0 then | |
return `terralib.asm(uint64, instr, | |
'=*m,={rax},{rax},~{rcx},~{r11},~{rdx}', true, | |
&errno, | |
[uint64](num + 0x2000000)) | |
elseif #args == 1 then | |
return `terralib.asm(uint64, instr, | |
'=*m,={rax},{rax},{rdi},~{rcx},~{r11},~{rdx}', true, | |
&errno, | |
[uint64](num + 0x2000000), | |
[uint64](arg1)) | |
elseif #args == 2 then | |
return `terralib.asm(uint64, instr, | |
'=*m,={rax},{rax},{rdi},{rsi},~{rcx},~{r11},~{rdx}', true, | |
&errno, | |
[uint64](num + 0x2000000), | |
[uint64](arg1), [uint64](arg2)) | |
elseif #args == 3 then | |
return `terralib.asm(uint64, instr, | |
'=*m,={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{rdx}', true, | |
&errno, | |
[uint64](num + 0x2000000), | |
[uint64](arg1), [uint64](arg2), [uint64](arg3)) | |
elseif #args == 4 then | |
return `terralib.asm(uint64, instr, | |
'=*m,={rax},{rax},{rdi},{rsi},{rdx},{r10},~{rcx},~{r11},~{rdx}', true, | |
&errno, | |
[uint64](num + 0x2000000), | |
[uint64](arg1), [uint64](arg2), [uint64](arg3), [uint64](arg4)) | |
elseif #args == 5 then | |
return `terralib.asm(uint64, instr, | |
'=*m,={rax},{rax},{rdi},{rsi},{rdx},{r10},{r8},~{rcx},~{r11},~{rdx}', true, | |
&errno, | |
[uint64](num + 0x2000000), | |
[uint64](arg1), [uint64](arg2), [uint64](arg3), [uint64](arg4), [uint64](arg5)) | |
elseif #args == 6 then | |
return `terralib.asm(uint64, instr, | |
'=*m,={rax},{rax},{rdi},{rsi},{rdx},{r10},{r8},{r9},~{rcx},~{r11},~{rdx}', true, | |
&errno, | |
[uint64](num + 0x2000000), | |
[uint64](arg1), [uint64](arg2), [uint64](arg3), [uint64](arg4), [uint64](arg5), [uint64](arg6)) | |
else | |
error('too many arguments to syscall') | |
end | |
end) | |
local DBG = terralib.includec('stdio.h') | |
-- https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/kern/syscalls.master.auto.html | |
local terra _syscall_exit(exit_status: int) syscall(1, exit_status) end | |
local terra _syscall_write(fd: int, buf: &int8, size: uint64): uint64 return syscall(4, fd, buf, size) end | |
local terra _syscall_mmap_0(ptr: &opaque, size: uint64, protections: int, flags: int): uint64 return syscall(197, ptr, size, protections, flags) end | |
local terra _syscall_mmap_1(ptr: &opaque, size: uint64, protections: int, flags: int, fd: int, offset: uint64): &opaque return [&opaque](syscall(197, ptr, size, protections, flags, fd, offset)) end | |
local _syscall_mmap = terralib.overloadedfunction('_syscall_mmap', {_syscall_mmap_0, _syscall_mmap_1}) | |
local terra _syscall_munmap(ptr: &opaque, size: uint64) syscall(73, ptr, size) end | |
-- TODO these belong somewhere else, not here. | |
local terra malloc4096(): &opaque | |
-- 0x03 = READ|WRITE (does not include EXEC) - XXX should it include EXEC? | |
-- 0x1002 = ANONYMOUS (no file, no offset) and PRIVATE | |
var ptrint: uint64 = _syscall_mmap_0(nil, 4096, 0x03, 0x1002); | |
if ptrint == [uint64](-1) then | |
DBG.printf("WARNING: mmap failed with errno: %lu\n", errno) | |
return nil | |
end | |
return [&opaque](ptrint) | |
end | |
local terra free4096(ptr: &opaque) | |
_syscall_munmap(ptr, 4096) | |
end | |
return { | |
exit = _syscall_exit, | |
write = _syscall_write, | |
mmap = _syscall_mmap, | |
munmap = _syscall_munmap, | |
-- TODO High level stuff that belongs elsewhere | |
malloc4096 = malloc4096, | |
free4096 = free4096 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local sys = require('./syscall-macos-x64') | |
terra main() | |
var c: &int8 = [&int8](sys.malloc4096()) | |
if c == nil then | |
sys.write(2, 'Allocation of page failed!\n', 27) | |
sys.exit(1) | |
end | |
sys.write(1, 'Created page!\n', 14) | |
var str: &int8 = "Hello from the page!\n" | |
var i: uint64 = 0 | |
repeat | |
c[i] = str[i] | |
i = i + 1 | |
until str[i] == 0 | |
sys.write(1, c, i) | |
sys.write(1, 'Wrote page! Freeing it...\n', 26) | |
sys.free4096(c) | |
sys.write(1, 'Done!\n', 6) | |
sys.exit(0) | |
end | |
terralib.saveobj('bin/test-syscall', { main = main }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment