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位软件要对应,否则会出现运行错误。