Ios 使用svc调用实现fork()

Ios 使用svc调用实现fork(),ios,c,fork,inline-assembly,Ios,C,Fork,Inline Assembly,我实现了syscall宏来调用软件中断调用。对于许多系统调用来说,它工作得很好。但是,它不是用于fork()。父进程和子进程的返回pid相同。片段如下所示: #define SYSCALL0(N) ({ \ register int ip asm("ip") = N; \ register int r0 asm("r0");

我实现了syscall宏来调用软件中断调用。对于许多系统调用来说,它工作得很好。但是,它不是用于
fork()
。父进程和子进程的返回pid相同。片段如下所示:

#define SYSCALL0(N) ({                                          \
    register int ip asm("ip") = N;                              \
    register int r0 asm("r0");                                  \
    asm volatile("swi 0x80" : "=r"(r0) : "r"(ip) : "memory");   \
    r0;                                                         \
})

int main(int argc, char * argv[]) {
   NSLog(@"--beginning of program\n");
    int counter = 0;
    pid_t pid = SYSCALL0(2);
    if (pid == 0) {
        NSLog(@"pid = %d", getpid());
        // child process
        for (int i = 0; i < 3; ++i)
            NSLog(@"child process: counter=%d\n", ++counter);
    }
    else if (pid > 0)  {
        NSLog(@"pid = %d", getpid());
        // parent process
        for (int i = 0; i < 3; ++i)
            NSLog(@"parent process: counter=%d\n", ++counter);
    }
    else {
        // fork failed
        NSLog(@"fork() failed!\n");
        return 1;
    }
    NSLog(@"--end of program--\n");
}
#include <dlfcn.h>
int svc_fork() {
    register int r3 asm("r3") = (int)dlsym(RTLD_DEFAULT, "_current_pid");
    register int r12 asm("r12") = 2;
    register int r1 asm("r1") = 1;
    register int r0 asm("r0");
    asm volatile("swi   0x80                        \n"
                 "cmp   r1, #0                      \n"
                 "beq   Lparent                     \n"
                 "mov   r0, #0                      \n"
                 "str r0, [r3]                      \n"
                 "Lparent:                          \n"
                 : "=r"(r0)
                 : "r"(r1), "r"(r12), "r"(r3)
                 : "memory");
    return r0;
}
测试环境是一个在armv7上运行的破烂不堪的iOS(它不会在非越狱者上运行)。
我想我可能对swi调用的返回做得不够,所以它不能返回0来指示子进程。我错过了什么?如何使其正常工作?

您不会以这种方式进行系统调用。正如您刚才注意到的,系统调用的userland包装器所做的工作远不止这些。因此,要么找到操作系统的源代码,弄清楚系统调用是如何包装的,然后做同样的事情,要么就使用方便地为您提供的包装器

我很确定iOS仍然采用BSD方式进行系统调用。我碰巧知道fork使用了两个返回值syscall接口,一个寄存器包含进程是否为子进程,另一个包含返回值


此外,您的包装器可能没有正确地进行错误处理(这通常通过您必须特别处理的标志来表示)。而且至少有些操作系统(不知道iOS是否是其中之一)确切地知道哪些寄存器保存在系统调用包装器中,并且不必费心保存它们,因此像这样内联系统调用可能会破坏您的寄存器。

。结果表明,在svc调用之后,若后续代码是子代码或父代码,则r1被设置为指示符。代码段更改如下:

#define SYSCALL0(N) ({                                          \
    register int ip asm("ip") = N;                              \
    register int r0 asm("r0");                                  \
    asm volatile("swi 0x80" : "=r"(r0) : "r"(ip) : "memory");   \
    r0;                                                         \
})

int main(int argc, char * argv[]) {
   NSLog(@"--beginning of program\n");
    int counter = 0;
    pid_t pid = SYSCALL0(2);
    if (pid == 0) {
        NSLog(@"pid = %d", getpid());
        // child process
        for (int i = 0; i < 3; ++i)
            NSLog(@"child process: counter=%d\n", ++counter);
    }
    else if (pid > 0)  {
        NSLog(@"pid = %d", getpid());
        // parent process
        for (int i = 0; i < 3; ++i)
            NSLog(@"parent process: counter=%d\n", ++counter);
    }
    else {
        // fork failed
        NSLog(@"fork() failed!\n");
        return 1;
    }
    NSLog(@"--end of program--\n");
}
#include <dlfcn.h>
int svc_fork() {
    register int r3 asm("r3") = (int)dlsym(RTLD_DEFAULT, "_current_pid");
    register int r12 asm("r12") = 2;
    register int r1 asm("r1") = 1;
    register int r0 asm("r0");
    asm volatile("swi   0x80                        \n"
                 "cmp   r1, #0                      \n"
                 "beq   Lparent                     \n"
                 "mov   r0, #0                      \n"
                 "str r0, [r3]                      \n"
                 "Lparent:                          \n"
                 : "=r"(r0)
                 : "r"(r1), "r"(r12), "r"(r3)
                 : "memory");
    return r0;
}
#包括
int svc_fork(){
寄存器int r3 asm(“r3”)=(int)dlsym(RTLD_默认值,“_当前_pid”);
寄存器int r12 asm(“r12”)=2;
寄存器int r1 asm(“r1”)=1;
寄存器int r0 asm(“r0”);
asm易失性(“swi 0x80\n”
“cmp r1,#0\n”
“beq Lparent\n”
“mov r0,#0\n”
str r0,[r3]\n
“Lparent:\n”
:“=r”(r0)
:“r”(r1),“r”(r12),“r”(r3)
:“记忆”);
返回r0;
}

您的问题是什么?抱歉,如果不清楚,我正在编辑问题。问题是“我如何让它正确工作”问题是我似乎找不到任何源代码,所以我自己实现了它,通过查看此页面,如果你在web上搜索,你可能会找到一些达尔文的旧源代码,应该足够接近了。但是是的,这个想法是你不应该自己做这件事。使用操作系统提供的正确包装的系统调用有什么不对?我找到了达尔文代码。希望它能工作,让我们看看。代码在这里,但我不确定如何将此
MI\u GET\u地址(r3,\u current\u pid)
转换为内联asm代码。