在ESXi中调试运行虚拟机的vmx程序(How to debug vmx in ESXi)
ESXi自带一个子linux系统, 虽然能实现一部分功能, 但是目前为止, 依然没有公开的教程说过如何调试vmx进程, 本篇教程将分享我的研究成果, 帮助大家轻松调试虚拟机进程.
最简单的方法
首先, ESXi 自带一个gdbserver, 所以最简单的方法就是直接跑起程序, 再用gdbserver attach它. (最好用老一点的gdb, 比如gdb 7.8)
跑起虚拟机, 查看vmx对应的进程id
1
2
3
4
5
6
7[root@192:~] ps|grep vmx
70639 70639 vmx
70643 70639 vmx-vthread-706
70644 70639 vmx-filtPoll:c7
70645 70639 vmx-mks:c7
70646 70639 vmx-svga:c7
70647 70639 vmx-vcpu-0:c7gdbserver attach 上去
1
2
3
4
5
6
7
8
9
10
11[root@192:~] gdbserver --attach :8808 70639
Attached; pid = 70639
!gdb_connected()
!gdb_connected()
!gdb_connected()
!gdb_connected()
[root@192:~] gdbserver --attach :8808 70639
Attached; pid = 70639
!gdb_connected()
Listening on port 8808一定要保证出现
Listening on port
, 不然 ctrl+c 中断, 再重试就好, 目标进程不受影响.找一台可以使用gdb的机器, 把ESXi中的vmx文件拷贝到机器中, 然后使用如下命令连接
1
2
3
4
5
6
7
8
9
10[root@192 vv]# gdb -q
gdb$ file Desktop/vmx-7.0-15843807.elf
Reading symbols from /home/vv/Desktop/vmx-7.0-15843807.elf...Missing separate debuginfo for /home/vv/Desktop/vmx-7.0-15843807.elf
(no debugging symbols found)...done.
gdb$ target remote 192.168.170.240:8808
Remote debugging using 192.168.170.240:8808
=> 0x8ce2771248 <__libc_ifunc_impl_list+3304>: cmp rax,0xfffffffffffff000
0x8ce277124e <__libc_ifunc_impl_list+3310>: ja 0x8ce2771275 <__libc_ifunc_impl_list+3349>
gdb$这样就可以正常调试了
另一种方法-使用自己编译好的gdb
如果自带的gdbserver 不太好用, 那也可以自己源码静态编译一个gdb版本拷贝过去, 然后直接用.
自己源码编译一个gdb, 或者用我编译好的gdb7.8 no python 拷贝到esxi上
如果要自己编译支持带python的gdb, 先下载python源码. 使用
./configure --prefix=/home/vv/python; make; make install
编译安装python到/home/vv/python.然后下载gdb源码, 安装lzma开发组件
yum xz-devel texinfo
, 使用./configure --prefix=/home/vv/gdb --enable-static --with-python=/home/vv/Desktop/python --with-lzma;make
编译, 成功后make install
安装. 其它操作参考gdb10.2里给出的脚本.如果想编译11.0之后的gdb, 需要做一下修改, 修改如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20enum target_xfer_status
linux_nat_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
...
if (object == TARGET_OBJECT_MEMORY)
{
...
- return linux_proc_xfer_memory_partial (readbuf, writebuf,
- offset, len, xfered_len);
+ enum target_xfer_status ret = linux_proc_xfer_memory_partial (readbuf, writebuf,
+ offset, len, xfered_len);
+ if(ret == TARGET_XFER_OK){return ret;}
}
return inf_ptrace_target::xfer_partial (object, annex, readbuf, writebuf,
offset, len, xfered_len);
}在11.0之后的版本读取目标进程内存时, 默认从/proc/pid/mem读取, 而esxi上是没有这个文件的, 所以, 除非修改它的实现, 否则之后的版本不适合在esxi上用.
最好还是用7.8的版本, 否则容易有奇奇怪怪的问题
运行起虚拟机
运行gdb, 一般会告诉你缺失libtinfo.so.5文件或者libncurses.so.5, 最简单的方法就是创建一个软链接, 把它自带的一个文件软链接成缺失的文件.
1
[root@192:~] ln -s /lib64/libncurses.so.5 /lib64/libtinfo.so.5
或者从centos 7 3.10内核的系统中拷贝一个过去放在lib64目录下.
使用gdb调试
1
2
3gdb$ file /bin/vmx
gdb$ set architecture i386:x86-64:intel
gdb$ attach xxxxx
以下是编译的带python 2.7 的gdb7.8的分块包(因为github最大支持25M), 可以通过cat gdb78_p.tar.xz.* > gdb10.2.tar.xz
合并他们
注意事项
如果发现ctrl+c不好使, 那么就把虚拟机的cpu个数设置为1. 如果还是不好使, 建议重新选个guest安装测试.
其他
以下命令发表调试vmx
1 | apid=`ps|grep -m 1 "vmx"|cut -d " " -f 1`;gdb -ex "file /bin/vmx" -ex "handle SIGPIPE nostop noprint pass" -ex "attach $apid" -ex "shell echo \"set \\\$vmx=0x\$(cat /proc/\$(ps|grep -m 1 vmx|cut -d ' ' -f 1)/maps|grep -m 1 vmx|cut -d '-' -f 1)\">/tmp/cmd" -ex "shell echo \"set \\\$stk=0x\$(cat /proc/\$(ps|grep -m 1 vmx|cut -d ' ' -f 1)/maps|grep -m 1 stack|cut -d '-' -f 1)\">>/tmp/cmd" -ex "source /tmp/cmd" -ex "shell rm /tmp/cmd" |