optimized some syscalls

This commit is contained in:
Luxferre
2026-06-18 20:10:23 +03:00
parent 172ea779c6
commit b0caa63ea1
4 changed files with 413 additions and 197 deletions
+109 -195
View File
@@ -10,11 +10,7 @@
# fatal error reporting function
function trapout(msg, fd) {
for(fd in FD_PATH) {
if(FD_DIRTY[fd]) {
write_fd_to_file(fd)
}
}
for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd)
cmd = "cat 1>&2"
printf("Fatal: %s\n", msg) | cmd
close(cmd)
@@ -95,15 +91,15 @@ function qquote(str) {
function hex_to_dec(hex, dec, i, len, c, val) {
dec = 0
len = length(hex)
for (i = 1; i <= len; i++) {
for(i = 1; i <= len; i++) {
c = tolower(substr(hex, i, 1))
if (c ~ /[0-9]/) val = int(c)
else if (c == "a") val = 10
else if (c == "b") val = 11
else if (c == "c") val = 12
else if (c == "d") val = 13
else if (c == "e") val = 14
else if (c == "f") val = 15
if(c ~ /[0-9]/) val = int(c)
else if(c == "a") val = 10
else if(c == "b") val = 11
else if(c == "c") val = 12
else if(c == "d") val = 13
else if(c == "e") val = 14
else if(c == "f") val = 15
else continue
dec = dec * 16 + val
}
@@ -114,9 +110,7 @@ function hex_to_dec(hex, dec, i, len, c, val) {
function read_str(addr, c, s) {
s = ""
addr = uint32(addr)
while ((c = MEM[addr++]) != 0) {
s = s sprintf("%c", c)
}
while((c = MEM[addr++]) != 0) s = s sprintf("%c", c)
return s
}
@@ -126,21 +120,13 @@ function path_exists(path) {
}
# Checks if path is a directory using POSIX test -d
function is_dir(path) {
return (system("test -d " qquote(path)) == 0)
}
function is_dir(path) {return (system("test -d " qquote(path)) == 0)}
# Resolves relative path against dfd directory
function resolve_path(dfd, pathname, path) {
if (substr(pathname, 1, 1) == "/") {
return pathname
}
if (dfd == -100) { # AT_FDCWD
return pathname
}
if (dfd in FD_PATH) {
return FD_PATH[dfd] "/" pathname
}
if(substr(pathname, 1, 1) == "/") return pathname
if(dfd == -100) return pathname
if(dfd in FD_PATH) return FD_PATH[dfd] "/" pathname
return pathname
}
@@ -148,8 +134,8 @@ function resolve_path(dfd, pathname, path) {
# TV_SEC: 64-bit for clock_gettime64, 32-bit for clock_gettime
function get_system_time(time_arr, cmd, line) {
cmd = "date +%s%N"
if ((cmd | getline line) > 0) {
if (length(line) > 9 && line ~ /^[0-9]+$/) {
if((cmd | getline line) > 0) {
if(length(line) > 9 && line ~ /^[0-9]+$/) {
time_arr["sec"] = int(substr(line, 1, length(line) - 9))
time_arr["nsec"] = int(substr(line, length(line) - 8))
close(cmd)
@@ -160,16 +146,13 @@ function get_system_time(time_arr, cmd, line) {
# Fallback if %N is not supported
cmd = "date +%s"
if ((cmd | getline line) > 0) {
if((cmd | getline line) > 0) {
time_arr["sec"] = int(line)
} else {
time_arr["sec"] = 0
}
} else time_arr["sec"] = 0
close(cmd)
if (time_arr["sec"] == LAST_SEC) {
if(time_arr["sec"] == LAST_SEC) {
VIRT_NSEC += 500000
if (VIRT_NSEC >= 1000000000) {
if(VIRT_NSEC >= 1000000000) {
VIRT_NSEC = 999999999
}
} else {
@@ -183,7 +166,7 @@ function get_system_time(time_arr, cmd, line) {
function fill_stat_struct(path, addr, follow, cmd, line, parts, opt, mode_hex, mode_dec, size, atime, mtime, ctime, i) {
opt = follow ? "-L " : ""
cmd = "stat " opt "-c \"%f %s %X %Y %Z\" " qquote(path)
if ((cmd | getline line) > 0) {
if((cmd | getline line) > 0) {
split(line, parts)
mode_hex = parts[1]
mode_dec = hex_to_dec(mode_hex)
@@ -191,12 +174,9 @@ function fill_stat_struct(path, addr, follow, cmd, line, parts, opt, mode_hex,
atime = int(parts[3])
mtime = int(parts[4])
ctime = int(parts[5])
close(cmd)
for (i = 0; i < 104; i++) {
MEM[addr + i] = 0
}
for(i = 0; i < 104; i++) MEM[addr + i] = 0
write_mem(addr + 0, 1, 8)
write_mem(addr + 8, 1, 8)
@@ -226,96 +206,80 @@ function write_fd_to_file(fd, path, chunk, i, size) {
printf("") > path
close(path)
chunk = ""
for (i = 0; i < size; i++) {
for(i = 0; i < size; i++) {
chunk = chunk sprintf("%c", FD_DATA[fd, i])
if (length(chunk) >= 1024) {
if(length(chunk) >= 1024) {
printf("%s", chunk) >> path
chunk = ""
}
}
if (length(chunk) > 0) {
printf("%s", chunk) >> path
}
if(length(chunk) > 0) printf("%s", chunk) >> path
close(path)
}
function amach_exit(code, fd) {
for (fd in FD_PATH) {
if (FD_DIRTY[fd]) {
write_fd_to_file(fd)
}
}
for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd)
exit(code)
}
# syscall emulation
function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathname, flags, fd, count, now_time, dtype, full_path, reclen, bytes_written, idx, count_limit, buf_addr, name, status, follow, oldpath, newpath, access_mode, is_read, is_write, do_trunc, cmd, line, arr, size, buflen) {
if (callnum == 34) { # sys_mkdirat
if(callnum == 34) { # sys_mkdirat
pathname = read_str(a1)
path = resolve_path(a0, pathname)
if (path_exists(path)) {
setreg(10, -17) # -EEXIST
} else {
if(path_exists(path)) setreg(10, -17) # -EEXIST
else {
status = system("mkdir " qquote(path))
setreg(10, (status == 0) ? 0 : -2)
}
} else if (callnum == 35) { # sys_unlinkat
} else if(callnum == 35) { # sys_unlinkat
pathname = read_str(a1)
path = resolve_path(a0, pathname)
if (!path_exists(path)) {
if(!path_exists(path)) {
setreg(10, -2) # -ENOENT
} else {
if (bw_and(a2, 512)) { # AT_REMOVEDIR (0x200)
if(bw_and(a2, 512)) # AT_REMOVEDIR (0x200)
status = system("rmdir " qquote(path))
} else {
else
status = system("rm " qquote(path))
}
setreg(10, (status == 0) ? 0 : -1)
}
} else if (callnum == 38 || callnum == 276) { # sys_renameat / sys_renameat2
} else if(callnum == 38 || callnum == 276) { # sys_renameat / sys_renameat2
oldpath = resolve_path(a0, read_str(a1))
newpath = resolve_path(a2, read_str(a3))
status = system("mv " qquote(oldpath) " " qquote(newpath))
setreg(10, (status == 0) ? 0 : -1)
} else if (callnum == 56) { # sys_openat
} else if(callnum == 56) { # sys_openat
pathname = read_str(a1)
path = resolve_path(a0, pathname)
flags = a2
if (bw_and(flags, 64)) { # O_CREAT (0x40)
if (bw_and(flags, 128) && path_exists(path)) { # O_EXCL (0x80)
if(bw_and(flags, 64)) { # O_CREAT (0x40)
if(bw_and(flags, 128) && path_exists(path)) { # O_EXCL (0x80)
setreg(10, -17) # -EEXIST
return
}
if (!path_exists(path)) {
if(!path_exists(path)) {
printf("") > path
close(path)
}
} else {
if (!path_exists(path)) {
if(!path_exists(path)) {
setreg(10, -2) # -ENOENT
return
}
}
fd = NEXT_FD++
FD_PATH[fd] = path
FD_FLAGS[fd] = flags
FD_OFFSET[fd] = 0
FD_SIZE[fd] = 0
FD_DIRTY[fd] = 0
if (is_dir(path)) {
if(is_dir(path)) {
cmd = "ls -a1 " qquote(path)
count = 0
while ((cmd | getline line) > 0) {
if (line != "") {
FD_DIRENTS[fd, count++] = line
}
}
while((cmd | getline line) > 0)
if(line != "") FD_DIRENTS[fd, count++] = line
close(cmd)
FD_DIRENT_COUNT[fd] = count
} else {
@@ -324,64 +288,51 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathnam
is_write = (access_mode == 1 || access_mode == 2)
do_trunc = (is_write && bw_and(flags, 512)) # O_TRUNC (0x200)
if (is_read && !do_trunc) {
if(is_read && !do_trunc) {
cmd = "od -An -v -tu1 " qquote(path)
size = 0
while ((cmd | getline line) > 0) {
while((cmd | getline line) > 0) {
split(line, arr)
for (i = 1; i in arr; i++) {
for(i = 1; i in arr; i++)
FD_DATA[fd, size++] = arr[i]
}
}
close(cmd)
FD_SIZE[fd] = size
} else if (do_trunc) {
} else if(do_trunc) {
printf("") > path
close(path)
}
}
setreg(10, fd)
} else if (callnum == 57) { # sys_close
} else if(callnum == 57) { # sys_close
fd = a0
if (fd >= 3 && (fd in FD_PATH)) {
if (FD_DIRTY[fd]) {
write_fd_to_file(fd)
}
if(fd >= 3 && (fd in FD_PATH)) {
if(FD_DIRTY[fd]) write_fd_to_file(fd)
delete FD_PATH[fd]
delete FD_FLAGS[fd]
delete FD_OFFSET[fd]
delete FD_SIZE[fd]
delete FD_DIRTY[fd]
if (fd in FD_DIRENT_COUNT) {
for (i = 0; i < FD_DIRENT_COUNT[fd]; i++) {
delete FD_DIRENTS[fd, i]
}
if(fd in FD_DIRENT_COUNT) {
for(i = 0; i < FD_DIRENT_COUNT[fd]; i++) delete FD_DIRENTS[fd, i]
delete FD_DIRENT_COUNT[fd]
} else {
for (i = 0; i < FD_SIZE[fd]; i++) {
delete FD_DATA[fd, i]
}
}
} else for(i = 0; i < FD_SIZE[fd]; i++) delete FD_DATA[fd, i]
setreg(10, 0)
} else {
setreg(10, -9) # -EBADF
}
} else if (callnum == 61) { # sys_getdents64
} else setreg(10, -9) # -EBADF
} else if(callnum == 61) { # sys_getdents64
fd = a0
if (!(fd in FD_DIRENT_COUNT)) {
setreg(10, -9) # -EBADF
} else {
if(!(fd in FD_DIRENT_COUNT)) setreg(10, -9) # -EBADF
else {
bytes_written = 0
idx = FD_OFFSET[fd]
count_limit = a2
buf_addr = a1
while (idx < FD_DIRENT_COUNT[fd]) {
while(idx < FD_DIRENT_COUNT[fd]) {
name = FD_DIRENTS[fd, idx]
reclen = int((20 + length(name) + 7) / 8) * 8
if (bytes_written + reclen > count_limit) {
if (bytes_written == 0) {
if(bytes_written + reclen > count_limit) {
if(bytes_written == 0) {
setreg(10, -22) # -EINVAL
return
}
@@ -393,143 +344,116 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathnam
full_path = FD_PATH[fd] "/" name
dtype = is_dir(full_path) ? 4 : 8
write_mem(buf_addr + bytes_written + 18, dtype, 1)
for (i = 0; i < length(name); i++) {
for(i = 0; i < length(name); i++)
MEM[buf_addr + bytes_written + 19 + i] = ord(substr(name, i + 1, 1))
}
MEM[buf_addr + bytes_written + 19 + length(name)] = 0
for (i = 19 + length(name) + 1; i < reclen; i++) {
for(i = 19 + length(name) + 1; i < reclen; i++)
MEM[buf_addr + bytes_written + i] = 0
}
bytes_written += reclen
idx++
}
FD_OFFSET[fd] = idx
setreg(10, bytes_written)
}
} else if (callnum == 62) { # sys_lseek
} else if(callnum == 62) { # sys_lseek
fd = a0
if (fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) {
if(fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) {
idx = FD_OFFSET[fd]
size = FD_SIZE[fd]
if (a2 == 0) idx = a1 # SEEK_SET
else if (a2 == 1) idx = idx + a1 # SEEK_CUR
else if (a2 == 2) idx = size + a1 # SEEK_END
if(a2 == 0) idx = a1 # SEEK_SET
else if(a2 == 1) idx = idx + a1 # SEEK_CUR
else if(a2 == 2) idx = size + a1 # SEEK_END
else {
setreg(10, -22) # -EINVAL
return
}
if (idx < 0) {
setreg(10, -22) # -EINVAL
} else {
if(idx < 0) setreg(10, -22) # -EINVAL
else {
FD_OFFSET[fd] = idx
setreg(10, idx)
}
} else {
setreg(10, -9) # -EBADF
}
} else if (callnum == 63) { # sys_read
} else setreg(10, -9) # -EBADF
} else if(callnum == 63) { # sys_read
fd = a0
if (fd == 0) {
if(fd == 0) {
getline buf < "/dev/tty"
l = length(buf); if (l > a2) l = a2
for (i = 0; i < l; i++) MEM[uint32(a1 + i)] = ord(substr(buf, i + 1, 1))
l = length(buf); if(l > a2) l = a2
for(i = 0; i < l; i++) MEM[uint32(a1 + i)] = ord(substr(buf, i + 1, 1))
setreg(10, l)
} else if (fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) {
} else if(fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) {
idx = FD_OFFSET[fd]
size = FD_SIZE[fd]
count = a2
if (idx >= size) {
setreg(10, 0)
} else {
if (idx + count > size) count = size - idx
for (i = 0; i < count; i++) {
if(idx >= size) setreg(10, 0)
else {
if(idx + count > size) count = size - idx
for(i = 0; i < count; i++)
MEM[uint32(a1 + i)] = FD_DATA[fd, idx + i]
}
FD_OFFSET[fd] = idx + count
setreg(10, count)
}
} else {
setreg(10, -9) # -EBADF
}
} else if (callnum == 64) { # sys_write
} else setreg(10, -9) # -EBADF
} else if(callnum == 64) { # sys_write
fd = a0
if (fd == 1 || fd == 2) {
for (i = 0; i < a2; i++) printf("%c", MEM[uint32(a1 + i)])
if(fd == 1 || fd == 2) {
for(i = 0; i < a2; i++) printf("%c", MEM[uint32(a1 + i)])
setreg(10, a2)
} else if (fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) {
} else if(fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) {
idx = FD_OFFSET[fd]
count = a2
if (bw_and(FD_FLAGS[fd], 1024)) { # O_APPEND (0x400)
idx = FD_SIZE[fd]
}
for (i = 0; i < count; i++) {
if(bw_and(FD_FLAGS[fd], 1024)) idx = FD_SIZE[fd] # O_APPEND (0x400)
for(i = 0; i < count; i++)
FD_DATA[fd, idx + i] = MEM[uint32(a1 + i)]
}
FD_OFFSET[fd] = idx + count
if (FD_OFFSET[fd] > FD_SIZE[fd]) {
FD_SIZE[fd] = FD_OFFSET[fd]
}
if(FD_OFFSET[fd] > FD_SIZE[fd]) FD_SIZE[fd] = FD_OFFSET[fd]
FD_DIRTY[fd] = 1
setreg(10, count)
} else {
setreg(10, -9) # -EBADF
}
} else if (callnum == 78) { # sys_readlinkat
} else setreg(10, -9) # -EBADF
} else if(callnum == 78) { # sys_readlinkat
path = resolve_path(a0, read_str(a1))
cmd = "readlink " qquote(path)
if ((cmd | getline line) > 0) {
if((cmd | getline line) > 0) {
close(cmd)
l = length(line)
if (l > a3) l = a3
for (i = 0; i < l; i++) {
if(l > a3) l = a3
for(i = 0; i < l; i++)
MEM[uint32(a2 + i)] = ord(substr(line, i + 1, 1))
}
setreg(10, l)
} else {
close(cmd)
setreg(10, -22) # -EINVAL
}
} else if (callnum == 79) { # sys_newfstatat
} else if(callnum == 79) { # sys_newfstatat
pathname = read_str(a1)
flags = a3
if (pathname == "" && bw_and(flags, 4096)) { # AT_EMPTY_PATH
if (a0 == -100) path = "."
else if (a0 in FD_PATH) path = FD_PATH[a0]
if(pathname == "" && bw_and(flags, 4096)) { # AT_EMPTY_PATH
if(a0 == -100) path = "."
else if(a0 in FD_PATH) path = FD_PATH[a0]
else {
setreg(10, -9) # -EBADF
return
}
} else {
path = resolve_path(a0, pathname)
}
} else path = resolve_path(a0, pathname)
follow = (bw_and(flags, 256) == 0) # follow link if AT_SYMLINK_NOFOLLOW (0x100) is NOT set
status = fill_stat_struct(path, a2, follow)
setreg(10, status)
} else if (callnum == 80) { # sys_fstat
} else if(callnum == 80) { # sys_fstat
fd = a0
if (fd == 0) path = "/dev/stdin"
else if (fd == 1) path = "/dev/stdout"
else if (fd == 2) path = "/dev/stderr"
else if (fd >= 3 && (fd in FD_PATH)) path = FD_PATH[fd]
if(fd == 0) path = "/dev/stdin"
else if(fd == 1) path = "/dev/stdout"
else if(fd == 2) path = "/dev/stderr"
else if(fd >= 3 && (fd in FD_PATH)) path = FD_PATH[fd]
else {
setreg(10, -9) # -EBADF
return
}
status = fill_stat_struct(path, a1, 1)
setreg(10, status)
} else if (callnum == 93 || callnum == 94) { # sys_exit / sys_exit_group
} else if(callnum == 93 || callnum == 94) { # sys_exit / sys_exit_group
amach_exit(a0)
} else if (callnum == 113 || callnum == 403) { # sys_clock_gettime / sys_clock_gettime64
} else if(callnum == 113 || callnum == 403) { # sys_clock_gettime / sys_clock_gettime64
get_system_time(now_time)
if (callnum == 113) {
if(callnum == 113) {
write_mem(a1, now_time["sec"], 4)
write_mem(a1 + 4, now_time["nsec"], 4)
} else {
@@ -537,24 +461,18 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathnam
write_mem(a1 + 8, now_time["nsec"], 4)
}
setreg(10, 0)
} else if (callnum == 169) { # sys_gettimeofday
} else if(callnum == 169) { # sys_gettimeofday
get_system_time(now_time)
write_mem(a0, now_time["sec"], 4)
write_mem(a0 + 4, int(now_time["nsec"] / 1000), 4)
setreg(10, 0)
} else if (callnum == 278) { # sys_getrandom
} else if(callnum == 278) { # sys_getrandom
buf_addr = a0
buflen = a1
for (i = 0; i < buflen; i++) {
for(i = 0; i < buflen; i++)
MEM[uint32(buf_addr + i)] = int(rand() * 256)
}
setreg(10, buflen)
} else {
trapout(sprintf("Unimplemented environment call %d at 0x%X", callnum, pc - 4))
}
} else trapout(sprintf("Unimplemented environment call %d at 0x%X", callnum, pc - 4))
}
# instruction type executors
@@ -861,9 +779,5 @@ END {
instr += 65536 * MEM[pc++] + 16777216 * MEM[pc++]
amach_exec(instr) # decode and execute
}
for(fd in FD_PATH) {
if(FD_DIRTY[fd]) {
write_fd_to_file(fd)
}
}
for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd)
}
Binary file not shown.
+302
View File
@@ -0,0 +1,302 @@
.section .text
.option norvc
.global _start
# Helper macro to exit with code if condition fails
# Example: ASSERT_EQ a0, 0, 4 (if a0 != 0, exit with code 4)
.macro ASSERT_EQ reg, val, error_code
li t4, \val
beq \reg, t4, .L_ok_\@
li a0, \error_code
li a7, 93
ecall
.L_ok_\@:
.endm
# Helper macro to exit with code if registers are not equal
.macro ASSERT_REG_EQ reg1, reg2, error_code
beq \reg1, \reg2, .L_ok_reg_\@
li a0, \error_code
li a7, 93
ecall
.L_ok_reg_\@:
.endm
# Helper macro to exit with code if a register is negative
.macro ASSERT_GEZ reg, error_code
bgez \reg, .L_ok_gez_\@
li a0, \error_code
li a7, 93
ecall
.L_ok_gez_\@:
.endm
_start:
# 1. Write welcome message to stdout
li a7, 64 # sys_write
li a0, 1 # stdout
la a1, msg_welcome
li a2, 29 # welcome message length
ecall
ASSERT_EQ a0, 29, 1
# 2. Test clock_gettime
li a7, 113 # sys_clock_gettime
li a0, 0 # CLOCK_REALTIME
la a1, timespec_buf
ecall
ASSERT_EQ a0, 0, 2
# verify we wrote something non-zero to seconds
lw t0, timespec_buf
ASSERT_GEZ t0, 3
# 3. Test gettimeofday
li a7, 169 # sys_gettimeofday
la a0, timeval_buf
li a1, 0 # NULL timezone
ecall
ASSERT_EQ a0, 0, 4
lw t0, timeval_buf
ASSERT_GEZ t0, 5
# 4. Test openat to create file
li a7, 56 # sys_openat
li a0, -100 # AT_FDCWD
la a1, file_name
li a2, 577 # O_CREAT | O_WRONLY | O_TRUNC (64 | 1 | 512 = 577)
li a3, 0644 # permissions
ecall
ASSERT_GEZ a0, 6
mv s2, a0 # save fd in s2
# 5. Write to the new file
li a7, 64 # sys_write
mv a0, s2 # fd
la a1, msg_to_file
li a2, 29 # length
ecall
ASSERT_EQ a0, 29, 7
# 6. Close the file
li a7, 57 # sys_close
mv a0, s2 # fd
ecall
ASSERT_EQ a0, 0, 8
# 7. Open file O_RDONLY
li a7, 56 # sys_openat
li a0, -100 # AT_FDCWD
la a1, file_name
li a2, 0 # O_RDONLY
li a3, 0
ecall
ASSERT_GEZ a0, 9
mv s2, a0 # save fd in s2
# 7b. Test fstat
li a7, 80 # sys_fstat
mv a0, s2 # fd
la a1, stat_buf
ecall
ASSERT_EQ a0, 0, 20
lw t0, stat_buf + 48
ASSERT_EQ t0, 29, 21
# 7c. Test newfstatat
li a7, 79 # sys_newfstatat
li a0, -100 # AT_FDCWD
la a1, file_name
la a2, stat_buf
li a3, 0 # flags
ecall
ASSERT_EQ a0, 0, 22
lw t0, stat_buf + 48
ASSERT_EQ t0, 29, 23
# 8. Read from the file
li a7, 63 # sys_read
mv a0, s2 # fd
la a1, read_buf
li a2, 50 # buffer size
ecall
ASSERT_EQ a0, 29, 10 # should read 29 bytes
# verify read content matches
la t0, msg_to_file
la t1, read_buf
li t2, 0 # index
.L_loop:
add t3, t0, t2
lb t3, 0(t3)
add t5, t1, t2
lb t5, 0(t5)
ASSERT_REG_EQ t3, t5, 11
addi t2, t2, 1
li t6, 29
blt t2, t6, .L_loop
# 9. Close the file
li a7, 57 # sys_close
mv a0, s2 # fd
ecall
ASSERT_EQ a0, 0, 12
# 9b. Test renameat (rename test_output.txt to test_output_new.txt)
li a7, 38 # sys_renameat
li a0, -100 # AT_FDCWD
la a1, file_name
li a2, -100 # AT_FDCWD
la a3, file_name_new
ecall
ASSERT_EQ a0, 0, 24
# 9c. Verify renamed file can be opened O_RDONLY
li a7, 56 # sys_openat
li a0, -100 # AT_FDCWD
la a1, file_name_new
li a2, 0 # O_RDONLY
li a3, 0
ecall
ASSERT_GEZ a0, 25
mv s3, a0
# 9d. Close renamed file
li a7, 57 # sys_close
mv a0, s3
ecall
ASSERT_EQ a0, 0, 26
# 10. Test mkdirat
li a7, 34 # sys_mkdirat
li a0, -100 # AT_FDCWD
la a1, dir_name
li a2, 0755
ecall
ASSERT_EQ a0, 0, 13
# 11. Open directory fd
li a7, 56 # sys_openat
li a0, -100 # AT_FDCWD
la a1, dir_name
li a2, 0 # O_RDONLY
li a3, 0
ecall
ASSERT_GEZ a0, 14
mv s2, a0 # save fd in s2
# 12. Test getdents64
li a7, 61 # sys_getdents64
mv a0, s2 # fd
la a1, dirents_buf
li a2, 512 # buffer size
ecall
ASSERT_GEZ a0, 15
# 13. Close directory fd
li a7, 57 # sys_close
mv a0, s2 # fd
ecall
ASSERT_EQ a0, 0, 16
# 13b. Test readlinkat
li a7, 78 # sys_readlinkat
li a0, -100 # AT_FDCWD
la a1, link_name
la a2, read_buf
li a3, 50 # buffer size
ecall
ASSERT_EQ a0, 19, 27
# verify symlink target string
la t0, file_name_new
la t1, read_buf
li t2, 0
.L_loop_link:
add t3, t0, t2
lb t3, 0(t3)
add t5, t1, t2
lb t5, 0(t5)
ASSERT_REG_EQ t3, t5, 28
addi t2, t2, 1
li t6, 19
blt t2, t6, .L_loop_link
# 14. Test unlinkat for renamed file
li a7, 35 # sys_unlinkat
li a0, -100 # AT_FDCWD
la a1, file_name_new
li a2, 0
ecall
ASSERT_EQ a0, 0, 17
# 14b. Test unlinkat for symlink
li a7, 35 # sys_unlinkat
li a0, -100 # AT_FDCWD
la a1, link_name
li a2, 0
ecall
ASSERT_EQ a0, 0, 29
# 15. Test unlinkat with AT_REMOVEDIR for directory
li a7, 35 # sys_unlinkat
li a0, -100 # AT_FDCWD
la a1, dir_name
li a2, 512 # AT_REMOVEDIR
ecall
ASSERT_EQ a0, 0, 18
# 15b. Test getrandom
li a7, 278 # sys_getrandom
la a0, random_buf
li a1, 16 # 16 bytes
li a2, 0 # no flags
ecall
ASSERT_EQ a0, 16, 185
# 16. Write success message
li a7, 64 # sys_write
li a0, 1 # stdout
la a1, msg_success
li a2, 33 # success message length
ecall
ASSERT_EQ a0, 33, 19
# 17. Exit with 0
li a7, 93 # sys_exit
li a0, 0 # status 0
ecall
.section .rodata
msg_welcome:
.string "Running Syscall Verification\n"
msg_to_file:
.string "Hello from RISC-V A-Machine!\n"
msg_success:
.string "All Extended Syscall Tests PASS!\n"
file_name:
.string "test_output.txt"
file_name_new:
.string "test_output_new.txt"
link_name:
.string "test_link.txt"
dir_name:
.string "test_dir"
.section .bss
.align 4
timespec_buf:
.space 16
timeval_buf:
.space 8
read_buf:
.space 64
dirents_buf:
.space 512
random_buf:
.space 16
stat_buf:
.space 104
Binary file not shown.