一、中断向量表介绍

中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
以上是中断在百度百科中些较为浅显的解释,中断实际上是操作系统中较为重要的一种概念及机制,关于中断的一些详细的说明可以在由张银奎老师主讲的《在调试器下理解计算系统》中观看到(视频在nano code中;下载链接:Nano Code下载)。
        上面提到“转入处理新情况的程序”,那么中断后,该如何确定这个新程序呢?这时候就需要系统的中断向量表了,中断描述符表中存储了中断的相关信息,当CPU被中断后,CPU会获取中断向量,然后查阅这张表,找到对应的中断信息,然后根据中断信息跳去相应的位置处理事情。
        今天我们就来详细研究一下ARM框架下的中断向量表。并编写代码把向量表以友好的方式解析出来。


二、查看中断向量表

那么该如何查看中断向量表呢?在ARM框架下系统寄存器VBAR_EL1(Vector Base Address Register)指向的就是中断向量表。

1 . 在Nano Code中获取VBAR_EL1寄存器的地址。

rdmsr VBAR_EL1

2 . 解析这个地址,获取该地址处指令和函数。

ln ffffff8008081800

3 . 此时,我们可以在代码中根据这个函数找到它的地址,编写跨内核版本的代码。

ULONG64 VBAR_EL1_ADDR;
// 获取 lk!vectors 函数的地址,并把地址存储到 变量 VBAR_EL1_ADDR 中
GetExpressionEx("lk!vectors", &VBAR_EL1_ADDR, NULL);

三、解析中断向量表

参考和引用

寄存器VBAR_EL1指向的是中断向量表。其中不同向量表间的偏移量、中断类型、中断级别可以参考下图。

(reference:Anatomy of Linux system call in ARM64 | East River Village)

Offset from VBAR_EL1

Exception type

Exception set level

+0x000

Synchronous

Current EL with SP0

+0x080

IRQ/vIRQ

+0x100

FIQ/vFIQ

+0x180

SError/vSError

+0x200

Synchronous

Current EL with SPx

+0x280

IRQ/vIRQ

+0x300

FIQ/vFIQ

+0x380

SError/vSError

+0x400

Synchronous

Lower EL using ARM64

+0x480

IRQ/vIRQ

+0x500

FIQ/vFIQ

+0x580

SError/vSError

+0x600

Synchronous

Lower EL with ARM32

+0x680

IRQ/vIRQ

+0x700

FIQ/vFIQ

+0x780

SError/vSError

稍加分析,可以看到,总共有16张中断向量表,其中:

  • 每个表都占用128字节(十六进制0x80就是十进制128),
  • 每张向量表最多存放32条大小为4字节的汇编指令,
  • 每张向量表的起始地址都是VBAR_EL1 + n * 0x80 (n的取值范围 [0, 15])。

再对照下图内核源码:可以看到源码和上图表格中的分析是一一对应的。

源码Website:kernel/entry.S at main · gdk8/kernel (github.com)

ENTRY(vectors)kernel_ventry   1, sync_invalid         // Synchronous EL1tkernel_ventry   1, irq_invalid          // IRQ EL1tkernel_ventry   1, fiq_invalid          // FIQ EL1tkernel_ventry   1, error_invalid        // Error EL1tkernel_ventry   1, sync                 // Synchronous EL1hkernel_ventry   1, irq                  // IRQ EL1hkernel_ventry   1, fiq_invalid          // FIQ EL1hkernel_ventry   1, error                // Error EL1hkernel_ventry   0, sync                 // Synchronous 64-bit EL0kernel_ventry   0, irq                  // IRQ 64-bit EL0kernel_ventry   0, fiq_invalid          // FIQ 64-bit EL0kernel_ventry   0, error                // Error 64-bit EL0#ifdef CONFIG_COMPATkernel_ventry   0, sync_compat, 32      // Synchronous 32-bit EL0kernel_ventry   0, irq_compat, 32       // IRQ 32-bit EL0kernel_ventry   0, fiq_invalid_compat, 32   // FIQ 32-bit EL0kernel_ventry   0, error_compat, 32     // Error 32-bit EL0
#elsekernel_ventry   0, sync_invalid, 32     // Synchronous 32-bit EL0kernel_ventry   0, irq_invalid, 32      // IRQ 32-bit EL0kernel_ventry   0, fiq_invalid, 32      // FIQ 32-bit EL0kernel_ventry   0, error_invalid, 32    // Error 32-bit EL0
#endif
END(vectors)

