当前位置: 首页 > news >正文

解决QEMU无法从非0x80000000处开始执行

解决QEMU无法从非0x80000000处开始执行

  • 1 背景介绍
  • 2 问题描述
  • 3 原因分析
  • 4 解决办法
  • 5 踩坑回忆
    • 5.1 坑1 - 怀疑设备树有问题
    • 5.2 坑2 - 怀疑QEMU中内存未写入成功
    • 5.3 QEMU地址空间分析过程

1 背景介绍

在使用NEMU与QEMU做DiffTest的场景下,运行的固件为《RISC-V体系结构编程与实践》中示例代码chapter_2,编译出来的固件二进制文件为:benos_payload.bin

将benos_payload.bin,放置在NEMU中内存0x80000000处,NEMU通过Socket发送放置到QEMU中内存0x31e00000处。

计划让QEMU直接从0x31e00000开始执行,而不是常规的0x80000000。

对NEMU源码,做了如下修改。将nemu/src/cpu/difftest/dut.c文件,init_difftest函数,修改为如下:

void init_difftest(char *ref_so_file, long img_size, int port) {...ref_difftest_init(port);// 将benos_payload.bin发送到QEMU的0x31e00000内存处ref_difftest_memcpy(0x31e00000, guest_to_host(RESET_VECTOR), img_size, DIFFTEST_TO_REF);// pc寄存器设置为0x31e00000cpu.pc = 0x31e00000;// 将NEMU的x0 ~ x31和pc寄存器值,发送到QEMU中,覆盖QEMU原有寄存器ref_difftest_regcpy(&cpu, DIFFTEST_TO_REF);// 让QEMU执行3000条指令ref_difftest_exec(3000);
}

只要NEMU执行了上述代码,那么QEMU的0x31e00000处保存的就是benos_payload.bin,并且pc寄存器值为0x31e00000,当执行ref_difftest_exec函数时,预期QEMU就可以从0x31e00000开始执行。

2 问题描述

QEMU无法从0x31e00000开始执行,甚至一条指令都取不出来(qemu-7.1.0/target/riscv/translate.c中decode_opc函数第1052行,不会中断停下来)。

3 原因分析

我们调试QEMU源码,发现NEMU通过Socket发给QEMU的二进制镜像,并没有被写入QEMU的0x31e00000内存中,而是跳过了。
这点找一个正常向0x80000000写入成功的例子,来对照一下,就很容易定位。
因此,内存中没有该二进制可执行内容,故无法取指执行。

4 解决办法

在qemu-7.1.0/hw/riscv/spike.c文件,spike_board_init函数中,有如下调用:

/* register system main memory (actual RAM) */
memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base, machine->ram);

注册系统主内存时,默认使用spike.c文件中spike_memmap数组,第SPIKE_DRAM个元素,该数组定义如下:

static const MemMapEntry spike_memmap[] = {[SPIKE_MROM] =     {     0x1000,     0xf000 },[SPIKE_HTIF] =     {  0x1000000,     0x1000 },[SPIKE_CLINT] =    {  0x2000000,    0x10000 },[SPIKE_DRAM] =     { 0x80000000,        0x0 },
};

因此,QEMU只认为0x80000000开始为DRAM,其他不认。
我们只需要,将0x80000000修改为0x30000000,再次尝试从0x31e00000运行,就成功了。

5 踩坑回忆

5.1 坑1 - 怀疑设备树有问题

当时第一反应,是以为设备树不对,因此修改了设备树中memory地址定义。事实证明没用。

后面看了QEMU的spike_board_init函数代码,其实QEMU会默认创建一个设备树,该设备树中memory地址,默认使用的是spike_memmap数组,因此我们只要改了spike_memmap数组,那设备树中memory地址也会改变。

以下,附一些设备树的常用命令。

从QEMU中导出设备树,启动QEMU时,添加如下选项:

-M virt,dumpdtb=123.dtb 

将DTS编译为DTB:

dtc -I dts -O dtb -o 123.dtb 123.dts

将DTB转为DTS:

dtc -I dtb -O dts 123.dtb -o 123.dts

5.2 坑2 - 怀疑QEMU中内存未写入成功

真实原因就是这个。
其实在qemu-7.1.0/gdbstub.c中有一对函数:

  • handle_write_mem函数
  • handle_read_mem函数

NEMU发送数据给QEMU时,会调用handle_write_mem,如果在NEMU中再实现一个读内存的发包函数,那么就可以从QEMU中读取内存,在NEMU中将读到的数据与之前写入的数据,进行比较,很容易定位,两次数据不一致,内存写入有问题。

附,写内存数据包格式

