win7中编译qemu-system-arm,仿真arm设备

1、下载qemu源码,实验通过的是5.2.0,

2、下载msys2,在msys2中通过pacman指令安装mingw32,mingw64编译不能通过。

3、运行mingw32.exe,安装依赖包,缺什么安装什么,编译过程有提示

4、不用mingw32自带的python,mingw32默认安装的是3.12,配置时总是提示Cannot use 3.12, Python >= 3.6 is required。3.12竟然小于3.6!!! 估计用的字串比较,没找到好的跳过的办法,后来用另外下载的python3.8

5、进入qemu源码文件夹,配置,关闭不必要的功能,

bash 复制代码
./configure \
  --target-list=arm-softmmu \
  --python="C:/Users/Administrator/AppData/Local/Programs/Python/Python38/python.exe" \
  --audio-drv-list= \
  --block-drv-rw-whitelist= \
  --block-drv-ro-whitelist= \
  --disable-slirp \
  --disable-vde \
  --disable-netmap \
  --disable-libiscsi \
  --disable-libnfs \
  --disable-sdl \
  --disable-gtk \
  --disable-vnc \
  --disable-cocoa \
  --disable-gnutls \
  --disable-nettle \
  --disable-gnutls \
  --disable-gcrypt \
  --disable-seccomp \
  --disable-brlapi \
  --disable-curl \
  --disable-libxml2 \
  --disable-live-block-migration \
  --disable-numa \
  --disable-tpm \
  --disable-libssh \
  --disable-virtfs \
  --disable-virtiofsd \
  --disable-xen \
  --disable-rdma \
  --disable-pvrdma \
  --disable-tools \
  --disable-docs \
  --disable-user \
  --disable-guest-agent

6、进入 build ,用ninja -j$(nproc)编译,就可生成 qemu-system-arm.exe

7、修改挂载的设备在qemu->hw->arm,versatilepb.c(这个看各人用什么开机器仿真)versatile_init()函数中修改,可把所有设备初始化都注释了,自己定义。从 cpu = ARM_CPU(cpuobj);/*之后一直到*/versatile_binfo.ram_size = machine->ram_size;

8、中间添加 my_soc_init(sysmem); 这个函数中实现 内存、设备

cpp 复制代码
//flash固件
//0x00000000-0x00400000
    {
   		MemoryRegion *ram2 = g_new(MemoryRegion, 1);
   		uint8_t *ram2_data = g_malloc(0x400000);
   		memory_region_init_ram_ptr(ram2, NULL, "ram-flash", 0x400000, ram2_data);
   		memory_region_add_subregion(sysmem, 0x00000000, ram2);
       }
//内存
  //0x20000000-0x20800000
    {
		MemoryRegion *ram2 = g_new(MemoryRegion, 1);
		uint8_t *ram2_data = g_malloc(0x800000);
		memory_region_init_ram_ptr(ram2, NULL, "ram-20000000", 0x800000, ram2_data);
		memory_region_add_subregion(sysmem, 0x20000000, ram2);
    }
//设备
   /*  0xC0C82000 - 定时器 (4KB) */
    {

        MemoryRegion *mr = g_new(MemoryRegion, 1);
        memory_region_init_io(mr, NULL, &timer_ops, NULL,
                            "timer", 0x1000);
        memory_region_add_subregion(sysmem, 0xC0C82000, mr);
        fprintf(stderr, "  已映射: 定时器 0xC0C82000-0xC0C82FFF (4KB)\n");
    }

static uint64_t timer_read(void *opaque, hwaddr offset, unsigned size)
{
    if (offset == 0x08) {
        /* 计数器寄存器:每次读取增加 1000 */

        return ((uint32_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)-canon_timer_counter);
    }

    else if (offset == 0x0C) {
        /* 控制寄存器:总是返回 1(已启动) */
        return 1;
    }
    else if(offset == 0x404){
    	 return 1;
    } else{
    	 fprintf(stderr, "my soc 未知地址:0x%8x\n",(uint32_t)opaque);
    	return 0;
    }
}

//
static void timer_write(void *opaque, hwaddr offset,
                       uint64_t value, unsigned size)
{
	 if (offset == 0x0c) {
	       //计数器寄存器重置
	        canon_timer_counter =(uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));

	        return ;
	    }

}

static const MemoryRegionOps timer_ops = {
    .read = timer_read,
    .write = timer_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = { .min_access_size = 4, .max_access_size = 4 },
    .impl = { .min_access_size = 4, .max_access_size = 4 },
};
//========0xC0C82000-0xC0C82FFF

9、再下一gdb,将cmd建立一个快捷方式,将下面文件保存存成bat文件,1键调试

cpp 复制代码
@echo off
REM chcp 65001 >nul
REM setlocal enabledelayedexpansion

title bin调试工具
color 0A

REM 注意: 等号两边不能有空格!
set CONFIG_FILE=qemu_debug_config.ini
set QEMU_PATH=E:\SoftEngin\tools\qemu32
set GDB_PATH=E:\SoftEngin\tools\eabi\bin
set QEMU=qemu-system-arm.exe
set GDB=arm-none-eabi-gdb.exe
set FIRMWARE_FILE=firmware.bin
set QEMU_MACHINE=versatilepb
set QEMU_CPU=arm946
set QEMU_MEMORY=64M
set DEBUG_PORT=1234
set MONITOR_PORT=5555
set ARCHITECTURE=arm
set ENTRY_POINT=0x000000
set LOAD_BASE=0x000000
set BREAKPOINTS=0x10C
set LOG_DIR=debug_output
set LOG_FILE=log.txt
set PYTHONPATH=E:\SoftEngin\tools\Python27
echo %PATH% | findstr /i "%QEMU_PATH%" >nul
if errorlevel 1 (  
 set path=C:\windows\system32;C:\windows;E:\SoftEngin\tools\Python27;%GDB_PATH%;%QEMU_PATH%
) 

