11cb0ef41Sopenharmony_ci// Copyright 2021 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst util = require('util'); 61cb0ef41Sopenharmony_ciconst execFile = util.promisify(require('child_process').execFile); 71cb0ef41Sopenharmony_ciconst fs = require('fs') 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciasync function sh(cmd, ...params) { 101cb0ef41Sopenharmony_ci console.log(cmd, params.join(' ')); 111cb0ef41Sopenharmony_ci const options = {maxBuffer: 256 * 1024 * 1024}; 121cb0ef41Sopenharmony_ci const {stdout} = await execFile(cmd, params, options); 131cb0ef41Sopenharmony_ci return stdout; 141cb0ef41Sopenharmony_ci} 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciclass Symbolizer { 171cb0ef41Sopenharmony_ci constructor() { 181cb0ef41Sopenharmony_ci this.nmExec = 'nm'; 191cb0ef41Sopenharmony_ci this.objdumpExec = 'objdump'; 201cb0ef41Sopenharmony_ci } 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci middleware(config) { 231cb0ef41Sopenharmony_ci return async (ctx, next) => { 241cb0ef41Sopenharmony_ci if (ctx.path == '/v8/loadVMSymbols') { 251cb0ef41Sopenharmony_ci await this.parseVMSymbols(ctx) 261cb0ef41Sopenharmony_ci } 271cb0ef41Sopenharmony_ci await next() 281cb0ef41Sopenharmony_ci } 291cb0ef41Sopenharmony_ci } 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci async parseVMSymbols(ctx) { 321cb0ef41Sopenharmony_ci const query = ctx.request.query; 331cb0ef41Sopenharmony_ci const result = { 341cb0ef41Sopenharmony_ci libName: query.libName, 351cb0ef41Sopenharmony_ci symbols: ['', ''], 361cb0ef41Sopenharmony_ci error: undefined, 371cb0ef41Sopenharmony_ci fileOffsetMinusVma: 0, 381cb0ef41Sopenharmony_ci }; 391cb0ef41Sopenharmony_ci switch (query.platform) { 401cb0ef41Sopenharmony_ci case 'macos': 411cb0ef41Sopenharmony_ci await this.loadVMSymbolsMacOS(query, result); 421cb0ef41Sopenharmony_ci break; 431cb0ef41Sopenharmony_ci case 'linux': 441cb0ef41Sopenharmony_ci await this.loadVMSymbolsLinux(query, result); 451cb0ef41Sopenharmony_ci break; 461cb0ef41Sopenharmony_ci default: 471cb0ef41Sopenharmony_ci ctx.response.status = '500'; 481cb0ef41Sopenharmony_ci return; 491cb0ef41Sopenharmony_ci } 501cb0ef41Sopenharmony_ci ctx.response.type = 'json'; 511cb0ef41Sopenharmony_ci ctx.response.body = JSON.stringify(result); 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci async loadVMSymbolsMacOS(query, result) { 551cb0ef41Sopenharmony_ci let libName = 561cb0ef41Sopenharmony_ci (query.targetRootFS ? query.targetRootFS : '') + query.libName; 571cb0ef41Sopenharmony_ci try { 581cb0ef41Sopenharmony_ci // Fast skip files that don't exist. 591cb0ef41Sopenharmony_ci if (libName.indexOf('/') === -1 || !fs.existsSync(libName)) return; 601cb0ef41Sopenharmony_ci result.symbols = [await sh(this.nmExec, '--demangle', '-n', libName), '']; 611cb0ef41Sopenharmony_ci } catch (e) { 621cb0ef41Sopenharmony_ci result.error = e.message; 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci async loadVMSymbolsLinux(query, result) { 671cb0ef41Sopenharmony_ci let libName = query.libName; 681cb0ef41Sopenharmony_ci if (query.apkEmbeddedLibrary && libName.endsWith('.apk')) { 691cb0ef41Sopenharmony_ci libName = query.apkEmbeddedLibrary; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci if (query.targetRootFS) { 721cb0ef41Sopenharmony_ci libName = libName.substring(libName.lastIndexOf('/') + 1); 731cb0ef41Sopenharmony_ci libName = query.targetRootFS + libName; 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci try { 761cb0ef41Sopenharmony_ci // Fast skip files that don't exist. 771cb0ef41Sopenharmony_ci if (libName.indexOf('/') === -1 || !fs.existsSync(libName)) return; 781cb0ef41Sopenharmony_ci result.symbols = [ 791cb0ef41Sopenharmony_ci await sh(this.nmExec, '-C', '-n', '-S', libName), 801cb0ef41Sopenharmony_ci await sh(this.nmExec, '-C', '-n', '-S', '-D', libName) 811cb0ef41Sopenharmony_ci ]; 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci const objdumpOutput = await sh(this.objdumpExec, '-h', libName); 841cb0ef41Sopenharmony_ci for (const line of objdumpOutput.split('\n')) { 851cb0ef41Sopenharmony_ci const [, sectionName, , vma, , fileOffset] = line.trim().split(/\s+/); 861cb0ef41Sopenharmony_ci if (sectionName === '.text') { 871cb0ef41Sopenharmony_ci result.fileOffsetMinusVma = 881cb0ef41Sopenharmony_ci parseInt(fileOffset, 16) - parseInt(vma, 16); 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci } catch (e) { 921cb0ef41Sopenharmony_ci console.log(e); 931cb0ef41Sopenharmony_ci result.error = e.message; 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_cimodule.exports = Symbolizer 99