From 1491ef306160fa9296fdfbf0e4b422863a49f9b9 Mon Sep 17 00:00:00 2001 From: machunyu Date: Sun, 20 Nov 2022 16:15:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=BA=93=E6=B3=A8=E5=85=A5?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E9=94=81=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- detect-plugin/package.json | 2 +- detect-plugin/src/detectTaskProvider.ts | 71 ++++++++++++++++++++----- detect-plugin/src/extension.ts | 26 ++++++--- detect-plugin/src/utils.ts | 5 +- 4 files changed, 82 insertions(+), 22 deletions(-) diff --git a/detect-plugin/package.json b/detect-plugin/package.json index c995aaf5..7ecebb12 100644 --- a/detect-plugin/package.json +++ b/detect-plugin/package.json @@ -57,7 +57,7 @@ "description": "%deadlockdetect.taskDefinitions.options.cwd.description%" }, "env": { - "type": "array", + "type": "object", "description": "%deadlockdetect.taskDefinitions.options.env.description%" } } diff --git a/detect-plugin/src/detectTaskProvider.ts b/detect-plugin/src/detectTaskProvider.ts index 4206e8d2..cd4aa096 100644 --- a/detect-plugin/src/detectTaskProvider.ts +++ b/detect-plugin/src/detectTaskProvider.ts @@ -1,17 +1,23 @@ import * as vscode from 'vscode'; import * as child from 'child_process'; -import {execDetect, testPwd, prase_yaml2html} from './utils'; +import {execDetect, archs, testPwd, prase_yaml2html} from './utils'; import { dirname, join } from 'path'; import { kill } from 'process'; import * as fs from 'fs'; type Options = { cwd?: string; - env?: string[]; + env?: { + [name: string]: any; + }; }; +var isNotSupport = false; +const arch = archs.get(process.arch); const binLoader: string = join(dirname(__dirname), "detect-tools/bincheck_loader.sh"); +const hijackLib: string = join(dirname(__dirname), "detect-tools", arch? arch : "x86_64", ""); +const hijackTool: string = join(dirname(__dirname), "detect-tools", arch? arch : "x86_64", ""); interface DetectTaskDefinition extends vscode.TaskDefinition { command: string; @@ -19,14 +25,15 @@ interface DetectTaskDefinition extends vscode.TaskDefinition { options?: Options; } - export class DetectTaskProvider implements vscode.TaskProvider { static customBuildScriptType = 'deadlockdetect'; private tasks: vscode.Task[] | undefined; private sharedState: string | undefined; private cmd: child.ChildProcessWithoutNullStreams | undefined; - constructor(private workspaceRoot: string, private context: vscode.ExtensionContext) { } + constructor(private workspaceRoot: string, private context: vscode.ExtensionContext, private _isNotSupport: boolean) { + isNotSupport = this._isNotSupport; + } public async provideTasks(): Promise { return this.getTasks(); @@ -47,7 +54,6 @@ export class DetectTaskProvider implements vscode.TaskProvider { } this.tasks = []; var option: Options = { - env: ["程序执行所需额外环境变量:如 DISPALY=1"], }; this.tasks!.push(this.getTask("被检测可执行程序", ["可执行程序参数(可选)"], option)); return this.tasks; @@ -77,16 +83,16 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { onDidClose?: vscode.Event = this.closeEmitter.event; private passwd: string | undefined; private checkedPid: number = 0; + private hadChecked: boolean = false; constructor(private cmd: child.ChildProcessWithoutNullStreams | undefined, private context: vscode.ExtensionContext, private command: string, private args: string[], private option: Options, private getSharedState: () => string | undefined, private setSharedState: (state: string) => void) { } - open(initialDimensions: vscode.TerminalDimensions | undefined): void { // At this point we can start using the terminal. if (this.command.length) { let found = false; vscode.workspace.workspaceFolders?.forEach((value)=>{ // value.uri.fsPath - if(this.command[0] == '/' && !found){ + if(this.command[0] === '/' && !found){ this.option.cwd = value.uri.fsPath; found = true; } @@ -131,10 +137,35 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { this.closeEmitter.fire(0); } } + + private hijackCheck(){ + // 注入方式 + child.exec(`${hijackTool} ${this.checkedPid}`, (err, o, e)=>{ + if(o.match(/normal/)?.length){ + const webPanel = vscode.window.createWebviewPanel( + 'detectResultWebview', + "检测结果", + vscode.ViewColumn.One, + { + enableScripts: true, + retainContextWhenHidden: true, + } + ); + webPanel.webview.html = prase_yaml2html(this.command, this.context.extensionPath, webPanel.webview, o); + return; + } + vscode.window.showInformationMessage("未检测到相关锁信息"); + }); + } + close(): void { if(this.cmd){ kill(this.checkedPid, 9); vscode.window.showWarningMessage("检测任务已退出"); + if(isNotSupport && !this.hadChecked){ + this.hadChecked = true; + this.hijackCheck(); + } } } @@ -142,13 +173,18 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private async doExec(): Promise { return new Promise((resolve) => { this.writeEmitter.fire('正在检测 ...\r\n'); - this.option.env?.forEach(e =>{ - let kv = e.split('=', 2); - if(kv.length === 2){ - process.env[kv[0]] = kv[1]; - } - }); + if(this.option.env){ + Object.keys(this.option.env).forEach(key => { + let value = this.option.env?.[key]; + process.env[key] = value; + }); + } let hadPid = false; + if(isNotSupport){ + // 库注入 + this.hadChecked = false; + process.env["LD_PRELOAD"] = hijackLib; + } let coption: child.SpawnOptionsWithoutStdio = { env: process.env }; @@ -180,6 +216,11 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { if(errmsg.length){ vscode.window.showErrorMessage(errmsg); } + if(errmsg.length === 0 && isNotSupport && !this.hadChecked){ + // 注入后锁分析 + this.hadChecked = true; + this.hijackCheck(); + } this.writeEmitter.fire('被检测程序已终止 ... \r\n'); const date = new Date(); this.setSharedState(date.toTimeString() + ' ' + date.toDateString()); @@ -204,6 +245,10 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { if(result.length >= 4){ hadPid = true; this.checkedPid = parseInt(result[3].trim()); + if(isNotSupport){ + // 注入方式 + return; + } execDetect(this.passwd, result[1].trim(), this.checkedPid, (detectResult)=>{ if(detectResult.match(/fatal/)?.length){ kill(this.checkedPid, 9); diff --git a/detect-plugin/src/extension.ts b/detect-plugin/src/extension.ts index 46d2f0f2..05cc69e1 100644 --- a/detect-plugin/src/extension.ts +++ b/detect-plugin/src/extension.ts @@ -5,7 +5,7 @@ import path = require('path'); import fs = require("fs"); import {DetectTaskProvider} from './detectTaskProvider'; import { homedir } from 'os'; -import {exec} from 'child_process'; +import {exec, execSync} from 'child_process'; import {testPwd} from './utils'; import {doLocalPidLockAnalyse} from './analysePid'; // linux命令操作模块 @@ -157,13 +157,27 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.showWarningMessage("检测环境失败, C/C++程序锁分析插件功能受限"); return; } - exec(`grep -r "^CONFIG_BPF_EVENTS=" /boot/config-${o}`, (e1, o1, err1)=>{ - if(e1){ - vscode.window.showWarningMessage("由于内核限制, C/C++程序锁分析插件功能受限"); - return; + var kernelOptions: string[] = [ + "CONFIG_UPROBES=y", + "CONFIG_UPROBE_EVENTS=y", + "CONFIG_TRACEPOINTS=y", + "CONFIG_PERF_EVENTS=y", + "CONFIG_BPF_EVENTS=y" + ]; + var isNotSupport = false; + fs.readFile(`/boot/config-${o}`, 'utf8', function (err, buffer) { + if(err){ + isNotSupport = true; + }else{ + var str = buffer.toString(); + kernelOptions.forEach(elem=>{ + if(!str.includes(elem)){ + isNotSupport = true; + } + }); } const workspaceRoot = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) ? vscode.workspace.workspaceFolders[0].uri.fsPath : homedir(); - detectTaskProvider = vscode.tasks.registerTaskProvider(DetectTaskProvider.customBuildScriptType, new DetectTaskProvider(workspaceRoot, context)); + detectTaskProvider = vscode.tasks.registerTaskProvider(DetectTaskProvider.customBuildScriptType, new DetectTaskProvider(workspaceRoot, context, isNotSupport)); }); }); context.subscriptions.push(...[disposable,disposable0]); diff --git a/detect-plugin/src/utils.ts b/detect-plugin/src/utils.ts index 9483bfca..3b060e67 100644 --- a/detect-plugin/src/utils.ts +++ b/detect-plugin/src/utils.ts @@ -3,10 +3,11 @@ import * as vscode from 'vscode'; import { dirname, join } from 'path'; import * as YAML from 'yaml'; -const archs = new Map([ +export const archs = new Map([ ["x86_64", "x86_64"], ["x64", "x86_64"], - ["arm64", "arm64"] + ["arm64", "arm64"], + ["aarch64", "arm64"] ]); const myArch = archs.get(process.arch);