linux下64位汇编的系统调用(4)
2015-04-12 10:12
218 查看
经过上一篇的铺垫貌似可以很轻松的用汇编写出mmap的代码来,可仔细一看,还是有不少问题需要解决:
1.系统调用mmap如果出错并不直接返回MAP_FAILED(-1),而是一个“类似”值;C库中的mmap函数对其做了包装,使其最终返回-1;如果我们直接调用mmap syscall,则这些事必须自己来做。
2.C库函数如果出错会设置errno的值,而在汇编中没法直接用:
的方法使用外部的值,连接时会报错:
C语言的解决办法很简单,直接把:
但nasm下这招没法使;我们先看一下errno对应的C代码:
可以看到其调用另一个函数,在nasm中我们可以大致这么写:
不过貌似也不太对 :( ,不过我们可以在mmap系统调用后自己操作errno的值,以下代码将填充变量errno的值并且如果出错将修正mmap的返回值为-1:
3 可以看到C代码中调用mmap参数压栈,是将第4个参数放到rcx里,但是在C库mmap函数里又将rcx赋值给r10;这正应了前面调用规则里的内核系统调用第4个参数是放在r10里,而不是rcx里的哦;所以汇编中我们直接放在r10里即可,不用先转到rcx里了。
最后的代码如下:
编译连接:
如果mmap成功结果如下:
可以用strace查看其返回的syscall:
如果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_location call __errno_location mov rax,qword [rax]
不过貌似也不太对 :( ,不过我们可以在mmap系统调用后自己操作errno的值,以下代码将填充变量errno的值并且如果出错将修正mmap的返回值为-1:
section .data errno dq 0 ;mmap syscall 之后 cmp rax,0xfffffffffffff001 jb next push rax neg rax mov [errno],rax pop rax or rax,-1 next: ;处理mmap返回后的逻辑
3 可以看到C代码中调用mmap参数压栈,是将第4个参数放到rcx里,但是在C库mmap函数里又将rcx赋值给r10;这正应了前面调用规则里的内核系统调用第4个参数是放在r10里,而不是rcx里的哦;所以汇编中我们直接放在r10里即可,不用先转到rcx里了。
最后的代码如下:
section .data errno dq 0 addr dq 0 MAP_FAILED equ -1 ;MAP_LEN equ 40960 MAP_LEN equ 0xffffffffffffffff PROT_READ_WRITE equ 3 MAP_SHARED_ANON equ 33 ;MAP_SHARED_ANON equ 0x20 section .text ;extern errno extern __errno_location extern strerror extern printf ;if use ld ;global _start ;if use gcc global 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,-1 next: 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 exit map_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 printf exit: 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.s gcc -o p p.o
如果mmap成功结果如下:
wisy@wisy-pad:~/src/asm_src/nasm_src/linux$ ./p map successed , addr at 0x7fbe5c94e000
可以用strace查看其返回的syscall:
mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) = 0x7fc6b2397000
如果mmap出错则会显示出错原因:
//将MAP_LEN 设为超大的值 ./p map failed ,due to Cannot allocate memory //传递给flags错误的参数 ./p map failed ,due to Invalid argument
相关文章推荐
- linux下64位汇编的系统调用(3)
- linux下64位汇编的系统调用(1)
- 64位汇编之linux系统调用
- linux下64位汇编的系统调用(3)
- linux下64位汇编的系统调用(3)
- linux下64位汇编的系统调用(4)
- linux下64位汇编的系统调用(5)
- linux下64位汇编的系统调用(4)
- linux下64位汇编的系统调用(5)
- linux下64位汇编的系统调用(1)
- linux下64位汇编的系统调用(2)
- linux系统调用64位汇编与32位汇编不同及兼容
- linux下64位汇编的系统调用(2)
- linux下64位汇编的系统调用(1)
- linux下64位汇编的系统调用(2)
- linux下64位汇编的系统调用(5)
- Linux 汇编程序 系统调用 [李园7舍_404]
- 汇编语言调用Linux系统调用read和write
- Linux 系统调用的实现及其汇编代码的嵌入到C中
- Linux下汇编程序及系统调用的深入分析