vs不能调试_使用Visual Studio调试zsim模拟器

正值暑假,准备做一些体系结构方面的实验。之前使用的模拟器是GEM5[1],使用起来非常不方便,无法并行模拟不说,运行起来还贼慢。一个实验全系统模式(Full System, FS)下需要跑俩星期,而且经常跑到一半发现参数错了或者需要代码调整,又得重新开始,费工费力。即使是使用系统调用模式(System-call Emulation, SE),也难以通过IDE进行DEBUG。虽然也略懂一些gdb的调试方法,但是与IDE的图形化调试相比效率还是低了很多。

为了提高一下科研效率,想要更换一款更加易于修改、而且运行快一点的模拟器。通过调研,发现了一款模拟器,zsim[2]。zsim同样使用了SE的执行模式,并且效率非常高,支持多线程并发模拟。可惜的是,zsim与GEM5一样,都使用了基于python的scons[3]进行代码构建,虽然一直不理解为什么那么多程序一定得用scons构架代码,但是scons对IDE调试支持的缺乏对希望使用IDE的我来说是非常不便的。

还好,zsim的代码量比较少,而且大部分都是c/cpp,只需要少量修改即可适用于IDE调试。经过两天的不断尝试,终于完成了。现将过程记录下来,供需要使用IDE调试pintool或者zsim的小伙伴参考。


准备工作

从学习编程以来一直用Visual Studio进行编程和调试,用着顺手,所以准备使用VS作为IDE。由于zsim需要Linux下的头文件<syscall.h>,需要远程连接Linux。这里使用了VisualGDB[4]作为远程连接的工具。

windows端:

安装Microsoft Visual Studio 和VisualGDB
XMing [5](可选,用以将结果输出在其他terminal上)
这里使用的版本是VS2013专业版和VisualGDB5.1.6

Linux端:

使用Ubuntu 14.04.6 server系统,server版本没有GUI可以大量减少空间占用(虚拟机用户福音)

尽量不要使用docker安装ubuntu,否则运行zsim会出现如下错误

[panic] personality() call failed: Operation not permitted

搜索后发现似乎与docker相关[6],尚未解决,最终换了虚拟机版本的Ubuntu

安装完ubuntu后,首先安装必要的ssh组件:

sudo apt-get update
sudo apt-get install openssh-server

随后运行ssh服务,如果使用root登录,记得在/etc/ssh/sshd_config文件中添加PermitRootLogin yes

sudo service ssh start

在windows终端中测试ssh连接畅通,并保存RSA key:

ssh user@ubuntu-host-ip

随后,通过ssh可以在Ubuntu系统中安装zsim相关依赖包

sudo apt-get install gcc g++ gdb git
sudo apt-get install scons libconfig-dev libconfig++-dev
sudo apt-get install libhdf5-dev libhdf5-serial-dev
sudo apt-get install libelfg0 libelfg0-dev

下载pin[7],这里选择的是2.14版本

7cd03f34801887e3a1b1f62c1e5eb13d.png
tar -xvf pin-2.14-71313-gcc.4.4.7-linux.tar
export PINPATH=/vine/pin-2.14-71313-gcc.4.4.7-linux(指向解压后pin的位置)

下载zsim,并在ubuntu上build成功一次,编译debug版本(添加--d选项)

git clone https://github.com/s5z/zsim.git
cd zsim
scons --d -j8

编译完成后,将整个zsim-master文件夹拷贝到Windows上备用

如果在Ubuntu上运行出现以下错误

vine@ubuntu-linux:/vine/zsim$ scons --d
scons: Reading SConscript files ...
Building debug zsim at build/debug
gcc: error: /usr/include/asm/unistd.h: No such file or directory
gcc: fatal error: no input files
compilation terminated.
Traceback (most recent call last):
  File "../../misc/list_syscalls.py", line 7, in <module>
    denseList = ["INVALID"]*(max([num for (num, name) in sysList]) + 1)
ValueError: max() arg is an empty sequence

解决方案如下,修改misc/list_syscalls.py:4,以避免后面-Werror产生的错误

syscallCmd = "gcc -E -dD /usr/include/asm/unistd.h | grep __NR"
修改为:
syscallCmd = "gcc -E -dD /usr/include/asm-generic/unistd.h | grep __NR"