// 写入内存,数据包
"M0x31e00000,5dc:1711000013010100b7120000330151006f00001e1301..."
  • M表示写入内存,m表示读取内存。
  • 0x31e00000:表示写入内存的地址为0x31e00000。
  • 0x5dc:表示后面跟的,数据长度为1500字节,实际数据包中因为是2个字符表示一个字节,因此后面实际字符串数据长度为1500*2。
  • 1711000013010…:表示数据,"171100"解析后,就是0x17 0x11 0x00,低字节在前,高字节在后。

5.3 QEMU地址空间分析过程

以下内容很乱,请忽略,纯记录。

QEMU中有一个结构GDBState,包含了很多信息,就包含CPU的地址空间。
该结构中有个成员g_cpu,层次关系如下:

// 是否为DRAM地址
g_cpu->cpu_ases[0].as->current_map->dispatch->mru_section->mr->ram
// DRAM基址
g_cpu->cpu_ases[0].as->current_map->dispatch->mru_section->offset_within_address_space
// DRAM空间大小
g_cpu->cpu_ases[0].as->current_map->dispatch->mru_section->size

MemoryRegionSection表示一个地址范围,如[0x80000000, 0x88000000]。
其offset_within_address_space表示基址,size表示大小。

typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
// 展开后为:
typedef union CPUTailQ {struct CPUState* tqh_first;    // first elementQTailQLink tqh_circ;       // last element
} CPUTailQ;extern CPUTailQ cpus;
CPUState* cpu = first_cpu = (&cpus)->tqh_first

打的一些断点:

  • b gdbstub.c:836,gdbstub.c中gdb_first_attached_cpu()
  • b cpus-common.c:92

相关文章:

解决QEMU无法从非0x80000000处开始执行

解决QEMU无法从非0x80000000处开始执行 1 背景介绍2 问题描述3 原因分析4 解决办法5 踩坑回忆5.1 坑1 - 怀疑设备树有问题5.2 坑2 - 怀疑QEMU中内存未写入成功5.3 QEMU地址空间分析过程 1 背景介绍 在使用NEMU与QEMU做DiffTest的场景下,运行的固件为《RISC-V体系结…...

AI在候选人评估中的作用:精准筛选与HR决策的助力

一、引言 随着科技的迅猛发展,人工智能(AI)技术已逐渐渗透到各个行业和领域,人力资源管理(HRM)亦不例外。在候选人评估的环节中,AI技术以其高效、精准的特性,正在逐步改变着传统的招…...

自动化测试的艺术:Xcode中GUI测试的全面指南

自动化测试的艺术:Xcode中GUI测试的全面指南 在软件开发过程中,图形用户界面(GUI)测试是确保应用质量和用户体验的关键环节。Xcode,作为苹果的官方集成开发环境(IDE),提供了一套强大…...

uniapp封装请求拦截器,封装请求拦截和响应拦截的方法

首先我们先看一下uni官方给开发者提供的uni.request用来网络请求的api 1 2 3 4 5 6 7 8 9 uni.request({ url: , method: GET, data: {}, header: {}, success: res > {}, fail: () > {}, complete: () > {} }); 可以看到我们每次请求数据的时候都需…...

开局一个启动器:从零开始入坑ComfyUI

前几天刷某乎的时候看到了一位大佬写的好文,可图 IP-Adapter 模型已开源,更多玩法,更强生态! - 知乎 (zhihu.com) 久闻ComfyUI大名,决定试一下。这次打算不走寻常路,不下载现成的一键包了,而是…...

34_YOLOv5网络详解

1.1 简介 YOLOV5是YOLO(You Only Look Once)系列目标检测模型的一个重要版本,由 Ultralytics 公司的Glenn Jocher开发并维护。YOLO系列以其快速、准确的目标检测能力而闻名,尤其适合实时应用。YOLOV5在保持高效的同时&#xff0c…...

深入解析Perl的正则表达式:功能、应用与技巧

在编程世界中,正则表达式是一种强大的文本处理工具,它能够用于搜索、替换、匹配字符串等操作。Perl语言以其强大的文本处理能力著称,而其正则表达式功能更是其核心特性之一。本文将深入探讨Perl中的正则表达式,包括其基本语法、应…...

【JAVA】Hutool CollUtil.sort 方法:多场景下的排序解决方案

在 Java 开发中&#xff0c;集合的排序是常见需求。Hutool 库的 CollUtil.sort 方法提供了一系列用于排序的实用功能&#xff0c;适用于不同的场景。以下是对几种常见场景及其实现方式的总结&#xff1a; <dependency><groupId>org.dromara.hutool</groupId>…...

