[tools][system-analyzer] Add local symbol server
Start a local symbol server using the local-web-sever node package: ws --stack system-analyzer/lws-middleware.js lws-static cors The system-analyzer will then use it to symbolize profiles. Note: The symbol server will execute `nm` and `objdump` locally. Change-Id: Icff6e9f5af24f214f353c049f5cd13eedccf0f88 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2979591 Commit-Queue: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Victor Gomes <victorgomes@chromium.org> Cr-Commit-Position: refs/heads/master@{#75501}
This commit is contained in:
parent
56fe020eec
commit
f2d079bc97
@ -6,7 +6,7 @@ import {
|
|||||||
CppProcessor, LinuxCppEntriesProvider
|
CppProcessor, LinuxCppEntriesProvider
|
||||||
} from "../../../tools/dumpcpp.mjs" ;
|
} from "../../../tools/dumpcpp.mjs" ;
|
||||||
|
|
||||||
(function testProcessSharedLibrary() {
|
await (async function testProcessSharedLibrary() {
|
||||||
var oldLoadSymbols = LinuxCppEntriesProvider.prototype.loadSymbols;
|
var oldLoadSymbols = LinuxCppEntriesProvider.prototype.loadSymbols;
|
||||||
|
|
||||||
LinuxCppEntriesProvider.prototype.loadSymbols = function(libName) {
|
LinuxCppEntriesProvider.prototype.loadSymbols = function(libName) {
|
||||||
@ -20,7 +20,7 @@ import {
|
|||||||
|
|
||||||
var testCppProcessor = new CppProcessor(new LinuxCppEntriesProvider(),
|
var testCppProcessor = new CppProcessor(new LinuxCppEntriesProvider(),
|
||||||
false, false);
|
false, false);
|
||||||
testCppProcessor.processSharedLibrary(
|
await testCppProcessor.processSharedLibrary(
|
||||||
'/usr/local/google/home/lpy/v8/out/native/d8',
|
'/usr/local/google/home/lpy/v8/out/native/d8',
|
||||||
0x00000100, 0x00000400, 0);
|
0x00000100, 0x00000400, 0);
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ const result = doWork();
|
|||||||
|
|
||||||
const logString = d8.log.getAndStop();
|
const logString = d8.log.getAndStop();
|
||||||
const processor = new Processor();
|
const processor = new Processor();
|
||||||
processor.processChunk(logString);
|
await processor.processChunk(logString);
|
||||||
processor.finalize();
|
await processor.finalize();
|
||||||
|
|
||||||
const maps = processor.mapTimeline;
|
const maps = processor.mapTimeline;
|
||||||
const ics = processor.icTimeline;
|
const ics = processor.icTimeline;
|
||||||
|
@ -82,7 +82,7 @@ import {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
(function testUnixCppEntriesProvider() {
|
await (async function testUnixCppEntriesProvider() {
|
||||||
var oldLoadSymbols = LinuxCppEntriesProvider.prototype.loadSymbols;
|
var oldLoadSymbols = LinuxCppEntriesProvider.prototype.loadSymbols;
|
||||||
|
|
||||||
// shell executable
|
// shell executable
|
||||||
@ -99,13 +99,10 @@ import {
|
|||||||
'081f08a0 00000004 B stdout\n'
|
'081f08a0 00000004 B stdout\n'
|
||||||
].join('\n'), ''];
|
].join('\n'), ''];
|
||||||
};
|
};
|
||||||
|
|
||||||
var shell_prov = new LinuxCppEntriesProvider();
|
var shell_prov = new LinuxCppEntriesProvider();
|
||||||
var shell_syms = [];
|
var shell_syms = [];
|
||||||
shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000, 0,
|
await shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000, 0,
|
||||||
function (name, start, end) {
|
(...params) => shell_syms.push(params));
|
||||||
shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
[['_init', 0x08049790, 0x08049f50],
|
[['_init', 0x08049790, 0x08049f50],
|
||||||
['_start', 0x08049f50, 0x08139150],
|
['_start', 0x08049f50, 0x08139150],
|
||||||
@ -128,10 +125,8 @@ import {
|
|||||||
};
|
};
|
||||||
var libc_prov = new LinuxCppEntriesProvider();
|
var libc_prov = new LinuxCppEntriesProvider();
|
||||||
var libc_syms = [];
|
var libc_syms = [];
|
||||||
libc_prov.parseVmSymbols('libc', 0xf7c5c000, 0xf7da5000, 0,
|
await libc_prov.parseVmSymbols('libc', 0xf7c5c000, 0xf7da5000, 0,
|
||||||
function (name, start, end) {
|
(...params) => libc_syms.push(params));
|
||||||
libc_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
var libc_ref_syms = [['__libc_init_first', 0x000162a0, 0x000162a0 + 0x5],
|
var libc_ref_syms = [['__libc_init_first', 0x000162a0, 0x000162a0 + 0x5],
|
||||||
['__isnan', 0x0002a5f0, 0x0002a5f0 + 0x2d],
|
['__isnan', 0x0002a5f0, 0x0002a5f0 + 0x2d],
|
||||||
['scalblnf', 0x0002aaa0, 0x0002aaa0 + 0xd],
|
['scalblnf', 0x0002aaa0, 0x0002aaa0 + 0xd],
|
||||||
@ -165,10 +160,8 @@ import {
|
|||||||
};
|
};
|
||||||
var android_prov = new LinuxCppEntriesProvider();
|
var android_prov = new LinuxCppEntriesProvider();
|
||||||
var android_syms = [];
|
var android_syms = [];
|
||||||
android_prov.parseVmSymbols('libmonochrome', 0xf7c5c000, 0xf9c5c000, 0,
|
await android_prov.parseVmSymbols('libmonochrome', 0xf7c5c000, 0xf9c5c000, 0,
|
||||||
function (name, start, end) {
|
(...params) => android_syms.push(params));
|
||||||
android_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
var android_ref_syms = [
|
var android_ref_syms = [
|
||||||
['v8::internal::interpreter::BytecodeGenerator::BytecodeGenerator(v8::internal::UnoptimizedCompilationInfo*)', 0x013a1088, 0x013a1088 + 0x224],
|
['v8::internal::interpreter::BytecodeGenerator::BytecodeGenerator(v8::internal::UnoptimizedCompilationInfo*)', 0x013a1088, 0x013a1088 + 0x224],
|
||||||
['v8::internal::interpreter::BytecodeGenerator::FinalizeBytecode(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Script>)', 0x013a12ac, 0x013a12ac + 0xd0],
|
['v8::internal::interpreter::BytecodeGenerator::FinalizeBytecode(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Script>)', 0x013a12ac, 0x013a12ac + 0xd0],
|
||||||
@ -187,7 +180,7 @@ import {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
(function testMacOSCppEntriesProvider() {
|
await (async function testMacOSCppEntriesProvider() {
|
||||||
var oldLoadSymbols = MacOSCppEntriesProvider.prototype.loadSymbols;
|
var oldLoadSymbols = MacOSCppEntriesProvider.prototype.loadSymbols;
|
||||||
|
|
||||||
// shell executable
|
// shell executable
|
||||||
@ -203,13 +196,10 @@ import {
|
|||||||
'00137400 v8::internal::Runtime_DebugGetPropertyDetails\n'
|
'00137400 v8::internal::Runtime_DebugGetPropertyDetails\n'
|
||||||
].join('\n'), ''];
|
].join('\n'), ''];
|
||||||
};
|
};
|
||||||
|
|
||||||
var shell_prov = new MacOSCppEntriesProvider();
|
var shell_prov = new MacOSCppEntriesProvider();
|
||||||
var shell_syms = [];
|
var shell_syms = [];
|
||||||
shell_prov.parseVmSymbols('shell', 0x00001c00, 0x00163256, 0x100,
|
await shell_prov.parseVmSymbols('shell', 0x00001c00, 0x00163256, 0x100,
|
||||||
function (name, start, end) {
|
(...params) => shell_syms.push(params));
|
||||||
shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
[['start', 0x00001c00, 0x00001c40],
|
[['start', 0x00001c00, 0x00001c40],
|
||||||
['dyld_stub_binding_helper', 0x00001c40, 0x0011b810],
|
['dyld_stub_binding_helper', 0x00001c40, 0x0011b810],
|
||||||
@ -229,10 +219,8 @@ import {
|
|||||||
};
|
};
|
||||||
var stdc_prov = new MacOSCppEntriesProvider();
|
var stdc_prov = new MacOSCppEntriesProvider();
|
||||||
var stdc_syms = [];
|
var stdc_syms = [];
|
||||||
stdc_prov.parseVmSymbols('stdc++', 0x95728fb4, 0x95770005, 0,
|
await stdc_prov.parseVmSymbols('stdc++', 0x95728fb4, 0x95770005, 0,
|
||||||
function (name, start, end) {
|
(...params) => stdc_syms.push(params));
|
||||||
stdc_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
var stdc_ref_syms = [['__gnu_cxx::balloc::__mini_vector<std::pair<__gnu_cxx::bitmap_allocator<char>::_Alloc_block*, __gnu_cxx::bitmap_allocator<char>::_Alloc_block*> >::__mini_vector', 0x0000107a, 0x0002c410],
|
var stdc_ref_syms = [['__gnu_cxx::balloc::__mini_vector<std::pair<__gnu_cxx::bitmap_allocator<char>::_Alloc_block*, __gnu_cxx::bitmap_allocator<char>::_Alloc_block*> >::__mini_vector', 0x0000107a, 0x0002c410],
|
||||||
['std::basic_streambuf<char, std::char_traits<char> >::pubseekoff', 0x0002c410, 0x0002c488],
|
['std::basic_streambuf<char, std::char_traits<char> >::pubseekoff', 0x0002c410, 0x0002c488],
|
||||||
['std::basic_streambuf<char, std::char_traits<char> >::pubseekpos', 0x0002c488, 0x000466aa],
|
['std::basic_streambuf<char, std::char_traits<char> >::pubseekpos', 0x0002c488, 0x000466aa],
|
||||||
@ -247,7 +235,7 @@ import {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
(function testWindowsCppEntriesProvider() {
|
await (async function testWindowsCppEntriesProvider() {
|
||||||
var oldLoadSymbols = WindowsCppEntriesProvider.prototype.loadSymbols;
|
var oldLoadSymbols = WindowsCppEntriesProvider.prototype.loadSymbols;
|
||||||
|
|
||||||
WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) {
|
WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) {
|
||||||
@ -272,10 +260,8 @@ import {
|
|||||||
};
|
};
|
||||||
var shell_prov = new WindowsCppEntriesProvider();
|
var shell_prov = new WindowsCppEntriesProvider();
|
||||||
var shell_syms = [];
|
var shell_syms = [];
|
||||||
shell_prov.parseVmSymbols('shell.exe', 0x00400000, 0x0057c000, 0,
|
await shell_prov.parseVmSymbols('shell.exe', 0x00400000, 0x0057c000, 0,
|
||||||
function (name, start, end) {
|
(...params) => shell_syms.push(params));
|
||||||
shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
[['ReadFile', 0x00401000, 0x004010a0],
|
[['ReadFile', 0x00401000, 0x004010a0],
|
||||||
['Print', 0x004010a0, 0x00402230],
|
['Print', 0x004010a0, 0x00402230],
|
||||||
@ -289,7 +275,7 @@ import {
|
|||||||
|
|
||||||
|
|
||||||
// http://code.google.com/p/v8/issues/detail?id=427
|
// http://code.google.com/p/v8/issues/detail?id=427
|
||||||
(function testWindowsProcessExeAndDllMapFile() {
|
await (async function testWindowsProcessExeAndDllMapFile() {
|
||||||
function exeSymbols(exeName) {
|
function exeSymbols(exeName) {
|
||||||
return [
|
return [
|
||||||
' 0000:00000000 ___ImageBase 00400000 <linker-defined>',
|
' 0000:00000000 ___ImageBase 00400000 <linker-defined>',
|
||||||
@ -312,11 +298,9 @@ import {
|
|||||||
|
|
||||||
read = exeSymbols;
|
read = exeSymbols;
|
||||||
var exe_exe_syms = [];
|
var exe_exe_syms = [];
|
||||||
(new WindowsCppEntriesProvider()).parseVmSymbols(
|
await (new WindowsCppEntriesProvider()).parseVmSymbols(
|
||||||
'chrome.exe', 0x00400000, 0x00472000, 0,
|
'chrome.exe', 0x00400000, 0x00472000, 0,
|
||||||
function (name, start, end) {
|
(...params) => exe_exe_syms.push(params));
|
||||||
exe_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
[['RunMain', 0x00401780, 0x00401ac0],
|
[['RunMain', 0x00401780, 0x00401ac0],
|
||||||
['_main', 0x00401ac0, 0x00472000]],
|
['_main', 0x00401ac0, 0x00472000]],
|
||||||
@ -324,22 +308,18 @@ import {
|
|||||||
|
|
||||||
read = dllSymbols;
|
read = dllSymbols;
|
||||||
var exe_dll_syms = [];
|
var exe_dll_syms = [];
|
||||||
(new WindowsCppEntriesProvider()).parseVmSymbols(
|
await (new WindowsCppEntriesProvider()).parseVmSymbols(
|
||||||
'chrome.exe', 0x00400000, 0x00472000, 0,
|
'chrome.exe', 0x00400000, 0x00472000, 0,
|
||||||
function (name, start, end) {
|
(...params) => exe_dll_syms.push(params));
|
||||||
exe_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
[],
|
[],
|
||||||
exe_dll_syms, '.exe with .dll symbols');
|
exe_dll_syms, '.exe with .dll symbols');
|
||||||
|
|
||||||
read = dllSymbols;
|
read = dllSymbols;
|
||||||
var dll_dll_syms = [];
|
var dll_dll_syms = [];
|
||||||
(new WindowsCppEntriesProvider()).parseVmSymbols(
|
await (new WindowsCppEntriesProvider()).parseVmSymbols(
|
||||||
'chrome.dll', 0x01c30000, 0x02b80000, 0,
|
'chrome.dll', 0x01c30000, 0x02b80000, 0,
|
||||||
function (name, start, end) {
|
(...params) => dll_dll_syms.push(params));
|
||||||
dll_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
[['_DllMain@12', 0x01c31780, 0x01c31ac0],
|
[['_DllMain@12', 0x01c31780, 0x01c31ac0],
|
||||||
['___DllMainCRTStartup', 0x01c31ac0, 0x02b80000]],
|
['___DllMainCRTStartup', 0x01c31ac0, 0x02b80000]],
|
||||||
@ -347,11 +327,9 @@ import {
|
|||||||
|
|
||||||
read = exeSymbols;
|
read = exeSymbols;
|
||||||
var dll_exe_syms = [];
|
var dll_exe_syms = [];
|
||||||
(new WindowsCppEntriesProvider()).parseVmSymbols(
|
await (new WindowsCppEntriesProvider()).parseVmSymbols(
|
||||||
'chrome.dll', 0x01c30000, 0x02b80000, 0,
|
'chrome.dll', 0x01c30000, 0x02b80000, 0,
|
||||||
function (name, start, end) {
|
(...params) => dll_exe_syms.push(params));
|
||||||
dll_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
|
|
||||||
});
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
[],
|
[],
|
||||||
dll_exe_syms, '.dll with .exe symbols');
|
dll_exe_syms, '.dll with .exe symbols');
|
||||||
@ -431,7 +409,7 @@ class PrintMonitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(function testProcessing() {
|
await (async function testProcessing() {
|
||||||
const testData = {
|
const testData = {
|
||||||
'Default': [
|
'Default': [
|
||||||
'tickprocessor-test.log', 'tickprocessor-test.default',
|
'tickprocessor-test.log', 'tickprocessor-test.default',
|
||||||
@ -462,30 +440,30 @@ class PrintMonitor {
|
|||||||
};
|
};
|
||||||
for (var testName in testData) {
|
for (var testName in testData) {
|
||||||
console.log('=== testProcessing-' + testName + ' ===');
|
console.log('=== testProcessing-' + testName + ' ===');
|
||||||
testTickProcessor(...testData[testName]);
|
await testTickProcessor(...testData[testName]);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function testTickProcessor(logInput, refOutput, args=[]) {
|
async function testTickProcessor(logInput, refOutput, args=[]) {
|
||||||
// /foo/bar/tickprocesser.mjs => /foo/bar/
|
// /foo/bar/tickprocesser.mjs => /foo/bar/
|
||||||
const dir = import.meta.url.split("/").slice(0, -1).join('/') + '/';
|
const dir = import.meta.url.split("/").slice(0, -1).join('/') + '/';
|
||||||
const params = ArgumentsProcessor.process(args);
|
const params = ArgumentsProcessor.process(args);
|
||||||
testExpectations(dir, logInput, refOutput, params);
|
await testExpectations(dir, logInput, refOutput, params);
|
||||||
// TODO(cbruni): enable again after it works on bots
|
// TODO(cbruni): enable again after it works on bots
|
||||||
// testEndToEnd(dir, 'tickprocessor-test-large.js', refOutput, params);
|
// await testEndToEnd(dir, 'tickprocessor-test-large.js', refOutput, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExpectations(dir, logInput, refOutput, params) {
|
async function testExpectations(dir, logInput, refOutput, params) {
|
||||||
const symbolsFile = dir + logInput + '.symbols.json';
|
const symbolsFile = dir + logInput + '.symbols.json';
|
||||||
const cppEntries = new CppEntriesProviderMock(symbolsFile);
|
const cppEntries = new CppEntriesProviderMock(symbolsFile);
|
||||||
const tickProcessor = TickProcessor.fromParams(params, cppEntries);
|
const tickProcessor = TickProcessor.fromParams(params, cppEntries);
|
||||||
const printMonitor = new PrintMonitor(dir + refOutput);
|
const printMonitor = new PrintMonitor(dir + refOutput);
|
||||||
tickProcessor.processLogFileInTest(dir + logInput);
|
await tickProcessor.processLogFileInTest(dir + logInput);
|
||||||
tickProcessor.printStatistics();
|
tickProcessor.printStatistics();
|
||||||
printMonitor.finish();
|
printMonitor.finish();
|
||||||
};
|
};
|
||||||
|
|
||||||
function testEndToEnd(dir, sourceFile, ignoredRefOutput, params) {
|
async function testEndToEnd(dir, sourceFile, ignoredRefOutput, params) {
|
||||||
// This test only works on linux.
|
// This test only works on linux.
|
||||||
if (!os?.system) return;
|
if (!os?.system) return;
|
||||||
if (os.name !== 'linux' && os.name !== 'macos') return;
|
if (os.name !== 'linux' && os.name !== 'macos') return;
|
||||||
@ -499,6 +477,6 @@ function testEndToEnd(dir, sourceFile, ignoredRefOutput, params) {
|
|||||||
// hence we cannot properly compare output expectations.
|
// hence we cannot properly compare output expectations.
|
||||||
// Let's just use a dummy file and only test whether we don't throw.
|
// Let's just use a dummy file and only test whether we don't throw.
|
||||||
const printMonitor = new PrintMonitor(dir + ignoredRefOutput);
|
const printMonitor = new PrintMonitor(dir + ignoredRefOutput);
|
||||||
tickProcessor.processLogFileInTest(tmpLogFile);
|
await tickProcessor.processLogFileInTest(tmpLogFile);
|
||||||
tickProcessor.printStatistics();
|
tickProcessor.printStatistics();
|
||||||
}
|
}
|
@ -20,5 +20,5 @@ const cppProcessor = new CppProcessor(
|
|||||||
new (entriesProviders[params.platform])(params.nm, params.targetRootFS,
|
new (entriesProviders[params.platform])(params.nm, params.targetRootFS,
|
||||||
params.apkEmbeddedLibrary),
|
params.apkEmbeddedLibrary),
|
||||||
params.timedRange, params.pairwiseTimedRange);
|
params.timedRange, params.pairwiseTimedRange);
|
||||||
cppProcessor.processLogFile(params.logFileName);
|
await cppProcessor.processLogFile(params.logFileName);
|
||||||
cppProcessor.dumpCppSymbols();
|
cppProcessor.dumpCppSymbols();
|
||||||
|
@ -22,7 +22,7 @@ class ArgumentsProcessor extends BaseArgumentsProcessor {
|
|||||||
|
|
||||||
const params = ArgumentsProcessor.process(arguments);
|
const params = ArgumentsProcessor.process(arguments);
|
||||||
const processor = new Processor();
|
const processor = new Processor();
|
||||||
processor.processLogFile(params.logFileName);
|
await processor.processLogFile(params.logFileName);
|
||||||
|
|
||||||
const typeAccumulator = new Map();
|
const typeAccumulator = new Map();
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@ export class LogReader {
|
|||||||
*
|
*
|
||||||
* @param {string} chunk A portion of log.
|
* @param {string} chunk A portion of log.
|
||||||
*/
|
*/
|
||||||
processLogChunk(chunk) {
|
async processLogChunk(chunk) {
|
||||||
this.processLog_(chunk.split('\n'));
|
await this.processLog_(chunk.split('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,14 +126,14 @@ export class LogReader {
|
|||||||
*
|
*
|
||||||
* @param {string} line A line of log.
|
* @param {string} line A line of log.
|
||||||
*/
|
*/
|
||||||
processLogLine(line) {
|
async processLogLine(line) {
|
||||||
if (!this.timedRange_) {
|
if (!this.timedRange_) {
|
||||||
this.processLogLine_(line);
|
await this.processLogLine_(line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (line.startsWith("current-time")) {
|
if (line.startsWith("current-time")) {
|
||||||
if (this.hasSeenTimerMarker_) {
|
if (this.hasSeenTimerMarker_) {
|
||||||
this.processLog_(this.logLinesSinceLastTimerMarker_);
|
await this.processLog_(this.logLinesSinceLastTimerMarker_);
|
||||||
this.logLinesSinceLastTimerMarker_ = [];
|
this.logLinesSinceLastTimerMarker_ = [];
|
||||||
// In pairwise mode, a "current-time" line ends the timed range.
|
// In pairwise mode, a "current-time" line ends the timed range.
|
||||||
if (this.pairwiseTimedRange_) {
|
if (this.pairwiseTimedRange_) {
|
||||||
@ -146,7 +146,7 @@ export class LogReader {
|
|||||||
if (this.hasSeenTimerMarker_) {
|
if (this.hasSeenTimerMarker_) {
|
||||||
this.logLinesSinceLastTimerMarker_.push(line);
|
this.logLinesSinceLastTimerMarker_.push(line);
|
||||||
} else if (!line.startsWith("tick")) {
|
} else if (!line.startsWith("tick")) {
|
||||||
this.processLogLine_(line);
|
await this.processLogLine_(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ export class LogReader {
|
|||||||
* @param {Array.<string>} fields Log record.
|
* @param {Array.<string>} fields Log record.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
dispatchLogRow_(fields) {
|
async dispatchLogRow_(fields) {
|
||||||
// Obtain the dispatch.
|
// Obtain the dispatch.
|
||||||
const command = fields[0];
|
const command = fields[0];
|
||||||
const dispatch = this.dispatchTable_[command];
|
const dispatch = this.dispatchTable_[command];
|
||||||
@ -222,7 +222,7 @@ export class LogReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run the processor.
|
// Run the processor.
|
||||||
dispatch.processor.apply(this, parsedFields);
|
await dispatch.processor.apply(this, parsedFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,9 +231,9 @@ export class LogReader {
|
|||||||
* @param {Array.<string>} lines Log lines.
|
* @param {Array.<string>} lines Log lines.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
processLog_(lines) {
|
async processLog_(lines) {
|
||||||
for (let i = 0, n = lines.length; i < n; ++i) {
|
for (let i = 0, n = lines.length; i < n; ++i) {
|
||||||
this.processLogLine_(lines[i]);
|
await this.processLogLine_(lines[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,11 +243,11 @@ export class LogReader {
|
|||||||
* @param {String} a log line
|
* @param {String} a log line
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
processLogLine_(line) {
|
async processLogLine_(line) {
|
||||||
if (line.length > 0) {
|
if (line.length > 0) {
|
||||||
try {
|
try {
|
||||||
const fields = this.csvParser_.parseLine(line);
|
const fields = this.csvParser_.parseLine(line);
|
||||||
this.dispatchLogRow_(fields);
|
await this.dispatchLogRow_(fields);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.printError(`line ${this.lineNum_ + 1}: ${e.message || e}\n${e.stack}`);
|
this.printError(`line ${this.lineNum_ + 1}: ${e.message || e}\n${e.stack}`);
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,4 @@ import { ParseProcessor, ArgumentsProcessor } from "./parse-processor.mjs";
|
|||||||
|
|
||||||
const params = ArgumentsProcessor.process(arguments);
|
const params = ArgumentsProcessor.process(arguments);
|
||||||
const parseProcessor = new ParseProcessor();
|
const parseProcessor = new ParseProcessor();
|
||||||
parseProcessor.processLogFile(params.logFileName);
|
await parseProcessor.processLogFile(params.logFileName);
|
||||||
|
@ -56,7 +56,7 @@ class App {
|
|||||||
'fileuploadchunk', (e) => this.handleFileUploadChunk(e));
|
'fileuploadchunk', (e) => this.handleFileUploadChunk(e));
|
||||||
this._view.logFileReader.addEventListener(
|
this._view.logFileReader.addEventListener(
|
||||||
'fileuploadend', (e) => this.handleFileUploadEnd(e));
|
'fileuploadend', (e) => this.handleFileUploadEnd(e));
|
||||||
this._startupPromise = this.runAsyncInitialize();
|
this._startupPromise = this._loadCustomElements();
|
||||||
this._view.codeTrack.svg = true;
|
this._view.codeTrack.svg = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ class App {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async runAsyncInitialize() {
|
async _loadCustomElements() {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
import('./view/list-panel.mjs'),
|
import('./view/list-panel.mjs'),
|
||||||
import('./view/timeline-panel.mjs'),
|
import('./view/timeline-panel.mjs'),
|
||||||
@ -84,6 +84,10 @@ class App {
|
|||||||
import('./view/property-link-table.mjs'),
|
import('./view/property-link-table.mjs'),
|
||||||
import('./view/tool-tip.mjs'),
|
import('./view/tool-tip.mjs'),
|
||||||
]);
|
]);
|
||||||
|
this._addEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
_addEventListeners() {
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
'keydown', e => this._navigation?.handleKeyDown(e));
|
'keydown', e => this._navigation?.handleKeyDown(e));
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
@ -359,15 +363,14 @@ class App {
|
|||||||
this._processor = new Processor();
|
this._processor = new Processor();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFileUploadChunk(e) {
|
async handleFileUploadChunk(e) {
|
||||||
this._processor.processChunk(e.detail);
|
this._processor.processChunk(e.detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleFileUploadEnd(e) {
|
async handleFileUploadEnd(e) {
|
||||||
try {
|
try {
|
||||||
const processor = this._processor;
|
const processor = this._processor;
|
||||||
processor.finalize();
|
await processor.finalize();
|
||||||
|
|
||||||
await this._startupPromise;
|
await this._startupPromise;
|
||||||
|
|
||||||
this._state.profile = processor.profile;
|
this._state.profile = processor.profile;
|
||||||
|
98
tools/system-analyzer/lws-middleware.js
Normal file
98
tools/system-analyzer/lws-middleware.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
const util = require('util');
|
||||||
|
const execFile = util.promisify(require('child_process').execFile);
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
async function sh(cmd, ...params) {
|
||||||
|
console.log(cmd, params.join(' '));
|
||||||
|
const options = {maxBuffer: 256 * 1024 * 1024};
|
||||||
|
const {stdout} = await execFile(cmd, params, options);
|
||||||
|
return stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Symbolizer {
|
||||||
|
constructor() {
|
||||||
|
this.nmExec = 'nm';
|
||||||
|
this.objdumpExec = 'objdump';
|
||||||
|
}
|
||||||
|
|
||||||
|
middleware(config) {
|
||||||
|
return async (ctx, next) => {
|
||||||
|
if (ctx.path == '/v8/loadVMSymbols') {
|
||||||
|
await this.parseVMSymbols(ctx)
|
||||||
|
}
|
||||||
|
await next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async parseVMSymbols(ctx) {
|
||||||
|
const query = ctx.request.query;
|
||||||
|
const result = {
|
||||||
|
libName: query.libName,
|
||||||
|
symbols: ['', ''],
|
||||||
|
error: undefined,
|
||||||
|
fileOffsetMinusVma: 0,
|
||||||
|
};
|
||||||
|
switch (query.platform) {
|
||||||
|
case 'macos':
|
||||||
|
await this.loadVMSymbolsMacOS(query, result);
|
||||||
|
break;
|
||||||
|
case 'linux':
|
||||||
|
await this.loadVMSymbolsLinux(query, result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ctx.response.status = '500';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.response.type = 'json';
|
||||||
|
ctx.response.body = JSON.stringify(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadVMSymbolsMacOS(query, result) {
|
||||||
|
let libName =
|
||||||
|
(query.targetRootFS ? query.targetRootFS : '') + query.libName;
|
||||||
|
try {
|
||||||
|
// Fast skip files that don't exist.
|
||||||
|
if (libName.indexOf('/') === -1 || !fs.existsSync(libName)) return;
|
||||||
|
result.symbols = [await sh(this.nmExec, '--demangle', '-n', libName), ''];
|
||||||
|
} catch (e) {
|
||||||
|
result.error = e.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadVMSymbolsLinux(query, result) {
|
||||||
|
let libName = query.libName;
|
||||||
|
if (query.apkEmbeddedLibrary && libName.endsWith('.apk')) {
|
||||||
|
libName = query.apkEmbeddedLibrary;
|
||||||
|
}
|
||||||
|
if (query.targetRootFS) {
|
||||||
|
libName = libName.substring(libName.lastIndexOf('/') + 1);
|
||||||
|
libName = query.targetRootFS + libName;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Fast skip files that don't exist.
|
||||||
|
if (libName.indexOf('/') === -1 || !fs.existsSync(libName)) return;
|
||||||
|
result.symbols = [
|
||||||
|
await sh(this.nmExec, '-C', '-n', '-S', libName),
|
||||||
|
await sh(this.nmExec, '-C', '-n', '-S', '-D', libName)
|
||||||
|
];
|
||||||
|
|
||||||
|
const objdumpOutput = await sh(this.objdumpExec, '-h', libName);
|
||||||
|
for (const line of objdumpOutput.split('\n')) {
|
||||||
|
const [, sectionName, , vma, , fileOffset] = line.trim().split(/\s+/);
|
||||||
|
if (sectionName === '.text') {
|
||||||
|
result.fileOffsetMinusVma =
|
||||||
|
parseInt(fileOffset, 16) - parseInt(vma, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
result.error = e.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Symbolizer
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
import {LogReader, parseString, parseVarArgs} from '../logreader.mjs';
|
import {LogReader, parseString, parseVarArgs} from '../logreader.mjs';
|
||||||
import {Profile} from '../profile.mjs';
|
import {Profile} from '../profile.mjs';
|
||||||
|
import {RemoteLinuxCppEntriesProvider, RemoteMacOSCppEntriesProvider} from '../tickprocessor.mjs'
|
||||||
|
|
||||||
import {ApiLogEntry} from './log/api.mjs';
|
import {ApiLogEntry} from './log/api.mjs';
|
||||||
import {CodeLogEntry, DeoptLogEntry, SharedLibLogEntry} from './log/code.mjs';
|
import {CodeLogEntry, DeoptLogEntry, SharedLibLogEntry} from './log/code.mjs';
|
||||||
@ -15,6 +16,37 @@ import {Timeline} from './timeline.mjs';
|
|||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
|
class AsyncConsumer {
|
||||||
|
constructor(consumer_fn) {
|
||||||
|
this._chunks = [];
|
||||||
|
this._consumer = consumer_fn;
|
||||||
|
this._pendingWork = Promise.resolve();
|
||||||
|
this._isConsuming = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get pendingWork() {
|
||||||
|
return this._pendingWork;
|
||||||
|
}
|
||||||
|
|
||||||
|
push(chunk) {
|
||||||
|
this._chunks.push(chunk);
|
||||||
|
this.consumeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
async consumeAll() {
|
||||||
|
if (!this._isConsuming) this._pendingWork = this._consumeAll();
|
||||||
|
return await this._pendingWork;
|
||||||
|
}
|
||||||
|
|
||||||
|
async _consumeAll() {
|
||||||
|
this._isConsuming = true;
|
||||||
|
while (this._chunks.length > 0) {
|
||||||
|
await this._consumer(this._chunks.shift());
|
||||||
|
}
|
||||||
|
this._isConsuming = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Processor extends LogReader {
|
export class Processor extends LogReader {
|
||||||
_profile = new Profile();
|
_profile = new Profile();
|
||||||
_apiTimeline = new Timeline();
|
_apiTimeline = new Timeline();
|
||||||
@ -32,6 +64,8 @@ export class Processor extends LogReader {
|
|||||||
MINOR_VERSION = 6;
|
MINOR_VERSION = 6;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
this._chunkConsumer =
|
||||||
|
new AsyncConsumer((chunk) => this._processChunk(chunk));
|
||||||
const propertyICParser = [
|
const propertyICParser = [
|
||||||
parseInt, parseInt, parseInt, parseInt, parseString, parseString,
|
parseInt, parseInt, parseInt, parseInt, parseString, parseString,
|
||||||
parseString, parseString, parseString, parseString
|
parseString, parseString, parseString, parseString
|
||||||
@ -149,6 +183,8 @@ export class Processor extends LogReader {
|
|||||||
processor: this.processApiEvent
|
processor: this.processApiEvent
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
// TODO(cbruni): Choose correct cpp entries provider
|
||||||
|
this._cppEntriesProvider = new RemoteLinuxCppEntriesProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
printError(str) {
|
printError(str) {
|
||||||
@ -157,6 +193,10 @@ export class Processor extends LogReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processChunk(chunk) {
|
processChunk(chunk) {
|
||||||
|
this._chunkConsumer.push(chunk)
|
||||||
|
}
|
||||||
|
|
||||||
|
async _processChunk(chunk) {
|
||||||
let end = chunk.length;
|
let end = chunk.length;
|
||||||
let current = 0;
|
let current = 0;
|
||||||
let next = 0;
|
let next = 0;
|
||||||
@ -174,21 +214,21 @@ export class Processor extends LogReader {
|
|||||||
this._chunkRemainder = '';
|
this._chunkRemainder = '';
|
||||||
}
|
}
|
||||||
current = next + 1;
|
current = next + 1;
|
||||||
this.processLogLine(line);
|
await this.processLogLine(line);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error occurred during parsing, trying to continue: ${e}`);
|
console.error(`Error occurred during parsing, trying to continue: ${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processLogFile(fileName) {
|
async processLogFile(fileName) {
|
||||||
this.collectEntries = true;
|
this.collectEntries = true;
|
||||||
this.lastLogFileName_ = fileName;
|
this.lastLogFileName_ = fileName;
|
||||||
let i = 1;
|
let i = 1;
|
||||||
let line;
|
let line;
|
||||||
try {
|
try {
|
||||||
while (line = readline()) {
|
while (line = readline()) {
|
||||||
this.processLogLine(line);
|
await this.processLogLine(line);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -199,7 +239,8 @@ export class Processor extends LogReader {
|
|||||||
this.finalize();
|
this.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize() {
|
async finalize() {
|
||||||
|
await this._chunkConsumer.consumeAll();
|
||||||
// TODO(cbruni): print stats;
|
// TODO(cbruni): print stats;
|
||||||
this._mapTimeline.transitions = new Map();
|
this._mapTimeline.transitions = new Map();
|
||||||
let id = 0;
|
let id = 0;
|
||||||
@ -227,12 +268,16 @@ export class Processor extends LogReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processSharedLibrary(name, start, end, aslr_slide) {
|
async processSharedLibrary(name, startAddr, endAddr, aslrSlide) {
|
||||||
const entry = this._profile.addLibrary(name, start, end);
|
const entry = this._profile.addLibrary(name, startAddr, endAddr);
|
||||||
entry.logEntry = new SharedLibLogEntry(entry);
|
entry.logEntry = new SharedLibLogEntry(entry);
|
||||||
// Many events rely on having a script around, creating fake entries for
|
// Many events rely on having a script around, creating fake entries for
|
||||||
// shared libraries.
|
// shared libraries.
|
||||||
this._profile.addScriptSource(-1, name, '');
|
this._profile.addScriptSource(-1, name, '');
|
||||||
|
await this._cppEntriesProvider.parseVmSymbols(
|
||||||
|
name, startAddr, endAddr, aslrSlide, (fName, fStart, fEnd) => {
|
||||||
|
this._profile.addStaticCode(fName, fStart, fEnd);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
processCodeCreation(type, kind, timestamp, start, size, name, maybe_func) {
|
processCodeCreation(type, kind, timestamp, start, size, name, maybe_func) {
|
||||||
@ -329,6 +374,7 @@ export class Processor extends LogReader {
|
|||||||
this._profile.addSourcePositions(
|
this._profile.addSourcePositions(
|
||||||
start, scriptId, startPos, endPos, sourcePositions, inliningPositions,
|
start, scriptId, startPos, endPos, sourcePositions, inliningPositions,
|
||||||
inlinedFunctions);
|
inlinedFunctions);
|
||||||
|
if (this._lastCodeLogEntry === undefined) return;
|
||||||
let profileEntry = this._profile.findEntry(start);
|
let profileEntry = this._profile.findEntry(start);
|
||||||
if (profileEntry !== this._lastCodeLogEntry._entry) return;
|
if (profileEntry !== this._lastCodeLogEntry._entry) return;
|
||||||
this.addSourcePosition(profileEntry, this._lastCodeLogEntry);
|
this.addSourcePosition(profileEntry, this._lastCodeLogEntry);
|
||||||
@ -383,7 +429,7 @@ export class Processor extends LogReader {
|
|||||||
const script = profileEntry.source?.script;
|
const script = profileEntry.source?.script;
|
||||||
if (script !== undefined) return script;
|
if (script !== undefined) return script;
|
||||||
let fileName;
|
let fileName;
|
||||||
if (profileEntry.type = 'SHARED_LIB') {
|
if (profileEntry.type === 'SHARED_LIB') {
|
||||||
fileName = profileEntry.name;
|
fileName = profileEntry.name;
|
||||||
} else {
|
} else {
|
||||||
// Slow path, try to get the script from the url:
|
// Slow path, try to get the script from the url:
|
||||||
|
@ -297,6 +297,7 @@ export class TimelineTrackBase extends V8CustomElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updateToolTip(event) {
|
_updateToolTip(event) {
|
||||||
|
if (!this._focusedEntry) return false;
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new ToolTipEvent(this._focusedEntry, this.toolTipTargetNode));
|
new ToolTipEvent(this._focusedEntry, this.toolTipTargetNode));
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
@ -350,7 +351,6 @@ export class TimelineTrackBase extends V8CustomElement {
|
|||||||
if (chunk === undefined) return [-1, -1];
|
if (chunk === undefined) return [-1, -1];
|
||||||
const xFrom = (chunk.index * kChunkWidth + kChunkVisualWidth / 2) | 0;
|
const xFrom = (chunk.index * kChunkWidth + kChunkVisualWidth / 2) | 0;
|
||||||
const yFrom = kTimelineHeight - chunk.yOffset(entry) | 0;
|
const yFrom = kTimelineHeight - chunk.yOffset(entry) | 0;
|
||||||
console.log(xFrom, yFrom);
|
|
||||||
return [xFrom, yFrom];
|
return [xFrom, yFrom];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ import { ArgumentsProcessor, TickProcessor } from "./tickprocessor.mjs";
|
|||||||
|
|
||||||
const params = ArgumentsProcessor.process(arguments);
|
const params = ArgumentsProcessor.process(arguments);
|
||||||
const tickProcessor = TickProcessor.fromParams(params);
|
const tickProcessor = TickProcessor.fromParams(params);
|
||||||
tickProcessor.processLogFile(params.logFileName);
|
await tickProcessor.processLogFile(params.logFileName);
|
||||||
if (params.serializeVMSymbols) {
|
if (params.serializeVMSymbols) {
|
||||||
tickProcessor.printVMSymbols();
|
tickProcessor.printVMSymbols();
|
||||||
} else {
|
} else {
|
||||||
|
@ -60,12 +60,17 @@ class V8Profile extends Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CppEntriesProvider {
|
class CppEntriesProvider {
|
||||||
|
constructor() {
|
||||||
|
this._isEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
inRange(funcInfo, start, end) {
|
inRange(funcInfo, start, end) {
|
||||||
return funcInfo.start >= start && funcInfo.end <= end;
|
return funcInfo.start >= start && funcInfo.end <= end;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseVmSymbols(libName, libStart, libEnd, libASLRSlide, processorFunc) {
|
async parseVmSymbols(libName, libStart, libEnd, libASLRSlide, processorFunc) {
|
||||||
this.loadSymbols(libName);
|
if (!this._isEnabled) return;
|
||||||
|
await this.loadSymbols(libName);
|
||||||
|
|
||||||
let lastUnknownSize;
|
let lastUnknownSize;
|
||||||
let lastAdded;
|
let lastAdded;
|
||||||
@ -121,12 +126,41 @@ class CppEntriesProvider {
|
|||||||
addEntry({ name: '', start: libEnd });
|
addEntry({ name: '', start: libEnd });
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSymbols(libName) {}
|
async loadSymbols(libName) {}
|
||||||
|
|
||||||
|
async loadSymbolsRemote(platform, libName) {
|
||||||
|
this.parsePos = 0;
|
||||||
|
const url = new URL("http://localhost:8000/v8/loadVMSymbols");
|
||||||
|
url.searchParams.set('libName', libName);
|
||||||
|
url.searchParams.set('platform', platform);
|
||||||
|
this._setRemoteQueryParams(url.searchParams);
|
||||||
|
let response;
|
||||||
|
let json;
|
||||||
|
try {
|
||||||
|
response = await fetch(url);
|
||||||
|
json = await response.json();
|
||||||
|
if (json.error) console.warn(json.error);
|
||||||
|
} catch (e) {
|
||||||
|
if (!response || response.status == 404) {
|
||||||
|
// Assume that the local symbol server is not reachable.
|
||||||
|
console.error("Disabling remote symbol loading:", e);
|
||||||
|
this._isEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._handleRemoteSymbolsResult(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
_setRemoteQueryParams(searchParams) {
|
||||||
|
// Subclass responsibility.
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleRemoteSymbolsResult(json) {
|
||||||
|
this.symbols = json.symbols;
|
||||||
|
}
|
||||||
|
|
||||||
parseNextLine() { return false }
|
parseNextLine() { return false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
||||||
constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
|
constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
|
||||||
super();
|
super();
|
||||||
@ -142,8 +176,18 @@ export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
|||||||
this.FUNC_RE = /^([0-9a-fA-F]{8,16}) ([0-9a-fA-F]{8,16} )?[tTwW] (.*)$/;
|
this.FUNC_RE = /^([0-9a-fA-F]{8,16}) ([0-9a-fA-F]{8,16} )?[tTwW] (.*)$/;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setRemoteQueryParams(searchParams) {
|
||||||
|
super._setRemoteQueryParams(searchParams);
|
||||||
|
searchParams.set('targetRootFS', this.targetRootFS ?? "");
|
||||||
|
searchParams.set('apkEmbeddedLibrary', this.apkEmbeddedLibrary);
|
||||||
|
}
|
||||||
|
|
||||||
loadSymbols(libName) {
|
_handleRemoteSymbolsResult(json) {
|
||||||
|
super._handleRemoteSymbolsResult(json);
|
||||||
|
this.fileOffsetMinusVma = json.fileOffsetMinusVma;
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadSymbols(libName) {
|
||||||
this.parsePos = 0;
|
this.parsePos = 0;
|
||||||
if (this.apkEmbeddedLibrary && libName.endsWith('.apk')) {
|
if (this.apkEmbeddedLibrary && libName.endsWith('.apk')) {
|
||||||
libName = this.apkEmbeddedLibrary;
|
libName = this.apkEmbeddedLibrary;
|
||||||
@ -172,9 +216,7 @@ export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseNextLine() {
|
parseNextLine() {
|
||||||
if (this.symbols.length == 0) {
|
if (this.symbols.length == 0) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const lineEndPos = this.symbols[0].indexOf('\n', this.parsePos);
|
const lineEndPos = this.symbols[0].indexOf('\n', this.parsePos);
|
||||||
if (lineEndPos == -1) {
|
if (lineEndPos == -1) {
|
||||||
this.symbols.shift();
|
this.symbols.shift();
|
||||||
@ -196,6 +238,12 @@ export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class RemoteLinuxCppEntriesProvider extends LinuxCppEntriesProvider {
|
||||||
|
async loadSymbols(libName) {
|
||||||
|
return this.loadSymbolsRemote('linux', libName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
export class MacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
||||||
constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
|
constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
|
||||||
super(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary);
|
super(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary);
|
||||||
@ -203,14 +251,16 @@ export class MacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
|||||||
this.FUNC_RE = /^([0-9a-fA-F]{8,16})() (.*)$/;
|
this.FUNC_RE = /^([0-9a-fA-F]{8,16})() (.*)$/;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSymbols(libName) {
|
async loadSymbols(libName) {
|
||||||
this.parsePos = 0;
|
this.parsePos = 0;
|
||||||
libName = this.targetRootFS + libName;
|
libName = this.targetRootFS + libName;
|
||||||
|
|
||||||
// It seems that in OS X `nm` thinks that `-f` is a format option, not a
|
// It seems that in OS X `nm` thinks that `-f` is a format option, not a
|
||||||
// "flat" display option flag.
|
// "flat" display option flag.
|
||||||
try {
|
try {
|
||||||
this.symbols = [os.system(this.nmExec, ['-n', libName], -1, -1), ''];
|
this.symbols = [
|
||||||
|
os.system(this.nmExec, ['--demangle', '-n', libName], -1, -1),
|
||||||
|
''];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If the library cannot be found on this system let's not panic.
|
// If the library cannot be found on this system let's not panic.
|
||||||
this.symbols = '';
|
this.symbols = '';
|
||||||
@ -218,6 +268,12 @@ export class MacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class RemoteMacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
||||||
|
async loadSymbols(libName) {
|
||||||
|
return this.loadSymbolsRemote('macos', libName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class WindowsCppEntriesProvider extends CppEntriesProvider {
|
export class WindowsCppEntriesProvider extends CppEntriesProvider {
|
||||||
constructor(_ignored_nmExec, _ignored_objdumpExec, targetRootFS,
|
constructor(_ignored_nmExec, _ignored_objdumpExec, targetRootFS,
|
||||||
@ -640,19 +696,19 @@ export class TickProcessor extends LogReader {
|
|||||||
return name !== "UNKNOWN" && !(name in this.codeTypes_);
|
return name !== "UNKNOWN" && !(name in this.codeTypes_);
|
||||||
}
|
}
|
||||||
|
|
||||||
processLogFile(fileName) {
|
async processLogFile(fileName) {
|
||||||
this.lastLogFileName_ = fileName;
|
this.lastLogFileName_ = fileName;
|
||||||
let line;
|
let line;
|
||||||
while (line = readline()) {
|
while (line = readline()) {
|
||||||
this.processLogLine(line);
|
await this.processLogLine(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processLogFileInTest(fileName) {
|
async processLogFileInTest(fileName) {
|
||||||
// Hack file name to avoid dealing with platform specifics.
|
// Hack file name to avoid dealing with platform specifics.
|
||||||
this.lastLogFileName_ = 'v8.log';
|
this.lastLogFileName_ = 'v8.log';
|
||||||
const contents = d8.file.read(fileName);
|
const contents = d8.file.read(fileName);
|
||||||
this.processLogChunk(contents);
|
await this.processLogChunk(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
processSharedLibrary(name, startAddr, endAddr, aslrSlide) {
|
processSharedLibrary(name, startAddr, endAddr, aslrSlide) {
|
||||||
|
Loading…
Reference in New Issue
Block a user