使用ARM中的返回值执行系统调用的内联程序集



我发现了许多使用asm运行Hello World系统调用的示例,但没有一个涉及到使用返回值调用系统调用。我的代码是

int my_syscall(int sn)
{
int output_variable = 0;
int input_variable = sn;
__asm__ volatile(
"mov r7,%1nt"
"svc 0nt"
"mov %0,r0nt"
:"=r"(output_variable)
:"r"(input_variable)
);
return output_variable;
}

在ARM linux(BeagleBone Black)上运行这个程序会导致分段错误。

修复:修复是在使用arm-linux-gnueabihf-gcc编译时使用"-fomit frame pointer"指令(可能也适用于其他风格)。

$arm-linux-gnueabihf-gcc {YOUR FILE NAME}.c -fomit-frame-pointer -o {YOUR OUTPUT FILE NAME}

谢谢大家的评论。因此,为了记录在案,上述问题中的代码逻辑是有效的。据我所知,问题是编译器出于某种原因使用r7作为帧指针。您可以继续添加参数作为输入,并使用内联程序集创建更通用的系统调用实现。考虑一下人们在评论中所说的内容,以获得更好的实现。

伪码

returntype my_syscall(int syscallnumber,type arg1,type arg2,..)
{
int output_variable = 0;
__asm__ volatile
(
"mov r7,[sysnum]nt"
"mov r0,[var1]nt"
"mov r1,[var2]nt"
//continue similarly for more input arguments etc 
"svc 0nt"
"mov %0,r0nt"      //Return value of syscall will be available in r0 for ARM EABI
:"=r"(output_variable)
:[sysnum]"r"(syscallnumber),[var1]"r"(arg1),[var2]"r"(arg2) //and so on for other arguments
:"memory" //clobber others based on usage
);
return output_variable;
}

Backstory(对于任何感兴趣的人):当我实现一个简单的"Hello World"字符串写入时,相同的代码(问题中存在的代码)略有变化(变化包括不同的系统调用编号和参数)。但当我调用返回所需值的自定义系统调用时,它就不起作用了(或者,你可以将系统调用设计为使用参数而不是返回指令来返回值,以避免整个问题。我没有这样做,因为那样我将不得不重新编译整个内核,但我跑题了)。我用内置的syscall()函数测试了我的syscall,它运行得很好。但是MYsyscall()函数的实现无法调用MY自定义syscall。我尝试了寄存器变量,尝试了不同的指令,并破坏了r0、内存等(在我问这个问题之前),但似乎什么都不起作用。然后我试着破解r7,编译器说你不能这么做。就在那时,我发现r7寄存器也被用于其他用途。当我在谷歌上搜索错误时,我找到了上面的修复方法。具有讽刺意味的是,在修复后,它在没有破坏r7或其他任何东西的情况下发挥了作用。lol.

相关内容

最新更新