内核 3.10.40
Android版本: Android 6.0.1_r1
手机 Nexus 6
参考资料:
http://android.blogs.rice.edu/2013/09/25/adding-system-call-in-android-bionic-library/http://www.it1352.com/231359.html
一.编译源码
由于Android系统中不包含内核的源码,所以需要分别下载编译Android和Kernel的源码。这部分比较复杂且不是本文的重点,读者需自行解决。这里给出几个参考文档,实测比较靠谱:
Android编译:
内核编译:
以上两项编译成功后才能进行下面步骤
二、内核修改
1. 函数声明
在kernel/include/linux/syscalls.h文件末尾添加函数声明
asmlinkage long sys_getpos(unsigned int fd);
2.函数实现
可以在一个已存在的C文件中添加或者新建一个C文件添加,这里出于简单选择前者。(如果选择后者,需要在相对应的makefile文件中修改相对应的配置)
在kernel/kernel/timer.c中实现函数:
SYSCALL_DEFINE1(getpos,unsigned int,fd)
{
return fd * 2;
}
3.添加系统调用号
在kernel/arch/arm/include/uapi/asm/unistd.h中添加系统调用号
#define __NR_getpos (__NR_SYSCALL_BASE+384)
修改系统调用计数器((kernel/arch/arm/include/asm/unistd.h)
#define __NR_syscalls (384)
修改为
#define __NR_syscalls (388)
注意这里的__NR_syscalls只能以4为单位递增否则编译会出错!!!
4. 在系统调用表中声明
在文件kernel/arch/arm/kernel/calls.S中添加:
/* 384 */ CALL(sys_getpos)
编译刷入后即可
三.Android源码修改
1. 声明系统调用
在bionic/libc/SYSCALLS.TXT中添加系统调用的声明:
int getpos(int) arm
按照参考文档的说法,只需要在SYSCALL.TXT中添加这一句话就可以通过脚本/bionic/libc/tools/gensyscalls.py自动生成其余文件,但是我这脚本运行报错,所以其余文件通过手动修改,读者可以自己测试下脚本能否正常运行。
2.汇编调用实现
这里的汇编程序并不需要自己编写,因为汇编程序功能都是一样的,只是保存一下寄存器现场传入参数然后调用系统调用后恢复现场,所以将汇编程序修改一下函数名就可以了。
在/bionic/libc/arch-arm/syscalls中新建一个getpos.S文件,写入以下内容:
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(getpos)
mov ip, r7
ldr r7, =__NR_getpos
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(getpos)
3. 添加映射表
在/bionic/libc/libc.map中添加一行函数名即可:
LIBC {
global:
getpos; #Add here
__assert;
4. 添加调用号
在文件中添加调用号,注意要与之前内核添加的调用号一致。在文件bionic/libc/kernel/uapi/asm-arm/asm/unistd.h中添加:
#define __NR_getpos (__NR_SYSCALL_BASE + 384)
注意这里有个问题,系统调用号384已经被之前的某些系统调用占用了。但是我们从内核中可以得知内核根本没有提供这个调用号的系统调用所以之前的肯定没有作用的,删掉即可。
5. 测试系统调用
在bionic/libc/bionic/open.cpp中进行测试,添加以下代码:
注:必须声明: extern “C” int getpos(int);
extern "C" int getpos(int);
int open(const char* pathname, int flags, ...) {
const char * tag = "DebugPos";
const char * format = "%d*2 = %d";
__libc_format_log(ANDROID_LOG_DEBUG, tag, format, 5,getpos(5));
.......
.......
6. 编译写入
注意编译写入时不要写入boot.img,否则把我们之前编译的内核覆盖掉了,会无法开机。
四、运行结果
开机后在终端输入 adb logcat | grep ‘DebugPos’
就可以了!!!