Mysql-安装(Linux)

1、下载mysql 切换到/opt/app目录下&#xff0c;执行如下命令&#xff0c;下载mysql 5.7.38版本。 [rootywxtdb app]# wget https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz 解压安装包 [rootywxtdb app]# tar -zxvf mysql-5.7.38-l…...

如何查看日志

别用 cat cat 把整个日志文件刷屏 慎用 vim 日志不大随便整&#xff0c;因为vim会把整个日志文件读到内存&#xff0c;大日志文件&#xff08;G级别&#xff09;会造成内存占用过高&#xff0c;影响其他程序&#xff0c;在业务机器上查看日志这样尤其危险 less is more 还…...

python实现责任链模式

把多个处理方法串成一个list。下一个list的节点是上一个list的属性。 每个节点都有判断是否能处理当前数据的方法。能处理&#xff0c;则直接处理&#xff0c;不能处理则调用下一个节点&#xff08;也就是当前节点的属性&#xff09;来进行处理。 Python 实现责任链模式&#…...

Prometheus监控ZooKeeper

1. 简介 ZooKeeper是一个分布式协调服务,在分布式系统中扮演着重要角色。为了确保ZooKeeper集群的健康运行,有效的监控至关重要。本文将详细介绍如何使用Prometheus监控ZooKeeper,包括安装配置、关键指标、告警设置以及最佳实践。 2. 安装和配置 2.1 安装ZooKeeper Exporter…...

vuepress搭建个人文档

vuepress搭建个人文档 文章目录 vuepress搭建个人文档前言一、VuePress了解二、vuepress-reco主题个人博客搭建三、vuepress博客部署四、vuepress后续补充 总结 vuepress搭建个人文档 所属目录&#xff1a;项目研究创建时间&#xff1a;2024/7/23作者&#xff1a;星云<Xing…...

面试题 17.14.最小K个数

题目&#xff1a;如下图 答案&#xff1a;如下图 /*** Note: The returned array must be malloced, assume caller calls free().*/ void AdjustDown(int* a,int n,int root) {int parent root;int child parent * 2 1;//默认左孩子是大的&#xff0c;将其与右孩子比较&am…...

C++实现LRU缓存(新手入门详解)

LRU的概念 LRU&#xff08;Least Recently Used&#xff0c;最近最少使用&#xff09;是一种常用的缓存淘汰策略&#xff0c;主要目的是在缓存空间有限的情况下&#xff0c;优先淘汰那些最长时间没有被访问的数据项。LRU 策略的核心思想是&#xff1a; 缓存空间有限&#xff1…...

汇昌联信数字做拼多多运营实力好吗?

汇昌联信数字在拼多多运营方面的实力如何?汇昌联信数字作为一家专注于电子商务运营服务的公司&#xff0c;其在拼多多平台的运营能力是值得关注的。根据市场反馈和客户评价&#xff0c;汇昌联信数字在拼多多的运营实力表现良好&#xff0c;能够为客户提供专业的店铺管理、产品…...

【云原生】Prometheus 服务自动发现使用详解

目录 一、前言 二、Prometheus常规服务监控使用现状​​​​​​​ 2.1 Prometheus监控架构图 2.2 Prometheus服务自动发现的解决方案 三、Prometheus服务自动发现介绍 3.1 什么是Prometheus服务自动发现 3.2 Prometheus自动服务发现策略 3.3 Prometheus自动服务发现应用…...

(十九)原生js案例之h5地里位置信息与高德地图的初使用

h5 地里位置信息 1. 获取当前位置信息 window.onload function () {const oBtn document.querySelector("#btn");const oBox document.querySelector("#box");oBtn.onclick function () {window.navigator.geolocation.getCurrentPosition(function (…...

三、基础语法2(30小时精通C++和外挂实战)

三、基础语法2&#xff08;30小时精通C和外挂实战&#xff09; B-02内联函数B-04内联函数与宏B-05_constB-06引用B-07引用的本质B-08-汇编1-X86-X64汇编B-09-汇编2-内联汇编B-10-汇编3-MOV指令C-02-汇编5-其他常见指令C-05-汇编8-反汇编分析C-07-const引用、特点 B-02内联函数 …...

gitee设置ssh公钥密码频繁密码验证

gitee中可以创建私有项目&#xff0c;但是在clone或者push都需要输入密码&#xff0c; 比较繁琐。 公钥则可以解决该问题&#xff0c;将私钥放在本地&#xff0c;公钥放在gitee上&#xff0c;当对项目进行操作时带有的私钥会在gitee和公钥进行验证&#xff0c;避免了手动输入密…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...