Showing posts with label qemu. Show all posts
Showing posts with label qemu. Show all posts

Tuesday, November 12, 2013

pass QEMU monitor commands to virsh


Virsh supports qemu-monitor-command to pass any QEMU monitor commands. Following is an example:

virsh # qemu-monitor-command 45 --hmp info cpus
* CPU #0: pc=0xffffffff8144d27a thread_id=19994

"45" is the domainID
"--hmp" tells the virsh to use human readable mode
"info cpus" are QEMU monitor commands, you can use any supported by QEMU. 


Monday, October 10, 2011

QEMU : change cdrom

http://en.wikibooks.org/wiki/QEMU/Monitor#change

(qemu) info block
ide0-hd0: type=hd removable=0 file=/path/to/winxp.img
ide0-hd1: type=hd removable=0 file=/path/to/pagefile.raw
ide1-hd1: type=hd removable=0 file=/path/to/testing_data.img
ide1-cd0: type=cdrom removable=1 locked=0 file=/dev/sr0 ro=1 drv=host_device
floppy0: type=floppy removable=1 locked=0 [not inserted]
sd0: type=floppy removable=1 locked=0 [not inserted]
(qemu) change ide1-cd0 /path/to/my.iso
(qemu) change ide1-cd0 /dev/sr0 host_device

Tuesday, August 17, 2010

用GDB+QEMU找WINDOWS KERNEL BASE的方法






目标:找到WINDOWS KERNEL BASE ADDRESS.

环境+工具: LINUX HOST, GDB, QEMU , WINDOWS XP VM
方法:

1. 启动 QEMU WINDOWS VM. 然后按 CTL+ALT+2 , 切换到 QEMU MONITOR. 输入 gdbserver 1234

2. On Linux host, start gdb, then type "target remote localohost:1234". Then the Windows VM is debugged by GDB.

3. On qemu monitor, type "info registers", then look fs segment, find its base address, (the second number), as shown in the figure1. This is the address of "kpcr", it is 0xffdff000 on the test VM.

4. Then get the value of KdVersionBlock :
kdversionblock = Dword(kpcr+0x34). It is 0x8054c738 on the test VM.

5. Then get the "kernbase" :
kernbase = Dword (kdversionblock+ 16). It is 0x804d7000 on the test VM.

6. Verify that is the correct address. Should see 0x4d 0x5a, 0x90 as the signature of the pe file.

(step 4,5,6 is shown in the figure 2).

Thursday, May 27, 2010

How to debug Linux kernel using QEMU?

How to debug Linux kernel using QEMU?
1. Install QEMU and install a QEMU VM, the Linux on VM is the one being debugged.
2. Enable some debug configurations, then recompile the kernel. The debugging configurations is described on LDD3 (Linux device driver), chapter 4.
3. Start QEMU VM, use –S argument. It means the VM will be suspended when start.
4. Click on the window of the QEMU VM, press ctrl+alt+2 to switch to QEMU monitor, then type: gdbserver 1234. This will start gdbserver built in QEMU and it listens on the port 1234. Then press “c” to “continue”. Then press alt+ctrl+1 to switch back to OS console.
5. Start a GDB on the host. To get the symbols of the linux kernel, put the source files of the compiled kernel on the same path on the host. Use “gdb vmlinux” to start gdb. Note the vmlinux is an uncompressed file and its size is about 30MB. If it is too small, it may not have necessary debug symbols.
6. In gdb command line, type: “target remote localhost:1234”. This 1234 is the port number used in the gdbserver in step 4.
7. Press “enter”, then the VM should be stopped, and gdb will display some source files, telling where the current function is.
8. To setup a breakpoint, use “b xxx” in gdb, then press “c” to continue.

Thursday, February 25, 2010

How to find all processes in Linux manually

How to find all processes in Linux manually

Linux kernel already provides a MACRO called for_each_process to go through each process. However, you may need to find all the processes manually sometimes. Following is the method:

Environment:

QEMU 0.10.2
QEMU VM: Cent OS 5.3 (Linux 2.6.18)
ARCH :X86-32

Basic idea:

We know that every process has a task_struct in Linux. The task_struct has a member called “tasks”. It is a list_head and all the processes are linked together by task_struct.tasks.

