将文件信息(char数组)嵌入编译二进制文件

时间:2017-07-26 15:01:34

标签: c++ visual-c++

有没有办法将(每个翻译单元)字符串嵌入到优化的二进制文件中?

在我们的开发环境中,生成构建非常简单。碰巧客户有时最终会得到一个自定义构建,当他们遇到该构建的问题时,很难弄清楚二进制来自哪个代码库。

我正在尝试找到一种合理的策略,以便在只能对二进制文件进行取证分析时能够重建构建环境。

将版本信息嵌入到每个翻译单元

我的一个想法是将版本信息嵌入到每个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)并将其中某种形式嵌入到二进制文件中。这样做的好处是可以封装对文件/项目所做的任何未提交的源级更改。

这看起来有点乏味,但可以做到。

其他解决方案?

改变开发人员/支持人员构建的方式对我们来说不是一个可行的选择。我正在寻找一些我可以做的事情,不依赖于他们阅读更多文档和遵循程序规则。我意识到这并不理想,但添加更多人为驱动的政策并不值得花费。

出于我预见的所有实际目的,我可能只会使用此信息来查找源文件的特定修订版中的问题,而不是实际尝试修补自定义版本。

是否有更好的方法来标记/标记二进制文件,以便我找到有问题的源文件的近似修订版以供审查?

2 个答案:

答案 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