Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Qemu插件函数-如何访问来宾内存和寄存器 背景_C_Arm_Qemu_Bare Metal - Fatal编程技术网

C Qemu插件函数-如何访问来宾内存和寄存器 背景

C Qemu插件函数-如何访问来宾内存和寄存器 背景,c,arm,qemu,bare-metal,C,Arm,Qemu,Bare Metal,12月19日发布的Qemu包含了一个新功能,名为。目录中有一些示例,API或多或少是在中定义的 该文件定义了两种枚举类型,qemu-plugin\u-cb\u-flags和qemu-plugin\u-mem\u-rw,它们被传递到注册回调的函数中。这些枚举似乎指示回调是读取还是写入CPU寄存器或内存。但是,所有示例插件都使用QEMU-PLUGIN\u-CB\u-NO\u-REGS,只有2个插件使用内存访问枚举hotpages.c和mem.c使用QEMU-PLUGIN\u-mem\u-RW作为注册

12月19日发布的Qemu包含了一个新功能,名为。目录中有一些示例,API或多或少是在中定义的

该文件定义了两种枚举类型,
qemu-plugin\u-cb\u-flags
qemu-plugin\u-mem\u-rw
,它们被传递到注册回调的函数中。这些枚举似乎指示回调是读取还是写入CPU寄存器或内存。但是,所有示例插件都使用
QEMU-PLUGIN\u-CB\u-NO\u-REGS
,只有2个插件使用内存访问枚举
hotpages.c
mem.c
使用
QEMU-PLUGIN\u-mem\u-RW
作为注册内存回调的默认值(
QEMU-PLUGIN\u-register\u-vcpu\u-mem\u-cb
mem.c
在加载插件时有一个参数来选择是读还是写,但是,它似乎对回调函数没有任何影响

问题: 我的问题是,如何从插件回调函数访问来宾内存和寄存器?API似乎表明这是可能的,因为回调注册要求您说出是否要访问它们,以及是RW还是刚读

是否有使用API这一部分的示例?我意识到这是Qemu功能的一个非常新的部分

代码 在指令上注册回调时(如中),可以获得指令的虚拟地址

uint64_t insn_vaddr = qemu_plugin_insn_vaddr(insn);
我正在运行一个裸机ARM程序,这个虚拟地址似乎与ELF文件中的指令地址相关

在内存回调函数中,您可以调用
qemu\u plugin\u get\u hwaddr
来获取内存访问的硬件地址,但我不确定该结构到底代表什么

相关的

这个答案已经有7年历史了,建议使用GDB接口。我的问题与使用TCG插件功能特别相关。

我刚刚遇到了完全相同的问题。qemu团队似乎真的试图阻止我们使用插件中的CPU或内存。我试图通过修改makefile来包含所需的头文件,但这些头文件不应该包含在插件之类的外部代码中。我无法使它编译

正如你所说,有一些旗帜表明这是可能的。我的猜测是该功能没有完全实现,也许这很快就会实现

与此同时,当我们等待一个合适的方法来做这件事的时候,下面是我如何破解它的:

登记 在我的例子中,CPU是一个ARM。我将首先显示代码,然后进行解释

void*qemu\u get\u cpu(int索引);
静态uint32获取cpu寄存器(无符号int cpu索引,无符号int reg){
uint8_t*cpu=qemu_get_cpu(cpu_索引);
返回*(uint32_t*)(cpu+33488+5424+reg*4);
}
我首先声明
qemu\u get\u cpu
函数,因为我们不能包含它的头。该函数返回一个
CPUState*
。因为我的CPU是ARM,所以我知道指针实际上是一个
ARMCPU*
。由于继承是在qemu中实现的,因此从
CPUState*
ARMCPU*
的转换是不可操作的,因此在那里没有什么可做的

然后,查看
target/arm/cpu.h
,我们可以看到结构:

struct ARMCPU{
/**/
CPUState parent_obj;
/**/
CPUNegativeOffsetState neg;
CPUARMState环境;
// ...
我曾经得到CPUState和CPUNegativeOffsetState的大小,在我的例子中分别是33488和5424。这给我们提供了
CPUARMState
的偏移量,其开始如下:

typedef结构CPUARMState{
/*当前模式的注册表*/
uint32_t regs[16];
// ...
所以寄存器才刚开始,这就是为什么我使用
reg*4

现在我们可以读取寄存器了,下一步是

凭记忆阅读 这个更简单,我从qemu本身的
gdbstub.c
中获得:

void cpu\u physical\u memory\u rw(uint64\u t addr,uint8\u t*buf,
uint64_t len,int是_write);
//在我的职责中:
字符名[9]={0};
cpu \物理\内存\ rw(名称\地址,名称,8,0);

我们只需声明所需的方法并调用它。该方法似乎从未失败,从未映射的内存中读取不会产生任何效果。

我刚刚发现,在用户模式下,您可以只需取消引用
vaddr
即可从内存中获取值

char *val = (char*) vaddr;
此外,我在
cpu.c
中发现了以下方法,当gdbstub不可用时,也可以使用该方法

int cpu_memory_rw_debug(void *cpu, uint64_t addr,
                        void *ptr, uint64_t len, bool is_write);

尽管如此,这是一个解决办法,我希望TCG插件有更多的功能。

我很高兴你找到了一种方法来实现这一点。我得出的结论是,这是不可能的,至少使用QEMU插件接口提供的工具是不可能的。对于我的应用程序,我可以不使用它,除了那些dify缓存状态。这将非常有帮助,所以谢谢你。