Decoda1.17重编译实录

最近一直在忙着开发剑网三插件,需要用到Decoda这个软件进行程序注入和调试代码。因为对Decoda原有功能并不满意,又很早的听说这个软件已经开源,决定尝试自行重编译并且改进软件功能。整个过程蛋疼的一波三折,因此作文记录之,供后来人参考。


Decoda是神马


这个高端问题可以戳这里 http://unknownworlds.com/decoda/

官网的描述是这样的

Decoda is a free and open-sourced professional development environment fordebugging Lua script in your applications (A Lua IDE). It’s familiar and fast and you’ll wonder how you ever worked without it.

总而言之 想象它就是一个高端的Lua IDE就好了..


我们的目标


和标题一样,就是重编译啦。

详细一点说:对Decoda最新版本源代码进行本地重编译,并且修改部分功能直到它可以正常运行。

在这里,我使用Microsoft Visual Studio 2010 sp1作为我的IDE。重复这点很重要——因为如果用vs13的话就不会有这篇文章了。不过由于硬件原因(我只能/只想在32位环境下工作),vs10就是我唯一的选择了。


准备工作


本着事后诸葛亮的精神,我把所有可能用到的材料都提前罗列:

> vc++集成开发环境  vs2010/08/05/12/13  当然你也可以选择其他开发环境  不过这篇文章可能无法给你带来帮助
> Decoda最新源代码  它托管在github上 地址为 https://github.com/unknownworlds/decoda 我在写这篇文章的时候程序版本为1.17beta 代码最新提交时间为 Apr.10 2014
> premake4  这是一个基于lua语法的工程配置工具 decoda工程使用premake来创建 你在github的readme中可以看到这个说明 地址为 http://industriousone.com/premake/download 请使用4.4beta以上的版本。写这篇文章时最新版本为4.4-beta5,使用4.3或更早的版本会出错 
> tinyXml源代码  它托管在sourceforge上 地址为 http://sourceforge.net/projects/tinyxml/ 虽然我承认跳跃性很大...不过它在后续的工作中是会用到的... 写这篇文章时最新版本为2.6.2 如何获取适当的版本 后面也会提到

你可以一边下载一边阅读后续的内容


重构工程文件


decoda源代码下载后请解压到你的工作空间。我使用的文件夹为 D:\Library\decoda-master

把premake4下载好,解压到上述相同目录中

