通过无法优化的标头嵌入字符串

uml*_*ute 10 c compiler-optimization copyright-display

在开发仅标头的库时,我想确保将给定的字符串嵌入使用标头的所有二进制文件中,即使编译器配置为优化未使用的常量,并且二进制文件也被剥离。

嵌入不应有任何副作用(除了使生成的二进制文件更大一点以外)。

我不知道人们将如何使用标题,但是

  • 标头可能会包含在多个编译单元中,并且都链接到一个二进制文件中
  • 目标平台是Linux / macOS / Windows
  • 编译器很可能是gcc / clang / MSVC

我的小尝试等于:

static char frobnozzel_version_string[] = "Frobnozzel v0.1; © 2019 ACME; GPLv3";
Run Code Online (Sandbox Code Playgroud)

...,但是在构建过程中很容易将其删除(由于实际未使用该字符串,因此对于优化编译器而言很容易被攻击)。

因此问题是:是否可以在包含给定标头的二进制文件中嵌入一个字符串,而该字符串不会被构建“发布”二进制文件的常规策略优化/删除?

我知道,任何使用该库的人都可以(手动)删除我输入的内容,但是让我们假设,人们只是按原样使用标题。


上下文:所涉及的标头是根据GPL发布的,我希望能够检查用户是否确实遵守了许可证。

klu*_*utt 0

我不知道是否有任何标准方法可以做到这一点,但根据您的库的工作方式,我可能有一个合理的解决方案。许多库都有 init 函数,这些函数通常在代码中仅调用一次或至少很少调用。srand()就是一个例子。

\n\n

您可能需要一个 init 函数才能使您的库正常工作,并且在没有确切指定其用途的情况下,您可以只是说 main 函数需要initlib();在使用任何库函数之前具有该行。这是一个例子:

\n\n

左:

\n\n
// Macro disguised as a function\n#define initlib() init("Frobnozzel v0.1; \xc2\xa9 2019 ACME; GPLv");  \n\nvoid init(const char *);\nvoid libfunc(void);\n
Run Code Online (Sandbox Code Playgroud)\n\n

LC:

\n\n
#include "l.h"\n#include <string.h>\n#include <stdlib.h>\n\nint initialized = 0;\n\nvoid init(const char *str) {\n    if(strcmp(str, "Frobnozzel v0.1; \xc2\xa9 2019 ACME; GPLv3") == 0)\n        initialized = 1;\n}\n\nvoid libfunc(void) {\n    if(!initialized)\n        exit(EXIT_FAILURE);\n    /* Do stuff */\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

笔记:\nI know that you asked for header only, but the principle is the same. And afterall, converting a .h,.c pair to just a .h file is the simplest task in the world.

\n\n

libfunc如果在使用初始化宏之前使用库函数initlib, the program will just exit. The same thing will happen if the copyright string is changed in the header file.

\n\n

当然,如果你愿意的话,解决这个问题并不难,但它确实有效。

\n\n

为了进行测试,我使用了以下代码:

\n\n
int main()\n{\n    initlib();\n    libfunc();\n    printf("Hello, World!\\n");\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我通过编译l.c成共享库来尝试这一点。然后我编译了一个简单的主程序,clanggcc使用-O3. The binaries worked as they should and they contained the copyright string.

\n