//函数原型:版本号linux-3.0.8

struct task_struct *__switch_to(structtask_struct *, struct thread_info *, struct thread_info *);

#define switch_to(prev,next,last)                                       \

do {                                                                   \

last =__switch_to(prev,task_thread_info(prev), task_thread_info(next));        \

} while (0)

//首先我们看一下以下的宏:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)

//以下事实上就是指向相应的struct成员

/*

CC_STACKPROTECT补丁是Tejun Heo在年给主线kernel提交的一个用来防止内核堆栈溢出的补丁。

默认的config是将这个选项关闭的,能够在编译内核的时候。改动.config文件为CONFIG_CC_STACKPROTECTOR=y

来启用。未来飞天内核能够将这个选项开启来防止利用内核stack溢出的day攻击。这个补丁的防

溢出原理是:在进程启动的时候,在每一个buffer的后面放置一个预先设置好的stack canary。你

能够把它理解成一个哨兵,当buffer发生缓冲区溢出的时候。肯定会破坏stack canary的值,当

stack canary的值被破坏的时候。内核就会直接当机。

那么是怎么推断stack canary被覆盖了呢?

事实上这个事情是gcc来做的,内核在编译的时候给gcc加了个-fstack-protector參数.

*/

DEFINE(TSK_STACK_CANARY,     offsetof(struct task_struct,stack_canary));

//task_struct

DEFINE(TI_TASK,              offsetof(struct thread_info, task));

//

/*

* Domain types

*/

/*

#define DOMAIN_NOACCESS 0

#define DOMAIN_CLIENT  1//是用户的域(运行程序,訪问数据),以及由所述接入加以防护

//个别章节和页面组成域的权限。

#ifdef CONFIG_CPU_USE_DOMAINS

#define DOMAIN_MANAGER 3//控制域的行为(当前域的sections和page。以及域訪问)。

#else

#define DOMAIN_MANAGER 1

#endif

*/

//相应图

//这个domain通过协处理器设置寄存器DomainAccess Control

DEFINE(TI_CPU_DOMAIN,        offsetof(struct thread_info,cpu_domain));

/*

struct cpu_context_save {

__u32   r4;

__u32   r5;

__u32   r6;

__u32   r7;

__u32   r8;

__u32   r9;

__u32   sl;

__u32   fp;

__u32   sp;

__u32   pc;

__u32   extra[2];               /* Xscale 'acc' register, etc */

};

*/

DEFINE(TI_CPU_SAVE,          offsetof(struct thread_info,cpu_context));

/*

在以下有个set_tls,相应我的平台set_tls_v6k

.macroset_tls_v6k, tp, tmp1, tmp2

mcr     p15, 0, \tp, c13, c0, 3         @ set TLS register

.endm

tp_value就是为了设置TLS register的值

在多线程应用程序。当中一个进程共享同样的地址空间中的全部线程。还有常常出现须要维护的数据是唯一

的一个线程。TLS或线程本地存储。由于你或许能够从它的名字如今弄清楚。是用于线程抽象的概念。它是

一种高速和有效的方式来存储每一个线程的本地数据。

线程的本地数据的偏移量是通过TLS寄存器(H / W或S

/ W块),它指向线程各自的线程控制块訪问。

之前ARM内核。甚至ARM9和ARM11核心的一些不具备这样的TLS注冊物理上可用。

操作系统(Linux从这里開始)

须要效仿的软件。新一代的ARM内核。Cortex-AX起,确实有这TLS的寄存器可用(CP15)。

内核对TLS须要做的事情是可以让用户态程序(一般是nptl——一个pthread的实现)在某个时刻可以设置

线程唯一的基址值到内核的线程信息结构内。

*/

DEFINE(TI_TP_VALUE,          offsetof(struct thread_info, tp_value));

/*

* These are the reasoncodes for the thread notifier.

*/

#define THREAD_NOTIFY_FLUSH    0

#define THREAD_NOTIFY_EXIT     1

