Skip to content

Commit

Permalink
Merge pull request #387 from mason-lgtm/wasmsourcemap
Browse files Browse the repository at this point in the history
Wasm source maps
  • Loading branch information
haberman authored Oct 1, 2024
2 parents 0c89acd + 4ba799b commit e115514
Show file tree
Hide file tree
Showing 13 changed files with 566 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ add_library(libbloaty STATIC
src/range_map.cc
src/range_map.h
src/re.h
src/source_map.cc
src/source_map.h
src/util.cc
src/util.h
src/webassembly.cc
Expand Down
32 changes: 32 additions & 0 deletions doc/using.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ Options:
-c FILE Load configuration from <file>.
-d SOURCE,SOURCE Comma-separated list of sources to scan.
--debug-file=FILE Use this file for debug symbols and/or symbol table.
--source-map=ID=FILE
Use this source map file for the binary. The ID can be
the build ID (or Wasm sourceMappingURL) or the file path
as specified in the command line.
Currently only supported for Wasm.
-C MODE How to demangle symbols. Possible values are:
--demangle=MODE --demangle=none no demangling, print raw symbols
--demangle=short demangle, but omit arg/return types
Expand Down Expand Up @@ -845,6 +850,33 @@ $ ./bloaty -c config.bloaty -d bloaty_package,compileunits bloaty
100.0% 29.5Mi 100.0% 6.69Mi TOTAL
```

# Source maps

Bloaty provides a `--source-map` option which allows
specifying a source map for the binary. It takes an ID and
source map file name, separated by '='. The ID can be the
build ID or path to the binary file as specified in the
command line.

For example, to use the `compileunits` and `inlines` data
sources for Wasm, a source map must be provided. For Wasm,
the ID can be the text in the `sourceMappingURL` section of
the binary.

```cmdoutput
$ ./bloaty -d compileunits --domain=file --source-map=o.wasm=o.wasm.map o.wasm
FILE SIZE
--------------
45.0% 49 [section sourceMappingURL]
19.3% 21 Main.java
12.8% 14 [section Export]
7.3% 8 [WASM Header]
6.4% 7 [section Code]
5.5% 6 [section Type]
3.7% 4 [section Function]
100.0% 109 TOTAL
```

# Source filter

Sometimes, you are only interested in parts of the binary
Expand Down
41 changes: 41 additions & 0 deletions src/bloaty.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,7 @@ class Bloaty {

void AddFilename(const std::string& filename, bool base_file);
void AddDebugFilename(const std::string& filename);
void AddSourceMapFilename(const std::string& filename);

size_t GetSourceCount() const { return sources_.size(); }

Expand Down Expand Up @@ -1535,6 +1536,7 @@ class Bloaty {
std::vector<InputFileInfo> input_files_;
std::vector<InputFileInfo> base_files_;
std::map<std::string, std::string> debug_files_;
std::map<std::string, std::string> sourcemap_files_;

// For allocating memory, like to decompress compressed sections.
std::unique_ptr<google::protobuf::Arena> arena_;
Expand Down Expand Up @@ -1592,6 +1594,18 @@ void Bloaty::AddDebugFilename(const std::string& filename) {
debug_files_[build_id] = filename;
}

void Bloaty::AddSourceMapFilename(const std::string& filename) {
std::size_t delimiter = filename.find('=');
if (delimiter == std::string::npos) {
THROWF("Source map filename '$0' must have a build id and file name "
"separated by '='",
filename);
}
std::string sourcemap_build_id = filename.substr(0, delimiter);
std::string sourcemap_filename = filename.substr(delimiter + 1);
sourcemap_files_[sourcemap_build_id] = sourcemap_filename;
}

void Bloaty::DefineCustomDataSource(const CustomDataSource& source) {
if (source.base_data_source() == "symbols") {
THROW(
Expand Down Expand Up @@ -1761,6 +1775,22 @@ void Bloaty::ScanAndRollupFile(const std::string& filename, Rollup* rollup,
file->set_debug_file(debug_file.get());
out_build_ids->push_back(build_id);
}

// Maybe it's a source map file?
auto sourcemap_iter = sourcemap_files_.find(build_id);
// If the source map by build id isn't found, try the file name.
if (sourcemap_iter == sourcemap_files_.end()) {
sourcemap_iter = sourcemap_files_.find(filename);
}
if (sourcemap_iter != sourcemap_files_.end()) {
std::unique_ptr<InputFile> sourcemap_file(
file_factory_.OpenFile(sourcemap_iter->second));
// The build id is not present in the source map file itself, so it must
// be passed here.
debug_file = TryOpenSourceMapFile(sourcemap_file, build_id);
file->set_debug_file(debug_file.get());
out_build_ids->push_back(build_id);
}
}

int64_t filesize_before =
Expand Down Expand Up @@ -1943,6 +1973,11 @@ USAGE: bloaty [OPTION]... FILE... [-- BASE_FILE...]
-c FILE Load configuration from <file>.
-d SOURCE,SOURCE Comma-separated list of sources to scan.
--debug-file=FILE Use this file for debug symbols and/or symbol table.
--source-map=ID=FILE
Use this source map file for the binary. The ID can be
the build ID (or Wasm sourceMappingURL) or the file path
as specified in the command line.
Currently only supported for Wasm.
-C MODE How to demangle symbols. Possible values are:
--demangle=MODE --demangle=none no demangling, print raw symbols
--demangle=short demangle, but omit arg/return types
Expand Down Expand Up @@ -2166,6 +2201,8 @@ bool DoParseOptions(bool skip_unknown, int* argc, char** argv[],
}
} else if (args.TryParseOption("--source-filter", &option)) {
options->set_source_filter(std::string(option));
} else if (args.TryParseOption("--source-map", &option)) {
options->add_source_map(std::string(option));
} else if (args.TryParseFlag("-v")) {
options->set_verbose_level(1);
} else if (args.TryParseFlag("-vv")) {
Expand Down Expand Up @@ -2260,6 +2297,10 @@ void BloatyDoMain(const Options& options, const InputFileFactory& file_factory,
bloaty.AddDebugFilename(debug_filename);
}

for (auto& sourcemap : options.source_map()) {
bloaty.AddSourceMapFilename(sourcemap);
}

for (const auto& custom_data_source : options.custom_data_source()) {
bloaty.DefineCustomDataSource(custom_data_source);
}
Expand Down
2 changes: 2 additions & 0 deletions src/bloaty.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ std::unique_ptr<ObjectFile> TryOpenELFFile(std::unique_ptr<InputFile>& file);
std::unique_ptr<ObjectFile> TryOpenMachOFile(std::unique_ptr<InputFile>& file);
std::unique_ptr<ObjectFile> TryOpenWebAssemblyFile(std::unique_ptr<InputFile>& file);
std::unique_ptr<ObjectFile> TryOpenPEFile(std::unique_ptr<InputFile>& file);
std::unique_ptr<ObjectFile> TryOpenSourceMapFile(
std::unique_ptr<InputFile>& file, std::string build_id);

// Provided by dwarf.cc. To use these, a module should fill in a dwarf::File
// and then call these functions.
Expand Down
4 changes: 4 additions & 0 deletions src/bloaty.proto
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ message Options {
// debug_filename will *not* have their file size counted.
repeated string debug_filename = 10;

// Build id to source map file names, delimited by '='.
repeated string source_map = 15;

// The data sources to scan in each file. At least one data source must be
// specified. If more than one source is specified, the output is
// hierarchical.
Expand Down Expand Up @@ -101,3 +104,4 @@ message Regex {
optional string pattern = 1;
optional string replacement = 2;
}

Loading

0 comments on commit e115514

Please sign in to comment.