Home > database >  opendir causing crash when accessing x0 in any way (ArmV8)
opendir causing crash when accessing x0 in any way (ArmV8)

Time:02-21

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

  • Related