分析ELF二进制文件以最小化其大小

Mat*_*ine 5 linker gcc arm v8 elf

我正在使用GCC arm-gnueabi交叉编译器将V8项目交叉编译为嵌入式ARM目标.我成功地对V8库进行了交叉编译,作为一个冒烟测试,我想将它链接到Google的hello world示例并在ARM板上运行它.

这些库本身的时钟超过1.2 MB:

v8 % find out/arm.release/obj.target/ -name '*.a' -exec du -h {} + 
1.2M    out/arm.release/obj.target/tools/gyp/libv8_base.a
12K     out/arm.release/obj.target/tools/gyp/libv8_libbase.a
4.0K    out/arm.release/obj.target/tools/gyp/libv8_libplatform.a
4.0K    out/arm.release/obj.target/tools/gyp/libv8_snapshot.a
4.0K    out/arm.release/obj.target/tools/gyp/libv8_nosnapshot.a
4.0K    out/arm.release/obj.target/third_party/icu/libicudata.a
164K    out/arm.release/obj.target/third_party/icu/libicuuc.a
336K    out/arm.release/obj.target/third_party/icu/libicui18n.
Run Code Online (Sandbox Code Playgroud)

然而,当我建立和链接

arm-linux-gnueabi-g++ -pthread -Iv8/include hi.cpp -Os -o hi_v8 -Wl,--start-group v8/out/arm.release/obj.target/{tools/gyp/libv8_{base,libbase,snapshot},third_party/icu/libicu{uc,i18n,data}}.a -Wl,--end-group
Run Code Online (Sandbox Code Playgroud)

我得到一个20 MB的可执行文件.剥离它只能让我降到17 MB

那个气球链接的文件大小如此之多?我怎么能避免呢?我可以使用哪些工具来诊断问题?在我定位的平台上,此大小可能会出现问题.

我已经看了一下readelf --sections,但它只是告诉我整个.text部分的大小,这不是特别有用.我也看了一下这里的建议并尝试使用nm,但它具体了 - 我只是一堆名称错误的符号_ZN2v88internal11FLAG_log_gcE.

Ros*_*dge 6

首先,如果您还没有,请使用size -A hi_v8以确定哪个部分比您预期的更大.它并不总是文本部分.

接下来添加-Wl,-Map,hi_v8.mapg++命令行.这将在文件中生成链接器映射hi_v8.map.该文件的内容将非常详细,但它将显示每个目标文件对可执行文件中每个部分的贡献.

链接器映射将包含许多部分.第一部分"由于文件(符号)而包含的归档成员"有助于确定导致对象链接到可执行文件的原因,但不足以说明是什么导致可执行文件的大小膨胀.一旦你想出来,它变成了一个错误的库,你可以回到这一部分."分配公共符号","废弃输入部分","内存配置"部分可能不会非常有用.

"链接器脚本和内存映射"部分是您希望集中注意力的部分.它本质上是用于生成可执行文件的链接描述文件的跟踪.首先检查LOAD开头的语句,它们显示可执行文件链接的每个文件.检查是否有任何你不希望看到的文件,但是这里将提到库,即使它们的目标文件都没有链接到可执行文件中.

现在,您将不得不浏览每个链接对象文件的跟踪,并将其符号添加到可执行文件的每个部分.因为它只是一个"Hello World"问题,所以不应该太糟糕.跳到您已确定为问题的部分.现在扫描对象列表,看看是否可以找到大量不明显必需的目标文件被链接的位置或者地址突然大量跳跃的位置.后者应该相对容易发现,但前者很难识别.如果您在本机平台上为静态链接的"Hello World"程序生成链接器映射,以查看它链接的库例程,则可能会有所帮助.

我的猜测是你的问题会显示为地址中的大跳,或者显然不应该链接的某个文件.所以不要被地图文件的冗长所拖延.C++符号也应该被解码,因此它不会那么糟糕nm.(虽然您也可以nm使用该-C选项对名称进行解码.)