echo 步骤1: 检查端口占用
netstat -an | findstr ":1234" >nul
if not errorlevel 1 (
    echo 警告: 端口1234被占用
    echo 尝试停止占用进程...
    for /f "tokens=5" %%p in ('netstat -ano ^| findstr ":1234"') do (
        taskkill /F /PID %%p 2>nul && echo 已停止进程: %%p
    )
    timeout /t 1 /nobreak >nul
)



REM 检查必要文件




if not exist "%FIRMWARE_FILE%" (
    echo 错误: 固件文件不存在: %FIRMWARE_FILE%
    pause
    exit /b 1   
)

if not exist "%QEMU_PATH%\%QEMU%" (
    echo 错误: QEMU文件不存在: %QEMU%    
    pause
    exit /b 1
)

REM 比较文件时间
for %%I in ("E:\SoftEngin\tools\msys32\home\Administrator\qemu-5.2.0\build\%QEMU%") do set SOURCE_TIME=%%~tI
for %%I in ("%QEMU_PATH%\%QEMU%") do set TARGET_TIME=%%~tI
if "%SOURCE_TIME%" gtr "%TARGET_TIME%" (

    echo qemu被重新编译,更新。
    copy /Y "E:\SoftEngin\tools\msys32\home\Administrator\qemu-5.2.0\build\%QEMU%" "%QEMU_PATH%\%QEMU%"   
) else (
 REM   echo 目标文件已是最新,无需更新。
)



if not exist "%GDB_PATH%\%GDB%" (
    echo 错误: GDB文件不存在: %GDB%
    echo 注意: 需要arm-none-eabi-gdb.exe,不是普通gdb
    pause
    exit /b 1
)



REM 创建日志目录
if not exist "!LOG_DIR!" mkdir "!LOG_DIR!"

REM 处理命令行参数
if not "%~1"=="" set BREAKPOINTS=%~1

echo ====================================================
echo                调试配置
echo ====================================================
echo 固件文件:   %FIRMWARE_FILE%
echo QEMU机器:   %QEMU_MACHINE%
echo CPU类型:    %QEMU_CPU%
echo 内存大小:   %QEMU_MEMORY%
echo 调试端口:   %DEBUG_PORT%
echo 监控端口:   %MONITOR_PORT%
echo 入口地址:   %ENTRY_POINT%
echo 断点地址:  	%BREAKPOINTS%
echo ====================================================
echo.

echo 正在启动QEMU模拟器...
echo.

REM 启动QEMU(修复了参数格式)    -m %QEMU_MEMORY% ^
start "QEMU 模拟器" /B "%QEMU%" ^
    -M %QEMU_MACHINE% ^
    -cpu %QEMU_CPU% ^
    -m %QEMU_MEMORY% ^
    -device loader,file="%FIRMWARE_FILE%",addr=0x0  ^
    -s -S ^
    -monitor none ^
    -nographic ^
    -nodefaults ^
    -serial none 
  
echo 等待2秒让QEMU启动...
timeout /t 2 /nobreak >nul

echo.

REM 检查QEMU是否在运行
tasklist /FI "IMAGENAME eq %QEMU%" 2>nul | findstr "qemu-system-arm" >nul
if errorlevel 1 (
    echo 错误: QEMU可能没有成功启动   
    exit /b 1
   
)



echo 启动GDB调试器...
%GDB% -q ^
	-ex "target remote :%DEBUG_PORT%" ^
    -ex "b *%BREAKPOINTS%" ^
    -ex "display/i $pc" ^
    -ex "c"
echo.


taskkill /F /IM "%QEMU%" >nul 2>&1
if errorlevel 1 (
    echo QEMU进程未运行或无法终止
) else (
    echo QEMU进程已强制终止
)

taskkill /F /IM "%GDB%" >nul 2>&1
if errorlevel 1 (
    echo GDB进程未运行或无法终止
) else (
    echo GDB进程已强制终止
)


echo 调试会话结束
timeout /t 1 /nobreak >nul
exit /b 0

10、找不到dll可以下载官方qemu包或者用pacman安装qemu,将里面的dll复制到编译的qemu-system-arm.exe文件一起。注意32位软件要对应,否则会出现运行错误。

相关推荐
黎雁·泠崖18 小时前
二叉树知识体系全梳理:从基础到进阶一站式通关
c语言·数据结构·leetcode
山上三树18 小时前
详细介绍 C/C++ 中的内存泄漏
c语言·c++
Legendary_00818 小时前
LDR6020:单C口可充可放电PD协议芯片,开启USB2.0数据传输新体验
c语言·开发语言
山上三树19 小时前
详细介绍 C 语言中的匿名结构体
c语言·开发语言·算法
EXtreme3519 小时前
【数据结构】彻底搞懂二叉树:四种遍历逻辑、经典OJ题与递归性能全解析
c语言·数据结构·算法·二叉树·递归
山上三树19 小时前
详细介绍 C 语言 typedef 及与 #define 的核心对比
c语言·数据结构·算法
Java猿_21 小时前
开发 Java 项目,选哪个 IDE?Eclipse、MyEclipse 与 IntelliJ IDEA 深度对比
java·ide·eclipse
黎雁·泠崖21 小时前
栈和队列知识体系全梳理:从基础到实战一站式通关
c语言·数据结构·leetcode