开始解析

1、第一层解析:解析第一层向量表。

向量表之所以称之为表,说明他们内部含有其他数据,数据排列像表格一样。这里我们把sync看作第一层向量表,并对表sync进行解析。

a . 查看向量表的详情信息,根据偏移量0x200确定某个表的的起始地址,表sync的起始地址为VBAR_EL1+0x200,也就是 ffffff8008081800+0x200 。

b . 使用命令u来逐页查看该地址处的汇编指令。

u uffffff8008081800+0x200


再次输入u,会按照每页8条指令继续解析。

2、在表sync中寻找第二层向量表。

在表sync中所有汇编指令中,我们要找的是与函数跳转挂钩的指令,例如 b 或者 b.eq 或者 bl,解析b 的参数,解析出的函数名就是我们寻找的第二层向量表。

这里以解析黄圈内的地址为例

// 根据地址来获取函数名
ln 0xffffff8008082ac0// 解析地址处的汇编指令
u 0xffffff8008082ac0

此时我们了解到 地址 0xffffff8008082ac0处存放的是 el1_sync函数,该函数就是我们寻找的第二层向量表。

3、第二层解析:对照Linux内核源码,按照内核的逻辑解析第二层向量表el1_sync。

a . 在内核源码中查找该函数,查看其结构和逻辑。

b . 使用指令u在Nano Code中找到与源码对应的部分。

在解析向量表时,我们要显示出内核原本的逻辑和结构,例如解析 el1_sync函数时可以按照以下格式输出:

0x25: lk!el1_da
0x21: lk!el1_ia

按照这种输出格式,依次解析剩余的部分。

c . 到这里我们已经解析了三层了,当然还可以继续追根溯源,但是对于错误向量表的研究,这三层已经足够了。

4、根据以上研究,我们可以把向量表看作树形结构,并按照以下格式来输出。

5 . 每张向量表的处理方式都相似,我们按照上述方法依次处理16张总的向量表。