Therefore, to find out all the processes, we could find one task_struct and then follow the tasks member. Other useful members in task_struct are: pid (it is similar to thread id on Windows), tgid ( it is similar to process id on Windows), comm (command line, can be used as process name ).

Next, we are going to use QEMU to find all the processes manually from QEMU monitor. In GDB, we could use “p task->tgid” command to print out the tgid. But QEMU does not support that. So we have to know the exact offset for each interesting member of task_struct.

To find out the offset for members such as tasks, pid, I use a kernel module to print out them. Following is the result: (pid =0xbc means the offset of pid in tasks_struct is at 0xbc)

pid = 0Xbc
tgid = 0Xc0
comm = 0X1AC
tasks = 0X80

The next thing we need to know is how to find the first task_struct. You can read ULK3 or LKD2 to find the answer. In sum, find esp first, in QEMU, esp can be obtained by using “p $esp”, let’s say it is 0xc100,4566. Set the low 13bit of the esp to 0, we get 0xc100,4000. This is the value of “current”, and it’s first member is the *task_struct.

OK, let’s do a real experiment :
1) Setup a QEMU VM with CentOS 5.3 installed as the guest OS. And run it.
2) Press alt+ctrl+2 to switch to QEMU monitor. Then type “stop” in the QEMU monitor. This stops the QEMU emulation so that we don’t need to worry about the memory changes due to a process exit.
3) Type p$esp to find esp. It is 0xc3a94f78 in my experiment.
4) Find THEAD_INFO . That is to set the low 13bit of esp to 0. We got 0xc3a94000
5) x /20w 0xc3a94000 . This will show the content of THREAD_INFO. The first member is the *task. The result is 0xc3aaa370. (Note that, sometimes the value here might be 0, just press “c” to let QEMU continue and “stop” to try more times.)
6) Now we know the address for task_struct, then it is easy to find tgid, tasks and comm. For example, pid is at 0xc3aaa42c (task_struct+0XBC). Note that when checking the content of “comm”, use following command in QEMU : x /20b 0xc3aaa51c. Otherwise, the byte order is reversed by QEMU.
7) Now we know the info about the current process. To find out the next one, just follow task_struct->tasks. Note that the address of task_struct->tasks->next is not the base address of task_struct. The base address of next task_strcut is 0x80 smaller. Then you can repeat the above steps to find out all the processes.

Wednesday, January 27, 2010

QEMU小实验:手工遍历所有进程的方法

QEMU小实验:手工遍历所有进程的方法

在内核中已经提供了遍历所有进程的方法,比如用for_each_process宏。但是如果你想加深对这部分的了解,那么可以不用这个宏,完全手工遍历一遍。下面介绍了在QEMU中,利用QEMU MONITOR,手工找出所有PROCESS的方法

环境:
QEMU 0.9.1
QEMU VM: CENT OS 5.3 (LINUX 2.6.18)
ARCH :X86-32

主要思路:
我们已经知道LINUX中的所有进程都对应一个TASK_STRUCT. 同时这些TASK_STRUCT里面有一个成员叫做TASKS。它的类型是一个LIST_HEAD(有NEXT, PRE2个成员,构成一个双向链表)。所有的进程就是通过这个TASK_STRUCT里的TASKS连接在一起的。

