Я добавил -fPCI к опции компиляции исходного файла QEMU и добавил -shared к последней команде компоновки, так что QEMU стал разделяемой библиотекой, которая может быть загружена динамически. С тех пор я начал пытаться понять QEMU. Я использую dlopen для динамической загрузки qemu и использую dlsym для поиска функций в qemu. Это мой код:
#include<iostream>
#include<dlfcn.h>
#include<stdint.h>
using namespace std;
int main(int argc,char* argv[],char* envp[])
{
void* handle = dlopen("/home/jack/qemu/qemu-5.0.0/arm-softmmu/libqemu-system-arm.so",RTLD_NOW);
if(handle == nullptr)
{
printf("%s\n",dlerror());
return 0;
}
void (* qemu_init )(int,char**,char**);
void (* qemu_main_loop )(void);
void (* qemu_cleanup )(void);
bool (* main_loop_should_exit )(void);
void (* main_loop_wait )(int);
int64_t (* cpu_get_icount )(void);
int64_t (* cpu_get_icount_raw )(void);
int64_t (* cpu_icount_to_ns )(int64_t);
int64_t (* cpu_get_clock )(void);
int64_t (* cpu_get_ticks )(void);
#define GET_SYMBOL_AND_CHECK(X) *((void**)(&X)) = dlsym(handle,#X);if(nullptr == X){printf("lost symbol: "#X"\n");return 0;}
GET_SYMBOL_AND_CHECK(qemu_init);
GET_SYMBOL_AND_CHECK(qemu_main_loop);
GET_SYMBOL_AND_CHECK(qemu_cleanup);
GET_SYMBOL_AND_CHECK(main_loop_should_exit);
GET_SYMBOL_AND_CHECK(main_loop_wait);
GET_SYMBOL_AND_CHECK(cpu_get_icount);
GET_SYMBOL_AND_CHECK(cpu_get_icount_raw);
GET_SYMBOL_AND_CHECK(cpu_icount_to_ns);
GET_SYMBOL_AND_CHECK(cpu_get_clock);
GET_SYMBOL_AND_CHECK(cpu_get_ticks);
#undef GET_SYMBOL_AND_CHECK
char* _argv[]=
{
"qemu-system-arm",
"-M",
"vexpress-a9",
"-nographic",
"-kernel",
"/home/jack/temp/u-boot-2015.01/u-boot",
"-icount",
"1",
"-singlestep",
"-S",
"-s",
};
int _argc=sizeof(_argv) / sizeof(_argv[0]);
qemu_init(_argc,_argv,envp);
while(!main_loop_should_exit())
{
main_loop_wait(false);
//my test code:
int64_t icount_raw = cpu_get_icount_raw();
int64_t icount = cpu_get_icount();
int64_t ticks = cpu_get_ticks();
int64_t clock = cpu_get_clock();
printf("----------icount_raw: %jd\n",icount_raw);
printf("----------icount: %jd\n",icount);
printf("----------ticks: %jd\n",ticks);
printf("----------clock: %jd\n",clock);
}
qemu_cleanup();
dlclose(handle);
return 0;
}
Результат программы следующий:
----------icount_raw: 0
----------icount: 0
----------ticks: 0
----------clock: 27595
----------icount_raw: 0
----------icount: 0
----------ticks: 0
----------clock: 47394
U-Boot 2015.01 (May 25 2020 - 14:42:11)
DRAM: 128 MiB
WARNING: Caches not enabled
Flash: 128 MiB
MMC: MMC: 0
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: smc911x-0
Warning: smc911x-0 using MAC address from net device
Warning: Your board does not use generic board. Please read
doc/README.generic-board and take action. Boards not
upgraded by the late 2014 may break or be removed.
Hit any key to stop autoboot: 2 ----------icount_raw: 60040125
----------icount: 120271139
----------ticks: 120271139
----------clock: 1001128004
----------icount_raw: 119738560
----------icount: 239668009
----------ticks: 239668009
----------clock: 2002239949
----------icount_raw: 180295711
----------icount: 360782311
----------ticks: 360782311
----------clock: 3003347066
----------icount_raw: 240405702
----------icount: 481002293
----------ticks: 481002293
----------clock: 4004446427
----------icount_raw: 300858002
----------icount: 601906893
----------ticks: 601906893
----------clock: 5005552419
----------icount_raw: 361297422
----------icount: 722785733
----------ticks: 722785733
----------clock: 6006625721
----------icount_raw: 420679210
----------icount: 841549309
----------ticks: 841549309
----------clock: 7007717838
----------icount_raw: 424900860
----------icount: 849992609
----------ticks: 849992609
----------clock: 7082080834
----------icount_raw: 424900883
----------icount: 849992655
----------ticks: 849992655
----------clock: 7082105752
----------icount_raw: 424900906
----------icount: 849992701
----------ticks: 849992701
----------clock: 7082120318
QEMU: Terminated
Я смоделировал основной l oop QEMU и написал его, пока l oop. Я печатаю полученные данные каждый раз в l oop и обнаруживаю, что icount_raw может указывать количество инструкций, выполняемых в данный момент процессором. Что касается других данных, я все еще в замешательстве. Когда эта программа запущена, программа uboot может работать нормально. Я обнаружил, что частота вывода данных на экран составляет примерно раз в секунду. Каждый раз icount_raw сильно увеличивается. Когда я использую gdb для удаленного управления программой для запуска. При использовании команды «si» icount_raw увеличивается на 1 каждый раз, чего я и хочу добиться: каждый раз, когда QEMU выполняет только одну инструкцию, он может вернуться к основному l oop. Я хочу знать, как изменить код QEMU, чтобы каждый раз, когда QEMU выполняет инструкцию, он мог возвращаться к основному l oop вместо использования команды gdb «si». В будущем я хочу знать, как управлять QEMU, чтобы он возвращался к основному l oop после каждого выполнения N инструкций. Я могу свободно установить это N. Я понимаю, что событие QEMU l oop основано на Glib, и я думаю, что моя проблема может потребовать изменения кода, который вызывает Glib в QEMU.