assembly x86_64程序集mmap系统调用[重复]

g9icjywg  于 2023-01-21  发布在  其他
关注(0)|答案(1)|浏览(145)
    • 此问题在此处已有答案**:

Why do we need MAP_PRIVATE flag when mapping memory?(1个答案)
7分钟前关门了。
我试着做一个非常简单的内存分配器,但是它在输出时给我错误,另外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系统调用和系统调用的信息,我不记得我是怎么处理代码来修复它的,但是我花了很长时间。

r6l8ljro

r6l8ljro1#

您必须提供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;

相关问题