commit | e9c0979f2c0535dc648b9b29fd7b14c32eea9f6d | [log] [tgz] |
---|---|---|
author | Joshua Haberman <jhaberman@gmail.com> | Thu Aug 12 23:24:05 2021 -0700 |
committer | Joshua Haberman <jhaberman@gmail.com> | Thu Aug 12 23:24:05 2021 -0700 |
tree | 1244f4d9a71045b5167dd40b9ecbe284c5038c1c | |
parent | e72c26dbdeea3d9693743f8353d2ce48510efeb5 [diff] |
Report ELF section/segment headers as such. Previously we attributed section/segment headers themselves to the section/segment they describe. eg. the `.text` header was counted as part of the `.text` section. After this change it is reported as part of `[ELF Section Headers]`. The rationale was that we generally want to account for the entire "footprint" of a given entity, including all of the metadata emitted as part of that entity. For example, for `-d symbols` we attribute the `.eh_frame` footprint of each function to the corresponding function. This is much more useful than just seeing a chunk of `[.eh_frame]` with no breakdown. However I think the case of section/segment headers is somewhat different. These headers are small and fixed-length, so there is nothing the section/segment itself could have done to grow or shrink its length except not existing to begin with. Consider a specific example: you have 100 functions that you compile with `-ffunction-sections`. This generates 100 section headers that total to 6400 bytes, since each section header is 64 bytes. It is not especially useful if Bloaty just reports each section of length N as N+64 to account for the section headers. In fact this obscures the fact that 6400 bytes of the binary are spent on section headers. And that 64 bytes is not really part of the "weight" of each function, the "weight" is actually coming from the `-ffunction-sections` argument which caused the 100 functions to emit 6400 bytes of section headers instead of 64. Ultimately, the strongest arguments for this change are: 1. As described above, the number of sections in the binary (and the resulting total section overhead) is really a function of the way the binary was compiled, and doesn't have much to do with the individual sections themselves or the data contained therein. If the section overhead is too high, the solution is to compile the binary in a different way, *not* to trim the contents of the individual sections. 2. If we do not surface the total weight of the section headers in `-d sections`, there is really no other way to get this information from Bloaty. There is no other data source that will split out section headers from section contents. 3. It makes the memory maps look much more concise and logical. I think the lit tests in this commit will make that clear. Seeing the section headers attributed by section made the memory map more noisy and less useful.
Ever wondered what‘s making your binary big? Bloaty will show you a size profile of the binary so you can understand what’s taking up space inside.
$ ./bloaty bloaty -d compileunits FILE SIZE VM SIZE -------------- -------------- 34.8% 10.2Mi 43.4% 2.91Mi [163 Others] 17.2% 5.08Mi 4.3% 295Ki third_party/protobuf/src/google/protobuf/descriptor.cc 7.3% 2.14Mi 2.6% 179Ki third_party/protobuf/src/google/protobuf/descriptor.pb.cc 4.6% 1.36Mi 1.1% 78.4Ki third_party/protobuf/src/google/protobuf/text_format.cc 3.7% 1.10Mi 4.5% 311Ki third_party/capstone/arch/ARM/ARMDisassembler.c 1.3% 399Ki 15.9% 1.07Mi third_party/capstone/arch/M68K/M68KDisassembler.c 3.2% 980Ki 1.1% 75.3Ki third_party/protobuf/src/google/protobuf/generated_message_reflection.cc 3.2% 965Ki 0.6% 40.7Ki third_party/protobuf/src/google/protobuf/descriptor_database.cc 2.8% 854Ki 12.0% 819Ki third_party/capstone/arch/X86/X86Mapping.c 2.8% 846Ki 1.0% 66.4Ki third_party/protobuf/src/google/protobuf/extension_set.cc 2.7% 800Ki 0.6% 41.2Ki third_party/protobuf/src/google/protobuf/generated_message_util.cc 2.3% 709Ki 0.7% 50.7Ki third_party/protobuf/src/google/protobuf/wire_format.cc 2.1% 637Ki 1.7% 117Ki third_party/demumble/third_party/libcxxabi/cxa_demangle.cpp 1.8% 549Ki 1.7% 114Ki src/bloaty.cc 1.7% 503Ki 0.7% 48.1Ki third_party/protobuf/src/google/protobuf/repeated_field.cc 1.6% 469Ki 6.2% 427Ki third_party/capstone/arch/X86/X86DisassemblerDecoder.c 1.4% 434Ki 0.2% 15.9Ki third_party/protobuf/src/google/protobuf/message.cc 1.4% 422Ki 0.3% 23.4Ki third_party/re2/re2/dfa.cc 1.3% 407Ki 0.4% 24.9Ki third_party/re2/re2/regexp.cc 1.3% 407Ki 0.4% 29.9Ki third_party/protobuf/src/google/protobuf/map_field.cc 1.3% 397Ki 0.4% 24.8Ki third_party/re2/re2/re2.cc 100.0% 29.5Mi 100.0% 6.69Mi TOTAL
Bloaty performs a deep analysis of the binary. Using custom ELF, DWARF, and Mach-O parsers, Bloaty aims to accurately attribute every byte of the binary to the symbol or compileunit that produced it. It will even disassemble the binary looking for references to anonymous data.
Bloaty supports many features:
For detailed info on all of Bloaty's features, see the User Documentation.
For more information about the analysis performed by Bloaty, please see How Bloaty Works.
To build, use cmake
. For example:
$ cmake -B build -G Ninja -S . $ cmake --build build $ cmake --build build --target install
Bloaty bundles libprotobuf
, re2
, capstone
, and pkg-config
as Git submodules, and uses protoc
build from libprotobuf, but it will prefer the system's versions of those dependencies if available. All other dependencies are included as Git submodules.
If the Git repository hasn't been cloned with the --recursive
, the submodules can be checked out with:
$ git submodule update --init --recursive
To run the tests, see the info in tests/README.md.
GitHub issues and PRs welcome. Please include tests when possible, see: tests/README.md.
This is not an official Google product.