搭建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.mzph.cn/diannao/42581.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓的组件

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

【Linux】打包命令——tar

打包和压缩 虽然打包和压缩都涉及将多个文件组合成单个实体,但它们之间存在重要差异。 打包和压缩的区别: 打包是将多个文件或目录组合在一起,但不对其进行压缩。这意味着打包后的文件大小可能与原始文件相同或更大。此外,打包…

数字化精益生产系统--APS 排程管理系统

APS(Advanced Planning and Scheduling)排程管理系统,即高级生产计划与排程系统,是一种高度智能化的计划和排程系统。它通过整合各种生产和供应链数据,运用先进的算法和数据模型,根据各种约束条件&#xff…

MySQL篇三:数据类型

文章目录 前言1. 数值类型1.1 tinyint类型1.2 bit类型1.3 小数类型1.3.1 float1.3.2 decimal 2. 字符串类型2.1 char2.2 varchar2.3 char和varchar比较 3. 日期类型4. enum和set 前言 数据类型分类: 1. 数值类型 1.1 tinyint类型 在MySQL中,整型可以指…

【Java13】包

“包”这个机制,类似于分组。主要作用是区分不同组内的同名类。例如,高三三班有一个“王五”,高二八班也有一个“王五”。高三三班和高三八班就是两个不同的包。 Java中的包(package)机制主要提供了类的多层命名空间&…

HTTP长连接

长连接优点 HTTP为什么要开启长连接呢? 主要是为了节省建立的时间,请求可以复用同一条TCP链路,不用重复进行三握+四挥 如果没有长连接,每次请求都做三握+四挥 如果有长链接,在一个 TCP 连接中可以持续发送多份数据而不会断开连接,即请求可以复用TCP链路 长连接缺点 …

第六十八回 东平府误陷九纹龙 宋公明义释双枪将-文心大模型ernie-speed免费使用方法

宋江和卢俊义抓阄儿,宋江打东平府,卢俊义打东昌府,谁先打下谁做梁山泊主。宋江带领林冲、花荣、刘唐等二十八人,卢俊义带领吴用、公孙胜、关胜等二十八人。 宋江等人到了东平府外安山镇,郁保四和王定六自告奋勇去下战…

代码随想录第45天|动态规划

300.最长递增子序列 参考 dp[i] 表示以 i 为结尾的最长递增子序列长度递推公式: 使用 i 和 j 判断 dp[i] max(dp[j] 1, dp[i])每次 j 都需要从头遍历 初始化: dp[i] 1 class Solution { public:int lengthOfLIS(vector<int>& nums) {vector<int> dp(nums…

国产化新标杆:TiDB 助力广发银行新一代总账系统投产上线

随着全球金融市场的快速发展和数字化转型的深入推进&#xff0c;金融科技已成为推动银行业创新的核心力量。特别是在当前复杂多变的经济环境下&#xff0c;银行业务的高效运作和风险管理能力显得尤为重要。总账系统作为银行会计信息系统的核心&#xff0c;承载着记录、处理和汇…

2024年06月CCF-GESP编程能力等级认证Python编程二级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证…

云动态摘要 2024-07-07

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 数据库上云优选 阿里云 2024-07-04 RDS、PolarDB、Redis、MongoDB 全系产品新用户低至首年6折起! [免费体验]智能助手ChatBI上线 腾讯云 2024-07-02 基于混元大模型打造,可通过对话方式生成可视化…

18_特征金字塔网络FPN结构详解

1.1 简介 在深度学习领域&#xff0c;尤其是计算机视觉和目标检测任务中&#xff0c;Feature Pyramid Networks (FPN) 是一种革命性的架构设计&#xff0c;它解决了多尺度特征检测和融合的关键问题。FPN最初由何凯明等人在2017年的论文《Feature Pyramid Networks for Object …

ansible常见问题配置好了密码还是报错

| FAILED! > { “msg”: “Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host’s fingerprint to your known_hosts file to manage this host.” } 怎么解决&#xf…

Stable Diffusion图像的脸部细节控制——采样器全解析

文章目录 艺术地掌控人物形象好易智算原因分析为什么在使用Stable Diffusion生成全身图像时&#xff0c;脸部细节往往不够精细&#xff1f; 解决策略 局部重绘采样器总结 艺术地掌控人物形象 在运用Stable Diffusion这一功能强大的AI绘图工具时&#xff0c;我们往往会发现自己…

ESP32 步进电机精准控制:打造高精度 DIY 写字机器人,实现流畅书写体验

摘要: 想让你的 ESP32 不再仅仅是控制灯光的工具吗&#xff1f; 本文将带你使用 ESP32 开发板、步进电机和简单的机械结构打造一个能够自动写字的机器人。我们将深入浅出地讲解硬件连接、软件代码以及控制逻辑&#xff0c;并提供完整的项目代码和电路图&#xff0c;即使是 Ardu…

在mac下 Vue2和Vue3并存 全局Vue2环境创建Vue3新项目(Vue cli2和Vue cli4)

全局安装vue2 npm install vue-cli -g自行在任意位置创建一个文件夹vue3&#xff0c;局部安装vue3,注意不要带-g npm install vue/cli安装完成后&#xff0c;进入目录&#xff0c;修改vue为vue3 找到vue3/node-moudles/.bin/vue&#xff0c;把vue改成vue3。 对环境变量进行配置…

Windows环境安装Redis和Redis Desktop Manager图文详解教程

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Redis概述 Redis是一个开源的高性能键值对数据库&#xff0c;以其卓越的读写速度而著称&#xff0c;广泛用于数据库、缓存和消息代理。它主要将数据存储在内存中&#xff0…

C++初学者指南-5.标准库(第一部分)--迭代器

C初学者指南-5.标准库(第一部分)–迭代器 Iterators 文章目录 C初学者指南-5.标准库(第一部分)--迭代器 Iterators1.默认正向迭代器2.反向迭代器3.基于迭代器的循环4.示例&#xff1a;交换相邻的一对元素5.迭代器范围6.迭代器范围中的元素数量7. 总结&#xff1a;迭代器 指向某…

护网在即,知攻善防助力每一位安服仔~

前言 是不是已经有师傅进场了呢~ 是不是有安服&#x1f412;在值守呢~ 您是不是被网上眼花缭乱的常用应急响应工具而烦恼呢&#xff1f; 何以解忧&#xff1f;唯有知攻善防&#xff01; 创作起源&#xff1a; 驻场、护网等&#xff0c;有的客户现场只允许用客户机器&…

Python网络爬虫:Scrapy框架的全面解析

Python网络爬虫&#xff1a;Scrapy框架的全面解析 一、引言 在当今互联网的时代&#xff0c;数据是最重要的资源之一。为了获取这些数据&#xff0c;我们经常需要编写网络爬虫来从各种网站上抓取信息。Python作为一种强大的编程语言&#xff0c;拥有许多用于网络爬虫的工具和库…