1 翻译缓存

qemu中翻译缓存是一块连续的内存单元,使用全局变量code_gen_buffer保存其首地址,缓存大小由全局变量code_gen_buffer_size指示;全局变量code_gen_ptr指示当前未使用的缓存地址。
static uint8_t *code_gen_buffer;
static unsigned long code_gen_buffer_size;
static uint8_t *code_gen_ptr;

这片内存可以采用静态分配方式,也可以采用动态分配方式,前者将code_gen_buffer指向静态分配的空间,后者将code_gen_buffer指向动态分配的空间。编译时由宏USE_STATIC_CODE_GEN_BUFFER控制选用那种方式。
#ifdef USE_STATIC_CODE_GEN_BUFFER
code_gen_buffer = static_code_gen_buffer;
code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
map_exec(code_gen_buffer, code_gen_buffer_size);
#else
...
code_gen_buffer = qemu_malloc(code_gen_buffer_size);
map_exec(code_gen_buffer, code_gen_buffer_size);
#endif

2 翻译块存储

翻译块用一块连续的存储空间存放,采用动态申请的方式,用全局变量tbs保存返回值,一次申请全部的空间,空间大小由全局变量code_gen_max_blocks决定。
static TranslationBlock *tbs;
static int code_gen_max_blocks;

code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));

3 翻译块的结构

struct TranslationBlock {
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
target_ulong cs_base; /* CS base for this block */
uint64_t flags; /* flags defining in which context the code was generated */
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint16_t cflags; /* compile flags */
#define CF_COUNT_MASK 0x7fff
#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */

uint8_t *tc_ptr; /* pointer to the translated code */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* first and second physical page containing code. The lower bit
of the pointer tells the index in page_next[] */
struct TranslationBlock *page_next[2];
tb_page_addr_t page_addr[2];

/* the following data are used to directly call another TB from
the code of this one. */
uint16_t tb_next_offset[2]; /* offset of original jump target */
#ifdef USE_DIRECT_JUMP
uint16_t tb_jmp_offset[2]; /* offset of jump instruction */
#else
unsigned long tb_next[2]; /* address of jump generated code */
#endif
/* list of TBs jumping to this one. This is a circular list using
the two least significant bits of the pointers to tell what is
the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
jmp_first */
struct TranslationBlock *jmp_next[2];
struct TranslationBlock *jmp_first;
uint32_t icount;
};

其中tc_ptr指向翻译块对应存放在翻译缓存中的翻译码;
jmp_first与jmp_next构成了循环链表,该链表既包含跳向当前TB的信息,也包含当前TB的跳转信息。这个循环链表是怎么构建的呢?设计者巧妙利用了jmp_next[n]与jmp_first的低两位,由于指针是4地址对齐,正常情况低两位为0,于是就用这两位指示那个是后继指针。
请看下面函数:
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
/* NOTE: this test is only needed for thread safety */
if (!tb->jmp_next[n]) {
/* patch the native jump address */
tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);

/* add in TB jmp circular list */
tb->jmp_next[n] = tb_next->jmp_first;
tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
}
}
下面举例说明,假设tb1,tb2,tb3是未建立任何跳转关系的TB,注意此时
tb1->jmp_first为(TranslationBlock*)((long)(tb1) | 2);
tb2->jmp_first为(TranslationBlock*)((long)(tb2) | 2);
tb3->jmp_first为(TranslationBlock*)((long)(tb3) | 2);
在n=0情况下,如果tb2,tb3均跳转到tb1,执行语句
(1) tb_add_jump(tb2, 0, tb1);
(2) tb_add_jump(tb3, 0, tb1);
(3) tb_add_jump(tb2, 1, tb1);
语句(1)执行后,
tb2->jmp_next[0] = tb1->jmp_first;//即 (TranslationBlock*)((long)(tb1) | 2);
tb1->jmp_first = (TranslationBlock*)((long)(tb2) | 0);
语句(2)执行后,
tb3->jmp_next[0] = tb1->jmp_first;//即(TranslationBlock*)((long)(tb2) | 0);
tb1->jmp_first = (TranslationBlock*)((long)(tb3) | 0);
语句(3)执行后,
tb2->jmp_next[1] = tb1->jmp_first;//即(TranslationBlock*)((long)(tb3) | 0);
tb1->jmp_first = (TranslationBlock*)((long)(tb2) | 1);
这时构建的循环链表节点是:
tb1, tb1->jmp_first, tb2->jmp_next[1], tb3->jmp_next[0], tb2->jmp_next[0]
即tb1-->tb2(1)-->tb3(0)-->tb2(0)-->tb1(2)

从上述例子不难看出,循环链表包含了两方面的信息,一是跳向TB块的TB信息,如跳向tb1的TB块有tb3和tb2;二是TB块沿着一条链路跳向了那个节点,如tb3着链路0跳向了tb1,tb2沿着链路0、1均能跳到tb1.

4 TB的分配与释放

分配与释放函数分别是tb_alloc, tb_free函数,它们并不真正进行内存的申请与释放,只是对code_gen_ptr与nb_tbs进行增减操作。

5 TB相互间链接信息的删除

当一个TB无效时,需要清除与它有关的链接信息,一是要清除TB的跳转信息,二是要清除跳向该TB的信息。
清除TB的跳转信息用下面语句,先后清除两条链路上的信息:
tb_jmp_remove(tb, 0);
tb_jmp_remove(tb, 1);
函数tb_jmp_remove声明如下:
static inline void tb_jmp_remove(TranslationBlock *tb, int n);
实现过程是从tb的jmp_next[n]开始遍历n链路循环链表,当找到待清除节点且n值匹配时将其从链表中移出。如上例中执行语句tb_jmp_remove(tb2, 0);后链表变为:
tb1-->tb2(1)-->tb3(0)-->tb1(2)
执行语句tb_jmp_remove(tb2, 1);后链表变为:
tb1-->tb3(0)-->tb1(2)

