After the foreshadowing of the previous article seems to be very easy to use the assembly to write mmap code, you can look carefully, or there are a number of problems need to be resolved:
1. System call Mmap If an error does not directly return map_failed (-1), but rather a "similar" value, the C library's mmap function wraps it so that it eventually returns-1; if we call Mmap Syscall directly, then these things have to be done by ourselves.
2.C Library function If an error sets the value of errno, it cannot be used directly in the assembly:
extern errno
method uses the external value, the connection will be error:
/usr/bin/ldin /lib/x86_64-linux-gnu/libc.so.6.tbssin p.o/lib/x86_64-linux-gnu/libc.so.6: error adding symbols: 错误的值
The solution to the C language is simple and straightforward:
externint errno;//替换为#include <errno.h>
But nasm this trick can not be made; let's look at the C code for errno:
#define errno() *errnofunc()int*errnofunc() { int*errnoptr = get_thread_data(ERRNOPTR); return errnoptr;}
You can see that it calls another function, which we can write roughly in NASM:
extern __errno_locationcall __errno_locationmov rax,qword [rax]
But it doesn't seem quite right:(, but we can manipulate the value of errno after the mmap system call, and the following code populates the value of the variable errno and if an error is corrected mmap return value is-1:
.data0;mmap syscall 之后cmp rax,0xfffffffffffff001jb nextpush raxneg raxmov [errno],raxpop raxor rax,-1next:;处理mmap返回后的逻辑
The final code is as follows:
Section. Dataerrno DQ0Addr DQ0map_failed Equ-1; Map_len equ 40960Map_len equ0xffffffffffffffffProt_read_write equ3Map_shared_anon equ -; Map_shared_anon equ 0x20Section. Text; extern errnoextern __errno_locationextern Strerrorextern printf; if use LD; global _start; if use gccGlobal Main; _start:Main: andrsp,~0xFFFF ; stack alignment equ 0xffffffffffff0000 movRax9 ; mmap NO movRdi0 ; map Address movRsi,map_len; Map Size movRdx,prot_read_writemov R10, Map_shared_anonmov R8,-1 ; ignore FD mov R9,0 ; offsetSyscall CMP Rax,0xfffffffffffff001JB NextPushRaxnegRaxmov[Errno],raxPopRaxorrax,-1Next:CMP rax,map_failed; CMP rax,0 ; JS map_failedJe map_failedmov[Addr],raxmovRSI,[ADDR]movRdi,msg_successPagerPrintfmovRax One movRdi,addrmovRsi,map_len SyscalljmpExitmap_failed: ; mov rdi,0xb ; Call __errno_location ; mov rax,qword [Rax] ; mov Rsi,[errno] movRdi,[errno]PagerStrerrormovRsi,raxmovRdi,msg_failedPagerPrintfexit: movRax - ; exit NO movRdi0 ; Error_codeSyscall msg_success:db"Map successed, addr at%p",0Ax0Msg_failed:db"Map failed, due to%s",0Ax0
To compile the connection:
nasm -f elf64 p.sgcc -o p p.o
If the mmap success results are as follows:
wisy@wisy-pad:~/src/asm_src/nasm_src/linux$ 0x7fbe5c94e000
You can use Strace to view the syscall that it returns:
mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) = 0x7fc6b2397000
If a mmap error occurs, the cause of the error is displayed:
//将MAP_LEN 设为超大的值./pmapto Cannot allocate memory//传递给flags错误的参数./pmapto Invalid argument
Linux under 64-bit assembly system call (4)