1.准备工作立libzsim.so库文件的VS工程

打开VS,新建Linux Project,命名为libzsim

dcdad365f26be4ede1b546aace35a0f5.png

选择Application-Use GNU Make,语言选择c++11及以上

516ce4cdf65bbf3060c21afb463e084b.png

配置好ssh,下一步

887de291bb30153dca576a58d13ff2d0.png

Transferred files这里修改成如下内容,以传输全部文件到ubuntu上

*.*;*

212e96c36cb51a747d6a04a2cdd8ad7b.png

删除默认的.cpp文件,选择删除而不是移除

2add7df4567ac377738ed25db9dcc196.png

由于zsim基于pin,源码中包含多个main入口,因此不能直接将整个工程拖到VS中,需要删除额外的文件。参与编译libzsim.so的源文件如下,可以通过在src/SConscript中加入print查看

961bc59b316b932e3d15f79a1501efd7.png
在src/SConscript中添加print查看每个目标需求的源文件

编译libzsim.so需要的cpp文件如下:

c21a212a127e8a93d9acf86a25842deb.png

只保留需要的c/cpp文件和全部.h头文件

需要注意的地方
删除: virt/syscall_name.cpp.in
确认: virt/syscall_name.cpp已经生成(在ubuntu上编译一次后生成)
将zsim/build/debug/version.h也添加至工程中

保留原有文件夹结构先复制到VS工程文件夹中,再拖入vs工程中,这样只有一个main入口,并且结合先前传输文件的设置,VisualGDB会将全部文件和文件结构保留传输到ubuntu上

1676b0db7338a3d1080172bc008a2681.png

修改galloc.cpp:35,删除原来的#include语句,将g_heap/dlmalloc.h.c的文件内容全部复制到这个位置,并将g_heap/dlmalloc.h.c从工程中删除

#include "g_heap/dlmalloc.h.c"

如果使用原有的#include方式,将产生multiple definition错误

最后修改工程属性(工程上点右键->VisualGDB Project Properties),按照下面设置

9a5487f2c2784f87a2c740c783890cfb.png

Makefile settings选项卡:

05c1aa74c8a0c980d978d26e95cc615f.png

Project type选择Shared library, Output file name填libzsim.so

删除Preprocessor macros中的"DEBUG=1",否则会和源代码中的DEBUG宏重复定义产生warning,导致-Werror产生错误(或者在CXXFLAGS中删掉-Werror)

Include directories:

/vine/pin-2.14-71313-gcc.4.4.7-linux/source/include/pin
/vine/pin-2.14-71313-gcc.4.4.7-linux/source/include/pin/gen
/vine/pin-2.14-71313-gcc.4.4.7-linux/extras/components/include
/vine/pin-2.14-71313-gcc.4.4.7-linux/extras/xed-intel64/include
/tmp/VisualGDB/c/Projects/libzsim/libzsim(工程文件在ubuntu上的目录位置)

Library directories:

/usr/lib
/usr/lib/x86_64-linux-gnu
/vine/pin-2.14-71313-gcc.4.4.7-linux/extras/xed-intel64/lib
/vine/pin-2.14-71313-gcc.4.4.7-linux/intel64/lib
/vine/pin-2.14-71313-gcc.4.4.7-linux/intel64/lib-ext
/usr/local/lib
/usr/lib

Library names:

config++ pin xed pindwarf elf dl rt hdf5 hdf5_hl

CXXFLAGS:

-g -O0 -std=c++0x 
-Wall -Wno-unknown-pragmas -fomit-frame-pointer -fno-stack-protector 
-MMD -DBIGARRAY_MULTIPLIER=1 
-DUSING_XED -DTARGET_IA32E -DHOST_IA32E 
-Werror -fPIC -DTARGET_LINUX 
-DPIN_PATH="/vine/pin-2.14-71313-gcc.4.4.7-linux/intel64/bin/pinbin" 
-DZSIM_PATH="/tmp/VisualGDB/c/Projects/libzsim/libzsim/Debug/libzsim.so" 
-DMT_SAFE_LOG

其中有一个需要注意的地方就是-DZSIM_PATH需要修改为实际生成的libzsim.so的位置

-DZSIM_PATH="/tmp/VisualGDB/c/Projects/libzsim/libzsim/Debug/libzsim.so"

