以任何方式访问 x0 时 opendir 导致崩溃 (ArmV8)
opendir causing crash when accessing x0 in any way (ArmV8)
所以我需要在 arm asm 中编写一个程序,它将打开一个目录并打印出每个条目的 ino_d、d_type 和 d_name 值。我正在使用函数 opendir 来执行此操作。但是,当我 运行 以下代码时(请注意,我不会一次 运行 所有测试,这些只是我尝试在几个单独的 运行 上用 x0 做的事情程序)
ldr x0, =dirname //dirname = ".[=10=]"
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 0x%02x %s\n[=10=]"
// or try this (seg fault)
ldr w1, [x0]
总是有一些错误导致程序崩溃。比如分段错误,或“__GI__readdir64 (dirp=0x1)”错误,或总线错误。
有谁知道(或者可以告诉我去哪里解决这个问题)发生了什么事?
更新:
我要 运行 这个程序,我用 gcc 编译它,然后 运行 使用 qemu-system-aarch64 在 aarch64 虚拟机下 运行 安装它。
// command in terminal
gcc -g -o "main.s" "main.out"
./main.out
完整的代码,以防它可以帮助任何有更多上下文的人
.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 0x%02x %s\n"
test_output: .asciz "%d\n"
dirname: .asciz "."
errmsg: .asciz "readdir() failed"
ret_val: .word 1
.end
更新:当运行将代码置于gdb之外,并且只是打印出来以跟踪程序在导致错误之前的位置时,似乎下面的代码部分是问题
printLoop:
// load de with proper dirent struct
mov x0, x20
bl readdir
// seems I'm calling readdir wrongly or something
// involving readdir
update:看来我出现奇怪错误的原因是因为在调用 opendir 之后,null 存储在 x0 中。当我用 null 调用 readdir 时,它会导致崩溃
我发现我做错了什么。我没有从 opendir 保存目录数据(将指针放在 x0 中),然后我调用了 readdir(然后将 dirent 放在 x0 中)。由于我没有备份 DIR* 形式的 opendir,它导致了崩溃
所以我需要在 arm asm 中编写一个程序,它将打开一个目录并打印出每个条目的 ino_d、d_type 和 d_name 值。我正在使用函数 opendir 来执行此操作。但是,当我 运行 以下代码时(请注意,我不会一次 运行 所有测试,这些只是我尝试在几个单独的 运行 上用 x0 做的事情程序)
ldr x0, =dirname //dirname = ".[=10=]"
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 0x%02x %s\n[=10=]"
// or try this (seg fault)
ldr w1, [x0]
总是有一些错误导致程序崩溃。比如分段错误,或“__GI__readdir64 (dirp=0x1)”错误,或总线错误。
有谁知道(或者可以告诉我去哪里解决这个问题)发生了什么事?
更新: 我要 运行 这个程序,我用 gcc 编译它,然后 运行 使用 qemu-system-aarch64 在 aarch64 虚拟机下 运行 安装它。
// command in terminal
gcc -g -o "main.s" "main.out"
./main.out
完整的代码,以防它可以帮助任何有更多上下文的人
.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 0x%02x %s\n"
test_output: .asciz "%d\n"
dirname: .asciz "."
errmsg: .asciz "readdir() failed"
ret_val: .word 1
.end
更新:当运行将代码置于gdb之外,并且只是打印出来以跟踪程序在导致错误之前的位置时,似乎下面的代码部分是问题
printLoop:
// load de with proper dirent struct
mov x0, x20
bl readdir
// seems I'm calling readdir wrongly or something
// involving readdir
update:看来我出现奇怪错误的原因是因为在调用 opendir 之后,null 存储在 x0 中。当我用 null 调用 readdir 时,它会导致崩溃
我发现我做错了什么。我没有从 opendir 保存目录数据(将指针放在 x0 中),然后我调用了 readdir(然后将 dirent 放在 x0 中)。由于我没有备份 DIR* 形式的 opendir,它导致了崩溃