[英]How do I troubleshoot the EINVAL and EPERM errors I'm getting in this x86-64 assembly code using the mmap syscall on Linux
我在弄清楚我在这段代码中做错了什么时遇到了一些麻烦,我将不胜感激任何可用的帮助:
.global _start
.section .text
_start:
# Grab our first argument from the stack
popq %rdi # This will be argc, which we don't care about
popq %rdi # Now the executable's path
popq %rdi # And the first argument, at last
# Open the file with open(argv[1], 0, O_RDONLY)
movq $2, %rax # The syscall number for open
xor %rsi, %rsi # There are no flags we need to specify
xor %rdx, %rdx # O_RDONLY is 0
syscall # Do the syscall
# Get the file length with lseek(rax, 0, SEEK_END)
pushq %rax # Save our file descriptor
pushq %rax # For the next lseek
pushq %rax # For mmap
movq $8, %rax # The syscall number for lseek
popq %rdi # Our file descriptor
xor %rsi, %rsi # The offset from where we're seeking in the file
movq $2, %rdx # SEEK_END is 2
syscall # Do the syscall
popq %rbx # Put the file descriptor into rbx so it can be last
pushq %rax # Then save the length
pushq %rbx # Put the file descriptor on the stack
# Now go back to the beginning of the file with
# lseek(fd, 0, SEEK_SET)
movq $8, %rax # lseek again
popq %rdi # Put the file descriptor in rdi
xor %rsi, %rsi # The start of the file
xor %rdx, %rdx # SEEK_SET is 0
syscall # Do the syscall
# Now that we _finally_ have the length of the file,
# mmap(0, length, PROT_READ (1), MAP_SHARED (1), fd, 0)
popq %rdi # The length of the file
popq %rax # Empty the stack
movq $1, %rsi # The permissions we want for the pages containing the file contents
movq $1, %rdx # We want other programs to see our changes (not that there will be any)
pushq $0 # The offset
pushq %rdi # Need this for write
pushq %rdi
xor %rdi, %rdi # We don't give a sh*t about the address
pushq %rax # The file descriptor
movq $9, %rax # mmap's number
syscall # Damn, that took too much setup
# Write out the mmap'ed "buffer" with write(stdout, mmap'ed stuff, the length value we've been yeeting around)
movq %rax, %rdi # mmap'ed stuff
movq $1, %rax # write's syscall number
popq %rsi # The length
syscall # write
# Exit (note: we could unmap the file, but exiting yeets that sh*t out the window for us)
mov $60, %rax # exit is 60
xor %rdi, %rdi # 0
syscall # Exit
基本上,我试图打开作为第一个参数给出的文件名,然后确定文件的长度,将其映射,然后将映射的页面写入标准输出。 经过一些调试,似乎我传递了无效的标志、长度或无效的文件描述符。
再次感谢任何帮助,并提前感谢。
--- 编辑:这是 strace 的 output ---
execve("./mmap_asm_test", ["./mmap_asm_test", "file"], 0x7ffc2cc61038 /* 48 vars */) = 0
brk(NULL) = 0x558c01b67000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fffd5f8eae0) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffa4432c000
arch_prctl(ARCH_SET_FS, 0x7ffa4432ca80) = 0
mprotect(0x558c015ba000, 4096, PROT_READ) = 0
open("file", O_RDONLY) = 3
lseek(3, 0, SEEK_END) = 5
lseek(3, 0, SEEK_SET) = 0
mmap(NULL, 1, PROT_READ, MAP_FILE, 0, 0) = -1 EINVAL (Invalid argument)
write(-22, 0x3, 1) = -1 EBADF (Bad file descriptor)
exit(0) = ?
+++ exited with 0 +++
感谢对这个问题的有用评论,我制作了一个按预期工作的程序的修订版本:
.global _start
.section .text
_start:
# Grab our first argument from the stack
popq %rdi # This will be argc, which we don't care about
popq %rdi # Now the executable's path
popq %rdi # And the first argument, at last
# Open the file with open(argv[1], 0, O_RDONLY)
movq $2, %rax # The syscall number for open
xor %rsi, %rsi # There are no flags we need to specify
xor %rdx, %rdx # O_RDONLY is 0
syscall # Do the syscall
movq %rax, %rdi # Put the file descriptor in rdi for later use
# Get the file length with lseek(rax, 0, SEEK_END)
movq $8, %rax # The syscall number for lseek
xor %rsi, %rsi # The offset from where we're seeking in the file
movq $2, %rdx # SEEK_END is 2
syscall # Do the syscall
movq %rax, %r10 # Save our file length
# Now go back to the beginning of the file with
# lseek(fd, 0, SEEK_SET). The file descriptor should still be in rdi here
movq $8, %rax # lseek again
xor %rsi, %rsi # The start of the file
xor %rdx, %rdx # SEEK_SET is 0
syscall # Do the syscall
# Now that we _finally_ have the length of the file,
# mmap(0, length, PROT_READ (1), MAP_SHARED (1), fd, 0)
movq $9, %rax # mmap's number
xor %r9, %r9 # The offset
movq %rdi, %r8 # The file descriptor
movq %r10, %rsi # The file length
movq $1, %rdx # The permissions we want for the pages containing the file contents
movq $1, %r10 # We want other programs to see our changes (not that there will be any)
xor %rdi, %rdi # We don't give a sh*t about the address
syscall # Damn, that took too much setup
# Write out the mmap'ed "buffer" with write(stdout, mmap'ed stuff, length)
movq %rsi, %rdx # The length
movq %rax, %rsi # mmap'ed stuff
movq $1, %rax # write's syscall number
movq $1, %rdi # stdout
syscall # write
# Exit (note: we could unmap the file, but exiting yeets that sh*t right out the window for us)
mov $60, %rax # exit is 60
xor %rdi, %rdi # 0
syscall # Exit
感谢您帮助我找到解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.