防止编译器常量折叠表达式的技巧

Tho*_*mas 5 c c++ optimization compiler-optimization constantfolding

我的程序中有一个字符串文字,我正在尝试创建一个业余校验和,以确保在可移植可执行文件中没有替换字符串文字.

为此,我创建了一个字符串文字的哈希值,并将其作为整数文字存储在程序中.现在我有两个文字,一个用于字符串,一个用于哈希.

在我的代码中,我通过使用以相同方式散列字符串文字的函数来实现校验和,我创建一个新的运行时哈希并检查哈希文字的哈希值.

问题当然是,通过编译器优化,它可以预先计算运行时哈希,然后我可以根据哈希文本检查哈希文字,并且校验和将始终返回true.

所以我正在寻找一个技巧,让编译器认为字符串文字是一个动态字符串,可以是任何东西,因此它不会对运行时哈希进行常量折叠优化,我的代码将正常工作.

Bas*_*tch 9

您可能可能将字符串文字声明为const volatile,例如

const volatile char myliteral[] = "some literal string";
Run Code Online (Sandbox Code Playgroud)

并且您还可以在构建时计算哈希值,例如,在构建过程中有一些东西可以提取适当的字符串并单独计算哈希值.

最后,如果字符串及其散列位于两个不同的转换单元(例如in file1.cfile2.c)中,则需要链接时优化以使内联在构建时发生.使用当前的GCC(即GCC 4.9或5),您需要在编译时和链接时明确地传递-flto以获得链接时优化,因此如果您没有明确地执行(例如CC=gcc -flto -O2在您的中Makefile),则不会发生.

顺便说一下,您可以校验整个可执行文件,或整个共享库,或某些给定的目标文件.细节是特定于操作系统 在Linux上看到dlopen(3),dlsym(3),dladdr(3),dl_iterate_phdr(5), elf(5),proc(5)

此外,您可以散列初始文字的一些随机后缀子字符串(例如myliteral+random()%strlen(myliteral)运行时的散列),并保持和比较这些部分散列的常量数组.编译器不太可能内联所有这些!

我实际上认为它在实践中不是一个真正的问题:没有人会关心你的可执行文件,没有人会花时间来反编译它.

顺便说一下,你可以生成一个__timestamp.c包含时间戳和校验和信息的单独文件(我在2018年夏天在我的bismon项目中这样做),并将它与你的可执行文件链接.