зеркало из https://github.com/mozilla/gecko-dev.git
152 строки
5.1 KiB
JavaScript
152 строки
5.1 KiB
JavaScript
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set sts=2 sw=2 et tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/* eslint-env mozilla/chrome-worker */
|
|
|
|
"use strict";
|
|
|
|
importScripts(
|
|
"resource://gre/modules/osfile.jsm",
|
|
"resource://gre/modules/profiler_get_symbols.js"
|
|
);
|
|
|
|
// This worker uses the wasm module that was generated from https://github.com/mstange/profiler-get-symbols.
|
|
// See ProfilerGetSymbols.jsm for more information.
|
|
//
|
|
// The worker instantiates the module, reads the binary into wasm memory, runs
|
|
// the wasm code, and returns the symbol table or an error. Then it shuts down
|
|
// itself.
|
|
|
|
// Read an open OS.File instance into the Uint8Array dataBuf.
|
|
function readFileInto(file, dataBuf) {
|
|
// Ideally we'd be able to call file.readTo(dataBuf) here, but readTo no
|
|
// longer exists.
|
|
// So instead, we copy the file over into wasm memory in 4MB chunks. This
|
|
// will take 425 invocations for a a 1.7GB file (such as libxul.so for a
|
|
// Firefox for Android build) and not take up too much memory per call.
|
|
const dataBufLen = dataBuf.byteLength;
|
|
const chunkSize = 4 * 1024 * 1024;
|
|
let pos = 0;
|
|
while (pos < dataBufLen) {
|
|
const chunkData = file.read({ bytes: chunkSize });
|
|
const chunkBytes = chunkData.byteLength;
|
|
if (chunkBytes === 0) {
|
|
break;
|
|
}
|
|
|
|
dataBuf.set(chunkData, pos);
|
|
pos += chunkBytes;
|
|
}
|
|
}
|
|
|
|
onmessage = async e => {
|
|
try {
|
|
const { binaryPath, debugPath, breakpadId, module } = e.data;
|
|
|
|
if (!(module instanceof WebAssembly.Module)) {
|
|
throw new Error("invalid WebAssembly module");
|
|
}
|
|
|
|
// Instantiate the WASM module.
|
|
await wasm_bindgen(module);
|
|
|
|
const { CompactSymbolTable, wasm } = wasm_bindgen;
|
|
|
|
const binaryFile = OS.File.open(binaryPath, { read: true });
|
|
const binaryDataBufLen = binaryFile.stat().size;
|
|
|
|
// Read the binary file into WASM memory.
|
|
const binaryDataBufPtr = wasm.__wbindgen_malloc(binaryDataBufLen);
|
|
const binaryDataBuf = new Uint8Array(
|
|
wasm.memory.buffer,
|
|
binaryDataBufPtr,
|
|
binaryDataBufLen
|
|
);
|
|
readFileInto(binaryFile, binaryDataBuf);
|
|
binaryFile.close();
|
|
|
|
// Do the same for the debug file, if it is supplied and different from the
|
|
// binary file. This is only the case on Windows.
|
|
let debugDataBufLen = binaryDataBufLen;
|
|
let debugDataBufPtr = binaryDataBufPtr;
|
|
if (debugPath && debugPath !== binaryPath) {
|
|
const debugFile = OS.File.open(debugPath, { read: true });
|
|
debugDataBufLen = debugFile.stat().size;
|
|
debugDataBufPtr = wasm.__wbindgen_malloc(debugDataBufLen);
|
|
const debugDataBuf = new Uint8Array(
|
|
wasm.memory.buffer,
|
|
debugDataBufPtr,
|
|
debugDataBufLen
|
|
);
|
|
readFileInto(debugFile, debugDataBuf);
|
|
debugFile.close();
|
|
}
|
|
|
|
// Call get_compact_symbol_table. We're calling the raw wasm function
|
|
// instead of the binding function that wasm-bindgen generated for us,
|
|
// because the generated function doesn't let us pass binaryDataBufPtr
|
|
// or debugDataBufPtr and would force another copy.
|
|
//
|
|
// The rust definition of get_compact_symbol_table is:
|
|
//
|
|
// #[wasm_bindgen]
|
|
// pub fn get_compact_symbol_table(binary_data: &[u8], debug_data: &[u8], breakpad_id: &str, dest: &mut CompactSymbolTable) -> bool
|
|
//
|
|
// It gets exposed as a wasm function with the following signature:
|
|
//
|
|
// pub fn get_compact_symbol_table(binaryDataBufPtr: u32, binaryDataBufLen: u32, debugDataBufPtr: u32, debugDataBufLen: u32, breakpadIdPtr: u32, breakpadIdLen: u32, destPtr: u32) -> u32
|
|
//
|
|
// We're relying on implementation details of wasm-bindgen here. The above
|
|
// is true as of wasm-bindgen 0.2.32.
|
|
|
|
// Convert the breakpadId string into bytes in wasm memory.
|
|
const breakpadIdBuf = new TextEncoder("utf-8").encode(breakpadId);
|
|
const breakpadIdLen = breakpadIdBuf.length;
|
|
const breakpadIdPtr = wasm.__wbindgen_malloc(breakpadIdLen);
|
|
new Uint8Array(wasm.memory.buffer).set(breakpadIdBuf, breakpadIdPtr);
|
|
|
|
const output = new CompactSymbolTable();
|
|
let succeeded;
|
|
try {
|
|
succeeded =
|
|
wasm.get_compact_symbol_table(
|
|
binaryDataBufPtr,
|
|
binaryDataBufLen,
|
|
debugDataBufPtr,
|
|
debugDataBufLen,
|
|
breakpadIdPtr,
|
|
breakpadIdLen,
|
|
output.ptr
|
|
) !== 0;
|
|
} catch (e) {
|
|
succeeded = false;
|
|
}
|
|
|
|
wasm.__wbindgen_free(breakpadIdPtr, breakpadIdLen);
|
|
wasm.__wbindgen_free(binaryDataBufPtr, binaryDataBufLen);
|
|
if (debugDataBufPtr != binaryDataBufPtr) {
|
|
wasm.__wbindgen_free(debugDataBufPtr, debugDataBufLen);
|
|
}
|
|
|
|
if (!succeeded) {
|
|
output.free();
|
|
throw new Error("get_compact_symbol_table returned false");
|
|
}
|
|
|
|
const result = [
|
|
output.take_addr(),
|
|
output.take_index(),
|
|
output.take_buffer(),
|
|
];
|
|
output.free();
|
|
|
|
postMessage({ result }, result.map(r => r.buffer));
|
|
} catch (error) {
|
|
postMessage({ error: error.toString() });
|
|
}
|
|
close();
|
|
};
|