搭建NEMU与QEMU的DiffTest环境(动态库方式)

搭建NEMU与QEMU的DiffTest环境(动态库方式)

  • 1 DiffTest原理简述
  • 2 编译NEMU
  • 3 编译qemu-dl-difftest
    • 3.1 修改NEMU/scripts/isa.mk
    • 3.2 修改NEMU/tools/qemu-dl-diff/src/diff-test.c
    • 3.3 修改NEMU/scripts/build.mk
    • 3.4 让qemu-dl-difftest带调试信息
    • 3.5 编译生成riscv64-qemu-so
  • 4 NEMU、动态库、QEMU之间的关系
  • 5 以difftest方式,运行NEMU
    • 5.1 坑1:dlopen失败
    • 5.2 坑2:xxx.debug文件

本文属于 《RISC-V指令集差分测试(DiffTest)系列教程》之一,欢迎查看其它文章。

环境:Ubuntu 18.04.5 LTS

1 DiffTest原理简述

DiffTest核心思想: 对于根据同一规范的两种实现, 给定相同的有定义的输入, 它们的行为应当一致。

如果,我们正在开发一款处理器或者模拟器,那么我们的指令集实现,可能存在无数错误,此时我们需要找一个标准实现,也就是参考对象(REF)。我们以该参考对象,进行指令级的一对一验证,以确保我们的处理器或模拟器,实现是正确的。

本文中,我们选择:

  • QEMU作为参考对象(REF)
  • NEMU作为测试对象(DUT)

当然,如果需要测试处理器硬件,那它也可以作为DUT。

2 编译NEMU

执行以下命令:

apt install build-essential man gcc gdb git libreadline-dev libsdl2-dev zstd libzstd-dev
git clone https://github.com/OpenXiangShan/NEMU.git
cd NEMU/
export NEMU_HOME=/home/test/NEMU    # /home/test/NEMU换成自己NEMU源码目录
make riscv64-benos_defconfig	    # riscv64-benos_defconfig需放入NEMU/configs/
make menuconfig

配置以下内容(让NEMU附带调试信息):

Build Options -> Optimization Level:选择O0,表示编译器不优化
Build Options -> Enable link-time optimization:取消选中,表示禁用链接时优化
Build Options -> Enable debug information:选中,表示使能调试信息

配置以下内容(开启动态库方式的DiffTest功能):

Testing and Debugging -> [*] Enable differential testing -> Reference design (QEMU, communicate with dynamic linking)

在NEMU/scripts/build.mk中,删除所有-Werror选项(否则编译报错),如下所示:

CFLAGS  := -O2 -MMD -Wall -Werror $(INCLUDES) $(CFLAGS)
CXXFLAGS  := -O2 -MMD -Wall -Werror --std=c++17 $(XINCLUDES) $(CFLAGS)

编译

make -j`nproc`

编译成功,生成NEMU/build/riscv64-nemu-interpreter可执行文件。

3 编译qemu-dl-difftest

3.1 修改NEMU/scripts/isa.mk

在NEMU/scripts/isa.mk中,将ISA ?= x86修改为ISA ?= riscv64,如下所示:

ISA ?= riscv64
ISAS = $(shell ls $(NEMU_HOME)/src/isa/)
ifeq ($(filter $(ISAS), $(ISA)), ) # ISA must be valid
$(error Invalid ISA=$(ISA). Supported: $(ISAS))
endif
NAME := $(ISA)-$(NAME)
CFLAGS += -D__ISA_$(ISA)__=1

3.2 修改NEMU/tools/qemu-dl-diff/src/diff-test.c

在NEMU/tools/qemu-dl-diff/src/diff-test.c中,将isa_raise_intr(NO);注释掉。

void difftest_raise_intr(uint64_t NO) {
	//  isa_raise_intr(NO);
}

这个函数在NEMU/tools/qemu-dl-diff/src/isa/x86/intr.c中定义(riscv怎么会用x86的代码?这里没深究,直接注释掉,继续)。

3.3 修改NEMU/scripts/build.mk

在NEMU/scripts/build.mk中,在LDFLAGS末尾,添加-ldl

.DEFAULT_GOAL = app

