aboutsummaryrefslogtreecommitdiff
path: root/elymas
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2013-10-04 12:50:41 +0200
committerDrahflow <drahflow@gmx.de>2013-10-04 12:50:41 +0200
commitef3ff192922d1b3a51ee85de64c210f0e8101271 (patch)
treead71ab2ac9c6c68cc3fad9016450b3785367ce23 /elymas
parentbb5a9deb5f17b0e4cc89c8577b745a44ae5b1bdd (diff)
"Hello World" via libc6
Diffstat (limited to 'elymas')
-rw-r--r--elymas/lib/sys/linux.ey103
-rw-r--r--elymas/lib/sys/opt.ey56
-rw-r--r--elymas/lib/sys/so.ey386
-rw-r--r--elymas/loaded.ey1
4 files changed, 500 insertions, 46 deletions
diff --git a/elymas/lib/sys/linux.ey b/elymas/lib/sys/linux.ey
index 31e4ba1..d4c97ec 100644
--- a/elymas/lib/sys/linux.ey
+++ b/elymas/lib/sys/linux.ey
@@ -11,7 +11,7 @@
# 159 ==:ADJTIMEX
# 183 ==:AFSSYSCALL
# 37 ==:ALARM
- # 158 ==:ARCHPRCTL
+ 158 ==:ARCHPRCTL
49 ==:BIND
# 12 ==:BRK
# 125 ==:CAPGET
@@ -63,7 +63,7 @@
# 57 ==:FORK
# 199 ==:FREMOVEXATTR
# 190 ==:FSETXATTR
- # 5 ==:FSTAT
+ 5 ==:FSTAT
# 138 ==:FSTATFS
# 74 ==:FSYNC
# 77 ==:FTRUNCATE
@@ -139,7 +139,7 @@
# 259 ==:MKNODAT
# 149 ==:MLOCK
# 151 ==:MLOCKALL
- # 9 ==:MMAP
+ 9 ==:MMAP
# 154 ==:MODIFYLDT
# 165 ==:MOUNT
# 279 ==:MOVEPAGES
@@ -158,7 +158,7 @@
# 26 ==:MSYNC
# 150 ==:MUNLOCK
# 152 ==:MUNLOCKALL
- # 11 ==:MUNMAP
+ 11 ==:MUNMAP
# 35 ==:NANOSLEEP
# 262 ==:NEWFSTATAT
# 180 ==:NFSSERVCTL
@@ -323,6 +323,8 @@
{ 0 0 0 0 0 ACCEPT } /accept defStdSyscall
+ { 4098 -01 0 0 0 0 ARCHPRCTL } /archSetFs defStdSyscall
+
{ _ len 0 0 0 BIND } /bind defStdSyscall
{ 0 0 0 0 0 CLOSE } /close defStdSyscall
@@ -390,8 +392,67 @@
} /wait deffd
> /epoll defvd
+ {
+ <
+ ->u64 ==dev
+ ->u64 ==ino
+ ->u32 ==nlink
+ ->u32 ==what0
+ ->u32 ==mode
+ ->u32 ==gid
+ ->u32 ==uid
+ ->u32 ==what1
+ ->u64 ==rdev
+ ->u64 ==size
+ ->u32 ==blksize
+ ->u32 ==what3
+ ->u64 ==blocks
+ ->u64 ==atime
+ ->u64 ==atimensec
+ ->u64 ==mtime
+ ->u64 ==mtimensec
+ ->u64 ==ctime
+ ->u64 ==ctimensec
+ ->u32 --
+ ->u32 --
+ >
+ } /parseStatStruct deffd
+
+ # 0 -> fd to stat
+ # 0 <- raw return value
+ # 1 <- (struct stat)-like scope
+ { # ==filename
+ # struct stat takes 144 bytes on a x64
+ 128 str .alloc ==buf
+ buf 0 0 0 0 FSTAT sys .asm .syscall =errno
+ buf parseStatStruct -02
+ } /fstat deffd
+
{ 0 0 0 0 LISTEN } /listen defStdSyscall
+ 1 ==:PROTREAD
+ 2 ==:PROTWRITE
+ 4 ==:PROTEXEC
+
+ 1 ==:MAPSHARED
+ 2 ==:MAPPRIVATE
+ 16 ==:MAPFIXED
+ 32 ==:MAPANONYMOUS
+ 256 ==:MAPGROWSDOWN
+ 8192 ==:MAPLOCKED
+ 16384 ==:MAPNORESERVE
+ 32768 ==:MAPPOPULATE
+ 65536 ==:MAPNONBLOCK
+ 262144 ==:MAPHUGETLB
+
+ # 0 -> offset (in file)
+ # 1 -> fd
+ # 2 -> flags
+ # 3 -> protection
+ # 4 -> length
+ # 5 -> address
+ { MMAP } /mmap defStdSyscall
+
1 ==:AFUNIX
1 ==:AFLOCAL
2 ==:AFINET
@@ -427,23 +488,27 @@
# struct stat takes 144 bytes on a x64
144 str .alloc ==buf
buf 0 0 0 0 STAT sys .asm .syscall =errno
- buf <
- ->u64 ==dev
- ->u64 ==ino
- ->u64 ==mode
- ->u64 ==nlink
- ->u64 ==uid
- ->u64 ==gid
- ->u64 ==rdev
- ->u64 ==size
- ->u64 ==blksize
- ->u64 ==blocks
- ->u64 ==atime
- ->u64 ==mtime
- ->u64 ==ctime
- > -02
+ buf parseStatStruct -02
} /stat deffd
+ 0 ==:ORDONLY
+ 1 ==:OWRONLY
+ 2 ==:ORDWR
+ 256 ==:OCREAT
+ 512 ==:OEXCL
+ 1024 ==:ONOCTTY
+ 8192 ==:OAPPEND
+ 4096 ==:OTRUNC
+ 16384 ==:ONONBLOCK
+ 131072 ==:OASYNC
+ 262144 ==:ODIRECT
+ 1048576 ==:OLARGEFILE
+ 2097152 ==:ODIRECTORY
+ 4194304 ==:ONOFOLLOW
+ 16777216 ==:ONOATIME
+ 33554432 ==:OCLOEXEC
+ 67174400 ==:OSYNC
+
{ 0 0 0 OPEN } /open defStdSyscall
<
diff --git a/elymas/lib/sys/opt.ey b/elymas/lib/sys/opt.ey
index 5f106cf..d07a5e7 100644
--- a/elymas/lib/sys/opt.ey
+++ b/elymas/lib/sys/opt.ey
@@ -1,7 +1,10 @@
<
- "../compiler/elymasAsm.ey" include
+ <
+ "../compiler/elymasAsm.ey" include
+ assembler /ops sys .asm .defv
+ > --
- assembler ":" via
+ sys .asm .ops ":" via
[
8 /r15 :subqImm8Reg
@@ -141,11 +144,11 @@
{ _ ==logic
logic { ==entry 0 entry * ==action
[
- { action CALL streq { 1 entry * "<" | +rawCodeAddress eq }' andif }' {
+ { action CALL streq { 1 entry * "<" | ::rawCodeAddress eq }' andif }' {
1 =containsScopeModifications
}
- { action CALL streq { 1 entry * ">" | +rawCodeAddress eq }' andif }' {
+ { action CALL streq { 1 entry * ">" | ::rawCodeAddress eq }' andif }' {
1 =containsScopeModifications
}
] conds
@@ -156,8 +159,8 @@
[ NOP ] ==last
[ logic { ==entry 0 entry * ==action
[
- { action CALL streq { 1 entry * "|" | +rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
- 1 last * +rawObject ==constant
+ { action CALL streq { 1 entry * "|" | ::rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
+ 1 last * ::rawObject ==constant
constant executingScope sys .resolveInfo {
==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea
@@ -185,8 +188,8 @@
[ NOP ] ==last
[ logic { ==entry 0 entry * ==action
[
- { action CALL streq { 1 entry * "=" | +rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
- 1 last * +rawObject ==constant
+ { action CALL streq { 1 entry * "=" | ::rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
+ 1 last * ::rawObject ==constant
constant executingScope sys .resolveInfo {
==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea
@@ -214,12 +217,12 @@
2 logic len range { ==i i logic * ==entry 0 entry * ==action i 1 sub logic * ==last i 2 sub logic * ==secondLast
[
{ action CALL streq
- { 1 entry * "." | +rawCodeAddress eq }' andif
+ { 1 entry * "." | ::rawCodeAddress eq }' andif
{ 0 last * PUSH streq }' andif
{ 0 secondLast * STATICTYPED streq }' andif
}' {
- 1 last * +rawObject ==constant
- 4 secondLast * +rawObject ==relevantScope
+ 1 last * ::rawObject ==constant
+ 4 secondLast * ::rawObject ==relevantScope
constant relevantScope sys .resolveInfo {
==mode -- ==parentCount 32 add ==offsetInScope ==inExtensionArea
@@ -231,7 +234,7 @@
{ mode 16 mod 0 eq }' {
[ NOP ] i logic =[]
} { mode 16 mod 1 eq }' {
- [ CALL "*" | +rawCodeAddress ] i logic =[]
+ [ CALL "*" | ::rawCodeAddress ] i logic =[]
} { 1 }' {
# TODO this might conceivably be legal though...
"Scope keys: " dump relevantScope keys dump
@@ -267,13 +270,13 @@
} /holdsInt deffd
action CALL streq
- { 1 entry * "*" | +rawCodeAddress eq }' andif
+ { 1 entry * "*" | ::rawCodeAddress eq }' andif
{ 0 last * PUSH streq }' andif
{ secondLast holdsInt }' andif
{ thirdLast holdsInt }' andif
{
[
- { 1 last * |add +rawAddress eq }' {
+ { 1 last * |add ::rawAddress eq }' {
[ NATIVE [
/rcx :popqReg
63 /rcx :btrqImm8Reg
@@ -317,7 +320,7 @@
}
{ ==negatedOpcodeName ==functionName
- { 1 last * functionName | +rawAddress eq }' {
+ { 1 last * functionName | ::rawAddress eq }' {
[ NATIVE [
/rcx :popqReg
63 /rcx :btrqImm8Reg
@@ -357,10 +360,10 @@
1 logic len range { ==i i logic * ==entry 0 entry * ==action i 1 sub logic * ==last
[
{ action CALL streq
- { 1 entry * "*" | +rawCodeAddress eq }' andif
+ { 1 entry * "*" | ::rawCodeAddress eq }' andif
{ 0 last * STATICTYPED streq }' andif
}' {
- 4 last * +rawObject ==executedObject
+ 4 last * ::rawObject ==executedObject
executedObject sys .typed .type ==type
type [
@@ -403,18 +406,18 @@
[ NOP ] ==last
[ logic { ==entry 0 entry * ==action
[
- { action CALL streq { 1 entry * "_" | +rawCodeAddress eq }' andif }' {
+ { action CALL streq { 1 entry * "_" | ::rawCodeAddress eq }' andif }' {
[ NATIVE [
0 /rsp :pushqMemDisp8
] ] =entry
}
- { action CALL streq { 1 entry * "--" | +rawCodeAddress eq }' andif }' {
+ { action CALL streq { 1 entry * "--" | ::rawCodeAddress eq }' andif }' {
[ NATIVE [
8 /rsp :addqImm8Reg
] ] =entry
}
- { action CALL streq { 1 entry * "-" | +rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
- 1 last * +rawObject ==constant
+ { action CALL streq { 1 entry * "-" | ::rawCodeAddress eq }' andif { 0 last * PUSH streq }' andif }' {
+ 1 last * ::rawObject ==constant
{ -1010 lt -012 ? } /max deffd
@@ -453,11 +456,10 @@
} each last ]
} /rewriteStackOps deffst
- sys .asm "+" via
+ sys .asm "::" via
sys .asm .|peek ==:peek
- sys .opt "::" via
- o +rawAddress ==addr
+ o ::rawAddress ==addr
[ addr _ 4 add range peek each ] 256 math .unbase ==totalLength
[ addr 8 add _ 4 add range peek each ] 256 math .unbase ==codeLength
addr 16 add ==i
@@ -500,7 +502,7 @@
[ calledAddress 3 add _ 8 add range peek each ] 256 math .unbase ==calledConstant
[ PUSH calledConstant ] emitLogic
- [ CALL "*" | +rawCodeAddress ] emitLogic
+ [ CALL "*" | ::rawCodeAddress ] emitLogic
}
{ constantNormalFunctionScopedUntypedPattern callTargetMatch }' {
@@ -557,7 +559,7 @@
[
{ staticLoadActivePattern callTargetMatch }' {
- [ CALL "*" | +rawCodeAddress ] emitLogic
+ [ CALL "*" | ::rawCodeAddress ] emitLogic
}
{ staticLoadPassivePattern callTargetMatch }' {
@@ -811,7 +813,7 @@
] emitOpcodes
}' ? *
- newReferences newOpcodes o ::replace
+ newOpcodes newReferences o ::replace
1 executingScope # return something different from o to signal successful optimization
} /optimize deffd
diff --git a/elymas/lib/sys/so.ey b/elymas/lib/sys/so.ey
new file mode 100644
index 0000000..15bd751
--- /dev/null
+++ b/elymas/lib/sys/so.ey
@@ -0,0 +1,386 @@
+# Access shared libraries (and link dynamically)
+
+<
+ sys .linux "+" via
+ sys .asm "::" via
+ sys .asm .ops ":" via
+ sys .asm .|peek =*:peek
+ sys .asm .|poke =*:poke
+
+ # hex decoding
+ { ==strNumber
+ strNumber len 2 neq { "not a valid hex-string" die } rep
+ 1 0 { strNumber * 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 ] * } -20*10* 16 mul add
+ } "%" defq
+
+ <
+ {
+ { 8 uw } /u64 deffd
+ { 4 uw } /u32 deffd
+ { 2 uw } /u16 deffd
+ { 1 uw } /u8 deffd
+ }" /defBitVariants deffd
+
+ <
+ # 0 -> number of bytes to combine into unsigned int
+ # 1 -> base address
+ # 0 <- first w bytes of string interpreted as unsigned int
+ { ==w ==a
+ [ a _ w add range |peek each ] 256 math .unbase
+ } /uw deffst
+
+ defBitVariants
+ > /consume defvd
+
+ <
+ # 0 -> number of bytes to produce
+ # 1 -> address to write at
+ # 2 -> int to convert to bytes
+ { ==w ==a ==i
+ a _ w add range { 0 -01 poke }" each
+ i 256 math .base _ dom { -101*0 poke }" each --
+ } /uw deffst
+
+ defBitVariants
+ > /produce defvd
+ > _
+ .consume "=>" via
+ .produce "<=" via
+
+ 17592186044416 ==threadLocalStorageAddress # 0x100000000000
+ 17592186044416 ==threadLocalStorageEnd
+ 17592186044416 ==threadLocalStorageAllocEnd
+
+ threadLocalStorageAddress +archSetFs
+
+ { ==reservedSize ==dataSize ==dataBase
+ threadLocalStorageEnd reservedSize add threadLocalStorageAllocEnd sub ==necessaryAllocation
+ necessaryAllocation 0 gt {
+ necessaryAllocation 1 sub 4096 div 1 add 4096 mul =necessaryAllocation
+ threadLocalStorageAllocEnd necessaryAllocation
+ +PROTREAD +PROTWRITE +PROTEXEC bor bor +MAPPRIVATE +MAPFIXED +MAPANONYMOUS bor bor 1 neg 0 +mmap -- # TODO: error handling
+ threadLocalStorageAllocEnd necessaryAllocation add =threadLocalStorageAllocEnd
+ } rep
+
+ 0 dataSize range { ==i
+ dataBase i add peek threadLocalStorageEnd i add poke
+ } each
+ dataSize reservedSize range { ==i
+ 0 threadLocalStorageEnd i add poke
+ } each
+ 0 8 range { ==i
+ %EE threadLocalStorageEnd i add poke # %fs:0x0 shall hold the TLS-pointer. FIXME: what to put here?
+ } each
+
+ threadLocalStorageEnd reservedSize add =threadLocalStorageEnd # return old start and add reserved size
+ } /addToTLSTemplate deffd
+
+ 35184372088832 ==freeAddress # 0x200000000000
+
+ < { ==? }' > /symbols defvst /saveSymbol deffst
+
+ # load a concrete shared library
+ # 0 -> filename of a shared library
+ {
+ "\0" cat +ORDONLY 0 +open ==fd # TODO: error handling
+ fd +fstat -- # TODO: error handling
+ .size 1 sub 4096 div 1 add 4096 mul ==size
+ freeAddress size +PROTREAD +PROTWRITE +PROTEXEC bor bor +MAPPRIVATE +MAPFIXED bor fd 0 +mmap -- # TODO: error handling
+ freeAddress ==loadedAt
+ freeAddress size add =freeAddress
+
+ { ==err 1 -021 { -011 ==a peek eq and a 1 add } each -- not { err die } rep } /expectAt deffd
+ { loadedAt add } /at deffst
+
+ 0 at [ %7F %45 %4C %46 ] "Not a valid ELF library (magic bytes missing)" expectAt
+ 4 at [ %02 ] "Not a valid ELF library (not ELFCLASS64)" expectAt
+ 5 at [ %01 ] "Not a valid ELF library (not little endian)" expectAt
+ 6 at [ %01 ] "Not a valid ELF library (wrong version)" expectAt
+ 7 at [ %00 %00 ] "Not a valid ELF library (non SYS-V ABI)" expectAt
+ 16 at =>u16 3 neq { "Not a dynamic library" die } rep
+ 18 at =>u16 62 neq { "Not valid for this architecture (AMD64 ABI expects EM_X86_64)" die } rep
+ 20 at =>u32 1 neq { "Not a valid ELF library (wrong version, 2nd field)" die } rep
+ 24 at =>u64 ==entryPoint # not that it would be useful
+ 32 at =>u64 ==programHeaderOffset
+ 40 at =>u64 ==sectionHeaderOffset
+ 48 at =>u32 0 neq { "Unexpected processor specific flags" die } rep
+ 52 at =>u16 %40 neq { "ELF header size wrong" die } rep
+ 54 at =>u16 %38 neq { "ProgramHeader size wrong" die } rep
+ 56 at =>u16 ==programHeaderCount
+ 58 at =>u16 %40 neq { "SectionHeader size wrong" die } rep
+ 60 at =>u16 ==sectionHeaderCount
+ 62 at =>u16 ==sectionNameTableIndex
+
+ 0 ==stringTable
+ 0 ==stringTableSize
+ 0 ==symbolTable
+ 0 ==symbolTableEntrySize
+ 0 ==initFunction
+ 0 ==initFunctionArray
+ 0 ==initFunctionArraySize
+ 0 ==symbolHashTable
+ 0 ==libraryName
+ 0 ==plt
+ 0 ==pltSize
+ 0 ==pltRelocationType
+ 0 ==pltRelocationAddress
+ [ ] ==neededLibraries
+ [ ] ==relaTables
+ [ ] ==relaTableSizes
+ 0 ==relaEntrySize
+ 0 ==flags
+ 0 ==tlsTemplateStart
+ 0 ==tlsTemplateFileSize
+ 0 ==tlsTemplateMemorySize
+ 0 ==tlsLoadedAddress
+
+ { -1010 gt -021 ? } /max deffd
+
+ [
+ loadedAt programHeaderOffset add
+ 0 programHeaderCount range %38 mul add
+ { 48 add =>u64 } each
+ ] |max fold ==loadingAlignment
+
+ freeAddress loadingAlignment div 1 add loadingAlignment mul ==loadingAddress
+
+ loadedAt programHeaderOffset add
+ 0 programHeaderCount range %38 mul add
+ { { add }_ /at deffst
+
+ 0 at =>u32 ==type
+ 4 at =>u32 ==flags
+ 8 at =>u64 ==fileOffset
+ 16 at =>u64 ==memoryAddress
+ # 24 is unused
+ 32 at =>u64 ==fileSize
+ 40 at =>u64 ==memorySize
+ 48 at =>u64 ==alignment
+
+ type 1 eq {
+ # "Mapping..." dump
+
+ fileOffset 4096 div 4096 mul ==alignedFileOffset
+ fileOffset memorySize add alignedFileOffset sub 1 sub 4096 div 1 add 4096 mul ==alignedSize
+ loadingAddress memoryAddress add 4096 div 4096 mul ==alignedMemoryAddress
+
+ # "Mapping start: " dump alignedMemoryAddress dump
+ # "Mapping end: " dump alignedMemoryAddress alignedSize add dump
+ # "File mapping start: " dump alignedFileOffset dump
+
+ flags 2 band { # writable segment, allocate full memory size and clone contents
+ alignedMemoryAddress alignedSize
+ +PROTREAD +PROTWRITE bor
+ +MAPPRIVATE +MAPFIXED +MAPANONYMOUS bor bor 1 neg 0 +mmap -- # TODO: error handling
+
+ { ==count ==dst ==src
+ 0 count range { ==i src i add peek dst i add poke } each
+ } /rawMemcopy deffd
+
+ loadedAt alignedFileOffset add alignedMemoryAddress fileSize rawMemcopy
+ } { # readonly segment, just mamp file
+ alignedMemoryAddress alignedSize
+ +PROTREAD +PROTEXEC bor
+ +MAPPRIVATE +MAPFIXED bor fd alignedFileOffset +mmap -- # TODO: error handling
+ } ? *
+
+ alignedMemoryAddress alignedSize add =freeAddress
+ } rep
+
+ type 2 eq {
+ # "Parsing relocations..." dump
+
+ loadedAt fileOffset add
+ 0 fileSize 16 div range 16 mul add
+ { { add }_ /at deffst
+ 0 at =>u64 ==tag
+ 8 at =>u64 ==value
+
+ [
+ { tag 0 eq }' { } # end of table (redundantly limited by size)
+ { tag 1 eq }' { neededLibraries [ value ] cat =neededLibraries }
+ { tag 2 eq }' { value =pltSize }
+ { tag 3 eq }' { value =plt }
+ { tag 4 eq }' { value =symbolHashTable }
+ { tag 5 eq }' { value =stringTable }
+ { tag 6 eq }' { value =symbolTable }
+ { tag 7 eq }' { relaTables [ value ] cat =relaTables }
+ { tag 8 eq }' { relaTableSizes [ value ] cat =relaTableSizes }
+ { tag 9 eq }' { value =relaEntrySize }
+ { tag 10 eq }' { value =stringTableSize }
+ { tag 11 eq }' { value =symbolTableEntrySize }
+ { tag 12 eq }' { value =initFunction }
+ { tag 14 eq }' { value =libraryName }
+ { tag 20 eq }' { value =pltRelocationType }
+ { tag 23 eq }' { value =pltRelocationAddress }
+ { tag 25 eq }' { value =initFunctionArray }
+ { tag 27 eq }' { value =initFunctionArraySize }
+ { tag 30 eq }' { value =flags }
+ { tag 65536 gt }' { } # environment specific use
+
+ { 1 }' { "unknown tag" die }
+ ] conds
+ } each
+ } rep
+
+ type 7 eq {
+ # "Parsing thread local storage initalization template..." dump
+ loadingAddress memoryAddress add =tlsTemplateStart
+ fileSize =tlsTemplateFileSize
+ memorySize =tlsTemplateMemorySize
+ } rep
+ } each
+
+ { ==a
+ 4096 str .alloc ==buf
+
+ 0 ==i
+ { i a add peek _ i buf len lt and } {
+ i buf =[]
+ i 1 add =i
+ } loop --
+
+ i buf str .prefix
+ } /peekString deffst
+
+ # "Following dependencies..." dump
+
+ neededLibraries {
+ stringTable add loadedAt add peekString
+ # "Library: " dump _ dump
+ -- # TOOD actually follow something here
+ } each
+
+ # "Loading symbols..." dump
+
+ <
+ 1 ==i
+
+ { i 24 mul symbolTable add loadedAt add ==symbolTableEntry
+ 0 symbolTableEntry add =>u32 ==name
+ 4 symbolTableEntry add =>u8 ==info
+ 5 symbolTableEntry add =>u8 ==other
+ 6 symbolTableEntry add =>u16 ==section
+ 8 symbolTableEntry add =>u64 ==value
+ 16 symbolTableEntry add =>u64 ==size
+
+ name stringTableSize lt
+ }' {
+ info value < loadingAddress add ==value ==info >
+ name stringTable add loadedAt add peekString saveSymbol
+ i 1 add =i
+ }' loop
+ > --
+
+ # "Executing RELA tables..." dump
+
+ 0 ==lastOffset
+
+ 0 relaTables len range { ==i
+ loadedAt i relaTables * add
+ 0 i relaTableSizes * 24 div range 24 mul add
+ { { add }_ /at deffst
+ 0 at =>u64 ==offset
+ 8 at =>u32 ==type
+ 12 at =>u32 ==symbolIndex
+ 16 at =>u64 ==addend
+
+ # [ /offset /type /symbolIndex /addend ] { _ | -01 dump dump } each
+
+ loadingAddress offset add ==finalAddress
+ # "loadingAddress: " dump loadingAddress dump
+ # "offset: " dump offset dump
+ # "final address: " dump finalAddress dump
+
+ loadedAt _ symbolTable add symbolIndex 24 mul add =>u32
+ add stringTable add peekString _ ==symbolName
+ symbols -01 . .value ==symbolValue
+
+ offset lastOffset eq { "Consecutive RELA not implemented" die } rep
+ offset =lastOffset
+
+ addend ==A loadingAddress ==B finalAddress ==P symbolValue ==S threadLocalStorageEnd threadLocalStorageAddress sub ==T
+
+ { 0 ==i
+ 256 math .base { finalAddress i add -10 poke i 1 add =i } each
+ i 8 range { finalAddress add 0 -01 poke } each
+ } /writeRela64 deffst
+
+ [
+ { type 1 eq }' { S A add writeRela64 }
+ { type 6 eq }' { S writeRela64 }
+ { type 8 eq }' { B A add writeRela64 }
+ { type 16 eq }' { } # FIXME: DTPMOD64 thread local storage ignored, let's hope stuff still works
+ { type 17 eq }' { } # FIXME: DTPOFF64 thread local storage ignored, let's hope stuff still works
+ { type 18 eq }' { T A add writeRela64 }
+ { 1 }' { type dump "unknown RELA type" die }
+ ] conds
+
+ # finalAddress 35184378017584 eq { "HERE ADDR" die } rep
+ # symbolName "stdout" streq { "HERE SYM" die } rep
+ } each
+ } each
+
+ # "Populating TLS area..." dump
+
+ threadLocalStorageEnd ==tlsAddress
+ # tlsTemplateStart dump
+ # tlsTemplateFileSize dump
+ # tlsTemplateMemorySize dump
+ tlsTemplateStart tlsTemplateFileSize tlsTemplateMemorySize addToTLSTemplate
+ # tlsAddress dump
+ # "--------------------------------" dump
+ } /loadFile deffd
+
+ # resolves a C function taking only pointer and integer arguments
+ # 0 -> number of arguments
+ # 1 -> name of symbol
+ # the resulting function will take as many arguments as specified and return a single integer
+ { ==args ==name
+ [ /rdi /rsi /rdx /rcx /r8 /r9 ] =*:availableRegisters
+
+ [
+ /rbx :popqReg
+
+ 0 args range reverse { availableRegisters ==reg
+ reg :popqReg
+ 63 reg :btrqImm8Reg
+ [ 8 reg reg :movqMemDisp8Reg ] len :jcRel8
+ 8 reg reg :movqMemDisp8Reg
+ } each
+ symbols name . .value /rax :movqImmReg
+ /rax :callqReg
+
+ /rax /rdx :movqRegReg
+ 32 /rdx :shrqImm8Reg
+
+ [
+ 63 /rax :btsqImm8Reg
+ /rax :pushqReg
+ 0 :jmpRel8
+ ] len :jnzRel8
+
+ 63 /rax :btsqImm8Reg
+ /rax :pushqReg
+
+ [
+ /rax :pushqReg
+ ::internalAllocateInteger /rax :movqImmReg
+ /rax :callqReg
+ 8 /rax :popqMemDisp8
+ /rax :pushqReg
+ ] len :jmpRel8
+
+ /rax :pushqReg
+ ::internalAllocateInteger /rax :movqImmReg
+ /rax :callqReg
+ 8 /rax :popqMemDisp8
+ /rax :pushqReg
+
+ /rbx :pushqReg
+ :retn
+ ] [ ] ::createFunction
+ } /resolveIntegerFunction deffd
+> /so sys .defv
+
+# vim: syn=elymas
diff --git a/elymas/loaded.ey b/elymas/loaded.ey
index f917b62..42b4818 100644
--- a/elymas/loaded.ey
+++ b/elymas/loaded.ey
@@ -5,6 +5,7 @@
"lib/txt.ey"
"lib/math.ey"
"lib/sys/linux.ey"
+ # "lib/sys/so.ey"
"lib/net.ey"
"lib/net/tcp.ey"
"lib/net/udp.ey"