note:
0. 環境:Linux 3.1.0 / Xen 4.1.3-rc1-pre / PV DomU
1. 我啟動並執行時候 直接使用System.map裡面的init_task地址[C086F4A0],讀取的值都是0,不能得到初始進程資訊。
經過與DomU實際地址對照,發現init_task的實際地址比設定檔中的多了0x6000(不帶xen直接啟動Linux3.1核心,地址也多出0x6000)。
所以需要在初始地址上加上一個magic number: #define OFFSET 0x6000。
May 4. 重新把核心編譯了一遍,問題解決。
原來是核心與system.map不匹配。也許是我後來又編譯了新的核心,但是沒有安裝吧?
2. 模仿list_for_each,寫了一個方便vmi使用的遍曆透視的鏈表的宏 很舒服了~(限定:全域vmi變數,Guest核心虛擬位址(process=0))
addr_t vmi_next_ptr(addr_t ptr){vmi_read_addr_va(vmi, ptr, 0, &ptr); //返回*ptr的值。return ptr;}#define vmi_list_for_each(iter, head) for (iter=vmi_next_ptr(head); iter!=head; iter=vmi_next_ptr(iter))
聲明部分:
#include <libvmi/libvmi.h>#include <stdio.h>#include "stdlib.h"#define str_(x) x#define Debug(format, ...) fprintf(stderr, "%s:%d: " str_(format) "\n", __FILE__, __LINE__, ##__VA_ARGS__)#define assert_(expr_, extra_op)do { if (!(expr_)) { Debug("在函數 `%s'中: 斷言錯誤: " #expr_, __FUNCTION__); \extra_op;exit (-1);} } while (0)#define assert(expr) assert_(expr,)#define vmi_assert(expr) assert((expr) == VMI_SUCCESS)//#define OFFSET 0x6000 //no need!char os_tag[]="debian-pv";char default_name[]="debian-pv-pv-shot1";vmi_instance_t vmi;addr_t vmi_next_ptr(addr_t ptr){vmi_read_addr_va(vmi, ptr, 0, &ptr);return ptr;}#define vmi_list_for_each(iter, head) for (iter=vmi_next_ptr(head); iter!=head; iter=vmi_next_ptr(iter))
主程式
int main(){Debug("init vmi instance...");vmi_assert(vmi_init(&vmi, VMI_AUTO | VMI_INIT_COMPLETE, default_name));int tasks_offset = vmi_get_offset(vmi, "linux_tasks");int name_offset = vmi_get_offset(vmi, "linux_name");int pid_offset = vmi_get_offset(vmi, "linux_pid");Debug("linux_tasks:0x%x proc_name:0x%x pid:0x%x", tasks_offset, name_offset, pid_offset);Debug("pause the vm");vmi_assert(vmi_pause_vm(vmi));// 1. get address of init_task(idle) process in system.map// the value in System.map is c086f4a0 but actually in DomU it is at c08754a0. why??addr_t init_task_ptr = vmi_translate_ksym2v(vmi, "init_task")/* + OFFSET*/;addr_t list_head, iter;// 2. get "pointer to next task_struct" in "idle process" as list headvmi_read_addr_va(vmi, init_task_ptr + tasks_offset, 0, &list_head);vmi_list_for_each(iter, list_head){//get name & pid of next processchar *proc_name = vmi_read_str_va(vmi, iter + name_offset - tasks_offset, 0); int pid; vmi_read_32_va(vmi, iter + pid_offset - tasks_offset, 0, &pid);//print informationprintf("[%5d] %s\n", pid, proc_name);if (proc_name){free(proc_name);proc_name = NULL;}}Debug("resume vm and exit");vmi_resume_vm(vmi);vmi_destroy(vmi);return 0;}
設定檔/etc/libvmi.conf
debian-pv-pv-shot1 {ostype = "Linux";sysmap = "/boot/System.map-3.1.0";linux_name = 0x2f8;linux_tasks = 0x1c8;linux_mm = 0x1e4;linux_pid = 0x218;linux_pgd = 0x24;linux_addr = 0x78;}
運行:
viktor@buxiang-OptiPlex-330:~/proj/vmids$ sudo ./proc_list proc_list.c:20: init vmi instance...proc_list.c:26: linux_tasks:0x1c8 proc_name:0x2f8 pid:0x218proc_list.c:28: pause the vm[ 1] init[ 2] kthreadd[ 3] ksoftirqd/0[ 4] kworker/0:0[ 5] kworker/u:0[ 6] migration/0[ 7] watchdog/0[ 8] cpuset[ 9] khelper[ 10] kdevtmpfs[ 11] netns[ 12] xenwatch[ 13] xenbus[ 14] sync_supers[ 15] bdi-default[ 16] kintegrityd[ 17] kblockd[ 18] kworker/0:1[ 19] ata_sff[ 20] khubd[ 21] md[ 22] khungtaskd[ 23] kswapd0[ 24] ksmd[ 25] fsnotify_mark[ 26] ecryptfs-kthrea[ 27] crypto[ 30] kworker/u:1[ 32] khvcd[ 33] kmpathd[ 34] kmpath_handlerd[ 35] kjournald[ 70] udevd[ 127] udevd[ 134] udevd[ 399] rsyslogd[ 451] cron[ 458] sshd[ 475] login[ 476] bash[ 0] swapperproc_list.c:58: resume vm and exit