ifdef SHARE
SO = -so
CFLAGS  += -fPIC -D_SHARE=1
LDFLAGS += -rdynamic -shared -fPIC -Wl,--no-undefined -lz -ldl
endif

注意:build.mk中有多处LDFLAGS,-ldl只能加在上文所示位置。

3.4 让qemu-dl-difftest带调试信息

在NEMU/scripts/build.mk中,将CFLAGS、CXXFLAGS、LDFLAGS中:

  • 所有-O2改为-O0
  • 并且在-O0后,增加-g

如下所示:

CFLAGS  := -O0 -g -MMD -Wall $(INCLUDES) $(CFLAGS)
CXXFLAGS  := -O0 -g -MMD -Wall --std=c++17 $(XINCLUDES) $(CFLAGS)
LDFLAGS := -O0 -g $(LDFLAGS)

3.5 编译生成riscv64-qemu-so

进入NEMU/tools/qemu-dl-difftest目录

cd tools/qemu-dl-difftest/

编译qemu-dl-difftest

make

在NEMU/tools/qemu-dl-diff/build目录下,生成riscv64-qemu-so动态库。

4 NEMU、动态库、QEMU之间的关系

在这里插入图片描述

首先,需要大致解释一下,NEMU、动态库、QEMU之间的关系和原理,如上图所示。

基本关系:

  • riscv64-qemu-so动态库,导出了difftest_xx系列函数。
  • qemu-system-riscv64可执行文件中,有cpu_xx、gdb_xx以及qemu_xx系列函数,会被动态库调用。
  • 基本关系就是,NEMU调用动态库,动态库再调用qemu-system-riscv64。

基本流程:

  • NEMU可执行程序riscv64-nemu-interpreter,通过调用dlopen函数加载riscv64-qemu-so,并将difftest_xx系列函数符号解析出来,以备后续调用。
  • 然后,NEMU调用difftest_init函数,进行初始化。
  • 在difftest_init函数中,会再次调用dlopen函数,去加载qemu-system-riscv64可执行文件,并解析cpu_xx、gdb_xx以及qemu_xx系列函数符号,这些函数符号,其实就是difftest_xx系列函数的底层实现代码。
  • 从qemu-system-riscv64文件中,解析的函数,就有main函数,随后difftest_init函数就会调用它,以启动qemu程序。
  • 随后,如果一切正常的话,就可以调用qemu函数,以实现指令结果比对了。

5 以difftest方式,运行NEMU

动态库启动qemu时,使用的启动参数(NEMU/tools/qemu-dl-diff/src/isa/riscv64/init.c),如下:

char *isa_qemu_argv[] = {
  "/usr/bin/qemu-system-riscv64",
  "-nographic", "-S", "-serial", "none", "-monitor", "none",
  NULL
};

因此,qemu路径,必须为/usr/bin/qemu-system-riscv64。

此外,还需要将benos_payload.bin、riscv64-qemu-so,均拷贝至NEMU/build目录下。

以difftest方式,运行NEMU:

./riscv64-nemu-interpreter -b benos_payload.bin -d ./riscv64-qemu-so

见证奇迹的时刻!!!

5.1 坑1:dlopen失败

哦豁,riscv64-qemu-so里面,dlopen打开/usr/bin/qemu-system-riscv64失败,报错信息:

cannot dynamically load executable

报错原因:dlopen是glibc库函数。我在老版机器上glibc 2.27,发现可以打开;在新版机器上glibc 2.31,发现打开失败;猜测是glibc版本问题,dlopen官方定义用途为打开so,这里用来打开可执行文件,新版glibc更严格,所以不允许这么用了?
解决办法:期间尝试dlopen劫持,以及移植重写dlopen函数,都挺麻烦的;暂时没什么好办法。

5.2 坑2:xxx.debug文件

因此,我回到老版系统上,这里dlopen打开成功,再次运行又报assert错误。

使用gdb --args ./riscv64-nemu-interpreter -b benos_payload.bin -d ./riscv64-qemu-so命令调试跟踪,发现报错原因,是需要一个debug文件,路径为:/usr/lib/debug/.build-id/97/612b9c612a179a100ded49c146a82904b8c5d8.debug

