Added support for profiling stripped Mach-O binaries.
diff --git a/README.md b/README.md
index da8e515..3972bdb 100644
--- a/README.md
+++ b/README.md
@@ -294,27 +294,26 @@
easy mistake to make, and one that I made several times even
as Bloaty's author!).
-Make sure you are compiling with build IDs enabled. For gcc
-this happens automatically, but [Clang decided not to make
-this the default, since it makes the link
-slower](http://releases.llvm.org/3.9.0/tools/clang/docs/ReleaseNotes.html#major-new-features).
-For Clang add `-Wl,--build-id` to your link line. (If you
-want a slightly faster link and don't care about
-reproducibility, you can use `-Wl,--build-id=uuid` instead).
-
-Then you can strip the binary and uses the unstripped binary
-as your debug file. For example, with bloaty itself:
+If your binary has a build ID, then using separate debug
+files is as simple as:
```
$ cp bloaty bloaty.stripped
$ strip bloaty.stripped
-$ ./bloaty -d compileunits --debug-file=bloaty bloaty.stripped
+$ ./bloaty -d symbols --debug-file=bloaty bloaty.stripped
```
-It is also possible to remove debug sections only (see
-`objcopy --strip-debug`) while keeping the symbol table.
-You can also create debug file that contain *only* debug
-info (see `objcopy --only-keep-debug`).
+Some format-specific notes follow.
+
+## ELF
+
+For ELF, make sure you are compiling with build IDs enabled.
+With gcc this happens automatically, but [Clang decided not
+to make this the default, since it makes the link
+slower](http://releases.llvm.org/3.9.0/tools/clang/docs/ReleaseNotes.html#major-new-features).
+For Clang add `-Wl,--build-id` to your link line. (If you
+want a slightly faster link and don't care about
+reproducibility, you can use `-Wl,--build-id=uuid` instead).
Bloaty does not currently support the GNU debuglink or
looking up debug files by build ID, [which are the methods
@@ -323,6 +322,17 @@
If there are use cases where Bloaty's `--debug-file` option
won't work, we can reconsider implementing these.
+## Mach-O
+
+Mach-O files always have build IDs (as far as I can tell),
+so no special configuration is needed to make sure you get
+them.
+
+TODO: Mach-O puts debug info in separate files, which are
+created using `dsymutil`. DWARF is not yet supported for
+Mach-O, but once it is then `--debug-file` will be necessary
+to help Bloaty find these separate debug files also.
+
# Configuration Files
Any options that you can specify on the command-line, you
diff --git a/src/macho.cc b/src/macho.cc
index a027952..3058774 100644
--- a/src/macho.cc
+++ b/src/macho.cc
@@ -416,7 +416,8 @@
});
}
-void ParseSymbolsFromSymbolTable(string_view command_data, string_view file_data, RangeSink* sink) {
+void ParseSymbolsFromSymbolTable(string_view command_data,
+ string_view file_data, RangeSink* sink) {
auto symtab_cmd = GetStructPointer<symtab_command>(command_data);
// TODO(haberman): use 32-bit symbol size where appropriate.
@@ -439,9 +440,9 @@
}
}
-void ParseSymbols(RangeSink* sink) {
+void ParseSymbols(string_view file_data, RangeSink* sink) {
ForEachLoadCommand(
- sink->input_file().data(), sink,
+ file_data, sink,
[sink](uint32_t cmd, string_view command_data, string_view file_data) {
switch (cmd) {
case LC_SYMTAB:
@@ -478,8 +479,24 @@
: ObjectFile(std::move(file_data)) {}
std::string GetBuildId() const override {
- // TODO(haberman): implement.
- return std::string();
+ std::string id;
+
+ ForEachLoadCommand(
+ file_data().data(), nullptr,
+ [&id](uint32_t cmd, string_view command_data,
+ string_view /* file_data */) {
+ if (cmd == LC_UUID) {
+ auto uuid_cmd =
+ GetStructPointerAndAdvance<uuid_command>(&command_data);
+ if (!command_data.empty()) {
+ THROWF("Unexpected excess uuid data: $0", command_data.size());
+ }
+ id.resize(sizeof(uuid_cmd->uuid));
+ memcpy(&id[0], &uuid_cmd->uuid[0], sizeof(uuid_cmd->uuid));
+ }
+ });
+
+ return id;
}
void ProcessFile(const std::vector<RangeSink*>& sinks) const override {
@@ -493,7 +510,7 @@
case DataSource::kRawSymbols:
case DataSource::kShortSymbols:
case DataSource::kFullSymbols:
- ParseSymbols(sink);
+ ParseSymbols(debug_file().file_data().data(), sink);
break;
case DataSource::kArchiveMembers:
case DataSource::kCompileUnits: