在我们的开发环境中,生成构建非常简单。碰巧客户有时最终会得到一个自定义构建,当他们遇到该构建的问题时,很难弄清楚二进制来自哪个代码库。
我正在尝试找到一种合理的策略,以便在只能对二进制文件进行取证分析时能够重建构建环境。
我的一个想法是将版本信息嵌入到每个cpp文件中。像
这样的东西static const char *__FILEVERSIONINFO = __FILE__ "___$Revision$___Build:" PRODUCT_VER_STR;
然后将svn:keywords
属性添加到文件中,以便在构建时,我至少可以知道文件所在的SVN版本。这不会告诉我它是否已经从该修订中修改过,但至少可以让我接近。
这方面的缺点是我无法将这些符号放入Release版本中。因为它们没有被引用,所以它们被优化掉(我希望将该优化保持为全局设置)。我尝试Force Symbol References(__FILEVERSIONINFO
作为链接器设置中“强制符号引用”的值),但链接器抱怨它无法找到符号。
error LNK2001: unresolved external symbol __FILEVERSIONINFO
dumpbin
将对象文件中的符号列为
09E 00000004 SECT5 notype Static | ___FILEVERSIONINFO
但在“强制符号引用”中使用此名称也不起作用。
微软的文档实际上没有提供任何使用它的例子,而且我的google-fu没有找到任何相关内容。
我尝试使用#pragma强制导出,
__pragma(comment (linker, "/export:__FILEVERSIONINFO"))
但是从链接器获得了相同的错误。 如何指定此符号的名称?
如果我没有随机化/取消每个翻译单元的符号名称会很方便,但我不知道链接器的/INCLUDE
参数能够包含具有相同名称的所有符号。
我实际上并不关心符号本身是否可访问,我只是想能够从二进制文件中取出字符串而grep用于“Revision”以查看二进制文件在/附近的修订版本构建时间。
似乎可以构建一个报告(例如svn diff
)并将其中某种形式嵌入到二进制文件中。这样做的好处是可以封装对文件/项目所做的任何未提交的源级更改。
这看起来有点乏味,但可以做到。
改变开发人员/支持人员构建的方式对我们来说不是一个可行的选择。我正在寻找一些我可以做的事情,不依赖于他们阅读更多文档和遵循程序规则。我意识到这并不理想,但添加更多人为驱动的政策并不值得花费。
出于我预见的所有实际目的,我可能只会使用此信息来查找源文件的特定修订版中的问题,而不是实际尝试修补自定义版本。
是否有更好的方法来标记/标记二进制文件,以便我找到有问题的源文件的近似修订版以供审查?
答案 0 :(得分:3)
问题是关键字static
。这给出了变量internal linkage,这意味着“这只会在这个文件中使用;随意不要将它包含在编译的目标文件中或以其他方式对其进行优化“。如果删除该关键字,编译器会将其包含在目标文件中,您可以使用强制符号引用来保留它。
编辑:extern
的错误引用,用于声明,而不是定义。
编辑2:强制符号引用的另一种方法是实际引用它,该方法适用于其他编译器并且可能更有用。添加命令行标志--build-info
,它打印字符串并退出,或者如果设置了详细标志,则在启动时打印它,或类似的东西。然后你不需要检查二进制文件,你知道字符串将不会被优化掉。
答案 1 :(得分:1)
SVN标签怎么样?你可以标记每个构建..
更新的: 也许做那样的事情:
#ifndef SRC_ID
#ifdef __GNUC__
#define SRC_ID(X, Y) static const char* const __attribute__((used)) X = Y
#else
#define SRC_ID(X, Y) static const char* const X = Y
#endif
#endif
SRC_ID(build_id, "SOMETHING TO IDENTIFY YOUR BUILD");
__attribute__((used))
变量属性用于向链接器发出信号,即使该变量似乎未被使用,也会使用此变量:
此属性附加到具有静态存储的变量,意味着 即使变量出现,也必须发出变量 没有引用。
来源:gnu.org