aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--compiler/elymasAsmLib.ey18
-rw-r--r--compiler/elymasGlobalSys.ey5
-rw-r--r--compiler/elymasGlobalSysAsm.ey10
-rw-r--r--compiler/standardClient.ey51
-rw-r--r--elymas/interpreter.ey2
-rw-r--r--elymas/lib/sys/so.ey165
-rw-r--r--elymas/loaded.ey2
-rw-r--r--elymas/optimized.ey2
-rw-r--r--elymas/shared.ey2
-rw-r--r--interpreter/ElymasGlobal.pm17
-rw-r--r--interpreter/ElymasSys.pm14
12 files changed, 246 insertions, 44 deletions
diff --git a/README.md b/README.md
index 711d401..e969c80 100644
--- a/README.md
+++ b/README.md
@@ -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 {