linux swi 内核sp,应用调试(四)系统调用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,找到入口函数arch\arm\kernel\entry-common.S

.align5

ENTRY(vector_swi)

@ 保存现场

subsp, sp, #S_FRAME_SIZE

stmiasp, {r0 - r12}@ Calling r0 - r12

addr8, sp, #S_PC

stmdbr8, {sp, lr}^@ Calling sp, lr

mrsr8, spsr@ called from non-FIQ mode, so ok.

strlr, [sp, #S_PC]@ Save calling PC

strr8, [sp, #S_PSR]@ Save CPSR

strr0, [sp, #S_OLD_R0]@ Save OLD_R0

zero_fp

@ 获得swi的指令地址,确保是swi指令

ldrscno, [lr, #-4]@ get SWI instruction

A710(andip, scno, #0x0f000000@ check for SWI)

A710(teqip, #0x0f000000)

A710(bne.Larm710bug)

@ tbl等于数组表基地址

get_thread_info tsk

adrtbl, sys_call_table@ load syscall table pointer

ldrip, [tsk, #TI_FLAGS]@ check for syscall tracing

@清除高8位

bicscno, scno, #0xff000000@ mask off SWI op-code

@ #define __NR_SYSCALL_BASE0x900000 这里swi的值实际上是0x900000 0x900001 ...所以要清除这个高位的9

eorscno, scno, #__NR_SYSCALL_BASE@ check OS number

@根据索引号,去tbl 这个数组中调用函数

@ tbl:数组表基地址, scno:要调用的sys_write()的索引值 lsl #2:左移2位,一个函数指针占据4个字节

cmpscno, #NR_syscalls@ check upper syscall limit

adrlr, ret_fast_syscall@ return address

ldrccpc, [tbl, scno, lsl #2]@ call sys_* routine

这里首先获得swi这条指令的内容,swi指令位于lr-4,原因如下图

f473f84a537aa54a90cfc0611d7b37dd.png

然后分析确保是swi指令,也就是andip, scno, #0x0f000000

376f0ff2dc7d7848469a5e52c6630121.png

获得全局的一个存有系统调用函数的数组的地址

通过swi的值去找到这个数组的索引,执行函数

分析sys_write

理论上,应该有sys_write存入这个指针数组,搜索下发现如下arch\arm\kernel\calls.S

/* 0 */CALL(sys_restart_syscall)

CALL(sys_exit)

CALL(sys_fork_wrapper)

CALL(sys_read)

CALL(sys_write)

/* 5 */CALL(sys_open)

......

同时有如下在arch\arm\kernel\entry-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 在arch\arm\kernel\calls.S 放在最后面

/* 350 */CALL(sys_timerfd)

CALL(sys_eventfd)

CALL(sys_hello)/* 添加一个自己的系统调用 */

构造sys_hello

仿照sys_write声明定义在include\linux\syscalls.h和fs\read_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]='\0';

printk("sys_hello:%s\n",ker_buf);

}

}

应用程序调用SWI

参考glibc-2.3.6/,这里没去仔细看了,这里有个__brk函数,仿照着写,具体看下注释

#include

#include

#define __NR_SYSCALL_BASE0x900000

void hello(char *buf, int count)

{

/* swi */

asm ("mov r0, %0\n" /* save the argment in r0 */

"mov r1, %1\n" /* save the argment in r0 */

"swi %2\n" /* do the system call */

/* 输出部分,这里不需要输出,但是需要 : 占位*/

:

/* 输入部分, r表示寄存器 ,使用 %0 表示第一个*/

/* %0 %1 i表示立即数,也是就是Immediate 这里就是 swi的具体的值 */

: "r"(buf), "r"(count), "i" (__NR_SYSCALL_BASE + 352)

/* 损坏部,指令执行过程中可能引起的哪些寄存器发生变化*/

: "r0", "r1");

}

int main(int argc, char **argv)

{

printf("in app, call hello\n");

hello("hello", 6);

return 0;

}

嵌入汇编语法

参考文件cnblog,这里不去仔细分析了,简单的分析在韦老师视频31课4.1节25分左右

参考linux内核源代码情景分析1.5.2节)

格式如下所示:

asm( 指令部 : 输出部 : 输入部 : 损坏部 );

如果没有的部分,冒号也不能省略

指令部

在指令部中,若出现%0、%1、%2等,则表示指令部后面的第几个变量.

比如上面代码的mov r0, %0\n

其中%0便会对应buf值,而r是一个约束条件字母,r表示任意一个寄存器,在预处理时,便会自动分配一个寄存器,将buf值放入该寄存器里,然后运行mov r0 (buf对应的寄存器)

输出部

每个输出部的约束条件字母都要加上"=",比如:

int num=5,val;

asm("mov %0,%1\n"

:"=r"(val) //指定val是一个输出部,执行mov后,val便等于5

:"i"(num) // "i"约束条件字母,表示num是一个立即数

: );

输入部

和输出部唯一不同的就是,在约束条件字母前不能加上=

常用的约束条件字母,如下图所示:

ebec38b5c003624d6ace7b23028e59f8.png

损坏部

和输入输出类似,一般用来处理操作的中间过程,因为这些原有的内容都会被损坏,比如上面的hello()里的r0, r1,只是用来当做参数,传递给内核的sys_hello()

测试APP

# mount -t nfs -o nolock,vers=2 192.168.95.222:/home/book/stu /mnt

# cd /mnt/code

# ./test_system_call

in app, call hello

sys_hello:hello # 这个“hello” 是系统调用打印的

参考

驱动调试&lpar;四&rpar;oops确定调用树

目录 驱动调试(四)oops确定调用树 内核开启调用树 栈指针分析 原理 寄存器别名 基础解释 例子分析 找到PC地址的位置 栈分析 附录:原文的excel title: 驱动调试(四)oops确定调 ...

42&period;Linux应用调试-初步制作系统调用&lpar;用户态-&gt&semi;内核态&rpar;

1首先来讲讲应用程序如何实现系统调用(用户态->内核态)? 我们以应用程序的write()函数为例: 1)首先用户态的write()函数会进入glibc库,里面会将write()转换为swi(S ...

Linux内核分析 笔记四 系统调用的三个层次 ——by王玥

一.知识点总结 (一)用户态.内核态和中断 1.内核态:在高的执行级别下,代码可以执行特权指令,访问任意的物理地址,这时的CPU就对应内核态 2.用户态:在低级别的指令状态下,代码 只能在级别允许的特 ...

Socket与系统调用深层分析

实验背景: Socket API编程接口之上可以编写基于不同网络协议的应用程序: Socket接口在用户态通过系统调用机制进入内核: 内核中将系统调用作为一个特殊的中断来处理,以socket相关系统调 ...

GDB调试系列之了解GDB

想要熟练利用GDB进行程序调试,首先要了解什么是GDB. 1. 什么是GDB GDB (the GNU Project Debugger) 是一个可以运行在大多数常见的UNIX架构.Windows.M ...

&lbrack;转&rsqb;Android逆向之动态调试总结

一.在SO中关键函数上下断点 刚学逆向调试时.大多都满足于在SO中某关键函数上下断点.然后通过操作应用程序,去触发这个断点,然后进行调试 详细的步骤可以参见非虫大大的

使用IntelliJ IDEA(PHPStorm)和xdebug在firefox、chrome中远程调试PHP

很多PHP程序员都习惯于使用echo.var_dump和exit来中断和调试web应用程序,本文主要介绍结合xdebug.IntelliJ IDEA.Firefox/chrome/IE来远程调试PHP ...

vscode 学习笔记 —— 调试 &lpar;以 node 为例&rpar;

一.建立配置文件 1.选择你的项目 2.选择你项目的语言 3.当前项目路径下生成 .vscode/launch.json { // Use IntelliSense to learn about po ...

如何调试触发器-MSSQL &lpar;转帖&rpar;

调试触发器 //------------------------------------- 作者:四海为圈(原创) //------------------------------------- 1. ...

随机推荐

带你实现开发者头条APP&lpar;四&rpar;---首页优化&lpar;加入design包&rpar;

title: 带你实现开发者头条APP(四)---首页优化(加入design包) tags: design,Toolbar,TabLayout,RecyclerView grammar_cjkRuby ...

LeetCode 27 Remove Element

Problem: Given an array and a value, remove all instances of that value in place and return the new ...

c&num; 6&period;0新特性(一)

写在前面 接近年底了,基本上没什么活了,就学点新东西,就想着了解下c# 6.0的新特性.在code project上看到了一篇不错的文章,就准备翻译一下,顺便照着学习学习.废话不多说,直奔主题. 原文 ...

C&num; Dispose Finalize

比较值得参考的文档:http://www.jb51.net/article/37214.htm. .NET 的内存管理过程: 托管堆假设内存无限大,线性连续分配内存: 实际内存不够使用时,遍历托管堆对 ...

每天进步一点点——Linux系统时间来处理

转载请注明出处:http://blog.csdn.net/cywosp/article/details/25839551 在程序中时间处理往往是一个麻烦的事.Linux系统提供了非常多关于时间处理的函 ...

linux 查看磁盘、文件夹、文件大小&lpar;df du&rpar;

du 查看文件夹大小 1.查看当前文件夹中所有文件夹及其子文件夹的大小,注意是文件夹大小,不是文件 # du -h -rw-r--r-- 1 root root 82785865 6月 9 15:53 ...

Apache中的gzip压缩作用及配置

gzip会对文本资源进行压缩,一般能节省40%的大小,二进制内容不需要开启Gzip压缩,因为这些文件是已经压缩过的,如果再进行gzip压缩可能反而会增加其大小,并且空耗cpu资源啊. 静态资源一般都会 ...

web&period;xml的&lt&semi;url-parttern&gt&semi;的匹配规则

顾名思义是对url(统一资源定位符)的一种匹配,是对“http:........."地址的匹配,但是会减去应用上下文,就是你的web程序的名字,如果你 ...

JVM基础系列第4讲:从源代码到机器码,发生了什么?

在上篇文章我们聊到,无论什么语言写的代码,其到最后都是通过机器码运行的,无一例外.那么对于 Java 语言来说,其从源代码到机器码,这中间到底发生了什么呢?这就是今天我们要聊的. 如下图所示,编译器可 ...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值