分析 ELF 二进制文件以最小化其大小 [英] Analyzing an ELF binary to minimize its size

查看:24
本文介绍了分析 ELF 二进制文件以最小化其大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm cross-compiling a V8 project to an embedded ARM target using the GCC arm-gnueabi cross compiler. I got the V8 library itself cross-compiled successfully, and as a smoke test I wanted to link it to Google's hello world example and run it on the ARM board.

库本身的时钟超过 1.2 MB:

The libraries themselves clock in at a bit over 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.

然而,当我构建并链接

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

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

I get an executable that's 20 MB. Stripping it only gets me down to 17 MB

链接中的内容使文件大小如此之大?我怎样才能避免它?我可以使用哪些工具来诊断问题?这个尺寸在我所针对的平台上可能会出现问题.

What is being linked in that balloons the file size so much? How can I avoid it? What tools can I use to diagnose the problem? This size may be problematic on the platform I am targeting.

我查看了 readelf --sections,但它只是告诉我 .text 部分的总体大小,这并不是特别有用.我还查看了此处的建议并尝试使用 nm,但它是 具体 - 我只是一堆名称混乱的符号,如_ZN2v88internal11FLAG_log_gcE.

I've taken a look at readelf --sections, but it just tells me how large the .text section is overall, which isn't particularly helpful. I also took a look at the suggestions here and tried using nm, but it's too specific - I just a bunch of name-mangled symbols like _ZN2v88internal11FLAG_log_gcE.

推荐答案

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

First, if you haven't already, use size -A hi_v8 to determine what section or sections are bigger than you expect. It's not always the text section.

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

Next add -Wl,-Map,hi_v8.map to the g++ command line. This will generate a linker map in the file hi_v8.map. The contents of the file will be very verbose, but it'll will show the contribution of each of object files to each section in the executable.

链接器映射将包含多个部分.第一部分由于文件(符号)而包含的存档成员"有助于确定导致对象链接到可执行文件的原因,但不是什么导致可执行文件的大小膨胀.一旦你弄清楚了,它变成了一个错误的库,你可以回到这个部分.分配通用符号"、丢弃的输入部分"、内存配置"部分可能不会很有帮助.

The linker map will have a number of sections. The first section "Archive member included because of file (symbol)" is helpful for figuring what caused an object be linked into the executable, but not so much what's inflating the size of the executable. Once you figured that out, and it turns to be an errant library, you can come back to this section. The "Allocating common symbols", "Discarded input sections", "Memory Configuration" sections are probably not going to be very helpful.

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

The "Linker script and memory map" section is where you want to be focusing your attention. It's essentially a trace of the linker script used to produce the executable. First check the LOAD statements at the start, they show every file that the executable was linked with. Check to see if there's any files you didn't expect to see, however libraries will be mentioned here even none of their object files were linked into the executable.

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

Now you'll have to wade through the trace of every linked object file and its symbols being adding to every section of the executable. Since it's just a "Hello World" problem it shouldn't be too bad. Skip to the section that you've identified as being the problem. Now scan through the list of objects and see if you can find either where a large number of not obviously necessary object files are being linked in or where the address suddenly jumps by a large amount. The later should be relatively easy to spot, but the former can be hard to identify. It might help if you generate linker map for a statically linked "Hello World" program on your native platform to see the sort of library routines it links in.

我的猜测是,您的问题将表现为地址中的一个大跳转,或者一些显然不应链接的文件.所以不要被地图文件的冗长所拖延.C++ 符号也应该被破坏,所以它不会像 nm 那样糟糕.(虽然你可以让 nm 也使用 -C 选项对名称进行解构.)

My guess is that your problem will show up as either a large jump in the address, or some file that obviously that shouldn't be linked in. So don't be put off by the verboseness of the map file. The C++ symbols should also be demangled so it won't be as bad as nm. (Though you can get nm to also demangle the names with the -C option.)

这篇关于分析 ELF 二进制文件以最小化其大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