fune/browser/components/extensions/ProfilerGetSymbols.jsm
Markus Stange 6dbd19aac8 Bug 1509549 - Add a ProfilerGetSymbols module which can dump symbols with the help of a dynamically-loaded WebAssembly module. r=kmag
The module can dump ELF binaries, Mach-O binaries, and pdb files. So it works
for all our supported platforms.

The module is currently hosted on https://zealous-rosalind-a98ce8.netlify.com/ ,
which is a netlify server that serves files from the following repo:
https://github.com/mstange/profiler-assets

To make all of this look a bit more official, I'm planning on doing two things:
 - Move the github repo under the devtools-html organization
 - Get a firefox.com subdomain such as profiler-assets.firefox.com for hosting

Depends on D13004

Differential Revision: https://phabricator.services.mozilla.com/D13005

--HG--
extra : moz-landing-system : lando
2019-02-07 19:36:43 +00:00

95 lines
3.7 KiB
JavaScript

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const EXPORTED_SYMBOLS = ["ProfilerGetSymbols"];
ChromeUtils.defineModuleGetter(this, "setTimeout",
"resource://gre/modules/Timer.jsm");
ChromeUtils.defineModuleGetter(this, "clearTimeout",
"resource://gre/modules/Timer.jsm");
Cu.importGlobalProperties(["fetch"]);
// This module obtains symbol tables for binaries.
// It does so with the help of a WASM module which gets pulled in from the
// internet on demand. We're doing this purely for the purposes of saving on
// code size. The contents of the WASM module are expected to be static, they
// are checked against the hash specified below.
// The WASM code is run on a ChromeWorker thread. It takes the raw byte
// contents of the to-be-dumped binary (and of an additional optional pdb file
// on Windows) as its input, and returns a set of typed arrays which make up
// the symbol table.
// Don't let the strange looking URLs and strings below scare you.
// The hash check ensures that the contents of the wasm module are what we
// expect them to be.
// The source code is at https://github.com/mstange/profiler-get-symbols/ .
// Generated from https://github.com/mstange/profiler-get-symbols/commit/0a0aadc68d6196823a5f102feacb2f04424cd681
const WASM_MODULE_URL =
"https://zealous-rosalind-a98ce8.netlify.com/wasm/4af7553b4848038c5a1e33a15ec107094bd0572e16fe2a367235bcb50a630b148ac4fe1d165859d7a9bb4ca4e2572c0e.wasm";
const WASM_MODULE_INTEGRITY =
"sha384-SvdVO0hIA4xaHjOhXsEHCUvQVy4W/io2cjW8tQpjCxSKxP4dFlhZ16m7TKTiVywO";
const EXPIRY_TIME_IN_MS = 5 * 60 * 1000; // 5 minutes
let gCachedWASMModulePromise = null;
let gCachedWASMModuleExpiryTimer = 0;
function clearCachedWASMModule() {
gCachedWASMModulePromise = null;
gCachedWASMModuleExpiryTimer = 0;
}
function getWASMProfilerGetSymbolsModule() {
if (!gCachedWASMModulePromise) {
gCachedWASMModulePromise = (async function() {
const request = new Request(WASM_MODULE_URL, {
integrity: WASM_MODULE_INTEGRITY,
credentials: "omit",
});
return WebAssembly.compileStreaming(fetch(request));
})();
}
// Reset expiry timer.
clearTimeout(gCachedWASMModuleExpiryTimer);
gCachedWASMModuleExpiryTimer = setTimeout(clearCachedWASMModule, EXPIRY_TIME_IN_MS);
return gCachedWASMModulePromise;
}
this.ProfilerGetSymbols = {
/**
* Obtain symbols for the binary at the specified location.
*
* @param {string} binaryPath The absolute path to the binary on the local
* file system.
* @param {string} debugPath The absolute path to the binary's pdb file on the
* local file system if on Windows, otherwise the same as binaryPath.
* @param {string} breakpadId The breakpadId for the binary whose symbols
* should be obtained. This is used for two purposes: 1) to locate the
* correct single-arch binary in "FatArch" files, and 2) to make sure the
* binary at the given path is actually the one that we want. If no ID match
* is found, this function throws (rejects the promise).
* @returns {Promise} The symbol table in SymbolTableAsTuple format, see the
* documentation for nsIProfiler.getSymbolTable.
*/
async getSymbolTable(binaryPath, debugPath, breakpadId) {
const module = await getWASMProfilerGetSymbolsModule();
return new Promise((resolve, reject) => {
const worker =
new ChromeWorker("resource://app/modules/ProfilerGetSymbols-worker.js");
worker.onmessage = (e) => {
if (e.data.error) {
reject(e.data.error);
return;
}
resolve(e.data.result);
};
worker.postMessage({binaryPath, debugPath, breakpadId, module});
});
},
};