LDFLAGS:

-Wl,-gc-sections 
-Wl,--hash-style=sysv 
-Wl,-Bsymbolic 
-Wl,--version-script=/vine/pin-2.14-71313-gcc.4.4.7-linux/source/include/pin/pintool.ver 
-shared

注意:上面几项内容中均不含换行,换行只是为了介绍清楚方便大家核对

点击确认后,如果出现Toolchain Test Failed,但是Detailed log里面又没有内容,可以直接Ignore(如下图所示),如果有内容需要按照内容修改。常见的错误就是因为没有安装依赖,如libconfig++,libhdf5等,或者路径错误等

020828095f47fbb59d1373a090b9b403.png

Debug settings选项卡

1d9c38f970cfc424c609a2478df94999.png

这里Start GDB in the following mode选择"Attach to an existing instance", Executable with symbols输入pin里面的intel64/bin/pinbin,我这里是

/vine/pin-2.14-71313-gcc.4.4.7-linux/intel64/bin/pinbin

进程附加选择"Ask for a process to attach when debugging is started",如果安装了xming的,可以选择在Forward program output to中选择xming

勾选"Run debugger as root with sudo"

此时,点击“生成->生成解决方案”即可以生成libzsim.so文件


3.生成zsim 的VS工程

在解决方案资源管理器中“解决方案”上点右键,新建Linux Project工程,命名为zsim. 和前面libzsim.so工程的新建方法一致,然后删除默认加入的.cpp文件。注意Files to transfer修改为

*.*;*

新建项目完成后,在zsim项目上点右键->生成依赖项->项目依赖项,勾选libzsim,保证libzsim.so在每次编译时先于zsim生成

08a7252d9d352f6f4be2046b1b6a105f.png

zsim编译需要的cpp文件如下:

c993c61333d6195c5aa81a079f44eb69.png

将这些.cpp文件和需要的.h文件,以及tests文件夹一起,保留文件夹结构,先复制到Windows上zsim工程的工程目录下,再拖进zsim项目中

32439c666370b5a2393ccc3a222d1f71.png

需要确认tests文件夹下的几个文件也出现在工程文件目录中,这样VisualGDB可以将tests文件夹也复制到生成目录下

最终zsim工程文件如下所示:

416c8cb60e38957c62c6fd27f92025f2.png

最后修改工程属性(zsim工程上点右键->VisualGDB Project Properties)

bc0473de990b13a4391611d1a6d4162b.png

同样,删除Preprocessor macros下的"DEBUG=1"

Project type选择Executable,Output file name输入zsim

Include directories与libzsim.so工程一致,Library directories添加libzsim.so库文件生成文件所在位置:

/usr/lib
/usr/lib/x86_64-linux-gnu
/vine/pin-2.14-71313-gcc.4.4.7-linux/extras/xed-intel64/lib
/vine/pin-2.14-71313-gcc.4.4.7-linux/intel64/lib
/vine/pin-2.14-71313-gcc.4.4.7-linux/intel64/lib-ext
/usr/local/lib
/usr/lib
/tmp/VisualGDB/c/Projects/libzsim/libzsim/Debug

Library names:

config++ pthread zsim

CXXFLAGS:(注意需要添加--static)

-g -O0 -std=c++0x --static
-Wall -Wno-unknown-pragmas -fomit-frame-pointer -fno-stack-protector
-MMD -DBIGARRAY_MULTIPLIER=1
-DUSING_XED -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX
-DPIN_PATH="/vine/pin-2.14-71313-gcc.4.4.7-linux/intel64/bin/pinbin"
-DZSIM_PATH="/tmp/VisualGDB/c/Projects/libzsim/libzsim/Debug/libzsim.so"
-DMT_SAFE_LOG

Debug settings选项卡

b38e63f0435e4b278974cba1a00ac0b4.png

Start GDB in the following mode选择“Debug a new instance”, Main executable arguments填要运行的.cfg配置文件。如果前面保留文件夹结构将tests文件夹拖进工程中,只需要使用

/tmp/VisualGDB/$(ProjectDirUnixStyle)/tests/simple.cfg

同样,Program output可以根据xming安装情况选择

至此,zsim 的VS工程文件创建完成


4.开始DEBUG!

