浅尝辄止24-Linux系统调用2

今天不拐弯抹角,直接验证一下浅尝辄止23-Linux系统调用1里面的说法。

绕过glibc

我们平时用的系统调用是glibc封装的(如果是Android平台,就是bionic),下面就来验证一下glibc里面看到的调用system call的方法。
可以看下面代码中#if defined(__arm__) && !defined(__thumb__)#endif包住的部分,这个测试只适合用ARM32并且使用ARM指令(非thumb)的平台。

代码演示

以下代码未经测试,只能保证用-marm编译选项可以编译通过。因为现在手上的设备是跑thumb指令的,相对于我在跑arm指令的平台上验证的代码(验证过),有些修改。

#include 
#include 
#include 
#include 
#include 

#if defined(__arm__) && !defined(__thumb__)
#include 
int three_paramter_syscall_wrapper(int nr, int p0, int p1, int p2){
    register int _p0 asm("r0") = p0;
    register int _p1 asm("r1") = p1;
    register int _p2 asm("r2") = p2;
    register int _nr asm("r7") = nr;
    asm volatile(
        "swi 0x0"
        :"=r" (_p0)
        :"r" (_nr), "r" (_p0), "r" (_p1), "r" (_p2)
        :"memory"
    );
    return _p1;
}
int my_write(int fd, void *buf, size_t count){
    return three_paramter_syscall_wrapper(__NR_write, fd, (int)buf, (int)count);
}
int my_read(int fd, void *buf, size_t count){
    return three_paramter_syscall_wrapper(__NR_read, fd, (int)buf, (int)count);
}
int my_lseek(int fd, off_t offset, int whence){
    return three_paramter_syscall_wrapper(__NR_lseek, fd, (int)offset, whence);
}
#endif

int main(int argc, char **argv){
    int tmp;
    int syscall = 1234;
    int my_syscall = 5678;
    int ret = -1;
    int fd = open("./tmp", O_CREAT | O_RDWR);

    printf("\n[Standard] system call:\n");
    ret = write(fd, &syscall, sizeof(syscall));
    printf("write %dB\n", ret);
    ret = lseek(fd, 0, SEEK_SET);
    printf("lseek %d\n", ret);
    ret = read(fd, &tmp, sizeof(tmp));
    printf("read %dB [%d]\n", ret, tmp);
    ret = lseek(fd, 0, SEEK_SET);
    printf("lseek %d\n", ret);

#if defined(__arm__) && !defined(__thumb__)
    printf("\n[My] system call:\n");
    ret = my_write(fd, &syscall, sizeof(syscall));
    printf("write %dB\n", ret);
    ret = my_lseek(fd, 0, SEEK_SET);
    printf("lseek %d\n", ret);
    ret = my_read(fd, &tmp, sizeof(tmp));
    printf("read %dB [%d]\n", ret, tmp);
    ret = my_lseek(fd, 0, SEEK_SET);
    printf("lseek %d\n", ret);
#else
    printf("Please use arm32 platform to test!\n", ret);
#endif
    unlink("./tmp");
    return 0;
}

输出

后一半输出是预计在跑arm指令的平台上运行的结果。

[Standard] system call:
write 4B
lseek 0
read 4B [1234]
lseek 0

[My] system call:
write 4B
lseek 0
read 4B [5678]
lseek 0

你可能感兴趣的:(浅尝辄止24-Linux系统调用2)