So I need to write a program in arm asm that will open a directory and print out every entry's ino_d, d_type, and d_name values. I am using the function opendir to do this. However when I run the following code (note I don't run all the tests at once, those are just the things I have tried to do with x0 on several seperate runs of the program)
ldr x0, =dirname //dirname = ".\0"
bl opendir
// and try this as a test (Bus error)
mov x0, xzr
// or try this as a test (__GI__readdir64)
ldr x0, =output // output = "%-20llu 0xx %s\n\0"
// or try this (seg fault)
ldr w1, [x0]
there is always some error that causes the program to crash. Like a segmentation fault , or a "__GI__readdir64 (dirp=0x1)" error, or a Bus error.
Does anyone know (or can give me a tip on where to go to solve this) what is going on?
update: I to run this program I am compiling it with gcc, and running it under aarch64 vm using qemu-system-aarch64.
// command in terminal
gcc -g -o "main.s" "main.out"
./main.out
the full code in case it helps anyone with more context
.global main
.align 2
.extern printf
.extern strcpy
.extern opendir
.extern closedir
.extern readdir
.extern perror
.extern __errno_location
.text
.equ _ino_d, 0
.equ _off_d, 8
.equ _d_reclen, 16
.equ _d_type, 18
.equ _d_name, 19
main:
stp x29, x30, [sp, -16]!
stp x20, x21, [sp, -16]!
mov w20, w0
mov x21, x1
cmp w20, 1
beq 2f
// set dirname to passed in arg if any was given from the command line
1:
// I don't know how to do the equivelent of
// dirname = argv[1]
// so I'm copying argv[1] into dirname
ldr x0, =dirname
ldr x1, [x21, 8]
bl strcpy
// point to jump to if no args were passed in
2:
// this is the part of the code the bug is originating in
ldr x0, =dirname
bl opendir
ldr x0, =output
// this is the part of the code the bug is originating in
printLoop:
// load de with proper dirent struct
mov x0, x20
bl readdir
cbz x0, errCheck
// loads the format text and d_ino member
mov x7, x0
ldr x0, =output
ldr x1, [x7]
// loads the d_typ member
add x7, x7, _d_type
ldrb w2, [x7]
// loads the dname member
add x7, x7, #1
ldrb w3, [x7]
bl printf
b printLoop
errCheck:
// prints out an error message if something went wrong with reading the directory
bl __errno_location
ldr w1, [x0]
cbz w1, closeDir
ldr x0, =errmsg
bl perror
closeDir:
mov x0, x20
bl closedir
// checks if errno was 0 or not. and stores 1 in retval if errno wasn't 0
bl __errno_location
ldr w1, [x0]
cbz w1, retIsZero
mov w1, #1
str w1, [x0]
b 5f
retIsZero:
str xzr, [x0]
b 5f
4:
// prints error message if error occured
ldr x0, =dirname
bl perror
5:
// cleanup and return retval
ldp x20, x21, [sp], 16
ldp x29, x30, [sp], 16
ldr x0, =ret_val
ldr w0, [x0]
ret
.data
output: .asciz "%-20llu 0xx %s\n"
test_output: .asciz "%d\n"
dirname: .asciz "."
errmsg: .asciz "readdir() failed"
ret_val: .word 1
.end
update: when running the code outside gdb, and just printing things out to keep track of where the program is before causing an error, it seems the below code section is the problem
printLoop:
// load de with proper dirent struct
mov x0, x20
bl readdir
// seems I'm calling readdir wrongly or something
// involving readdir
update: so it seems that the reason I'm getting weird errors is because after the call to opendir, null is stored in x0. And when I call readdir with null it causes a crash
CodePudding user response:
I figured out what I was doing wrong. I wasn't saving the the directory data from opendir (placed the pointer in x0) and then I called readdir (which then placed the dirent in x0). and since I didn't backup the DIR* form opendir it was causing crashes