標籤:linux syscall nasm mmap 系統調用
經過上一篇的鋪墊貌似可以很輕鬆的用彙編寫出mmap的代碼來,可仔細一看,還是有不少問題需要解決:
1.系統調用mmap如果出錯並不直接返回MAP_FAILED(-1),而是一個“類似”值;C庫中的mmap函數對其做了封裝,使其最終返回-1;如果我們直接調用mmap syscall,則這些事必須自己來做。
2.C庫函數如果出錯會設定errno的值,而在彙編中沒法直接用:
extern errno
的方法使用外部的值,串連時會報錯:
/usr/bin/ld: errno: TLS definition in /lib/x86_64-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in p.o/lib/x86_64-linux-gnu/libc.so.6: error adding symbols: 錯誤的值
C語言的解決辦法很簡單,直接把:
extern int errno;//替換為#include <errno.h>
但nasm下這招沒法使;我們先看一下errno對應的C代碼:
#define errno() *errnofunc()int *errnofunc() { int *errnoptr = get_thread_data(ERRNOPTR); return errnoptr;}
可以看到其調用另一個函數,在nasm中我們可以大致這麼寫:
extern __errno_locationcall __errno_locationmov rax,qword [rax]
不過貌似也不太對 :( ,不過我們可以在mmap系統調用後自己操作errno的值,以下代碼將填充變數errno的值並且如果出錯將修正mmap的傳回值為-1:
section .dataerrno dq 0;mmap syscall 之後cmp rax,0xfffffffffffff001jb nextpush raxneg raxmov [errno],raxpop raxor rax,-1next:;處理mmap返回後的邏輯
最後的代碼如下:
section .data errno dq 0 addr dq 0MAP_FAILED equ -1;MAP_LEN equ 40960MAP_LEN equ 0xffffffffffffffffPROT_READ_WRITE equ 3MAP_SHARED_ANON equ 33;MAP_SHARED_ANON equ 0x20section .text;extern errnoextern __errno_locationextern strerrorextern printf;if use ld;global _start;if use gccglobal main;_start:main: and rsp,~0xffff ;堆棧對齊 equ 0xffffffffffff0000 mov rax,9 ;mmap NO mov rdi,0 ;map address mov rsi,MAP_LEN ;map size mov rdx,PROT_READ_WRITE mov r10,MAP_SHARED_ANON mov r8,-1 ;忽略fd mov r9,0 ;offset syscall cmp rax,0xfffffffffffff001 jb next push rax neg rax mov [errno],rax pop rax or rax,-1next: cmp rax,MAP_FAILED ;cmp rax,0 ;js map_failed je map_failed mov [addr],rax mov rsi,[addr] mov rdi,msg_success call printf mov rax,11 mov rdi,addr mov rsi,MAP_LEN syscall jmp exitmap_failed: ;mov rdi,0xb ;call __errno_location ;mov rax,qword [rax] ;mov rsi,[errno] mov rdi,[errno] call strerror mov rsi,rax mov rdi,msg_failed call printfexit: mov rax,60 ;exit NO mov rdi,0 ;error_code syscall msg_success: db "map successed , addr at %p",0ax,0 msg_failed: db "map failed ,due to %s",0ax,0
編譯串連:
nasm -f elf64 p.sgcc -o p p.o
如果mmap成功結果如下:
wisy@wisy-pad:~/src/asm_src/nasm_src/linux$ ./pmap successed , addr at 0x7fbe5c94e000
可以用strace查看其返回的syscall:
mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) = 0x7fc6b2397000
如果mmap出錯則會顯示出錯原因:
//將MAP_LEN 設為超大的值./pmap failed ,due to Cannot allocate memory//傳遞給flags錯誤的參數./pmap failed ,due to Invalid argument
linux下64位彙編的系統調用(4)