经过了解,需要从该文件中,解析调试symbol信息,我的机器上没有这个文件。
这个文件是apt-get命令,使用包管理器,安装qemu时,自动创建的。

但是我这个老系统,最多只能升级到qemu 2.11.1,这个版本居然不带qemu-system-riscv64,自然也就没有这个debug文件。

QEMU emulator version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.42)

走到这里,已经没法继续了,要么只有一个版本一个版本去试:

  • 首先,要能装qemu-system-riscv64的系统;
  • 并且,系统上的glibc还要老的,比如:ubuntu glibc 2.27以前。(我在redhat上glibc 2.12,dlopen也失败,醉了,可能redhat上一直都很严格)

算了,麻烦得很,放弃。
后面,使用socket方式来试试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/782030.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在Docker部署DVWA

Docker的安装 apt install docker.io 查看安装是否成功: docker -v 弹出版本信息即安装成功!!! 配置镜像加速器 登录:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 下面可以看到下面界面&…

机器学习训练之使用静态图加速

前言 MindSpore有两种运行模式:动态图模式和静态图模式。默认情况下是动态图模式,也可以手工切换为静态图模式。 动态图模式 动态图的特点是计算图的构建和计算同时发生,符合Python的解释执行方式。在调试模型时较为方便,能够实…

代码随想录 数组部分+代码可在本地编译器运行

代码随想录 数组部分,代码可在本地编译器运行 文章目录 数组理论基础704.二分查找题目:思路二分法第一种写法二分法第二种写法 代码 27.移除元素题目:思路-双指针法代码 977.有序数组的平方题目思路-双指针代码 209.长度最小的子数组题目&am…

CDNOW_master.txt数据分析实战

一、数据详情 该数据集是常见的销售数据集,数据展示的是美国1997后的商品销售数据。包含四个字段,分别是用户id,购买时间,销售量,与销售金额。 二、数据读取与数据清洗 导入必要的包 \s代表的许多空格作为分割,names重…

区间最值问题-RQM(ST表,线段树)

1.ST表求解 ST表的实质其实是动态规划&#xff0c;下面是区间最小的递归公式&#xff0c;最大只需将min改成max即可 f[i][j] min(f[i][j - 1], f[i (1 << j - 1)][j - 1]); 二维数组的f[i][j]表示从i开始连续2*j个数的最小/大值。 例如&#xff1a;我们给出一个数组…

【论文解读】可灵(快手)|LivePortrait:具有拼接和重定向控制的高效肖像动画

&#x1f4dc; 文献卡 英文题目: LivePortrait: Efficient Portrait Animation with Stitching and Retargeting Control;作者: Jianzhu Guo; Dingyun Zhang; Xiaoqiang Liu; Zhizhou Zhong; Yuan Zhang; Pengfei Wan; Di ZhangDOI: 10.48550/arXiv.2407.03168摘要翻译: *旨在…

ESP32CAM物联网教学02

ESP32CAM物联网教学02 物联网门锁 小智来到姑姑家门口&#xff0c;按了门铃&#xff1b;还在公司上班的姑姑用电脑给小智开了门&#xff0c;让他先进屋休息。小智对物联网门锁产生了兴趣&#xff1a;什么是物联网&#xff1f;为什么这么厉害&#xff1f; 初识物联网 我们在百…

【论文阅读笔记】Meta 3D AssetGen

【论文阅读笔记】Meta 3D AssetGen: Text-to-Mesh Generation with High-Quality Geometry, Texture, and PBR Materials Info摘要引言创新点 相关工作T23D基于图片的3d 重建使用 PBR 材料的 3D 建模。 方法文本到图像:从文本中生成阴影和反照率图像Image-to-3D:基于pbr的大型重…

python 比webdriver更好用的ChromiumPage

优点&#xff08;目前发现的&#xff09;&#xff1a; 不用配合selenium不用下载对应浏览器的webdriver&#xff0c;不用对应浏览器版本不用设置webdriver路径之类的设置目前没看到有出现像webdriver类似的浏览器被控制的提示&#xff0c;使用过程中好像也没被检测出来。每次不…

