如何为linux静态库隐藏本地符号

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何为linux静态库隐藏本地符号相关的知识,希望对你有一定的参考价值。

我将向静态库发送给客户。为了最大化图书馆的隐私,我使用@ypsu Symbol hiding in static libraries built with Xcode

提供的技术对静态图书馆的符号进行了限制。

但是,上述方法仅限制用户调用隐藏函数,隐藏函数名称的名称对于“ nm”或“ strings”仍然可见。

隐藏功能的名称非常敏感。如何隐藏或从静态库中删除此信息?

答案

我最近也遇到过同样的问题。我决定将所有公共符号重命名为md5sum,以便用户看不到名称,包括文件名。下面的示例尝试对其进行演示:

cat >priv.c <<EOF
#include <stdio.h>
void priv()  printf("Hello, private function\n"); 
EOF

cat >interface.c <<EOF
void priv();
void interface()  priv(); 
EOF

cat >main.c <<EOF
void interface();
int main() 
    interface();

EOF

cat >compile.sh <<EOF3
#!/bin/bash   

namespace="namespace_"

# compile to object files
gcc -c -o priv.o priv.c
gcc -c -o interface.o interface.c

# rename the object file so the names of files are not visible
nofilename="$(echo "nofilenames" | md5sum | cut -d' ' -f1).o"
ld -relocatable priv.o interface.o -o "$nofilename"

# create the static library
ar rcs static.a "$nofilename"

# list of interface symbols    
public_symbols=( interface )

# list of private symbols - all symbols except interface symbols
private_symbols=($(
    nm static.a | sed '/^[0-9]\+ T /!d; s///' |
    sort | comm -13 <(printf "%s\n" "$public_symbols[@]" | sort) -
))

# strip unused symbols, leave only interface symbols
strip_args=($(printf " -K %s " "$public_symbols[@]"))
strip --strip-unneeded --strip-debug "$strip_args[@]" static.a

# rename all private symbols with it's md5sum
objcopy_args=($(
    printf "%s\n" "$private_symbols[@]" |
    while IFS= read -r sym; do
        new="$namespace$(echo "$sym" | md5sum | cut -d' ' -f1)"
        # replace the symbol with it's md5sum
        echo --redefine-sym "$sym=$new"
        # make the symbol local
        echo -L "$new"
    done
))
objcopy "$objcopy_args[@]" static.a

gcc main.c static.a 

# testing    
set -x
nm static.a
strings static.a
./a.out
EOF3

./compile.sh脚本将输出:

+ nm static.a

b8c84a861a264dfcb24ebf32892484dd.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000013 T interface
0000000000000000 t namespace_6b2f60f631c17ca910498adb47387adf
                 U puts
+ strings static.a
!<arch>
/               0           0     0     0       18        `
interface
//                                              36        `
b8c84a861a264dfcb24ebf32892484dd.o/
/0              0           0     0     644     1744      `
Hello, private function
GCC: (Arch Linux 9.3.0-1) 9.3.0
GCC: (Arch Linux 9.3.0-1) 9.3.0
namespace_6b2f60f631c17ca910498adb47387adf
puts
interface
_GLOBAL_OFFSET_TABLE_
.symtab
.strtab
.shstrtab
.rela.text
.rodata
.rela.eh_frame
.data
.bss
.comment
.note.GNU-stack
+ ./a.out
Hello, private function

priv符号被重命名为namespace_6b2f60f631c17ca910498adb47387adf,源文件与b8c84a861a264dfcb24ebf32892484dd.o合并为一个ld -relocatable目标文件。我愿意就如何改进此类脚本提供更多建议。

以上是关于如何为linux静态库隐藏本地符号的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 静态库中隐藏符号?

如何为 C 扩展链接 python 的静态库?

使用 Clang 作为编译器构建 Android 项目时从静态库中隐藏符号

Facebook iOS SDK - 如何为 Xcode 4.3 构建静态库?

如何为 XSLT 代码片段配置 CruiseControl 的 C# 版本?

近期遇到问题总结