- 论坛徽章:
- 0
|
libvmi是谷歌的一个开源项目,用于查看虚拟机内部情况,如在Xen虚拟化环境下,可以在Dom0中,通过libvmi查看其它虚拟机的内存情况,如获取模块链表、进程链表等,我在这个库的一个初始化地方有点疑问,希望可以和大家一起探讨下。
- status_t linux_init (vmi_instance_t vmi)
- {
- status_t ret = VMI_FAILURE;
- if (vmi->cr3){
- vmi->kpgd = vmi->cr3;
- }
- //如果vmi->cr3=0时,将执行这个分支
- else if (VMI_SUCCESS == linux_system_map_symbol_to_address(vmi, "swapper_pg_dir", &vmi->kpgd)){//此时,从System.map文件中获取到了swapper_pg_dir的虚拟地址,并赋值给了vmi->kpgd
- dbprint("--got vaddr for swapper_pg_dir (0x%.16llx).\n", vmi->kpgd);
- if (driver_is_pv(vmi)){
- vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd); //这里通过 vmi_translate_kv2p函数将虚拟地址转化为物理地址,转到vmi_translate_kv2p函数
- if (vmi_read_addr_pa(vmi, vmi->kpgd, &(vmi->kpgd)) == VMI_FAILURE){
- errprint("Failed to get physical addr for kpgd.\n");
- goto _exit;
- }
- }
- else{
- vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd);
- }
- }
- else{
- errprint("swapper_pg_dir not found and CR3 not set, exiting\n");
- goto _exit;
- }
- vmi->kpgd = vmi->cr3;
- dbprint("**set vmi->kpgd (0x%.16llx).\n", vmi->kpgd);
- addr_t address = vmi_translate_ksym2v(vmi, "init_task");
- address += vmi->os.linux_instance.tasks_offset;
- if (VMI_FAILURE == vmi_read_addr_va(vmi, address, 0, &(vmi->init_task))){
- errprint("Failed to get task list head 'init_task'.\n");
- goto _exit;
- }
- ret = VMI_SUCCESS;
- _exit:
- return ret;
- }
复制代码- addr_t vmi_translate_kv2p(vmi_instance_t vmi, addr_t virt_address)
- {
- reg_t cr3 = 0;
- if (vmi->kpgd){//由于在“linux_init”函数中,vmi->kpgd已经被赋值为"swapper_pg_dir"的虚拟地址,所以将执行此分支
- cr3 = vmi->kpgd; //cr3被赋值为vmi->kpgd
- }
- else{
- driver_get_vcpureg(vmi, &cr3, CR3, 0);
- }
- if (!cr3){
- dbprint("--early bail on v2p lookup because cr3 is zero\n");
- return 0;
- }
- else{
- return vmi_pagetable_lookup(vmi, cr3, virt_address); //在这里面进行页表查找操作,此时的cr3为swapper_pg_dir的虚拟地址
- }
- }
复制代码
想问下大家,觉得最后那一步vmi_pagetable_lookup,它以此时cr3的值为页全局目录地址,能够查找到对应虚拟地址的物理地址吗? |
|