Android添加内核系统调用

5 篇文章 0 订阅
3 篇文章 0 订阅

Author:Gary
Date:2019-4-30
Android版本:Android 6.0.1_r1
内核版本:Linux 3.10.40
手机:Nexus 6
参考资料:
http://android.blogs.rice.edu/2013/09/25/adding-system-call-in-android-bionic-library/
http://www.it1352.com/231359.html
https://www.cnblogs.com/wuyuegb2312/archive/2012/08/09/2629719.html

一.编译源码

由于Android系统中不包含内核的源码,所以需要分别下载编译Android和Kernel的源码。这部分比较复杂且不是本文的重点,读者需自行解决。这里给出几个参考文档,实测比较靠谱:

Android编译:https://blog.csdn.net/pcsxk/article/details/52013904
内核编译:https://blog.csdn.net/u012417380/article/details/73353670

以上两项编译成功后才能进行下面的步骤。

二.内核修改

1. 函数声明

在kernel/include/linux/syscalls.h文件末尾添加函数声明

asmlinkage long sys_getpos(unsigned int fd);

2. 函数实现

可以在一个已存在的C文件中添加或者新建一个C文件添加,这里出于简单选择前者。
在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)

5. 编译刷入后即可

三.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);
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'
在这里插入图片描述
可以看到调用成功了!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值