having this nasm:
%define O_RDONLY 0
%define PROT_READ 0x1
%define MAP_PRIVATE 0x2
section .data
fname: db 'test.txt', 0
section .text
global _start
print:
; ---- THIS PART ADDED
mov r15, [rdi]
add r15, 1 ; have tried `inc byte[rdi]` - did not work either
mov [rdi], r15
; ---- END OF ADDED PART
; else is according to book (so correct)
push rdi
call str_len
pop rsi
mov rdx, rax
mov rax, 1
mov rdi, 1
syscall
ret
str_len:
xor rax, rax
.loop:
cmp byte [rdi+rax], 0
je .end
inc rax
jmp .loop
.end:
ret
_start:
;call open
mov rax, 2
mov rdi, fname
mov rsi, O_RDONLY
mov rdx, 0
syscall
;mmap
mov r8, rax
mov rax, 9
mov rdi, 0
mov rsi, 4094
mov rdx, PROT_READ
mov r10, MAP_PRIVATE
mov r9, 0
syscall
mov rdi, rax ;returned address
call print
mov rax, 60
xor rdi, rdi
syscall
The file test.txt
contains only one char at the beginning - 5
.
I got address from region asked by mmap
in rax
, which I then mov
e to rdi
.
And I simply want to increment the value (at that address - now being in rdi
):
mov r15, [rdi]
add r15, 1 ; have tried `inc byte[rdi]` - did not work either
mov [rdi], r15
push rdi
So i temporary mov
e the value on r15
, the increment it (add
it 1), and try to mov
e it back to address of that region (address still in rdi
). But then segfault
.
Why is that? Why cannot I use the value on the address (to the acquired region from mmap), which contain 5
- one byte (on which the rdi
points), and use it in arithmetic?
If that would be address declared in data segment
, then there would be no problem (I have tried). But the address is from mmap
, So how does it differ, and how to fix that?
Writing to read-only memory segfaults (mov [rdi], r15
qword store, or inc byte [rdi]
byte RMW).
You need PROT_READ | PROT_WRITE
if you want to be able to write as well as read.
(Note that writing to a MAP_PRIVATE mapping triggers a copy-on-write, leaving you with a private page that's no longer backed by the file, just like if you'd done a read
into a MAP_ANONYMOUS page.)