想遍历进程的话,可以找到一个上面说的结构,然后顺着链表一个一个找下去。另外,还有一些重要的信息在TASK_STRUCT中。常用的有PID(线程ID), TGID(进程ID), COMM(进程的命令参数)。
(关于PID, TGID,可以看下面这个帖子:http://linux.chinaunix.net/bbs/thread-1155667-1-1.html

如果是在GDB里,那么找到了TASK_STRUCT之后,可以直接用 p task->pid 的方法来把PID之类的打印出来。但是我们的目的就是不用GDB的功能,而只用QEMU MONITOR的功能,纯手工的找出PID这些成员。

这样一来,我们需要自己计算下PID, TGID等成员在TASK_STRUCT中的偏移量。怎么算呢?最天真的办法是按照 .H 文件里TASK_STRUCT的声明,自己一个一个算过去,比如一个CHAR占一个字节,一个INT 4个字节等。但是由于TASK_STRUCT是一个很大的结构(包括几十或者上百个成员),同时考虑到编译的时候还有对齐的问题。这样手工算可以说既费力又不一定对。

最厉害的办法是自己写个类似的C编译器,直接把编译后的输出打印出来。感兴趣的可以看看CIL(C Intermediate Language)。但是CIL还是有点麻烦的。它是用OCAML语言写的。我不是很熟悉。

于是我采用了一个比较折中的办法:自己写个KERNEL MODULE, 在这个MODULE里直接定义一个TASK_STRUCT,然后把感兴趣的那些成员的地址和基地址都打印出来。或者直接把偏移量打印出来。

我就是用上述办法得到了几个关键成员的偏移量:
(前面是TASK_STRUCT里的成员,后面是它距离TASK_STRUCT基地址的偏移量)
pid = 0Xbc
tgid = 0Xc0
comm = 0X1AC
tasks = 0X80

还有一点,我们怎么找到第一个TASK_STRUCT呢?可以看这篇文章(如何找出CURRENT):
http://linux.chinaunix.net/bbs/viewthread.php?tid=1147973&extra=

好了,万事具备,开始行动吧。
1) 运行一个QEMU VM。我是在WINDOWS HOST上跑的QEMU. 在LINUX上也可以跑QEMU。但是LINUX上的QEMU有一点不好,那就是它的QEMU MONITOR的大小是固定的。太小了。而在WINDOWS上面,QEMU MONITOR可以变得很大。

2) 按ALT+CTRL+2, 切换到QEMU MONITOR. 输入STOP. 这样QEMU 就会暂停下来了。这样的好处是你可以花很多时间来遍历进程。而不用担心某个进程结束后,带来的地址无效的问题。

3) p $esp :找出当前的ESP。我实验的时的输出是 0xc3a94f78

4) 找出THREAD_INFO:也就是把ESP与上0XFFFFE000。得到0xc3a94000

5) x /20w 0xc3a94000。显示的这个内容的第一个指针(前4个字节)就是当前进程的TASK_STRUCT。因为THREAD_INFO里的第一个成员就是struct task_struct *task
我这里得到的结果是0xc3aaa370。

(注意:有的时候这个地方显示的数据全都是0。我怀疑是因为进程正在切换中,内核栈刚刚清空。碰到这种情况,可以在QEMU MONITOR里输入c, 让QEMU继续跑一段时间,然后输入stop. 从头开始。有时要多试几次)

6) 找到了TASK_STRUCT之后,根据前面找到的偏移量,可以方便的找到PID, TGID, COMM, TASKS 等成员的值。比如PID的位置在0xc3aaa42c (TASK+0XBC)。
注意,在看COMM的时候,要用下面这个命令: x /20b 0xc3aaa51c. 否则的话,QEMU会把数据当成DWORD处理,并自动转换Endian. 使得看到的字符串的顺序是反过来的。

7) 这样一来,当前进程的信息已经知道了 。在我的输出中,PID,TGID=0,COMM=SWAPPER. 我们开始找下一个。下一个进程是通过TASK_STRUCT->TASKS 连接在一起的。有一点要注意,TASK_STRUCT->TASKS->NEXT中的地址不是下个TASK_STRUCT的起始地址,而是下个TASK_STRUCT中的TASKS的地址。所以有了这个地址后,要先减去0X80才得到基地址。然后就可以用上面的方法找出PID, TGID, COMM来了。

Thursday, November 5, 2009

Using qemu to find out physical address of a given virtual address for Xen

Using qemu to find out physical address of a given virtual address for Xen

Environment: Xen 3.3 32bit PAE is installed as a QEMU virtual machine.
Input: 0xc0100000 (the virtual address of domain 0 kernel)
Output: the physical address of 0xc0100000.