首先,修改zsim工程下的pin_cmd.cpp:31,添加如下内容

args.push_back("-injection");
args.push_back("child");
args.push_back("-pause_tool");
args.push_back("20");

其中“-injection child”可以根据pin的版本修改,有一些pin版本不需要添加

如果出现下述错误,则一定需要添加

vine@ubuntu-linux:/tmp/VisualGDB/c/Projects/libzsim/zsim$ ./Debug/zsim tests/simple.cfg 
[H] Starting zsim, built Wed Jul 22 09:44:07 CST 2020 (rev no git repo)
[H] Creating global segment, 1024 MBs
[H] Global segment shmid = 1605648
[H] Deadlock detection OFF
E: 4.4 is not a supported linux release
[H] Child 15168 done
[H] All children done, exiting

“-pause_tool”后的20为等待debugger连接的时间,可以适当调整

将zsim工程设置为启动项目,点击调试,找到下面的VisualGDB Remote Console

dc996d774ee8c2cba456a6e8b9af3a64.png

复制add-symbol-file及后面的内容,并添加至"VisualGDB Project Properties->GDB startup commands"中下的第二个文本框中

第二行填写b main,可以使程序自动中断在main函数上(也可以根据实际需求修改)

a552a09017b01e353e668b0f9b2c663b.png

保存配置后,通过ssh在Ubuntu上运行zsim,出现等待连接提示:

vine@ubuntu-linux:/tmp/VisualGDB/c/Projects/libzsim/zsim$ ./Debug/zsim tests/simple.cfg 
[H] Starting zsim, built Wed Jul 22 09:44:07 CST 2020 (rev no git repo)
[H] Creating global segment, 1024 MBs
[H] Global segment shmid = 1802256
[H] Deadlock detection OFF
Pausing for 30 seconds to attach to process with pid 15820
To load the tool's debug info to gdb use:
   add-symbol-file /tmp/VisualGDB/c/Projects/libzsim/libzsim/Debug/libzsim.so 0x7ffff64c90a0 -s .data 0x7ffff6d56b00 -s .bss 0x7ffff6d58ec0

修改libzsim.so工程为启动工程,点击调试,第一次会要求输入ubuntu管理员账号的密码,随后会出现进程附加选择窗口

e71826a6900cb692af0dd1bf27be4d04.png

选择Ubuntu上输出pid后对应数字所在进程(上例PID 为15820)

715ac8fecec5cb0c699fe0f528d5cf1d.png

此时会出现帧不在模块中的提示,不用担心,点击继续,等待“-pause_tool”的时间结束

2e77aa2a2220941345ddfee021581403.png

时间结束后,VS自动中断至main函数位置,此时可以开始完美DEBUG了!

c9d7e9a2d28719bf86fa1078abebf915.png

5.不太完美的一键DEBUG设置

虽然上面已经可以开始进行调试,但是可以发现过程比较繁琐:需要先通过ssh在Ubuntu上运行zsim程序,再通过VS进行.so文件的进程附加和调试。

有没有什么办法可以一键DEBUG呢?经过多次尝试,目前有一个不太完美的解决方案。

为了解决这个问题有两个思路:

-> 通过VisualGDB在zsim生成后,后台ssh运行zsim,获得需要debug的进程PID后发送给VS 的GDB进行自动附加

->进入GDB命令行后调用shell或python命令,根据shell执行结果确定PID,并返回进行附加

最终,经过多次尝试,第二种难以实现,采用第一种方法,但是不太完美

如果有小伙伴找到完美解决办法,也可以给我留言

方法如下:

找到zsim工程中的zsim_harness.cpp:235,修改为如下内容

    int cpid = fork();
    if (cpid) { //parent
	    // *****ADD
	    std::ofstream ofs;
	    ofs.open("/tmp/VisualGDB/c/Projects/libzsim/zsim/Debug/command.pid", std::ios::out);
	    ofs << "PID = ";
	    ofs << (cpid + 2);
	    ofs.close();
	    // *****END
        assert(cpid > 0);
        childInfo[procIdx].pid = cpid;
        childInfo[procIdx].status = PS_RUNNING;
    } else { //child

这里的思路为当pin程序在开始执行.cfg中配置的进程时,将进程号写入文件中,写入的目录及文件名可以自行定义

打开libzsim工程->VisualGDB Project Properties->Debug settings,将进程附加选项原本的"Ask for a process to attach when debugging is started"改成"Attach to a process with the following PID",数字默认填0

3849f73855a10665da28134e21821c19.png

选择Custom debug steps,在Custom debug actions选项卡的Before launching GDB中选择Edit..

63409318bd6c9bb8c27017fd67b5b604.png

添加第一个命令:

2dd1fbc712203eabed4e11a03050fcdb.png

具体命令为

screen -m -d /tmp/VisualGDB/c/Projects/libzsim/zsim/Debug/zsim /tmp/VisualGDB/c/Projects/libzsim/zsim/tests/simple.cfg

这个命令的作用是利用screen命令,实现ssh断开后的zsim后台运行[8]

为此需要Ubuntu安装好依赖

sudo apt-get install screen

其实还有一种方法更为完美[9],但是在我的电脑上刚开始可以,Ubuntu reboot一遍后无法后台运行了。小伙伴们可以试试,如果下面的命令可以ssh后台运行zsim,则不需要添加上面的screen命令了,添加下面这个即可

sh -c 'nohup /tmp/VisualGDB/c/Projects/libzsim/zsim/Debug/zsim /tmp/VisualGDB/c/Projects/libzsim/zsim/Debug/tests/simple.cfg' > /dev/null 2>&1 &

一般情况下ssh下执行的程序会由fork()创建程子进程,在ssh结束后,子进程也会被强制结束

需要使用ssh后台运行(即ssh session结束后,程序还需要在运行)的原因,是VisualGDB需要等待ssh执行结束后才能进行下一项(不知道新的版本有没有改进)而且无法使用ssh -f的方法强制后台保留,因此,必须让ssh又运行程序,又完全不返回内容才能继续

因此使用command & 的方法也不行,VisualGDB仍然会等待zsim完全结束后才执行附加进程命令,而那时候需要附加的进程已经没了,造成错误

上述两个命令选择一个能ssh后台执行zsim的命令之后,添加第二个命令:

dddf5d7c1d311df7c6f2d154116374f2.png

这个命令的作用是通过shell的cat命令,读取刚才zsim写入的PID文件,并设置为$AttachPID环境变量,VisualGDB再根据$AttachPID,自动附加到进程。需要注意的是这里可以设置正则表达式匹配,要和前面的文件输出格式匹配。这里使用的"PID = ?"的格式

执行的流程是这样

  1. VS点击调试
  2. 生成libzsim.so
  3. 生成zsim pintool
  4. (开始调试前)后台运行zsim,得到要DEBUG的PID,并写入到文件
  5. (开始调试前)VisualGDB读取写的PID的文件,并加载到变量$AttachPID
  6. (开始调试)GDB附加到Ubuntu上PID=$AttachPID的进程上,完成调试

这里的问题是zsim_harness.cpp:235附近,cpid和.cfg中需要执行命令间的PID关系

经过试验,在没有别的进程干扰下,是顺序关系,只需要按照图中修改代码即可

有干扰的情况,小概率会失败(所以不完美)

猜测:使用screen时,screen本身PID+1,再运行新的程序再+1,所以.cfg中最终运行的程序PID是+2的;nohup本身不影响PID,所以只需要+1?

.cfg中存在多个process的情况,根据顺序再加就可以

8f731414c16c19300ddc5909daa3503c.png

希望能帮助到想要用IDE调试zsim或者pintool的小伙伴们!

码字不易,请勿转载

参考

  1. ^1 http://www.gem5.org
  2. ^2 https://github.com/s5z/zsim
  3. ^3 https://www.scons.org
  4. ^4 https://visualgdb.com
  5. ^5 https://sourceforge.net/projects/xming/
  6. ^6 https://github.com/travis-ci/travis-ci/issues/9061
  7. ^7 https://software.intel.com/content/www/us/en/develop/articles/pin-a-dynamic-binary-instrumentation-tool.html
  8. ^8 https://serverfault.com/questions/21806/how-can-i-launch-a-screen-session-with-a-command-over-ssh-on-a-remote-server-fro
  9. ^9 https://stackoverflow.com/questions/29142/getting-ssh-to-execute-a-command-in-the-background-on-target-machine
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值