#define THREAD_NOTIFY_SWITCH   2

#define THREAD_NOTIFY_COPY     3

/** Register switch for ARMv3 and ARMv4 processors* r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info* previous and next are guaranteed not to be the same.*/
ENTRY(__switch_to)UNWIND(.fnstart        )UNWIND(.cantunwind     )//ip就是上一个线程的thread_info里面的cpu_context的地址add     ip, r1, #TI_CPU_SAVE//r3里面存着下一个线程tp值ldr     r3, [r2, #TI_TP_VALUE]//存储r4 - sl, fp, sp, lr到thread_info->cpu_context里。

分别使用arm和thumb实现 //这就是保存现场。 ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack THUMB( str sp, [ip], #4 ) THUMB( str lr, [ip], #4 ) #ifdef CONFIG_CPU_USE_DOMAINS //r6存着下一个线程的DOMAIN属性 ldr r6, [r2, #TI_CPU_DOMAIN] #endif //set_tls 上面已分析 set_tls r3, r4, r5 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) ldr r7, [r2, #TI_TASK]//下一个线程的task_struct ldr r8, =__stack_chk_guard//r8里面是__stack_chk_guard地址 ldr r7, [r7, #TSK_STACK_CANARY]//到这里。r7里面是stack_canary值 #endif #ifdef CONFIG_CPU_USE_DOMAINS //设置domain寄存器。 mcr p15, 0, r6, c3, c0, 0 @ Set domain register #endif //r5里面是上一个线程的task_struct mov r5, r0 //r4就是下一个线程的thread_info里面的cpu_context的地址 add r4, r2, #TI_CPU_SAVE //r4 r5仅仅是暂时保存一下 //以下的thread_notify_head通知链,以下样例说明 ldr r0, =thread_notify_head mov r1, #THREAD_NOTIFY_SWITCH bl atomic_notifier_call_chain #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) str r7, [r8]//__stack_chk_guard = (next)threadinfo->task->stack_canary #endif THUMB( mov ip, r4 )//ip指向线程的thread_info里面的cpu_context的地址 mov r0, r5//r0从新指向上一个线程的task_struct //以下相应了上面的保存现场,这里就是恢复现场。

pc相应了下个进程的cpu_context->pc //从上面看到这个cpu_context->pc就是之前保存现场的lr,就是下个线程要运行的地方。 ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously THUMB( ldr sp, [ip], #4 ) THUMB( ldr pc, [ip] ) UNWIND(.fnend ) ENDPROC(__switch_to)

实验代码:

#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/module.h>
#include <asm/thread_notify.h>MODULE_LICENSE("GPL");static int test_event(struct notifier_block *this, unsigned long event, void *ptr)
{printk(KERN_INFO "In Event: Event Number is %ld\n",event);return NOTIFY_DONE;
}static struct notifier_block test_notifier =
{.notifier_call = test_event,
};static int __init reg_notifier(void)
{int err = 0;printk(KERN_INFO "Begin to register:\n");err = thread_register_notifier(&test_notifier);if (err){printk(KERN_ERR "register test_notifier error\n");goto fail1;}printk(KERN_INFO "register reboot_notifier completed\n");return 0;fail1:return err;
}static void __exit unreg_notifier(void)
{thread_unregister_notifier(&test_notifier);printk(KERN_INFO "Unregister finished\n");
}module_init(reg_notifier);
module_exit(unreg_notifier);

打印:

2都是THREAD_NOTIFY_SWITCH,当然会不断的切换!

转载于:https://www.cnblogs.com/gcczhongduan/p/5071882.html

