搭建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 = appifdef 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.xdnf.cn/news/1474637.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

React中的useMemo和memo

引言 React是一个声明式的JavaScript库,用于构建用户界面。在开发过程中,性能优化是一个重要的方面。useMemo和memo是React提供的工具,用于帮助开发者避免不必要的渲染和计算,从而提升应用性能。 问题背景 在React应用中&#…

Ubuntu编译 OSG

目录 一、安装步骤 二、配置 1、数据文件配置 2、OSG环境变量配置 一、安装步骤 在Ubuntu上安装OSG(OpenSceneGraph),你可以按照以下步骤操作: 打开终端,更新你的包管理器的包列表: sudo apt update 安装必要的依赖库 sudo apt install libglu1-mesa-dev freeglu…

数字信号处理及MATLAB仿真(3)——量化的其他概念

上回书说到AD转换的两个步骤——量化与采样两个步骤。现在更加深入的去了解以下对应的概念。学无止境,要不断地努力才有好的收获。万丈高楼平地起,唯有打好基础,才能踏实前行。 不说了,今天咱们继续说说这两个步骤,首先…

[激光原理与应用-101]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 5 - 3C行业应用 - 电子布局类型

目录 前言: 一、激光在3C行业的应用概述 1.1 概述 1.2 激光焊接在3C-电子行业应用 二、3C电子行业中激光焊接 2.1 纽扣电池 2.2 均温板 2.3 指纹识别器 2.4 摄像头模组 2.5 IC芯片切割 三、3C行业中激光切割 四、激光在3C行业中的其他应用 4.1 涂层去除…

【机器学习实战】Datawhale夏令营:Baseline精读笔记2

# AI夏令营 # Datawhale # 夏令营 在原有的Baseline上除了交叉验证,还有一种关键的优化方式,即特征工程。 如何优化特征,关系着我们提高模型预测的精准度。特征工程往往是对问题的领域有深入了解的人员能够做好的部分,因为我们要…

day01:项目概述,环境搭建

文章目录 软件开发整体介绍软件开发流程角色分工软件环境 外卖平台项目介绍项目介绍定位功能架构 产品原型技术选型 开发环境搭建整体结构:前后端分离开发前后端混合开发缺点前后端分离开发 前端环境搭建Nginx 后端环境搭建熟悉项目结构使用Git进行版本控制数据库环…

记录问题:解决vscode找不到Python自定义模块,报错No module named ‘xxx‘

1. 背景 我非要用vscode,不用pycharm,哼! 2. 问题 由于 import xx 自定义的模块, python run 的时候会报错 No module named ‘xxx‘ 报错信息: Traceback (most recent call last):File "d:\work\sf_financ…

90元搭建渗透/攻防利器盒子!【硬件篇】

前言 以下内容请自行思考后进行实践。 使用场景 在某些情况下开软件进行IP代理很麻烦,并不能实现真正全局,而且还老容易忘记,那么为了在实景工作中,防止蓝队猴子封IP,此文正现。 正文 先说一下实验效果&#xff1…

【JavaEE】多线程进阶

🤡🤡🤡个人主页🤡🤡🤡 🤡🤡🤡JavaEE专栏🤡🤡🤡 文章目录 1.锁策略1.1悲观锁和乐观锁1.2重量级锁和轻量级锁1.3自旋锁和挂起等待锁1.4可…

【讲解下iOS语言基础】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

昇思25天学习打卡营第14天|Pix2Pix实现图像转换

Pix2Pix是基于条件生成对抗网络(cGAN, Condition Generative Adversarial Networks )实现的一种深度学习图像转换模型,该模型是由Phillip Isola等作者在2017年CVPR上提出的,可以实现语义/标签到真实图片、灰度图到彩色图、航空图到…

git简介以及git操作软件下载以及安装教程,git基础指令介绍,持续更新中~

什么是Git? 最近在学一些git的基础指令,仔细地了解了一下git,发现了他的强大功能,分享一下: Git是一个强大的工具,它在软件开发中扮演着至关重要的角色。 Git是一个开源的分布式版本控制系统,…

使用RAID与LVM磁盘阵列技术

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 目录 一、RAID磁盘冗余阵列 1、部署磁盘整列 2、损坏磁盘阵列及修复 3、磁盘阵列备份盘 4、删除磁盘阵列 二、LVM逻辑卷管理器 致谢 一、RAID…

1958.力扣每日一题7/7 Java(100%解)

博客主页:音符犹如代码系列专栏:算法练习关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 思路 首先将指定位…

反编译kasada

继续研究反编译 这次的网站是 一个航司网站 他有 akamai和 kasada 两种防护 akamai 没啥好说的 结构分析 最开始有个长字符串 处理成 一个十几万的数组 通过 r.W[0] 走什么分支 还有数据的存取 M是一个98个函数组成的数组 代表不同的执行逻辑 这里给他转成了 switch case…

Python3极简教程(一小时学完)中

异常 在这个实验我们学习 Python 的异常以及如何在你的代码中处理它们。 知识点 NameErrorTypeError异常处理(try..except)异常抛出(raise)finally 子句 异常 在程序执行过程中发生的任何错误都是异常。每个异常显示一些相关…

【持续集成_03课_Jenkins生成Allure报告及Sonar静态扫描】

1、 一、构建之后的配置 1、安装allure插件 安装好之后,可以在这里搜到已经安装的 2、配置allure的allure-commandline 正常配置,是要么在工具里配置,要么在系统里配置 allure-commandline是在工具里进行配置 两种方式进行配置 1&#xff…

动手RAG: ocr调研

对于rag应用来说,文档是第一步,对于部分扫描件的文件来讲,主要就需要OCR. OCR tesseractppocrmmocr 还有诸如 chineseocr_litedarknet-ocrhttps://blog.csdn.net/CHYabc123456hh/article/details/107846268easyocr OCR包含几类&#x…

【Unity小技巧】Unity字典序列化

字典序列化 在 Unity 中&#xff0c;标准的 C# 字典&#xff08;Dictionary<TKey, TValue>&#xff09;是不能直接序列化的&#xff0c;因为 Unity 的序列化系统不支持非 Unity 序列化的集合类型。可以通过手写字典实现 效果&#xff1a; 实现步骤&#xff1a; 继承ISe…

基于AOP的数据字典实现:实现前端下拉框的可配置更新

作者&#xff1a;后端小肥肠 创作不易&#xff0c;未经允许严禁转载。 目录 1. 前言 2. 数据字典 2.1. 数据字典简介 2.2. 数据字典如何管理各模块的下拉框 3. 数据字典核心内容解读 3.1. 表结构 3.2. 核心代码 3.2.1. 根据实体类名称获取下属数据字典 3.2.2. 数据字…