我正在CMake中建立一个库,该库在私有标头中具有一些常量。当我在Release
配置(例如-O3 -DNDEBUG
)中编译并在输出上运行strings
时,这些常量会出现在输出中。这些常量的名称显示了一些实现细节,如果可能的话,我想将其隐藏。
这是一个演示问题的最小项目示例:
private.h
#pragma once
const int MY_CONSTANT = 42;
lib.c
#include "private.h"
extern int get_mask(void)
{
return MY_CONSTANT ^ 3;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(dummylib)
add_library(mylib SHARED lib.c)
构建并显示字符串输出:
$ mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build . --config Release -- VERBOSE=1 && strings libmylib.so | grep MY
MY_CONSTANT
还有其他一些我可以用来隐藏此信息的开关吗?
MY_CONSTANT
是需要在内存中放置的变量。 C的编译链接过程包括创建中间目标文件,然后将其链接到最终的ELF可执行文件中。需要跟踪该变量,并在链接的最后阶段分配其最终地址,并重新分配引用。
作为其产物,将为目标文件创建一个符号表,该符号表使用其名称引用MY_CONSTANT
。默认情况下,在创建最终可执行文件时,链接程序不会将其丢弃。
您可以通过运行strip --strip-unneeded ./a.out
手动删除该符号表。
注意,这与用于在运行时链接的dynamic符号表无关。应用程序仍然可以链接并调用get_mask(void)
我只是想通了。当您在常量前面添加static
关键字时,您仍然可以访问lib.c
和关联的源文件中的值,但是其名称不再出现在二进制文件的strings
转储中
private.h
#pragma once
const int MY_CONSTANT = 42;
结果:
$ strings libmylib.so | grep MY
MY_CONSTANT
MY_CONSTANT
使用static
关键字:
private.h
#pragma once
static const int MY_CONSTANT = 42;
结果:
$ strings libmylib.so | grep MY
在gcc
中,您也可以使用-g0
禁用调试符号>