Process:
1. Use "info registers" cmd in qemu monitor to get cr3. cr3 is 0x29cd00. This is the physical base addr of page directory pointer table (PDPT).
2. Get the top two bits of virtual address; it is the index for page directory pointer entry.
For 0xc0100000, the highest btye is 0xc, which is 1100(b). So the index is 11(b) = 3 .
3. The length of one entry of PDPT is 64bits (intel cpu manual 3a,3.8.5) = 8 byte. 3*8=24(d) = 0x18.
4. cr3+0x18 contains the entry for page directory table.
cr3+0x18 = 0x0029cd00+0x18 = 0x0029cd18.
xp /20hx 0x0029cd18 = 0x390b 6001. This is the base addr for page dir table.
5. Bits 21 to 29 of virtual address is the index for page dir table.
For 0xc010000, the top 4 bytes are 1100,0000,0001,0000 (b). Bits 21 to 29 are:00,0000,000(b). That is 0. So the index for page dir table is 0.
6. xp /20hx 0x390b,6000 (the lower byte(s) contains some flags, just ignore them for now.)
The output is 0x3dbc,a067.
7. Bits 20 to 12 of virtual address is the index for page table. (For 2MB pages, it is different)
That is 1,0000, 0000(b), which is 0x100. Since each entry is 8 byte (64bits). The position for page tabe is 0x100*8= 0x800.
8. The lower bits of 0x3dbc, a067 are some flags. Just ignore 067 for now. The physical address for page table is
0x3dbc,a000 + 0x800 = 0x3dbc,a800.
xp /20hx 0x3dbc, a800. The output is 0x3d10,0063. Again, the lower bits are flags. So we get final result: 0x3d10,0000. (I skipped the computation for offset with a page.)

Note: To verify that they are actually point the same data, use "x" and "xp" cmd in qemu monitor to show their content. E.g. x /20hx 0xc0100000 , and xp /20hx 0x3d100000. The output should be the same.

Reference:
Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 3A

Tuesday, September 29, 2009

虚拟地址到物理地址的转换过程

今天在QEMU上做了下实验。手工跟踪了下虚拟地址到物理地址的转换,又弄清楚了一些。下面记录下实验过程。

目的:给出虚拟地址0XC100,0000. 找出它的物理地址(我们已经知道答案是0X0100,0000. 但是要看一下是怎么得出这个结论的)。

环境:QEMU 0.9.2. 虚拟机是LINUX 2.6.18

方法及步骤:
1)在QEMU里按ALT+CTRL+2。切换到MONITOR模式。输入:info registers得到CR3内容:0x1132b000. 这个地址就是PAGE DIR TABLE的起始地址。
2) 虚拟地址的 C1加上后面2个0 决定了它在PAGE DIR TABLE里的位置。C1后面加2个0(总共10BIT) 翻译成2进制就是 1100,0001,00. 也就是十进制的772,16进制的304.
3)PAGE DIR TABLE里的0X304项的地址应该是 0X304*4=0XC10. 因为每个PAGE DIR ENTRY占4个字节。并且X86 CPU是按照字节寻址的。
4)查看 PAGE DIR TABLE里0X304的内容。在QEMU里输入xp /10hx 0x1132bc10 ( 0x1132bc10 =cr3+0xc10). 发现这个地址的内容是0X0130,F163. 注意X86是LITTLE ENDIAN的。
5)0X0130F (PAGE DIR ENTRY 的前20 位)是PAGE TABLE 的基地址。后面的是一些FLAG. PAGE TABLE的真正地址要再乘以0X1000. 所以PAGE TABLE的物理地址是 0X0130, F000.
6) 这时在看虚拟地址的中间10位。在本例中都是0。所以只要看PAGE TABLE的第一个ENTRY就可以了。用 xp /10hx 0x130f000. 发现内容是 0X0100,0163.
7)在 0X0100,0163 中,前20位是PAGE FRAME NUMBER. (后面的163是FLAG)其真正的地址应该再乘以0X1000。所以对应的地址就是0X0100,0000。由于虚拟地址的后面12位都是0,所以最后的真正物理地址就是0X0100,0000。也就是正确答案。

最后,几个想法:
1)在PAGE DIR, PAGE TABLE里放的是物理地址相关的或者物理的PAGE FRAME NUMBER. 这个是很容易理解的。如果放的是虚拟地址,那么又要用到另外一个PAGE DIR, PAGE TABLE来解释。结果就变成死循环了。
2)由于0XC100,0000在本例中是内核的起始地址,所以什么时候切换到QEMUMONITOR都没有关系。所有的进程这部分都一样的。我后来又转换过一次。第二次的CR3地址不同,也就是说此时运行的是另外一个进程。但是它的PAGE DIR ENTRY的内容和第一个是一样的。
3)如果是看虚拟地址0XC000,0000的话,结果有点奇怪。我猜是由于最开始的物理地址和BIOS啥等有关。目前还没完全搞清楚。

