diff --git a/.gitignore b/.gitignore index e6db6af..fa0feeb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /true /false /cat +/printstack +/env diff --git a/Makefile b/Makefile index c4f4d2f..616c360 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LD = $(TARGET)-ld .SUFFIXES: .PHONY: all -all: true false cat +all: true false cat env #all: echo %: %.o diff --git a/env.s b/env.s new file mode 100644 index 0000000..fc67901 --- /dev/null +++ b/env.s @@ -0,0 +1,71 @@ +.globl _start +.option rvc # enable compressed instructions + +.section .rodata +newline: .ascii "\n" + +# TODO: sort env, buffer output + +.text +_start: + # arguments are passed on the stack: + # --bottom of stack-- + # dd argc + # dd argv[0] + # dd ... + # dd 0 + # dd envp[0] + # dd ... + # dd 0 + ld s0, 0(sp) # get argc + addi s1, sp, 16 # add 8 for argc, 8 for the NULL at the end of argv + + # compute start of envp + # we could use a sh3add instruction + # but the tools i'm using don't support the bitmanip extension + #sh3add s1, sp, s0 + sll t0, s0, 3 # argc*8 + add s1, s1, t0 + +loop: + # check for null pointer, which signals the end of envp + ld a1, 0(s1) + beqz a1, end + + # compute length of string + mv t1, a1 + strlen: + lbu t0, 0(t1) + addi t1, t1, 1 + bnez t0, strlen + sub a2, t1, a1 + + # print string + li a7, 64 + li a0, 1 + # a1 already set to start of string + # a2 already set to string length + ecall + + # print newline + li a7, 64 + li a0, 1 + la a1, newline + li a2, 1 + ecall + + # increment envp and loop + addi s1, s1, 8 + j loop + +end: + li a7, 93 # exit + li a0, 0 + ecall + +write_error: + li a7, 93 # exit + li a0, 1 + ecall + + diff --git a/printstack.s b/printstack.s new file mode 100644 index 0000000..0a1daa2 --- /dev/null +++ b/printstack.s @@ -0,0 +1,84 @@ +.globl _start +.option rvc # enable compressed instructions +#.option norelax + +.data +sigaction: + .dword segv # sa_handler + .dword 0 # sa_flags + .dword 0 # sa_mask + +.data +buf: .zero 8 + +.text +_start: + # set up the gp register so that relaxed loads work + .option norelax + la gp, __global_pointer$ + .option relax + # the following is what the la instruction above gets expanded to, + # but writing it out explicitly like this causes ld to segfault + #auipc gp, %pcrel_hi(__global_pointer$) + #addi gp, gp, %pcrel_lo(__global_pointer$) + + # set up a signal handler for SIGSEGV + # XXX we don't actually need this because write will + # return EFAULT if the address isn't mapped + li a7, 134 # sys_rt_sigaction + li a0, 11 # SIGSEGv + la a1, sigaction # action + li a2, 0 # oldact = NULL + li a3, 8 # signal set size (bytes) + ecall + + # save sp + la s7, buf + sd sp, 0(s7) + + # print sp + li a7, 64 # sys_write + li a0, 1 # fd = stdout + mv a1, s7 # pointer to string + li a2, 8 # size of data + ecall + bltz a0, write_error + + # round sp down to multiple of 512 + # and move to s0 + andi s0, sp, -512 + +loop: + # print sp + sd s0, 0(s7) + li a7, 64 # sys_write + li a0, 1 # fd = stdout + mv a1, s7 # pointer to string + li a2, 8 # size of data + ecall + bltz a0, write_error + + # print 512 bytes of stack + li a7, 64 # sys_write + li a0, 1 + mv a1, s0 + li a2, 512 + ecall + bltz a0, write_error + + # increment sp by 512 + addi s0, s0, 512 + + beqz s0, segv + j loop + +write_error: + li a7, 93 # exit + li a0, 1 + ecall + + +segv: + li a7, 93 # exit + li a0, 0 + ecall