四、开发调试环境

  • 软件:NanoCode调试软件 (Website:Nano Code下载
  • 设备:GDK8套件(Website:GDK8) 挥码枪NTP(Website:NTP)
  • 关于NanoCode和GDK8的搭配使用,可以参考博客(GDK8——强大的Linux内核调试工具)
  • 代码中相关函数的使用可以参考微软官方:调试器概述 - Windows drivers | Microsoft Learn

五、牵扯到的函数

在NanoCode中可以使用 u、ln、x等命令可以很方便的解析相关信息,在代码中也有特定的函数与其对应。

函数的更多信息请参考微软官方:调试器概述 - Windows drivers | Microsoft Learn

下面是一些简单的用法:

typedef unsigned long long ULONG64;
void test(void)
{// GetExpressionEx :传入函数名称,获取该函数的地址。对应着NanoCode命令 xULONG64 VBAR_EL1_ADDR = 0;GetExpressionEx("lk!vectors", &VBAR_EL1_ADDR, NULL);dprintf("VBAR_EL1_ADDR: %p\n", VBAR_EL1_ADDR);// GetSymbol :根据传入的地址,获取函数名。对应着NanoCode命令 lnULONG64 FuncAddr = 0xffffff8008081800, SymOffset;char FuncName[50] = "";GetSymbol(FuncAddr, FuncName, &SymOffset);// Disasm :根据传入的地址,获取该地址处的一条汇编指令。对应着NanoCode命令 uchar Assembly[100] = "";ULONG64 Address = 0xffffff8008081800;Disasm(&Address, Assembly, 100);
}

通过GDK8观察ARM框架下的中断向量表相关推荐

  1. x86和arm框架下的centOS

    1 CPU架构分为 X86 , ARM ,MIPS , power , ia64 AMD64 = X86_64 = x64 ,是64位的CPU 架构,区分ARM64 1.x86 : 复制指令集cisc ...

  2. 如何在敏捷框架下做好工作交接

    这是一篇我最不想写的博客了.不过,随着部门里面一个可爱的小姑娘为了爱情不得不去上海工作同时也成功的拿到了SAP的offer,我不得不思考如何作好工作上的交接,毕竟法律规定的期限只有一个月的时间. 先说 ...

  3. Caffe使用step by step:caffe框架下的基本操作和分析

    Caffe使用step by step:caffe框架下的基本操作和分析 时间:2015-10-16 11:40:09      阅读:808      评论:0      收藏:0      [点我 ...

  4. 【阿里妈妈数据科学系列】第二篇:在线分流框架下的AB Test

    背景 AB Test 是为同一目标制定两个方案,在同一时间维度,保证其他条件一致的情况下,分析实验组跟对照组的区别,根据不同的实验类型以及应用场景,产生了不同分桶逻辑的AB Test,包括在线分流及离 ...

  5. 在线分流框架下的AB Test

    背景 AB Test 是为同一目标制定两个方案,在同一时间维度,保证其他条件一致的情况下,分析实验组跟对照组的区别,根据不同的实验类型以及应用场景,产生了不同分桶逻辑的AB Test,包括在线分流及离 ...

  6. Keras 和 Tensorflow 框架下五种视频分类

    目前视频分类是机器学习模式中独树一帜的挑战.今天我们就要来看看在Keras 和 Tensorflow 框架下的不同的视频行为识别策略,我们将会学着如何使用五深度学习的模式去学习UCF101数据组,具体 ...

  7. 深入剖析 RabbitMQ —— Spring 框架下实现 AMQP 高级消息队列协议

    前言 消息队列在现今数据量超大,并发量超高的系统中是十分常用的.本文将会对现时最常用到的几款消息队列框架 ActiveMQ.RabbitMQ.Kafka 进行分析对比. 详细介绍 RabbitMQ 在 ...

  8. 第14篇:Struts2框架下Log4j2漏洞检测方法分析与总结

     Part1 前言  Log4j2漏洞出现有大半年的时间了,这个核弹级别的漏洞危害很大,但是这个漏洞检测起来却很麻烦,因为黑盒测试无法预判网站哪个应用功能在后台调用了log4j2记录日志功能.目前通用 ...

  9. Scrapy框架下的海贼王漫画自动爬虫

    从小就是个海贼迷,学了爬虫后第一个上手自己写的爬虫自然而然就想到了爬海贼的漫画. 是在scrapy框架下写的爬虫,至于scrapy框架的安装就不多说了,网上有很多的安装教程. 前提准备 进到放置文件的 ...

最新文章

  1. 如何使用Python创建,读取,更新和搜索Excel文件
  2. 改变你的 KDE 桌面的外观和感觉方法介绍
  3. 安装配置Kali虚拟机----linux----kali
  4. php redbean update,redbeanphp和表前缀
  5. 自动生成文章的html,文章自动更新工具|自动生成文件|自动伪原创|文章自动插入关键词工具...
  6. easyui tree复选框是否打钩状态_实战PyQt5: 010-复选框控件QCheckBox
  7. python2和python3解释器的区别
  8. Java面试题:IO流中read()方法为什么返回值是int
  9. bzoj2752 高速公路
  10. 10.28-11.1-广州软件所-实习工作日记
  11. fastReport 绑定DataBand数据源后还是打印出一条数据
  12. python实现算法改进_运动目标检测vibe算法及其改进Python实现
  13. github客户端的使用
  14. 免费下载深度操作系统(deepin),三步快捷体验优秀国产操作系统
  15. python http请求时gzip解压
  16. 一些方便的LaTex在线编辑工具
  17. ubuntu安装git失败解决办法
  18. 无人船水下地形测量的应用及优势
  19. DDOS 攻击的防范教程
  20. Linux 下串口编程(C++ 程序设计)

热门文章

  1. gcc编译的四个过程
  2. 国内最值得关注的机器人底盘供应商
  3. 司法考试相关用书介绍,供大家参考
  4. 年末了,是该写点ww纪念acm…
  5. Baostock学习系列2:批量下载股市日交易明细
  6. ​5G套餐收费详情出炉,哪家划算?
  7. python—whl文件介绍与安装
  8. javafx实现聚光灯效果,圆形和矩形聚光灯效果,类似抠图效果
  9. C++多线程与信号signal
  10. 【微信小程序】运行机制和更新机制