为什么常量名称出现在已编译的 binaries/shared 库中?

Why do constant names appear in compiled binaries/shared libraries?

我正在 CMake 中构建一个库,它在私有 header 中有一些常量。当我在 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

我可以使用一些额外的开关来隐藏此信息吗?

我刚刚弄明白了。当您在常量前面添加 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

禁用调试符号

MY_CONSTANT 是一个需要在内存中占有一席之地的变量。 C 的编译 linking 过程涉及在 linking 到最终的 ELF executable 之前创建一个中间目标文件。需要跟踪变量并为其分配最终地址并在 link.

的最后阶段重新定位引用

作为此项目的产物,为目标文件创建了一个符号 table,该文件使用其名称引用 MY_CONSTANT。默认情况下,linker 在创建最终 executable 时不会丢弃它。

您可以通过 运行 strip --strip-unneeded ./a.out.

手动删除此符号 table

请注意,这与运行时用于 link 的 动态 符号 table 无关。应用程序仍然可以 link 反对和调用 get_mask(void)