rewritten 'sh' inside nob.sl from asm to l2 code, renamed strcpy to memcpy and put it in mem.sl
This commit is contained in:
237
nob.sl
237
nob.sl
@@ -1,127 +1,126 @@
|
|||||||
# Minimal nob-style helper: run a shell command via /bin/sh -c
|
import stdlib/stdlib.sl
|
||||||
|
import stdlib/linux.sl
|
||||||
|
import stdlib/mem.sl
|
||||||
|
|
||||||
# : sh ( cmd_addr cmd_len -- exit_code )
|
# sh ( cmd_addr cmd_len -- exit_code | neg_errno )
|
||||||
# Runs `/bin/sh -c <cmd>` and returns a waitpid-style exit code
|
word sh
|
||||||
# (WIFEXITED ? status>>8 : 128+signal). Returns neg errno on fork/exec failure.
|
swap
|
||||||
:asm sh {
|
>r # save cmd_addr
|
||||||
; stack: cmd_len (TOS), cmd_addr (NOS)
|
>r # save cmd_len
|
||||||
push r15 ; preserve callee-saved
|
|
||||||
push r14
|
|
||||||
push r13
|
|
||||||
push rbx
|
|
||||||
|
|
||||||
mov rbx, [r12] ; len
|
r@ 1 +
|
||||||
mov r13, [r12 + 8] ; addr (preserve across syscalls)
|
dup >r # stash len+1 for munmap
|
||||||
add r12, 16 ; pop args
|
alloc
|
||||||
|
dup 0 < if
|
||||||
|
rdrop
|
||||||
|
rdrop
|
||||||
|
rdrop
|
||||||
|
else
|
||||||
|
dup >r # remember buffer pointer
|
||||||
|
drop
|
||||||
|
|
||||||
mov r14, rbx ; len
|
3 rpick # src addr
|
||||||
inc r14 ; size = len + 1
|
0 rpick # dst addr
|
||||||
|
swap
|
||||||
|
2 rpick # len
|
||||||
|
memcpy
|
||||||
|
|
||||||
; mmap buffer for C-string command
|
0 rpick
|
||||||
mov rax, 9 ; mmap
|
2 rpick
|
||||||
xor rdi, rdi ; NULL addr
|
+
|
||||||
mov rsi, r14 ; size
|
0
|
||||||
mov rdx, 3 ; PROT_READ | PROT_WRITE
|
c!
|
||||||
mov r10, 34 ; MAP_PRIVATE | MAP_ANON
|
|
||||||
mov r8, -1 ; fd = -1
|
"/bin/sh" drop
|
||||||
xor r9, r9 ; offset = 0
|
0
|
||||||
|
mem +
|
||||||
|
!
|
||||||
|
"-c" drop
|
||||||
|
8
|
||||||
|
mem +
|
||||||
|
!
|
||||||
|
0 rpick
|
||||||
|
16
|
||||||
|
mem +
|
||||||
|
!
|
||||||
|
0
|
||||||
|
24
|
||||||
|
mem +
|
||||||
|
!
|
||||||
|
0
|
||||||
|
32
|
||||||
|
mem +
|
||||||
|
!
|
||||||
|
|
||||||
|
syscall.fork
|
||||||
syscall
|
syscall
|
||||||
cmp rax, -4095
|
dup 0 < if
|
||||||
jae .mmap_fail
|
>r
|
||||||
mov r15, rax ; cmd buffer
|
1 rpick
|
||||||
|
2 rpick
|
||||||
; copy cmd into buffer and add NUL
|
free
|
||||||
mov rcx, rbx ; len
|
r>
|
||||||
mov rdi, r15 ; dst
|
rdrop
|
||||||
mov rsi, r13 ; src
|
rdrop
|
||||||
rep movsb
|
rdrop
|
||||||
mov byte [r15 + rbx], 0
|
rdrop
|
||||||
|
else
|
||||||
; fork
|
dup 0 == if
|
||||||
mov rax, 57 ; fork
|
drop
|
||||||
|
"/bin/sh" drop
|
||||||
|
mem
|
||||||
|
dup
|
||||||
|
32 +
|
||||||
|
syscall.execve
|
||||||
syscall
|
syscall
|
||||||
cmp rax, 0
|
drop
|
||||||
jl .fork_fail
|
127
|
||||||
cmp rax, 0
|
syscall.exit
|
||||||
jne .parent
|
|
||||||
|
|
||||||
.child:
|
|
||||||
; child: argv = "/bin/sh" "-c" cmd NULL
|
|
||||||
sub rsp, 56
|
|
||||||
lea rbx, [rel .sh_path]
|
|
||||||
mov [rsp], rbx ; argv[0]
|
|
||||||
lea rbx, [rel .dash_c]
|
|
||||||
mov [rsp + 8], rbx ; argv[1]
|
|
||||||
mov [rsp + 16], r15 ; argv[2]
|
|
||||||
mov qword [rsp + 24], 0 ; argv[3] = NULL
|
|
||||||
lea rsi, [rsp] ; argv
|
|
||||||
mov qword [rsp + 32], 0 ; envp[0] = NULL
|
|
||||||
lea rdx, [rsp + 32] ; envp
|
|
||||||
lea rdi, [rel .sh_path] ; filename
|
|
||||||
mov rax, 59 ; execve
|
|
||||||
syscall
|
syscall
|
||||||
mov rdi, 127
|
else
|
||||||
mov rax, 60 ; exit
|
mem
|
||||||
|
40 +
|
||||||
|
dup >r
|
||||||
|
0
|
||||||
|
0
|
||||||
|
syscall.wait4
|
||||||
syscall
|
syscall
|
||||||
|
dup 0 < if
|
||||||
.parent:
|
>r
|
||||||
; rax holds child pid
|
rdrop
|
||||||
mov rbx, rax ; child pid
|
1 rpick
|
||||||
sub rsp, 8
|
2 rpick
|
||||||
lea rsi, [rsp] ; status*
|
free
|
||||||
xor rdx, rdx ; options = 0
|
r>
|
||||||
xor r10, r10 ; rusage = NULL
|
rdrop
|
||||||
mov rdi, rbx ; pid
|
rdrop
|
||||||
mov rax, 61 ; wait4
|
rdrop
|
||||||
syscall
|
rdrop
|
||||||
mov eax, [rsp]
|
else
|
||||||
add rsp, 8
|
drop
|
||||||
|
0 rpick
|
||||||
; decode exit status: if signaled -> 128+signal, else (status >> 8) & 0xff
|
@
|
||||||
mov ebx, eax
|
rdrop
|
||||||
and ebx, 0x7f
|
dup
|
||||||
cmp ebx, 0
|
128 %
|
||||||
jne .got_signal
|
dup 0 != if
|
||||||
shr eax, 8
|
swap drop
|
||||||
and eax, 0xff
|
128 +
|
||||||
jmp .status_ready
|
else
|
||||||
.got_signal:
|
drop
|
||||||
mov eax, ebx
|
256 /
|
||||||
add eax, 128
|
end
|
||||||
.status_ready:
|
>r
|
||||||
mov edi, eax ; save for return after unmap
|
1 rpick
|
||||||
|
2 rpick
|
||||||
; munmap command buffer
|
free
|
||||||
mov rax, 11 ; munmap
|
r>
|
||||||
mov rdi, r15 ; addr
|
rdrop
|
||||||
mov rsi, r14 ; size
|
rdrop
|
||||||
syscall
|
rdrop
|
||||||
|
rdrop
|
||||||
mov eax, edi
|
end
|
||||||
sub r12, 8
|
end
|
||||||
mov [r12], rax
|
end
|
||||||
pop rbx
|
end
|
||||||
pop r13
|
end
|
||||||
pop r14
|
|
||||||
pop r15
|
|
||||||
ret
|
|
||||||
|
|
||||||
.fork_fail:
|
|
||||||
mov rax, rax ; rax holds neg errno
|
|
||||||
jmp .cleanup_return
|
|
||||||
|
|
||||||
.mmap_fail:
|
|
||||||
mov rax, -12 ; -ENOMEM
|
|
||||||
.cleanup_return:
|
|
||||||
sub r12, 8
|
|
||||||
mov [r12], rax
|
|
||||||
pop rbx
|
|
||||||
pop r13
|
|
||||||
pop r14
|
|
||||||
pop r15
|
|
||||||
ret
|
|
||||||
|
|
||||||
.sh_path: db "/bin/sh", 0
|
|
||||||
.dash_c: db "-c", 0
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import nob.sl
|
import nob.sl
|
||||||
|
|
||||||
word main
|
word main
|
||||||
"echo gg" sh
|
"ls" sh
|
||||||
end
|
end
|
||||||
@@ -13,3 +13,30 @@ end
|
|||||||
word free
|
word free
|
||||||
munmap drop
|
munmap drop
|
||||||
end
|
end
|
||||||
|
|
||||||
|
word memcpy #(dst_addr src_addr len -- dst_addr len)
|
||||||
|
dup
|
||||||
|
>r
|
||||||
|
swap
|
||||||
|
dup c@
|
||||||
|
3 pick swap
|
||||||
|
c!
|
||||||
|
drop
|
||||||
|
swap
|
||||||
|
for
|
||||||
|
1 + dup
|
||||||
|
c@
|
||||||
|
swap
|
||||||
|
-rot
|
||||||
|
swap
|
||||||
|
1 +
|
||||||
|
dup
|
||||||
|
rot
|
||||||
|
c!
|
||||||
|
drop
|
||||||
|
swap
|
||||||
|
end
|
||||||
|
swap
|
||||||
|
nip
|
||||||
|
r> dup -rot - swap
|
||||||
|
end
|
||||||
46
strconcat.sl
46
strconcat.sl
@@ -1,4 +1,5 @@
|
|||||||
import stdlib/stdlib.sl
|
import stdlib/stdlib.sl
|
||||||
|
import stdlib/mem.sl
|
||||||
import stdlib/io.sl
|
import stdlib/io.sl
|
||||||
|
|
||||||
word strconcat
|
word strconcat
|
||||||
@@ -9,11 +10,11 @@ word strconcat
|
|||||||
alloc
|
alloc
|
||||||
r> r>
|
r> r>
|
||||||
dup >r
|
dup >r
|
||||||
strcpy
|
memcpy
|
||||||
swap
|
swap
|
||||||
r> dup -rot +
|
r> dup -rot +
|
||||||
r> r>
|
r> r>
|
||||||
strcpy
|
memcpy
|
||||||
swap
|
swap
|
||||||
3 pick
|
3 pick
|
||||||
-
|
-
|
||||||
@@ -27,47 +28,6 @@ word strconcat
|
|||||||
rdrop rdrop rdrop
|
rdrop rdrop rdrop
|
||||||
end
|
end
|
||||||
|
|
||||||
word alloc
|
|
||||||
0 # addr hint (NULL)
|
|
||||||
swap # size
|
|
||||||
3 # prot (PROT_READ | PROT_WRITE)
|
|
||||||
34 # flags (MAP_PRIVATE | MAP_ANON)
|
|
||||||
-1 # fd
|
|
||||||
0 # offset
|
|
||||||
mmap
|
|
||||||
end
|
|
||||||
|
|
||||||
word free
|
|
||||||
munmap drop
|
|
||||||
end
|
|
||||||
|
|
||||||
word strcpy #(dst_addr src_addr len -- dst_addr len)
|
|
||||||
dup
|
|
||||||
>r
|
|
||||||
swap
|
|
||||||
dup c@
|
|
||||||
3 pick swap
|
|
||||||
c!
|
|
||||||
drop
|
|
||||||
swap
|
|
||||||
for
|
|
||||||
1 + dup
|
|
||||||
c@
|
|
||||||
swap
|
|
||||||
-rot
|
|
||||||
swap
|
|
||||||
1 +
|
|
||||||
dup
|
|
||||||
rot
|
|
||||||
c!
|
|
||||||
drop
|
|
||||||
swap
|
|
||||||
end
|
|
||||||
swap
|
|
||||||
nip
|
|
||||||
r> dup -rot - swap
|
|
||||||
end
|
|
||||||
|
|
||||||
word main
|
word main
|
||||||
"hello world hello world hello " "world hello world hello world"
|
"hello world hello world hello " "world hello world hello world"
|
||||||
strconcat
|
strconcat
|
||||||
|
|||||||
Reference in New Issue
Block a user