unity3d:Shader知识点,矩阵,函数,坐标转换,Tags,半透明,阴影,深度,亮度,优化

基本结构 Shader "MyShaderName" {Properties {// 属性}SubShader {// 针对显卡A的SubShaderPass {// 设置渲染状态和标签Tags { "LightMode""ForwardBase" }// 开始Cg代码片段CGPROGRAM// 该代码片段的编译指令&#xff0c;例如&#xff1a;#p…

【vite创建项目】

搭建vue3tsvitepinia框架 一、安装vite并创建项目1、用vite构建项目2、配置vite3、找不到模块 “path“ 或其相对应的类型声明。 二、安装element-plus1、安装element-plus2、引入框架 三、安装sass sass-loader1、安装sass 四、安装vue-router-next 路由1、安装vue-router42搭…

python基础篇(8):异常处理

在Python编程中&#xff0c;异常是程序运行时发生的错误&#xff0c;它会中断程序的正常执行流程。异常处理机制使得程序能够捕获这些错误&#xff0c;并进行适当的处理&#xff0c;从而避免程序崩溃。 1 错误类型 代码的错误一般会有语法错误和异常错误两种&#xff0c;语法错…

CTF常用sql注入(一)联合注入和宽字节

0x01 前言 给自己总结一下sql注入的常用姿势吧&#xff0c;记录一下学习 0x02 联合 联合注入的关键词是union SQL的union联合注入原理是联合两个表进行注入攻击&#xff0c;使用union select关键词来进行联合查询。 那么为什么我们在题目中一般是只写一个呢 因为 $sql &quo…

逆变器学习笔记(三)

DCDC电源芯片外围器件选型_dcdc的comp补偿-CSDN博客、 1.芯片的COMP引脚通常用于补偿网络&#xff1a; 芯片的COMP引脚通常用于补偿网络&#xff0c;在控制环路中发挥重要作用。COMP引脚接电容和电阻串联接地&#xff0c;主要是为了稳定控制环路、调整环路响应速度和滤波噪声…

cs231n作业1——SVM

参考文章&#xff1a;cs231n assignment1——SVM SVM 训练阶段&#xff0c;我们的目的是为了得到合适的 &#x1d44a; 和 &#x1d44f; &#xff0c;为实现这一目的&#xff0c;我们需要引进损失函数&#xff0c;然后再通过梯度下降来训练模型。 def svm_loss_naive(W, …

NAT 打洞

由于 ipv4 地址数量的有限性&#xff0c;导致实际网络部署模式中存在大量的 NAT 网络。对于 NAT 内部的主机&#xff0c;可以主动发起去公网的流量&#xff0c;但对于位于不同 NAT 内的两台主机而言&#xff0c;想要直接进行点对点的连接&#xff0c;就需要用到打洞技术了。 常…

Bash ——shell

Bash作为用户与操作系统之间的接口&#xff0c;让用户通过命令行输入各种指令来控制和操作计算机系统。 shell的两种解释&#xff1a; 1.linux命令解释器 Terminal 终端 ——》shell命令 ——》 Linux kernel &#xff08;内核&#xff09; Linux内核的作用&#xff1a; 1.…

AI与编程:一个学生的心路历程与思考

前言 大家好&#xff0c;本人是在一个在校的大学生&#xff0c;方向是前端语言。爱好是码代码和看一点小新闻&#xff0c;游戏也是喜爱的。其实本篇文章的想法是源于网上一些人对AI以及对前端的看法&#xff0c;看完网上的评论后我也是有感而发。本篇文章的讨论中心也是围绕着A…

IDA*——AcWing 180. 排书

IDA* 定义 IDA*&#xff08;Iterative Deepening A*&#xff09;是一种结合了深度优先搜索&#xff08;DFS&#xff09;的递归深度限制特性和A搜索的启发式估价函数的搜索算法。它主要用于解决启发式搜索问题&#xff0c;尤其是当搜索空间很大或者搜索成本不确定时。 IDA* 是…

SprongBoot及其基础应用全套部署脚本和配置

POM.xml配置 </dependencies> <!--skywalking日志监控依赖--><dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version>8.5.0</version></dependency&g…