x86_64 assembly mmap syscall



我尝试制作非常简单的内存分配器,但它在输出上给了我错误,另外print_sys_error不能正常工作。如果我用下面的代码调用它就可以了:

_start:
sub $16, %rsp # preallocate stack
mov $20, %rdx
mov $STDOUT, %rdi
movq $_start.0, (%rsp)
jmp print_sys_error

,但在实际使用中不起作用。代码:

.global _start
.text
_start:
sub $16, %rsp # preallocate stack
mov $0x1000, %rsi # allocate 4 KIB
call alloc
mov %rax, 8(%rsp) # save page address for later
movq $_start.0, (%rsp) # prepearing for potential call of print_sys_error
mov $STDOUT, %rdi
cmpq $0, %rdx
jne print_sys_error
mov 8(%rsp), %rax # get back page address
movb $0xff, (%rax)
movb $0xff, 0xfff(%rax)
mov $SYS_EXIT, %rax # exit successfully
xor %rdi, %rdi
syscall
_start.0:
sub $8, %rsp # stack got smaller after return
mov $SYS_EXIT, %rax # fail successfully
mov $1, %rdi
syscall

### put file descriptor to %rdi and error code to %rdx (can't be over 34)
print_sys_error:
call sys_error_to_str
mov $SYS_WRITE, %rax
syscall
ret
### put error code to %rdx (can't be over 34)
### get string address in %rsi and string length in %rdx
sys_error_to_str:
shl $4, %rdx
mov error_table(%rdx), %rsi
mov (error_table + 8)(%rdx), %rdx
ret

### put new page size is rsi
### get error code in %rdx (0 if no error) and address in %rax (same as %rdx if error)
alloc:
mov $SYS_MMAP, %rax
xor %rdi, %rdi # page address, zero so set by kernel
mov $(PROT_READ | PROT_WRITE | PROT_EXEC), %rdx # page access flags
mov $(MAP_ANONYMOUS), %r10 # page/fd settings
mov $-1, %r8 # fd (not used)
xor %r9, %r9 # file offset (not used)
syscall # page address in %rax
cmpq $35, %rax # compare to error number (+1 as I see in glibc)
jl alloc.0 # jump if error
xor %rdx, %rdx # zero output error
ret
alloc.0:
mov %rax, %rdx # set output error
ret

.data
.equ SYS_READ, 0 # for sys read `xor %rax %rax` can be used 
.equ SYS_WRITE, 1
.equ SYS_MMAP, 9
.equ SYS_EXIT, 60
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2
.equ MAP_ANONYMOUS,    0x10
# some other map constants ...
.equ PROT_READ,             0x1
# some other prot constants ...
.section .data.sys_errors
.equ ERR_PERM, 1 # no permissions
.equ ERR_NOFILE, 2 # so such file or directory
# some other ERR constants

### each table element has address to the string and it's length, both values are qwords so each element has 16 bytes
error_table:
.quad ERR_WRONG_STR
.quad ERR_WRONG_STR_LEN
.quad ERR_PERM_STR
.quad ERR_PERM_STR_LEN
# ...

ERR_WRONG_STR:
.asciz "wrong error"
.equ ERR_WRONG_STR_LEN, . - ERR_WRONG_STR - 1
ERR_PERM_STR:
.asciz "no permissions"
.equ ERR_PERM_STR_LEN, . - ERR_PERM_STR - 1
# ...

对于堆栈溢出问题,代码相当大,但我认为它不是很复杂。

我试着在网上寻找更多关于mmap系统调用和系统调用的信息。我不记得我用代码做了什么来修复它,但是我花了很长时间来修复它。

您必须提供MAP_PRIVATE|MAP_ANONYMOUS

不能只使用MAP_ANONYMOUS

文档很清楚:

The flags argument determines whether updates to the mapping are
visible to other processes mapping the same region, and whether 
updates are carried through to the underlying file. This behavior
is determined by including exactly one of the following  values
in flags:
MAP_SHARED
Share  this  mapping.  Updates to the mapping are visible to other processes mapping the same region, and (in the case of
file-backed mappings) are carried through to the underlying file.  (To precisely control when updates are carried through
to the underlying file requires the use of msync(2).)
MAP_SHARED_VALIDATE (since Linux 4.15)
This  flag  provides  the  same behavior as MAP_SHARED except that MAP_SHARED mappings ignore unknown flags in flags.  By
contrast, when creating a mapping using MAP_SHARED_VALIDATE, the kernel verifies all passed flags are known and fails the
mapping  with  the error EOPNOTSUPP for unknown flags.  This mapping type is also required to be able to use some mapping
flags (e.g., MAP_SYNC).
MAP_PRIVATE
Create a private copy-on-write mapping.  Updates to the mapping are not visible to other processes mapping the same file,
and  are not carried through to the underlying file.  It is unspecified whether changes made to the file after the mmap()
call are visible in the mapped region.
In addition, zero or more of the following values can be ORed in flags:
...
MAP_ANONYMOUS 
The mapping is not backed by any file; 

最新更新