为premake4创建一个快捷方式,为其添加命令行参数"vs2010",并执行。 (这里可以对应你使用的IDE版本,premake的详细用法请参考 http://industriousone.com/premake/quick-start )

成功后你会看到新创建的build文件夹



用vs10打开build\Decoda.sln 如果成功的话可以看到解决方案下有3个工程

Frontend  前端 对应Decoda的主界面工程

LuaInject  对应lua钩子库  用于嵌入宿主程序进行调试

Shared  包含两个工程共用库


这里可以直接试图重编译一下,如果编译成功就大功告成了。不过更多可能性你可能会获得这样一大批错误:

错误 252error LNK2038: 检测到“_MSC_VER”的不匹配项: 值“1800”不匹配值“1600”(AboutDialog.obj 中)D:\Library\decoda-master\build\wxmsw28d_core.lib(treebkg.obj)Frontend

百度一下可以知道 是因为程序引用obj文件编译时使用的vc运行库,与当前使用运行库版本不符。究其原因,在github上的readme已经说明:

Decoda has only been tested with the vs2013 target, however it may be possible
to compile Decoda with older versions. It is not currently possible to build
Decoda as a 64-bit executable or a non-Windows application.

所以我们需要对全部引用库进行重编译


Decoda主要使用了wxWidgets,首先对wxWidgets进行重编译。

分别用vs10打开libs\wxWidgets\build\msw\wx.sln 以及 libs\wxScintilla\build\wxscintilla.sln 解决方案,对里面所有工程进行重新编译。虽然有很多warning不过应该会一次编译成功。

这里编译时需要注意解决方案配置,对于Debug和Release会生成不同的lib文件,当然对于不同的配置,生成文件也有不同的命名规则。主程序使用debug时,这里直接选择debug编译即可 如果顺利的话可以看到libs\wxWidgets\lib\vc_lib中的lib文件已被更新。

回到主工程,至此Frontend工程应该可以顺利编译了。


下面我们需要使LuaInject工程顺利编译。因为它引用了TinyXml,我们前面下载的TinyXml就派上了用场。至于使用哪个版本,可以查看工程文件libs\tinyxml\include\tinyxml.h,寻找这样一个段落:

const int TIXML_MAJOR_VERSION = 2;
const int TIXML_MINOR_VERSION = 6;
const int TIXML_PATCH_VERSION = 2;

这里描述了tinyXml的版本为2.6.2。如果未来有变化,最好下载对应的版本。

把tinyXml源代码随便解压,并打开工程。这里我们的目的是重编译tinyXml,使得版本对应。查看libs\tinyxml\lib下的文件,可以得知我们使用了STL库。所以我们只编译tinyxmlSTL工程即可。

首先修改输出路径为decoda的引用路径。简单的打开项目的属性,如下设置:

配置属性 - 库管理器 - 常规 输出文件  修改为decoda工程lib文件夹下的对应文件
注意 对于debug和release的文件名是不同的。



修改完成后,在debug和release下分别生成,然后回到decoda下重编译LuaInject工程查看结果,vc版本的问题解决,但是遇到了新的错误:

错误 35error LNK2019: 无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用D:\Library\decoda-master\build\LIBCMTD.lib(crt0.obj)LuaInject
警告 34 warning LNK4098: 默认库“LIBCMTD”与其他库的使用冲突;请使用 /NODEFAULTLIB:libraryD:\Library\decoda-master\build\LINK LuaInject
警告 33 warning LNK4098: 默认库“MSVCRTD”与其他库的使用冲突;请使用 /NODEFAULTLIB:libraryD:\Library\decoda-master\build\LINK LuaInject

查看百度,这是因为引用库所使用的基础库和自身基础库冲突的原因

查看LuaInject的项目属性 - 配置属性 - C/C++ - 代码生成 运行库 项  默认在debug下为多线程调试 DLL(/MDd)  在Release下为多线程 DLL(/MD)。所以,对于tinyXml也需要改成相同的选项才能正常编译。


如图,对于release也要改成对应。再次重新编译tinyXml后,回到decoda,LuaInject已经可以正常编译,至此大功告成。


DIY


到了这个阶段后,我们可以考虑对Decoda进行调试编辑了

比如,使用Decoda进行Hook调试时,如果源文件为已编译的Lua二进制文件无法查看代码,可以进行如下修改。

LuaInject工程  DebugBackend::RegisterScript函数为钩住虚拟机执行新的Lua脚本时的回调。修改此文件

    // Check if this is a compiled/binary file.
    if (source != NULL && size >= 4)
    {
        if (source[0] >= 27 && source[0] <= 33 && memcmp(source + 1, "Lua", 3) == 0)
        {
            state = CodeState_Binary;
            source = NULL;
        }
    }
段落,检查是否是编译的二进制文件。
我们可以预先声明一个ToHex函数如下:

void DebugBackend::ToHexString(std::string& strDest, const char* pData, int nLength)
{
	for(int i=0;i<nLength;i++) 
	{
		if (i%16==0)
		{
			char szBuf[12] = {0};
			sprintf(szBuf, "%08xh: ", i);
			strDest += szBuf;
		}

		char szBuf[4] = {0};
		sprintf(szBuf, "%02x ", (unsigned char)pData[i]);
		strDest += szBuf;

		if (i%16==15) 
		{
			strDest += "\r\n";
		}
	}
}
并修改原来函数段落为
    // Check if this is a compiled/binary file.
    if (source != NULL && size >= 4)
    {
        if (source[0] >= 27 && source[0] <= 33 && memcmp(source + 1, "Lua", 3) == 0)
        {
            state = CodeState_Binary;
            //source = NULL;
            std::string sb;
            this->ToHexString(sb, source, size);
            script->source = sb;        
        }
    }

即可以把二进制文件作为hex向前台传输。

下一步修改前台  在Frontend工程中寻找MainFrame::OpenFile* MainFrame::OpenProjectFile(Project::File* file)函数 寻找段落

else if (file->state == CodeState_Binary)
{
    .....
}
删掉即可。使代码自然进入else if (file->scriptIndex != -1)段落进行输出。
当然这里也可以做更多的判断,比如直接调用反编译函数的命令。因为这里不太熟悉C++,也不想借助C++.net/Cli完成,故此省略。

如果有其他修改的要求欢迎在下面讨论=w=

最后拿着这个利器去调试剑三插件应该很轻松了233333

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值