原创文章,转载请标注出处~
平台为兆芯x86-64环境
rename系统调用有两个入参,有一个返回值,首先用libc实现功能:
#include <stdio.h>
#include <string.h>
int main(void)
{
int error = -1;
char *oldname = "hello.c";
char *newname = "newhello.c";
error = rename(oldname,newname);
if(error == 0)
{
printf("Rename successfully!\n");
}
else
{
printf("Rename fail! %s(%d) !\n",strerror(-error),error);
}
}
编译:
root@henry-002:/usr/test_code# gcc rename_syscall.c -o rename_syscall --static
执行结果正常:
root@henry-002:/usr/test_code# ./rename_libc
Rename successfully!
不修改文件名的情况下再次执行:
root@henry-002:/usr/test_code# ./rename_libc
Rename fail! Operation not permitted(-1) !
发现明明是文件不存在,但是返回值却是-1,这里比较奇怪,详细分析可以查看《用GDB跟踪汇编代码排查返回值》。
反汇编:
root@henry-002:/usr/test_code# objdump -dlt rename_libc > rename_libc.dis
找到关键的代码部分:
000000000040105e <main>:
main():
40105e: 55 push %rbp
40105f: 48 89 e5 mov %rsp,%rbp
401062: 48 83 ec 20 sub $0x20,%rsp
401066: c7 45 ec ff ff ff ff movl $0xffffffff,-0x14(%rbp)
40106d: 48 c7 45 f0 04 3a 49 movq $0x493a04,-0x10(%rbp)
401074: 00
401075: 48 c7 45 f8 0c 3a 49 movq $0x493a0c,-0x8(%rbp)
40107c: 00
40107d: 48 8b 55 f8 mov -0x8(%rbp),%rdx
401081: 48 8b 45 f0 mov -0x10(%rbp),%rax
401085: 48 89 d6 mov %rdx,%rsi
401088: 48 89 c7 mov %rax,%rdi
40108b: e8 70 6f 00 00 callq 408000 <rename>
401090: 89 45 ec mov %eax,-0x14(%rbp)
401093: 83 7d ec 00 cmpl $0x0,-0x14(%rbp)
401097: 75 0c jne 4010a5 <main+0x47>
401099: bf 17 3a 49 00 mov $0x493a17,%edi
40109e: e8 ad 76 00 00 callq 408750 <_IO_puts>
4010a3: eb 21 jmp 4010c6 <main+0x68>
4010a5: 8b 45 ec mov -0x14(%rbp),%eax
4010a8: f7 d8 neg %eax
4010aa: 89 c7 mov %eax,%edi
4010ac: e8 df 83 01 00 callq 419490 <strerror>
4010b1: 8b 55 ec mov -0x14(%rbp),%edx
4010b4: 48 89 c6 mov %rax,%rsi
4010b7: bf 2c 3a 49 00 mov $0x493a2c,%edi
4010bc: b8 00 00 00 00 mov $0x0,%eax
4010c1: e8 0a 6e 00 00 callq 407ed0 <_IO_printf>
4010c6: c9 leaveq
4010c7: c3 retq
4010c8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
4010cf: 00
.................
0000000000408000 <rename>:
rename():
408000: b8 52 00 00 00 mov $0x52,%eax
408005: 0f 05 syscall
408007: 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax
40800d: 0f 83 bd 09 03 00 jae 4389d0 <__syscall_error>
408013: c3 retq
408014: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40801b: 00 00 00
40801e: 66 90 xchg %ax,%ax
下边就通过嵌入式汇编进行替换:
#include <stdio.h>
#include <string.h>
int main(void)
{
int error = -1;
char *oldname = "hello.c";
char *newname = "newhello.c";
asm volatile(
"mov %1,%%rdi\n\t"
"mov %2,%%rsi\n\t"
"mov $0x52,%%eax\n\t"
"syscall\n\t"
:"=a"(error)
:"m"(oldname),"m"(newname)
);
if(error == 0)
{
printf("Rename successfully!\n");
}
else
{
printf("Rename fail! %s(%d) !\n",strerror(-error),error);
}
}
编译:
root@henry-002:/usr/test_code# gcc rename_syscall.c -o rename_syscall --static
执行:
root@henry-002:/usr/test_code# ./rename_syscall
Rename fail! No such file or directory(-2) !
root@henry-002:/usr/test_code#
root@henry-002:/usr/test_code#
root@henry-002:/usr/test_code# mv newhello.c hello.c
root@henry-002:/usr/test_code# ./rename_syscall
Rename successfully!
发现自己实现的嵌入式系统调用返回的异常值是正确的,反汇编:
root@henry-002:/usr/test_code# objdump -dlt rename_syscall > rename_syscall.dis
找到关键执行代码:
000000000040105e <main>:
main():
40105e: 55 push %rbp
40105f: 48 89 e5 mov %rsp,%rbp
401062: 48 83 ec 20 sub $0x20,%rsp
401066: c7 45 ec ff ff ff ff movl $0xffffffff,-0x14(%rbp)
40106d: 48 c7 45 f0 e4 39 49 movq $0x4939e4,-0x10(%rbp)
401074: 00
401075: 48 c7 45 f8 ec 39 49 movq $0x4939ec,-0x8(%rbp)
40107c: 00
40107d: 48 8b 7d f0 mov -0x10(%rbp),%rdi
401081: 48 8b 75 f8 mov -0x8(%rbp),%rsi
401085: b8 52 00 00 00 mov $0x52,%eax
40108a: 0f 05 syscall
40108c: 89 45 ec mov %eax,-0x14(%rbp)
40108f: 83 7d ec 00 cmpl $0x0,-0x14(%rbp)
401093: 75 0c jne 4010a1 <main+0x43>
401095: bf f7 39 49 00 mov $0x4939f7,%edi
40109a: e8 91 76 00 00 callq 408730 <_IO_puts>
40109f: eb 21 jmp 4010c2 <main+0x64>
4010a1: 8b 45 ec mov -0x14(%rbp),%eax
4010a4: f7 d8 neg %eax
4010a6: 89 c7 mov %eax,%edi
4010a8: e8 c3 83 01 00 callq 419470 <strerror>
4010ad: 8b 55 ec mov -0x14(%rbp),%edx
4010b0: 48 89 c6 mov %rax,%rsi
4010b3: bf 0c 3a 49 00 mov $0x493a0c,%edi
4010b8: b8 00 00 00 00 mov $0x0,%eax
4010bd: e8 0e 6e 00 00 callq 407ed0 <_IO_printf>
4010c2: c9 leaveq
4010c3: c3 retq
4010c4: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
4010cb: 00 00 00
4010ce: 66 90 xchg %ax,%ax
本篇文章实现了两个参数的系统调用,并正确的接收到了返回值~