清除跳向该TB的信息则比较容易,沿着jmp_first链表逐个移除,知道遇到低两位bit值为2的指针,这是循环链表遍历完的标志。

QEMU翻译块(TB)分析相关推荐

  1. linux提取基因名称和序列,一种批量提取基因组基因信息并翻译比对分析序列的方法与流程...

    技术特征: 1.一种批量提取基因组基因信息并翻译比对分析序列的方法,其特征在于,将某一物种的转录本id或者基因id,依据供试基因组cds文件.蛋白质文件.gff文件和染色体fasta文件信息,通过6个 ...

  2. matlab patch 六面体,《有限元基础教程》_【MATLAB算例】4.8.2(1) 基于8节点六面体单元的空间块体分析(Hexahedral3D8Node)...

    [MATLAB 算例]4.8.2(1) 基于8节点六面体单元的空间块体分析(Hexahedral3D8Node) 如图4-23所示的一个空间块体,在右端部受两个集中力F 作用,其中的参数为: 1051 ...

  3. druid.io 海量实时OLAP数据仓库 (翻译+总结) (1)——分析框架如hive或者redshift(MPPDB)、ES等...

    介绍 我是NDPmedia公司的大数据OLAP的资深高级工程师, 专注于OLAP领域, 现将一个成熟的可靠的高性能的海量实时OLAP数据仓库介绍给大家: druid.io NDPmedia在2014年 ...

  4. 使用python对在线网易有道翻译接口进行分析及破解js加密

    文章目录 项目目标 温馨提示 项目分析 分析完毕,进行代码模拟加密过程,代码演示 项目目标 对网易有道翻译接口关键参数进行分析,并且进行js加密破解,实质上就是找出网易有道翻译接口对关键参数的加密的详 ...

  5. 有道翻译 爬虫,分析反爬 附代码

    有道翻译 爬虫,破解反爬加密 0引言 1准备工作 开始第一部分 开始第二部分 准备工作,下载并安装requests模块 确定反爬用的变量 确定变量的值 requests模块的使用 0引言 我在这里会很 ...

  6. hive olap 数据仓库_druid.io 海量实时OLAP数据仓库 (翻译+总结) (1)——分析框架如hive或者redshift(MPPDB)、ES等...

    介绍 我是NDPmedia公司的大数据OLAP的资深高级工程师, 专注于OLAP领域, 现将一个成熟的可靠的高性能的海量实时OLAP数据仓库介绍给大家: druid.io druid是个很新的平台, ...

  7. 翻译—使用Python分析离散心率信号–第1部分

    此文为翻译+自己的理解,github地址:https://github.com/paulvangentcom/heartrate_analysis_python 第1部分:打开数据,检测第一个峰并计算 ...

  8. (3)雅思屠鸭第三天:六种简单句翻译与句子成分分析

    前言 打基础部分,要一直持续一个多月,这部分主要涉及的还是听说读写四部分所需要的词汇与语法. 文章内容主要是今日所有课程的笔记.今天的重点是语法部分. 我自己总是习惯轻视语法.结果学习了这么多年的英语 ...

  9. 20220209-CTF MISC-BUUCTF-伪加密(ZIP文件块 十六进制分析)

    MISC-BUUCTF-zip伪加密 [1]下载附件提示要求输入解压密码 在Windows环境下可以看到有一个flag.txt 但是打开flag.txt需要输入密码: 如果用winhex打开,也可以看 ...

最新文章

  1. linux平台下防火墙iptables原理(转)
  2. OSPF LSA 类型
  3. LuoguP1948 电话线 【二分答案/图论】
  4. 3DSlicer23:Module-Create Loadable
  5. 打不开开php_(13)10个开源免费的PHP博客CMS
  6. 物联网 ToB 的背后,开发者应了解什么?| CSDN 博文精选
  7. 【图像去噪】基于matlab即插即用法图像去噪【含Matlab源码 152期】
  8. 百度下半年惩罚网站的低质量,坏消息到来硕士
  9. 基于echarts实现非常规可视化图表
  10. 基于python的计算基因组_【ROSALIND】【练Python,学生信】05 计算DNA序列GC含量
  11. android 模拟点击menu键,android编程之menu按键功能实现方法
  12. Sator提供其Orca流动性池的六周,增长更新一览
  13. VMware中性能分配的问题
  14. 在AWS Lambda上部署标准FFmpeg工具——Docker方案
  15. SQL48 将所有获取奖金的员工当前的薪水增加10%
  16. 数据结构考研大纲浅析
  17. 上号神器,穿越火线扫码登录教程
  18. Android拖动实现(一个流畅的拖动排序DragSortGridView,自动滚屏)
  19. Android支付接入(七):Google In-app-Billing
  20. 无痕埋点在Android中的实现

热门文章

  1. TM1652控制-2
  2. 程序员只能吃青春饭?3条晋升之路帮你摆脱程序员中年魔咒!
  3. html scale属性,scale() | CSS属性参考
  4. AndroidStudio SSL peer shut down incorrectly 问题
  5. Python爬取wallhaven壁纸 2023.1.31
  6. 计算机仿真技术生物,基于计算机仿真技术的人体生理特性和病理机制研究
  7. 读书笔记:《流畅的Python》第17章 使用future处理并发
  8. 模拟浏览器整理电影榜单
  9. 将英文kali改成中文kali
  10. 科学计算机怎么玩游戏,计算机也能玩文本游戏