diff options
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | compiler/elymasAsmLib.ey | 18 | ||||
| -rw-r--r-- | compiler/elymasGlobalSys.ey | 5 | ||||
| -rw-r--r-- | compiler/elymasGlobalSysAsm.ey | 10 | ||||
| -rw-r--r-- | compiler/standardClient.ey | 51 | ||||
| -rw-r--r-- | elymas/interpreter.ey | 2 | ||||
| -rw-r--r-- | elymas/lib/sys/so.ey | 165 | ||||
| -rw-r--r-- | elymas/loaded.ey | 2 | ||||
| -rw-r--r-- | elymas/optimized.ey | 2 | ||||
| -rw-r--r-- | elymas/shared.ey | 2 | ||||
| -rw-r--r-- | interpreter/ElymasGlobal.pm | 17 | ||||
| -rw-r--r-- | interpreter/ElymasSys.pm | 14 |
12 files changed, 246 insertions, 44 deletions
@@ -95,7 +95,7 @@ Technical Pecularities * no runtime interpreter, executes real assembly * same binary both interpretes and compiles * freeze arbitrary program states to ELF-binaries -* self hosted via `{ "/proc/self/fd/0" include }' "interpreter" sys .freeze` +* self hosted via `{ "/dev/stdin" include }' "interpreter" sys .freeze` * yes, this works and generates a stand-alone interpreter/compiler * bootstraps from perl * no perl left in final binaries diff --git a/compiler/elymasAsmLib.ey b/compiler/elymasAsmLib.ey index 71a4cab..b830a48 100644 --- a/compiler/elymasAsmLib.ey +++ b/compiler/elymasAsmLib.ey @@ -12,12 +12,24 @@ 2 ==MAP_PRIVATE 16 ==MAP_FIXED - 32 ==MAP_ANONYMOUS + + [ + { sys .?linux } { 32 } + { sys .?freebsd } { 4096 } + ] conds ==MAP_ANONYMOUS > ==MMAP < - 1 ==write - 9 ==mmap + [ + { sys .?linux } { + 1 ==write + 9 ==mmap + }' + { sys .?freebsd } { + 4 ==write + 477 ==mmap + }' + ] conds > ==SYSCALL 0 ==constantAllocBegin diff --git a/compiler/elymasGlobalSys.ey b/compiler/elymasGlobalSys.ey index e00009c..0ba45d8 100644 --- a/compiler/elymasGlobalSys.ey +++ b/compiler/elymasGlobalSys.ey @@ -138,6 +138,11 @@ "elymasGlobalSysDyn.ey" include "elymasGlobalSysTyped.ey" include + [ + { sys .?linux } { "linux" } + { sys .?freebsd } { "freebsd" } + ] conds enterSubScope leaveSubScope + leaveSubScope > -- diff --git a/compiler/elymasGlobalSysAsm.ey b/compiler/elymasGlobalSysAsm.ey index 14052f5..9fe2f2d 100644 --- a/compiler/elymasGlobalSysAsm.ey +++ b/compiler/elymasGlobalSysAsm.ey @@ -491,7 +491,15 @@ 8 /rax :addqImm8Reg } rep - /r8 /rsp :xchgqRegReg # swap to elymas stack to ensure correct GC behavior for what follows + [ + { sys .?linux } { + /r8 /rsp :xchgqRegReg # swap to elymas stack to ensure correct GC behavior for what follows + } + { sys .?freebsd } { + /r8 /rsp :movqRegReg # swap to elymas stack to ensure correct GC behavior for what follows + /rdi /r8 :movqRegReg # FreeBSD passes argc stack location in rdi + } + ] conds # empty encoding buffer to ensure the GC does not follow residue from freeze into unallocated memory :quoteEncodingBufferObjects /rdi :movqImmReg diff --git a/compiler/standardClient.ey b/compiler/standardClient.ey index 367d978..8d73236 100644 --- a/compiler/standardClient.ey +++ b/compiler/standardClient.ey @@ -389,25 +389,47 @@ 2 _ ==:RDWR bor bor ==:RWMASK - 64 ==:OCREAT - 512 ==:OTRUNC - 1024 ==:OAPPEND - 1 ==:PROTREAD 2 ==:PROTWRITE 4 ==:PROTEXEC 2 ==:MAPPRIVATE - 32 ==:MAPANONYMOUS - 0 ==:READ - 1 ==:WRITE - 2 ==:OPEN - 3 ==:CLOSE + [ + { sys .?linux } { 32 } + { sys .?freebsd } { 4096 } + ] conds ==:MAPANONYMOUS - 9 ==:MMAP - 11 ==:MUNMAP - 60 ==:EXIT + [ + { sys .?linux } { + 64 ==:OCREAT + 512 ==:OTRUNC + 1024 ==:OAPPEND + + 0 ==:READ + 1 ==:WRITE + 2 ==:OPEN + 3 ==:CLOSE + + 9 ==:MMAP + 11 ==:MUNMAP + 60 ==:EXIT + }' + { sys .?freebsd } { + 512 ==:OCREAT + 1024 ==:OTRUNC + 8 ==:OAPPEND + + 3 ==:READ + 4 ==:WRITE + 5 ==:OPEN + 6 ==:CLOSE + + 477 ==:MMAP + 73 ==:MUNMAP + 1 ==:EXIT + }' + ] conds { ==code code 0 0 0 0 0 EXIT sys .asm .syscall @@ -964,7 +986,10 @@ %02 # elfclass64 %01 # elf version %01 # little endian encoding - %00 %00 # Sys-V ABI + [ + { sys .?linux } { %00 %00 } # Sys-V ABI + { sys .?freebsd } { %09 %00 } # FreeBSD ABI + ] conds %00 %00 %00 %00 %00 %00 %00 # padding # Elf64_Half e_type; /* Object file type */ %02 %00 # executable file diff --git a/elymas/interpreter.ey b/elymas/interpreter.ey index c67658a..9a526ff 100644 --- a/elymas/interpreter.ey +++ b/elymas/interpreter.ey @@ -1,6 +1,6 @@ #!/usr/bin/env elymas { - sys .argv len { 0 sys .argv * } { "/proc/self/fd/0" } ? * include + sys .argv len { 0 sys .argv * } { "/dev/stdin" } ? * include 0 sys .exit }' "interpreter" sys .freeze diff --git a/elymas/lib/sys/so.ey b/elymas/lib/sys/so.ey index efb4d3b..d6148f2 100644 --- a/elymas/lib/sys/so.ey +++ b/elymas/lib/sys/so.ey @@ -18,6 +18,11 @@ 0 -01 { 48 sub [ 0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 10 11 12 13 14 15 ] * -01 16 mul -01 add } each } "%" defq + { 8 { _ 256 mod -01 256 div } rep -- } /uint64 deffd + { _ 0 lt { 4294967296 add } rep 4294967295 band 4 { _ 256 mod -01 256 div } rep -- } /uint32 deffd + { _ 0 lt { 65536 add } rep 65535 band 2 { _ 256 mod -01 256 div } rep -- } /uint16 deffd + { _ 0 lt { 256 add } rep 255 band } /uint8 deffd + [ /rdi /rsi /rdx /rcx /r8 /r9 ] _ =*:availableIntegerRegisters len ==:INTREGISTERS [ /xmm0 /xmm1 /xmm2 /xmm3 /xmm4 /xmm5 /xmm6 /xmm7 ] _ =*:availableFloatRegisters @@ -71,12 +76,21 @@ { ::rawAddress 24 add } /rawContentAddress deffd - 8 str .alloc _ str .zero ==:dlopenAddress - 8 str .alloc _ str .zero ==:dlsymAddress - 8 str .alloc ==:r15backup 8 str .alloc ==:rspbackup + 8 str .alloc _ str .zero ==:dlopenAddress + 8 str .alloc _ str .zero ==:dlsymAddress + + [ + { sys .?freebsd } { + "Elymas memory image" ==:prognameContent + [ prognameContent rawContentAddress uint64 ] str .fromArray ==:prognamePointer + 8 str .alloc _ str .zero ==:environContent + [ environContent rawContentAddress uint64 ] str .fromArray ==:environPointer + }' + ] conds + [ ] ==saveFromGC { ==f ==sym @@ -561,6 +575,12 @@ ] [ func ::rawAddress ] ::createFunction } /wrapCallback deffd + [ + { sys .?freebsd } { + [ ] ==allLibraries + }' + ] conds + { "\0" cat } [ /rbx :popqReg @@ -588,7 +608,13 @@ /rbx :pushqReg :retn - ] [ ] ::createFunction ; /dlopen deffd + ] [ ] ::createFunction ; + [ + { sys .?freebsd } { + { _ 0 neq { [ -101 ] allLibraries cat =allLibraries } rep } ; + } + ] conds + /dlopen deffd { -01 "\0" cat -01 } [ /rbx :popqReg @@ -650,19 +676,27 @@ # 1 -> argument specification string (see wrapFunction for details) # 2 -> name of function # the resulting function will take as many arguments as specified and return a single integer - { ==rets ==args ==name - name 0 dlsym _ not { "Could not resolve function: " name cat die } rep - args rets wrapFunction - } /resolveFunction deffd + [ + { sys .?linux } { + { ==rets ==args ==name + name 0 dlsym _ not { "Could not resolve function: " name cat die } rep + args rets wrapFunction + } + }' + { sys .?freebsd } { + 0 ==result + allLibraries { + result { -- } { name -01 dlsym =result } ? * + } each + result _ not { "Could not resolve function: " name cat die } rep + args rets wrapFunction + }' + ] conds + /resolveFunction deffd { ==filename # ==f (left on the stack a while and executed from sys .asm .programStart) sys .asm .patchProgramStart ==frozenAllocationCount ==heapSize - { 8 { _ 256 mod -01 256 div } rep -- } /uint64 deffd - { _ 0 lt { 4294967296 add } rep 4294967295 band 4 { _ 256 mod -01 256 div } rep -- } /uint32 deffd - { _ 0 lt { 65536 add } rep 65535 band 2 { _ 256 mod -01 256 div } rep -- } /uint16 deffd - { _ 0 lt { 256 add } rep 255 band } /uint8 deffd - { ==align ==value align value align mod sub align mod } /alignUpto deff @@ -731,6 +765,24 @@ 0 ==?dataSize # to be filled later { _ =data len =dataSize } /setData deff > _ ==?relocationTable + + [ + { sys .?freebsd } { + < + ".hash" ==?name + 0 ==?nameOffset { =nameOffset } /setNameOffset deff + 0 ==?dataOffset { =dataOffset } /setDataOffset deff + 5 ==?type # symbol hash table + 0 ==?flags # none + 0 ==?addr # not loaded + 3 ==?link # symbol table is associated (section index 3) + 0 ==?entsize # no uniform fixed-size entries here + [ ] ==?data # to be filled later + 0 ==?dataSize # to be filled later + { _ =data len =dataSize } /setData deff + > _ ==?hashTable + }' + ] conds ] ==?metaSections [ @@ -755,11 +807,23 @@ allocSections len 4 add ==programHeaderCount metaSections len allocSections len add ==sectionHeaderCount - "/lib64/ld-linux-x86-64.so.2" ==:INTERPRETERNAME 0 ==interpreterStringOffset - "libc.so.6" ==:LIBCNAME 0 ==libcStringOffset - "libdl.so.2" ==:LIBDLNAME 0 ==libdlStringOffset - "dlopen" ==:DLOPENNAME 0 ==dlopenStringOffset - "dlsym" ==:DLSYMNAME 0 ==dlsymStringOffset + [ + { sys .?linux } { + "/lib64/ld-linux-x86-64.so.2" ==:INTERPRETERNAME 0 ==interpreterStringOffset + "libc.so.6" ==:LIBCNAME 0 ==libcStringOffset + "libdl.so.2" ==:LIBDLNAME 0 ==libdlStringOffset + "dlopen" ==:DLOPENNAME 0 ==dlopenStringOffset + "dlsym" ==:DLSYMNAME 0 ==dlsymStringOffset + }' + { sys .?freebsd } { + "/libexec/ld-elf.so.1" ==:INTERPRETERNAME 0 ==interpreterStringOffset + "libc.so.7" ==:LIBCNAME 0 ==libcStringOffset + "dlopen" ==:DLOPENNAME 0 ==dlopenStringOffset + "dlsym" ==:DLSYMNAME 0 ==dlsymStringOffset + "__progname" ==:PROGNAME 0 ==prognameStringOffset + "environ" ==:ENVIRON 0 ==environStringOffset + } + ] conds < 1 ==stringOffset { =*saveOffset ==string @@ -778,12 +842,38 @@ INTERPRETERNAME { =interpreterStringOffset } stringTableEntry LIBCNAME { =libcStringOffset } stringTableEntry - LIBDLNAME { =libdlStringOffset } stringTableEntry DLOPENNAME { =dlopenStringOffset } stringTableEntry DLSYMNAME { =dlsymStringOffset } stringTableEntry + + [ + { sys .?linux } { + LIBDLNAME { =libdlStringOffset } stringTableEntry + }' + { sys .?freebsd } { + PROGNAME { =prognameStringOffset } stringTableEntry + ENVIRON { =environStringOffset } stringTableEntry + }' + ] conds ] stringTable .setData > -- + [ + { sys .?freebsd } { + [ + 1 uint32 # number of "hash" buckets (ahem) + 5 uint32 # number of symbols + + 1 uint32 # bucket starts at first real symbol + + 0 uint32 # reserved undefined symbol refers to itself + 2 uint32 # first symbol refers to the second, + 3 uint32 # ... which refers to the third, etc. + 4 uint32 + 0 uint32 # ... which refers to the undefined symbol + ] hashTable .setData + }' + ] conds + < [ 0 uint64 0 uint64 0 uint64 # symbol table index 0 is reserved @@ -801,6 +891,24 @@ 0 uint16 0 uint64 0 uint64 + + [ + { sys .?freebsd } { + prognameStringOffset uint32 + %11 # globally visible object (char * presumably) + %00 + %F1 %FF # SHN_ABS + prognamePointer rawContentAddress uint64 # value + 8 uint64 # size + + environStringOffset uint32 + %11 # globally visible object (char **) + %00 + %F1 %FF # SHN_ABS + environPointer rawContentAddress uint64 # value + 8 uint64 # size + }' + ] conds # FIXME: make a createSymbol function instead of having hash and symbol table data being dependent ] symbolTable .setData > -- @@ -821,7 +929,6 @@ [ # TAG VALUE 1 uint64 libcStringOffset uint64 # require libc (DT_NEEDED) - 1 uint64 libdlStringOffset uint64 # require libdl (DT_NEEDED) 5 uint64 %700000000000 stringTable .dataOffset add uint64 # string table address (DT_STRTAB) 6 uint64 %700000000000 symbolTable .dataOffset add uint64 # symbol table address (DT_SYMTAB) 7 uint64 %700000000000 relocationTable .dataOffset add uint64 # relocation table address (DT_RELA) @@ -829,6 +936,14 @@ 9 uint64 24 uint64 # relocation entry size (DT_RELAENT) 10 uint64 stringTable .dataSize uint64 # string table size (DT_STRSZ) 11 uint64 24 uint64 # symbol entry size (DT_SYMENT) + [ + { sys .?linux } { + 1 uint64 libdlStringOffset uint64 # require libdl (DT_NEEDED) + }' + { sys .?freebsd } { + 4 uint64 %700000000000 hashTable .dataOffset add uint64 # hash table address (DT_HASH) + }' + ] conds # 0x0000000000000015 (DEBUG) 0x0 # 0x0000000000000003 (PLTGOT) 0x604c48 # 0x0000000000000002 (PLTRELSZ) 888 (bytes) @@ -869,7 +984,10 @@ %02 # elfclass64 %01 # elf version %01 # little endian encoding - %00 %00 # Sys-V ABI + [ + { sys .?linux } { %00 %00 } # Sys-V ABI + { sys .?freebsd } { %09 %00 } # FreeBSD ABI + ] conds %00 %00 %00 %00 %00 %00 %00 # padding # Elf64_Half e_type; /* Object file type */ %02 %00 # executable file @@ -1016,7 +1134,10 @@ data str .fromArray out .writeall } each - 1 ==:WRITE + [ + { sys .?linux } { 1 ==:WRITE }' + { sys .?freebsd } { 4 ==:WRITE }' + ] conds # FIXME: get the constant from somewhere else [ ] _ =fileHeaders =metaSections diff --git a/elymas/loaded.ey b/elymas/loaded.ey index 2076e02..0fadb20 100644 --- a/elymas/loaded.ey +++ b/elymas/loaded.ey @@ -21,6 +21,6 @@ ] { _ dump include }' each { - sys .argv len { 0 sys .argv * } { "/proc/self/fd/0" } ? * include + sys .argv len { 0 sys .argv * } { "/dev/stdin" } ? * include 0 sys .exit }' "loaded" sys .freeze diff --git a/elymas/optimized.ey b/elymas/optimized.ey index 265ded7..631af4d 100644 --- a/elymas/optimized.ey +++ b/elymas/optimized.ey @@ -7,6 +7,6 @@ ] { _ dump include }' each { - sys .argv len { 0 sys .argv * } { "/proc/self/fd/0" } ? * include + sys .argv len { 0 sys .argv * } { "/dev/stdin" } ? * include 0 sys .exit }' "optimized" sys .freeze diff --git a/elymas/shared.ey b/elymas/shared.ey index 40a09e6..21b51f3 100644 --- a/elymas/shared.ey +++ b/elymas/shared.ey @@ -22,6 +22,6 @@ ] { _ dump include }' each { - sys .argv len { 0 sys .argv * } { "/proc/self/fd/0" } ? * include + sys .argv len { 0 sys .argv * } { "/dev/stdin" } ? * include 0 sys .exit }' "shared" sys .so .freeze diff --git a/interpreter/ElymasGlobal.pm b/interpreter/ElymasGlobal.pm index 4080661..d7f22dc 100644 --- a/interpreter/ElymasGlobal.pm +++ b/interpreter/ElymasGlobal.pm @@ -196,6 +196,7 @@ EOPERL my ($data) = @_; my $s = sub { my ($data, $lscope) = @_; + my $scope = $$lscope; EOPERL compileCode(\@code) . <<'EOPERL'; }; @@ -210,6 +211,7 @@ EOPERL my $sub = <<'EOPERL' . sub { my ($data, $lscope) = @_; + my $scope = $$lscope; EOPERL compileCode(\@code) . <<'EOPERL'; }; @@ -348,6 +350,21 @@ EOPERL push @$data, $struct->[0]->{$member}; }, ['func', '.|'], 'active'], + '.?' => [sub { + my ($data, $scope) = @_; + + my $member = pop @$data; + my $struct = pop @$data; + $member = $member->[0]; + + die "not a struct during member dereference in " . Dumper($struct) unless ref($struct->[1]) eq 'ARRAY' and $struct->[1]->[0] eq 'struct'; + + if(exists $struct->[0]->{$member}) { + push @$data, [1, 'int'], + } else { + push @$data, [0, 'int'], + } + }, ['func', '.?'], 'active'], 'deff' => [sub { my ($data, $scope) = @_; diff --git a/interpreter/ElymasSys.pm b/interpreter/ElymasSys.pm index ad79b02..a5219c6 100644 --- a/interpreter/ElymasSys.pm +++ b/interpreter/ElymasSys.pm @@ -9,6 +9,19 @@ use POSIX; my $rwmask = &POSIX::O_RDONLY | &POSIX::O_WRONLY | &POSIX::O_RDWR; +sub osType { + my $uname = qx(uname); + chomp $uname; + + if($uname eq 'Linux') { + return 'linux'; + } elsif($uname eq 'FreeBSD') { + return 'freebsd'; + } else { + die "Unknown uname output '$uname', cannot decide what ABI to use."; + } +} + our $sys = { 'file' => [sub { my ($data, $scope) = @_; @@ -21,6 +34,7 @@ our $sys = { 'err' => [createFile(2, &POSIX::O_WRONLY), ['struct'], 'passive'], 'argv' => [[map { [$_, 'string'] } @ARGV[1 .. $#ARGV]], ['array', 'sys .argv', ['range', 0, $#ARGV - 1], ['string']], 'passive'], 'asm' => [$ElymasAsm::asm, ['struct'], 'passive'], + osType() => [{ }, ['struct'], 'passive'], }; sub createFile { |
