应用调试系统调用SWI
Posted zongzi10010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了应用调试系统调用SWI相关的知识,希望对你有一定的参考价值。
目录
title: 应用调试(四)系统调用SWI
date: 2019/01/19 18:05:39
toc: true
---
应用调试(四)系统调用SWI
系统调用
我们App中的open,read
等实际上会触发swi
异常,触发系统调用sys_open,sys_read
等,内核根据swi的值来执行具体的操作
SWI代码片段分析
搜索下vector_swi
,找到入口函数archarmkernelentry-common.S
.align 5
ENTRY(vector_swi)
@ 保存现场
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0 - r12
add r8, sp, #S_PC
stmdb r8, {sp, lr}^ @ Calling sp, lr
mrs r8, spsr @ called from non-FIQ mode, so ok.
str lr, [sp, #S_PC] @ Save calling PC
str r8, [sp, #S_PSR] @ Save CPSR
str r0, [sp, #S_OLD_R0] @ Save OLD_R0
zero_fp
@ 获得swi的指令地址,确保是swi指令
ldr scno, [lr, #-4] @ get SWI instruction
A710( and ip, scno, #0x0f000000 @ check for SWI )
A710( teq ip, #0x0f000000 )
A710( bne .Larm710bug )
@ tbl等于数组表基地址
get_thread_info tsk
adr tbl, sys_call_table @ load syscall table pointer
ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
@清除高8位
bic scno, scno, #0xff000000 @ mask off SWI op-code
@ #define __NR_SYSCALL_BASE 0x900000 这里swi的值实际上是0x900000 0x900001 ...所以要清除这个高位的9
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
@根据索引号,去tbl 这个数组中调用函数
@ tbl:数组表基地址, scno:要调用的sys_write()的索引值 lsl #2:左移2位,一个函数指针占据4个字节
cmp scno, #NR_syscalls @ check upper syscall limit
adr lr, ret_fast_syscall @ return address
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
这里首先获得swi这条指令的内容,swi指令位于
lr-4
,原因如下图然后分析确保是swi指令,也就是
and ip, scno, #0x0f000000
- 获得全局的一个存有系统调用函数的数组的地址
通过swi的值去找到这个数组的索引,执行函数
分析sys_write
理论上,应该有sys_write
存入这个指针数组,搜索下发现如下archarmkernelcalls.S
/* 0 */ CALL(sys_restart_syscall)
CALL(sys_exit)
CALL(sys_fork_wrapper)
CALL(sys_read)
CALL(sys_write)
/* 5 */ CALL(sys_open)
......
同时有如下在archarmkernelentry-common.S
,也就是先定义这个CALL
,再将上面的定义全部包含进来
.equ NR_syscalls,0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
#include "calls.S"
#undef CALL
#define CALL(x) .long x
也就是说,我们可以自己定义一个swi val 在archarmkernelcalls.S
放在最后面
/* 350 */ CALL(sys_timerfd)
CALL(sys_eventfd)
CALL(sys_hello) /* 添加一个自己的系统调用 */
构造sys_hello
仿照sys_write
声明定义在includelinuxsyscalls.h
和fs
ead_write.c
asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
实现函数如下
asmlinkage void sys_hello(const char __user * buf, size_t count);
asmlinkage void sys_hello(const char __user * buf, size_t count)
{
char ker_buf[100];
if(buf)
{ copy_from_user(ker_buf, buf, (count<100)? count : 100);
ker_buf[99]='