具体分析contrex-A9的汇编代码__switch_to(进程切换)相关推荐

  1. 分析一个简单的汇编代码

    分析一个简单的汇编代码 部分常见的寄存器 寄存器 16位 32位 64位 累加寄存器 AX EAX RAX 基址寄存器 BX EBX RBX 计数寄存器 CX ECX RCX 数据寄存器 DX EDX ...

  2. 详细分析contrex-A9的汇编代码__switch_to(进程切换)

    //函数原型:版本linux-3.0.8 struct task_struct *__switch_to(structtask_struct *, struct thread_info *, stru ...

  3. 【Android 逆向】arm 汇编 ( 使用 IDA 解析 arm 架构的动态库文件 | 使用 IDA 打开 arm 动态库文件 | 切换 IDA 中汇编代码显示样式 )

    文章目录 一.使用 IDA 打开 arm 动态库文件 二.切换 IDA 中汇编代码显示样式 一.使用 IDA 打开 arm 动态库文件 分析 Android SDK 中的 arm 架构的动态库 , 动 ...

  4. 理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和进程切换

    学号:384 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ 实验目标 1.分析fork函数对应的内核处理过程do_fork,理解创建一个 ...

  5. Linux进程调用execve,实验:从整理上理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和...

    学号375 转载请注明出处 https://github.com/mengning/linuxkernel/ 阅读理解task_struct数据结构 task_struct实际上就是进程PCB以下是p ...

  6. 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    实验目的: 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 实验过程: 通过vi程序进行编程: int g(int x) { return x + 3; } int f(int x) ...

  7. c理c利用计算机怎么弹,通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的...

    通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 计算机的工作方式: 现代计算机的基本体系结构都是采用冯诺依曼结构,冯诺依曼的设计思想最重要之处是"存储程序"的这个概念 ...

  8. C++实现的利用LR(1)分析表对赋值表达式进行语法制导翻译生成四元式及汇编代码

    赋值语句的语法制导翻译 后续已完善算术运算文法.赋值文法.布尔运算文法.if.while.do-while和复合语句文法,编译器项目已上传GitHub,https://github.com/sleep ...

  9. Linux内核汇编代码分析

    Linux内核汇编代码分析 1.vmlinux.lds.S文件分析 1.2 vmlinux.lds.S文件总体框架 1.3 代码段 1.4 只读数据段 1.5 init段 1.6 数据段 1.7 未初 ...

最新文章

  1. 目标检测的常用数据处理方法!
  2. Mac上Homebrew的使用
  3. Java2WSDL 和 WSDL2Java(Axis)
  4. 火了,挡不住了:Facebook Move编程语言入门
  5. Debian部署postgresql并允许远程连接
  6. 【机器学习算法专题(蓄力计划)】十、机器学习中必备的高等数学和线性代数基础
  7. 2021广州黄冈中学高考成绩查询,黄冈中学广州学校2019高考成绩喜报、本科重本上线人数情况...
  8. OpenGL® ES 3.0 Programming Guide - Book Website
  9. 腾讯招.NET,居然要求精通MySQL,而不是SQLServer!
  10. JMeter场景设置与监控
  11. python标准输入_Python 处理标准输入
  12. sql server 锁与事务拨云见日(下)
  13. php 自减函数,Thinkphp中某个字段值从增或自减函数
  14. 剑指offer面试题[9-3]-矩形覆盖
  15. Java编程:栈的应用实例——逆波兰计算器
  16. AMOS问卷数据建模前传【SPSS 052期】
  17. Petya到底是个什么鬼
  18. phpcms代码学习笔记(globle.function.php)
  19. selenium自动化学习--截取长图的方法
  20. SCRUM浅谈,User Story,Sprint,Burn Down Chart

热门文章

  1. 最新 在线下载谷歌play apk 地址
  2. 制作手机远程控制开关
  3. python批量文件重命名
  4. 外贸人需要准备的浏览器插件有哪些?
  5. 最后1天,包邮送50豆瓣高分Python 好书
  6. React Demo Three - 简书掘金
  7. 量子计算机科学家,再破纪录!中国科学家实现18个量子比特纠缠 为量子计算机奠基...
  8. 操作系统基本原理 操作系统的功能
  9. 专题:拓扑排序(Topological sort)模式
  10. 互联网快讯:米巴资本完成首期美元基金募集;极米投影产品双十一持续热销;SpaceX星链成立印度子公司