Saturday, September 12, 2009

change CD-ROM in QEMU

http://www.chkh.com/Article/HTML/19486.html

在qemu中按ctrl+alt+2切换到qemu monitor模式 输入?或help可以查看可用命令及使用说明。(在其他版本的qemu中,运行qemu加载OS后,这个shell就会自动变成qemu monitor模式)change device filename -- change a removable media看来它就是用来换盘的了:

change ide1-cd0 /rhel4/EL_disc2.iso

http://blog.chinaunix.net/u/7793/showart_1793074.html
在用Qemu安装系统的时候,需要切换安装盘,除了GUI的操作,可以在控制台里面通过命令操作,但是有一点注意。change命令里面的对象,cdrom 的 device名为:ide1-cd0 而不是cdrom 了。

Tuesday, September 8, 2009

QEMU core functions call map

cpu-exec.c
static TranslationBlock *tb_find_slow(target_ulong pc, target_ulong cs_base, uint64_t flags)

tb_gen_code()

exec.c
cpu_gen_code()

translate-all.c
gen_intermediate_code()

target-i386/translate.c

Wednesday, July 15, 2009

Install QEMU on CentOS 5.3 from src

0. download qemu from qemu.org.
tar xzf qemu-0.10.5.tar.gz
1. Download zlib from http://www.zlib.net
tar xzf zlib-1.2.3.tar.gz
cd zlib-1.2.3
./configure
make
make install
2. Install SDL develop lib
yum install SDL-devel
3. cd qemu-0.10.5
./configure
make
make install

Friday, July 10, 2009

VM in VM: QEMU, Xen, VMware ESXi and HyperV

I am trying to test some virtualization technologies. I don't want to install them on the real hardware directly. It is hard to change and maintain. So I want to install a VM in another VM. Following is a short summary:

----------------------------------Xen------------ Hyper-V--------- VMware ESX i
Underlying virtualization:
QEMU 0.10.5 -----------------\/--------------- X-------------------------- X
Virtual Box 3 ------------------?-----------------X-------------------------- X
VMware WS 6.5 --------------\/----------------?---------------------------- \/

It means Xen can run in a QEMU VM, but hyper-v and ESXi cannot run on current QEMU.

Tuesday, July 7, 2009

Friday, June 19, 2009

用QEMU+GDB 调试LINUX KERNEL的方法

1。安装QEMU,安装个LINUX虚拟机。被调试的是虚拟机。
2。重新编译虚拟机里LINUX KERNEL,打开DEBUG相关设置,具体设置可以看LDD3的第四章
3。用QEMU 启动被调试的虚拟机的时候,加上 -S 参数。注意是大写S,表示虚拟机一启动起来就先暂停(SUSPEND).
4。选中QEMU那个虚拟机,按 CTL+ALT+2切换到控制窗口,然后输入
gdbserver 1234. 意思是启动GDBSERVER,同时端口为1234。然后这时可以按c, 让QEMU继续运行。然后按CTRL+ALT+1 切换回虚拟机本身的显示。
5。在HOST(主机)上面启动一个GDB。如果要看LINUX KERNEL SYMBOL的话,最好在和虚拟机里编译LINUX KERNEL同样的路径上放上KERNEL的源码。
在启动GDB 的时候,用 gdb vmlinux 来启动。其中的vmlinux 是没压缩过,并且带符号表的格式,大小应该为30M 以上。
6。在GDB 里,输入 target remote localhost:1234。 这里的1234是和QEMU里的设置相对应。
7。回车,这时虚拟机应该被停了下来,同时在GDB里会显示一些随机的源码,显示GDB停在了什么地方。
8。这时,在GDB里,可以用b xxx设置断点,然后按c继续运行。
9。如果虚拟机已经运行了一半,这时想停下来加断点,可以在GDB里按CTRL+C.

Tuesday, January 27, 2009