From e0c8ac702edf817e0e0a16a24c088662a4954ceb Mon Sep 17 00:00:00 2001 From: null Date: Sun, 11 Dec 2022 18:09:45 +0800 Subject: [PATCH 1/6] rm unused log --- src/ProblemMatcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProblemMatcher.ts b/src/ProblemMatcher.ts index 0e012a19..82abdf20 100644 --- a/src/ProblemMatcher.ts +++ b/src/ProblemMatcher.ts @@ -40,7 +40,7 @@ function parseLogLines(file: File): string[] { }); } catch (error) { - GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden')); + // nothing todo } return ccLogLines; From 578b92d2f452f867067b3abf54530ab6e40a961d Mon Sep 17 00:00:00 2001 From: null Date: Sat, 31 Dec 2022 15:59:04 +0800 Subject: [PATCH 2/6] [optimize] don't force override 'svdPath' in launch.json --- src/DebugConfigGenerator.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/DebugConfigGenerator.ts b/src/DebugConfigGenerator.ts index d438082a..a79f1c09 100644 --- a/src/DebugConfigGenerator.ts +++ b/src/DebugConfigGenerator.ts @@ -167,8 +167,7 @@ class CortexDebugConfigProvider extends IDebugConfigProvider { // setup svd file, if existed const device = prj.GetPackManager().getCurrentDevInfo(); - debugConfig.svdFile = undefined; - if (device && device.svdPath) { + if (device && device.svdPath && debugConfig.svdFile == undefined) { debugConfig.svdFile = prj.ToRelativePath(device.svdPath) || device.svdPath; } From c5582f14c5de522d2dbd7e4e9696e1db58fa4881 Mon Sep 17 00:00:00 2001 From: null Date: Sat, 31 Dec 2022 16:00:42 +0800 Subject: [PATCH 3/6] [optimize] add promt when remove source dir --- src/EIDEProjectExplorer.ts | 21 +++++++++++++++------ src/StringTable.ts | 23 +++++------------------ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index fbb830cd..871a3d73 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -62,6 +62,7 @@ import { view_str$prompt$unresolved_deps, view_str$prompt$prj_location, view_str$prompt$src_folder_must_be_a_child_of_root, + view_str$prompt$removeSrcDir, view_str$project$folder_type_virtual_desc, view_str$project$folder_type_fs_desc, view_str$msg$err_ewt_hash, @@ -70,7 +71,9 @@ import { view_str$prompt$need_reload_project, view_str$prompt$needReloadToUpdateEnv, getLocalLanguageType, - LanguageIndexs + LanguageIndexs, + txt_yes, + txt_no } from './StringTable'; import { CodeBuilder, BuildOptions } from './CodeBuilder'; import { ExceptionToMessage, newMessage } from './Message'; @@ -4046,11 +4049,17 @@ export class ProjectExplorer implements CustomConfigurationProvider { } async RemoveSrcDir(item: ProjTreeItem) { - const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); - if (item.val.obj instanceof File) { - prj.GetConfiguration().RemoveSrcDir(item.val.obj.path); - } else { - GlobalEvent.emit('error', new Error('remove source root failed !')); + + if (!(item.val.obj instanceof File)) { + return; + } + + const srcDir = item.val.obj; + + const answer = await vscode.window.showInformationMessage(view_str$prompt$removeSrcDir.replace('{}', srcDir.path), txt_yes, txt_no); + if (answer == txt_yes) { + const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); + prj.GetConfiguration().RemoveSrcDir(srcDir.path); } } diff --git a/src/StringTable.ts b/src/StringTable.ts index ad15d4ad..dfb160f5 100644 --- a/src/StringTable.ts +++ b/src/StringTable.ts @@ -360,24 +360,6 @@ export const switch_workspace_hint = [ //--------------- env --------------- -/* - "desc.task.cmd.env.target_name": "项目名称", - "desc.task.cmd.env.project_root": "项目根目录", - "desc.task.cmd.env.output_dir": "编译输出目录", - "desc.task.cmd.env.builer_folder": "构建器可执行文件目录", - "desc.task.cmd.env.toolchain_root": "工具链根目录", - "desc.task.cmd.env.compiler_prefix": "编译器前缀,例如:arm-none-eabi-", - "desc.task.cmd.env.compiler_folder": "编译器可执行文件目录", - - "desc.task.cmd.env.target_name": "Project name", - "desc.task.cmd.env.project_root": "Project root folder", - "desc.task.cmd.env.output_dir": "Build output folder", - "desc.task.cmd.env.builer_folder": "Builder executable file's folder", - "desc.task.cmd.env.toolchain_root": "Toolchain root folder", - "desc.task.cmd.env.compiler_prefix": "Compiler prefix, like: arm-none-eabi-", - "desc.task.cmd.env.compiler_folder": "Compiler executable file's folder", -*/ - export const view_str$env_desc$project_name = [ `项目名称`, `Project name` @@ -415,6 +397,11 @@ export const view_str$env_desc$compiler_folder = [ //---------------Other--------------- +export const view_str$prompt$removeSrcDir = [ + `从项目中移除源文件夹 '{}' ?`, + `Remove source folder '{}' from current project ?` +][langIndex]; + export const view_str$prompt$needReloadToUpdateEnv = [ `需要重启插件以刷新内置的环境变量,立即重启插件?`, `We need relaunch plug-in to refresh internal environment variables, relaunch now ?` From a99fd124041a7c293d7b72a1f1a78da689121bb4 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 1 Jan 2023 20:37:51 +0800 Subject: [PATCH 4/6] [new] Symbol Table View --- package.json | 38 ++- res/icon/Table_16x.svg | 1 + src/EIDEProject.ts | 23 +- src/EIDEProjectExplorer.ts | 513 +++++++++++++++++++++++++++++++++++-- src/VirtualDocsProvider.ts | 55 +++- src/extension.ts | 11 + src/utility.ts | 1 - 7 files changed, 610 insertions(+), 32 deletions(-) create mode 100644 res/icon/Table_16x.svg diff --git a/package.json b/package.json index 3a1aafa2..5d817318 100644 --- a/package.json +++ b/package.json @@ -603,6 +603,22 @@ "light": "./res/icon/Import_16x.svg" } }, + { + "command": "_cl.eide.project.symbol_view.sort_by_addr", + "title": "Sort By Address" + }, + { + "command": "_cl.eide.project.symbol_view.sort_by_size", + "title": "Sort By Size" + }, + { + "command": "_cl.eide.project.symbol_view.disp_hide_no_sized", + "title": "Hide no-size Symbols" + }, + { + "command": "_cl.eide.project.symbol_view.disp_show_all", + "title": "Show All Symbols" + }, { "command": "_cl.eide.project.cppcheck.check_all", "title": "%eide.project.run.cppcheck%" @@ -1121,6 +1137,26 @@ "command": "_cl.eide.project.source.show_cmsis_config_wizard", "group": "commands", "when": "resourceLangId =~ /^c$|^cpp$/ && !config.EIDE.Option.DisableEditorContextMenu" + }, + { + "command": "_cl.eide.project.symbol_view.sort_by_addr", + "group": "commands", + "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived" + }, + { + "command": "_cl.eide.project.symbol_view.sort_by_size", + "group": "commands", + "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived" + }, + { + "command": "_cl.eide.project.symbol_view.disp_hide_no_sized", + "group": "commands", + "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived" + }, + { + "command": "_cl.eide.project.symbol_view.disp_show_all", + "group": "commands", + "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived" } ], "explorer/context": [ @@ -1486,7 +1522,7 @@ { "id": "elf.info", "aliases": [ - "Gnu Elf Info" + "GNU ELF Info" ], "extensions": [ ".elf.info" diff --git a/res/icon/Table_16x.svg b/res/icon/Table_16x.svg new file mode 100644 index 00000000..93284dae --- /dev/null +++ b/res/icon/Table_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index f3930800..4d574cd9 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -838,6 +838,10 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr return this.GetRootDir(); } + public getExecutablePathWithoutSuffix(): string { + return [this.getRootDir().path, this.getOutputDir(), this.getProjectName()].join(File.sep); + } + public getUid(): string { const miscInfo = this.GetConfiguration().config.miscInfo; if (miscInfo.uid == undefined) miscInfo.uid = md5(`${this.getEideDir().path}-${Date.now()}`); @@ -1170,18 +1174,27 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr } } + /** + * get output dir top root name. like: `build` + */ + getOutputRoot(): string { + return this.GetConfiguration().getOutDirRoot(); + } + + /** + * get output dir name. like: 'build\Debug' + */ getOutputDir(): string { return this.GetConfiguration().getOutDir(); } + /** + * get output dir full file system path. like: 'c:\xxx\xxx\proj\build\Debug' + */ getOutputFolder(): File { return new File(this.ToAbsolutePath(this.GetConfiguration().getOutDir())); } - getOutputRoot(): string { - return this.GetConfiguration().getOutDirRoot(); - } - getEideDir(): File { return this.eideDir; } @@ -1974,7 +1987,7 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr this.registerBuiltinVar('ProjectName', () => this.GetConfiguration().config.name); this.registerBuiltinVar('ConfigName', () => this.GetConfiguration().config.mode); this.registerBuiltinVar('ProjectRoot', () => this.getRootDir().path); - this.registerBuiltinVar('ExecutableName', () => [this.getRootDir().path, this.GetConfiguration().getOutDir(), this.GetConfiguration().config.name].join(File.sep)); + this.registerBuiltinVar('ExecutableName', () => this.getExecutablePathWithoutSuffix()); } private RegisterEvent(): void { diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 871a3d73..1ba470e7 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -177,9 +177,11 @@ function getTreeItemTypeName(typ: TreeItemType): string { type GroupRegion = 'PACK' | 'Components' | 'ComponentItem'; interface TreeItemValue { - key?: string; // name will be show in label - alias?: string; // alias name will be show in label - value: string | File; // if TreeItem refer to a file, the value type is 'File' + label?: string; // UI item label, if it's null, item label is '${keyAlias || key} : ${value}' or '${value}' + key?: string; // key name will be show in label + keyAlias?: string; // key's alias name will be show in label + value: string | File; // if TreeItem refer to a file, the value type must be 'File' + isVirtualFile?: boolean; contextVal?: string; tooltip?: string | vscode.MarkdownString; icon?: string; @@ -263,8 +265,12 @@ export class ProjTreeItem extends vscode.TreeItem { if (val.value instanceof File) { this.label = val.value.name; } else { - const lableName: string | undefined = val.alias ? val.alias : val.key; - this.label = lableName ? (`${lableName} : ${val.value}`) : val.value; + const name = val.keyAlias || val.key; + this.label = name ? `${name} : ${val.value}` : val.value; + } + + if (val.label) { + this.label = val.label; } // setup unique id @@ -830,7 +836,14 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco return this.prjList[index]; } - getIndexByProject(uid: string): number { + getProjectByUid(uid: string): AbstractProject | undefined { + const idx = this.getIndexByProjectUid(uid); + if (idx != -1) { + return this.GetProjectByIndex(idx); + } + } + + getIndexByProjectUid(uid: string): number { return this.prjList.findIndex(prj => prj.getUid() == uid); } @@ -1109,7 +1122,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco if (cConfig.isKeyEnable(key) && !excludeKeys.includes(key)) { iList.push(new ProjTreeItem(TreeItemType.COMPILE_CONFIGURATION_ITEM, { key: key, - alias: cConfig.GetKeyDescription(key), + keyAlias: cConfig.GetKeyDescription(key), value: cConfig.getKeyValue(key), tooltip: newMarkdownString([ `${cConfig.GetKeyDescription(key)}`, @@ -1131,7 +1144,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco if (model.isKeyEnable(key)) { iList.push(new ProjTreeItem(TreeItemType.UPLOAD_OPTION_ITEM, { key: key, - alias: model.GetKeyDescription(key), + keyAlias: model.GetKeyDescription(key), value: model.getKeyValue(key), tooltip: newMarkdownString([ `${model.GetKeyDescription(key)}`, @@ -1177,7 +1190,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco iList.push(new ProjTreeItem(TreeItemType.SETTINGS_ITEM, { key: 'name', value: config.config.name, - alias: view_str$settings$prj_name, + keyAlias: view_str$settings$prj_name, tooltip: newMarkdownString(`**${view_str$settings$prj_name}**: \`${config.config.name}\``), projectIndex: element.val.projectIndex })); @@ -1186,7 +1199,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco iList.push(new ProjTreeItem(TreeItemType.SETTINGS_ITEM, { key: 'outDir', value: File.normalize(config.config.outDir), - alias: view_str$settings$outFolderName, + keyAlias: view_str$settings$outFolderName, tooltip: newMarkdownString(`**${view_str$settings$outFolderName}**: \`${config.config.outDir}\``), projectIndex: element.val.projectIndex })); @@ -1195,7 +1208,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco iList.push(new ProjTreeItem(TreeItemType.SETTINGS_ITEM, { key: 'project.env', value: 'object {...}', - alias: view_str$settings$prjEnv, + keyAlias: view_str$settings$prjEnv, tooltip: view_str$settings$prjEnv, projectIndex: element.val.projectIndex })); @@ -1362,11 +1375,11 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco // output folder case TreeItemType.OUTPUT_FOLDER: { + // put output files const outFolder = project.getOutputFolder(); if (outFolder.IsDir()) { const fList = outFolder.GetList([AbstractProject.buildOutputMatcher], File.EXCLUDE_ALL_FILTER); fList.forEach((file) => { - const fsize = file.getSize(); iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, { value: file, collapsibleState: vscode.TreeItemCollapsibleState.None, @@ -1379,6 +1392,25 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco })); }); } + + // put virtual views + { + // Symbol Table + let vFile = File.fromArray([project.getRootDir().path, `${project.getUid()}.elf-symbols`]); + iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, { + label: `Symbol Table`, + value: vFile, + isVirtualFile: true, + collapsibleState: vscode.TreeItemCollapsibleState.None, + projectIndex: element.val.projectIndex, + tooltip: `Symbols Of Program`, + icon: `Table_16x.svg` + })); + if (VirtualDocument.instance().hasDocument(vFile.path) == false) { + VirtualDocument.instance().registerDocumentGetter(vFile.path, + (uri, args) => this.printProjectBinarySymbols(uri, args[0], args[1])); + } + } } break; // output file item @@ -1510,6 +1542,441 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco return iList; } + /* + 文档:https://sourceware.org/binutils/docs-2.39/binutils.html#nm + 下面说明符号类型:对于每一个符号来说,其类型如果是小写的,则表明该符号是local的;大写则表明该符号是global(external)的。 + A 该符号的值是绝对的,在以后的链接过程中,不允许进行改变。这样的符号值,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。 + B 该符号的值出现在非初始化数据段(bss)中。例如,在一个文件中定义全局static int test。则该符号test的类型为b,位于bss section中。其值表示该符号在bss段中的偏移。一般而言,bss段分配于RAM中 + C 该符号为common。common symbol是未初始话数据段。该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示该符号需要的字节数。例如在一个c文件中,定义int test,并且该符号在别的地方会被引用,则该符号类型即为C。否则其类型为B。 + D 该符号位于初始话数据段中。一般来说,分配到data section中。例如定义全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},则会分配于初始化数据段中。 + G 该符号也位于初始化数据段中。主要用于small object提高访问small data object的一种方式。 + I 该符号是对另一个符号的间接引用。 + N 该符号是一个debugging符号。 + R 该符号位于只读数据区。例如定义全局const int test[] = {123, 123};则test就是一个只读数据区的符号。注意在cygwin下如果使用gcc直接编译成MZ格式时,源文件中的test对应_test,并且其符号类型为D,即初始化数据段中。但是如果使用m6812-elf-gcc这样的交叉编译工具,源文件中的test对应目标文件的test,即没有添加下划线,并且其符号类型为R。一般而言,位于rodata section。值得注意的是,如果在一个函数中定义const char *test = “abc”, const char test_int = 3。使用nm都不会得到符号信息,但是字符串“abc”分配于只读存储器中,test在rodata section中,大小为4。 + S 符号位于非初始化数据区,用于small object。 + T 该符号位于代码区text section。 + U 该符号在当前文件中是未定义的,即该符号的定义在别的文件中。例如,当前文件调用另一个文件中定义的函数,在这个被调用的函数在当前就是未定义的;但是在定义它的文件中类型是T。但是对于全局变量来说,在定义它的文件中,其符号类型为C,在使用它的文件中,其类型为U。 + V 该符号是一个weak object。 + W The symbol is a weak symbol that has not been specifically tagged as a weak object symbol. 未明确指定的弱链接符号;同链接的其他对象文件中有它的定义就用上,否则就用一个系统特别指定的默认值。 + - 该符号是a.out格式文件中的stabs symbol。 + ? 该符号类型没有定义 + */ + private convGnuSymbolType2ReadableString(typ: string): string { + + let typeStr: string | undefined; + + switch (typ.toLowerCase()) { + case 'a': + typeStr = 'ABS' + break; + case 'b': + typeStr = 'BSS' + break; + case 'c': + typeStr = 'COMMON' + break; + case 'd': + typeStr = 'DATA' + break; + case 'i': + typeStr = `Indirect Reference` + break; + case 'n': + typeStr = `Debug` + break; + case 'r': + typeStr = `DATA (Read Only)` + break; + case 't': + typeStr = `TEXT` + break; + case 'u': + typeStr = `Undefined` + break; + case 'v': + typeStr = `Weak` + break; + case 'w': + typeStr = `Weak (unspecified)` + break; + default: + break; + } + + if (typeStr) { + if (typ.toLowerCase() == typ) { // is a lowercase word + typeStr += ' (Local)' + } + } + + if (typeStr) { + return `${typ}: ${typeStr}`; + } + + return typ; + } + + private printProjectBinarySymbols(uri: vscode.Uri, + sortType?: 'addr' | 'size', dispType?: 'hide_no_sized' | 'show_all'): Promise { + + if (sortType == undefined) { + sortType = 'addr'; + } + + if (dispType == undefined) { + dispType = 'hide_no_sized'; + } + + return new Promise((resolve) => { + + const uid = new File(uri.fsPath).noSuffixName; + const prj = this.getProjectByUid(uid); + + if (prj == undefined) { + resolve(`Error: Not found project '${uid}' !`); + return; + } + + try { + + const toolchain = prj.getToolchain(); + const toolchainPrefix = toolchain.getToolchainPrefix ? toolchain.getToolchainPrefix() : ''; + + let elfpath = ''; + let elftool = ''; + let elfcmds = ['']; + let elfsort = false; // elftool has sorted ? + + let staMatcher: RegExp | undefined; + let endMatcher: RegExp | undefined; + let symMatcher: RegExp | undefined; + let symTypConv: ((type: string) => string) | undefined; + let locMatcher: RegExp | undefined; + + // sometimes a long line has been truncated, like this: + // 4183: Temperature_Sampling_NVIC_Configuration + // 0x800f4d1 5 Code Gb 0x38 + // we need match and recover them ! + let truncatStaMatcher: RegExp | undefined; + let truncatEndMatcher: RegExp | undefined; + + switch (toolchain.name) { + // armcc fmt: + // # Symbol Name Value Bind Sec Type Vis Size + case 'AC5': + case 'AC6': + elfpath = prj.getExecutablePathWithoutSuffix() + '.axf'; + elftool = [toolchain.getToolchainDir().path, 'bin', `fromelf${exeSuffix()}`].join(File.sep); + elfcmds = ['--text', '-s', elfpath]; + staMatcher = /\(SHT_SYMTAB\)/ + endMatcher = /^\*\* Section/ + truncatStaMatcher = /^\s*\d+\s+(?:[^\s]+)\s*$/i + truncatEndMatcher = /^\s*0x[0-9a-f]+\s+/i + symMatcher = /^\s*\d+\s+(?[^\s]+)\s+(?0x[0-9a-f]+)\s+(?:[^\s]+)\s+(?:[^\s]+)\s+(?[^\s]+)\s+(?:[^\s]+)(?\s+[^\s]+)?/i + break; + // iar fmt: + // # Name Value Sec Type Bd Size Group Other + case 'IAR_ARM': + elfpath = prj.getExecutablePathWithoutSuffix() + '.out'; + elftool = [toolchain.getToolchainDir().path, 'bin', `ielfdumparm${exeSuffix()}`].join(File.sep); + elfcmds = ['-s', '.symtab', elfpath]; + symMatcher = /^\s*\d+:\s+(?[^\s]+)\s+(?0x[0-9a-f]+)\s+(?:[^\s]+)\s+(?[^\s]+\s+[^\s]+)(?\s+0x[0-9a-f]+)?/i; + truncatStaMatcher = /^\s*\d+:\s+(?:[^\s]+)\s*$/i + truncatEndMatcher = /^\s*0x[0-9a-f]+\s+/i + break; + case 'IAR_STM8': + elfpath = prj.getExecutablePathWithoutSuffix() + '.out'; + elftool = [toolchain.getToolchainDir().path, 'stm8', 'bin', `ielfdumpstm8${exeSuffix()}`].join(File.sep); + elfcmds = ['-s', '.symtab', elfpath]; + symMatcher = /^\s*\d+:\s+(?[^\s]+)\s+(?0x[0-9a-f]+)\s+(?:[^\s]+)\s+(?[^\s]+\s+[^\s]+)(?\s+0x[0-9a-f]+)?/i; + truncatStaMatcher = /^\s*\d+:\s+(?:[^\s]+)\s*$/i + truncatEndMatcher = /^\s*0x[0-9a-f]+\s+/i + break; + case 'GCC': + case 'RISCV_GCC': + case 'ANY_GCC': + elfpath = prj.getExecutablePathWithoutSuffix() + '.elf'; + elftool = [toolchain.getToolchainDir().path, 'bin', `${toolchainPrefix}nm${exeSuffix()}`].join(File.sep); + elfcmds = sortType == 'size' ? ['-l', '-S', '--size-sort', elfpath] : ['-ln', '-S', elfpath]; + elfsort = true; + symMatcher = /^(?[0-9a-f]+)\s+(?[0-9a-f]+\s+)?(?\w)\s+(?[^\s]+)\s+(?.*)/i; + symTypConv = (t) => this.convGnuSymbolType2ReadableString(t) + break; + default: + throw new Error(`Not support symbol view for '${toolchain.name}' !`); + } + + if (!File.IsFile(elfpath)) { + throw new Error(`Not found elf file: '${elfpath}', please build your project !`); + } + + if (!File.IsFile(elftool)) { + throw new Error(`Not found elf tool: '${elftool}' !`); + } + + let textLines = child_process.execFileSync(elftool, elfcmds).toString().split(/\r\n|\n/); + + // filter lines + // notes: + // - will contain the line that matched by 'staMatcher' + // - Not contain the line that matched by 'endMatcher' + if (staMatcher) { + + let matchedLines: string[] = []; + let started = false; + + for (const line of textLines) { + + if (!started && staMatcher.test(line)) { + started = true; + } + + if (started) { + + if (matchedLines.length > 0 && + endMatcher && endMatcher.test(line)) { + break; + } + + matchedLines.push(line); + } + } + + textLines = matchedLines; + } + + // if no pattern, output raw text + if (symMatcher === undefined) { + resolve(textLines.join(os.EOL)); + return; + } + + const tableHeader: string[] = ['Address', 'Size', 'Type', 'Symbol Name', 'Location']; + + let resultLines: string[][] = []; + + let col_addr_maxLen = tableHeader[0].length; + let col_size_maxLen = tableHeader[1].length; + let col_type_maxLen = tableHeader[2].length; + let col_name_maxLen = tableHeader[3].length; + let col_loca_maxLen = tableHeader[4].length; + + let sym_cur_file_location: string | undefined; + + let sym_count = 0; + + for (let i = 0; i < textLines.length; i++) { + + let line = textLines[i]; + + if (locMatcher) { + const m = locMatcher.exec(line); + if (m && m.groups) { + sym_cur_file_location = m.groups['loca']?.trim(); + } + } + + if (truncatStaMatcher && truncatEndMatcher) { + let nxtLine = i + 1 < textLines.length ? textLines[i + 1] : undefined; + if (nxtLine && + truncatStaMatcher.test(line) && truncatEndMatcher.test(nxtLine)) { + line = line + nxtLine; + i++; + } + } + + const m = symMatcher.exec(line); + if (!(m && m.groups)) { // no matched + continue; + } + + let addr = m.groups['addr']?.trim(); + let size = m.groups['size']?.trim(); + let type = m.groups['type']?.trim(); + let name = m.groups['name']?.trim(); + let loca = m.groups['loca']?.trim(); + + if (!addr || !name) { + continue; + } + + sym_count++; + + if (type && symTypConv) { + type = symTypConv(type); + } + + // symbol name is a source file ? + if (/\.(?:c|cpp|cxx|c\+\+|cc|s|asm)$/i.test(name)) { + sym_cur_file_location = name; + continue; + } + + size = size || '--'; + type = type || '--'; + loca = loca || sym_cur_file_location || '--'; + + if (dispType == 'hide_no_sized' && size == '--') { + continue; // ignore no-size symbols + } + + col_addr_maxLen = addr.length > col_addr_maxLen ? addr.length : col_addr_maxLen; + col_size_maxLen = size.length > col_size_maxLen ? size.length : col_size_maxLen; + col_type_maxLen = type.length > col_type_maxLen ? type.length : col_type_maxLen; + col_name_maxLen = name.length > col_name_maxLen ? name.length : col_name_maxLen; + col_loca_maxLen = loca.length > col_loca_maxLen ? loca.length : col_loca_maxLen; + + resultLines.push([addr, size, type, name, loca]); + } + + // sort lines + if (!elfsort) { + + if (sortType == 'addr') { + + resultLines = resultLines.sort((a1, a2) => { + const addr_1 = parseInt(a1[0], 16); + const addr_2 = parseInt(a2[0], 16); + return addr_1 - addr_2; + }); + } + + else if (sortType == 'size') { + + let notSizeSyms: string[][] = []; + let hasSizeSyms: string[][] = []; + + resultLines.forEach(sym => { + if (sym[1].startsWith('--')) { + notSizeSyms.push(sym); + } else { + hasSizeSyms.push(sym); + } + }); + + hasSizeSyms = hasSizeSyms.sort((a1, a2) => { + const size_1 = parseInt(a1[1], 16); + const size_2 = parseInt(a2[1], 16); + return size_1 - size_2; + }); + + resultLines = notSizeSyms.concat(hasSizeSyms); + } + } + + // dump result + + let headerLines = [ + '', + 'ELF Symbols', + ` - Tool: '${elftool}'`, + ` - Cmds: '${elfcmds.join(' ')}'`, + ` - Symbol Count: ${sym_count}`, + '' + ]; + + let outputLines: string[] = headerLines; + + // make header + { + outputLines.push( + `--${''.padEnd(col_addr_maxLen, '-')}-` + + `--${''.padEnd(col_size_maxLen, '-')}-` + + `--${''.padEnd(col_type_maxLen, '-')}-` + + `--${''.padEnd(col_name_maxLen, '-')}-` + + `--${''.padEnd(col_loca_maxLen, '-')}-`); + + outputLines.push( + `| ${tableHeader[0].padEnd(col_addr_maxLen)} ` + + `| ${tableHeader[1].padEnd(col_size_maxLen)} ` + + `| ${tableHeader[2].padEnd(col_type_maxLen)} ` + + `| ${tableHeader[3].padEnd(col_name_maxLen)} ` + + `| ${tableHeader[4].padEnd(col_loca_maxLen)} `); + + outputLines.push( + `--${''.padEnd(col_addr_maxLen, '-')}-` + + `--${''.padEnd(col_size_maxLen, '-')}-` + + `--${''.padEnd(col_type_maxLen, '-')}-` + + `--${''.padEnd(col_name_maxLen, '-')}-` + + `--${''.padEnd(col_loca_maxLen, '-')}-`); + } + + for (let i = 1; i < resultLines.length; i++) { + + outputLines.push( + `| ${resultLines[i][0].padEnd(col_addr_maxLen)} ` + + `| ${resultLines[i][1].padEnd(col_size_maxLen)} ` + + `| ${resultLines[i][2].padEnd(col_type_maxLen)} ` + + `| ${resultLines[i][3].padEnd(col_name_maxLen)} ` + + `| ${resultLines[i][4].padEnd(col_loca_maxLen)} `); + } + + outputLines.push(''); + + resolve(outputLines.join(os.EOL)); + + // + // @deprecated Because this lib is too slow + // + + // let maxLen = 0; + // for (const l of headerLines) { + // if (l.length > maxLen) maxLen = l.length; + // } + + // for (let i = 1; i < headerLines.length; i++) { + // headerLines[i] = headerLines[i].padEnd(maxLen); + // } + + // const tableCfg: TxtTable.TableUserConfig = { + + // header: { + // alignment: 'center', + // content: headerLines.join('\n') + // }, + + // drawHorizontalLine: (idx, rowCount) => idx <= 2 || idx === rowCount, + + // columns: { + // 0: { width: col_addr_maxLen }, + // 1: { width: col_size_maxLen }, + // 2: { width: col_type_maxLen }, + // 3: { width: col_name_maxLen }, + // 4: { width: col_loca_maxLen } + // }, + + // border: { + // topBody: `─`, + // topJoin: `┬`, + // topLeft: `┌`, + // topRight: `┐`, + + // bottomBody: `─`, + // bottomJoin: `┴`, + // bottomLeft: `└`, + // bottomRight: `┘`, + + // bodyLeft: `│`, + // bodyRight: `│`, + // bodyJoin: `│`, + + // joinBody: `─`, + // joinLeft: `├`, + // joinRight: `┤`, + // joinJoin: `┼` + // } + // }; + + // const result = TxtTable.table(resultLines, tableCfg); + + // resolve(result); + + } catch (error) { + resolve('Error: ' + (error).message); + } + }); + } + private async _OpenProject(workspaceFilePath: string): Promise { const wsFile: File = new File(workspaceFilePath); @@ -3205,7 +3672,7 @@ export class ProjectExplorer implements CustomConfigurationProvider { private reloadProject(uid: string, workspaceFile: File) { - const idx = this.dataProvider.getIndexByProject(uid); + const idx = this.dataProvider.getIndexByProjectUid(uid); if (idx == -1) { GlobalEvent.emit('msg', newMessage('Error', `Project '${uid}' is not actived !`)); return; @@ -3488,7 +3955,7 @@ export class ProjectExplorer implements CustomConfigurationProvider { } for (const path in diag_res) { - const uri = vscode.Uri.parse(File.ToUri(path)); + const uri = vscode.Uri.file(path); cc_diags.set(uri, diag_res[path]); } } @@ -4710,7 +5177,7 @@ export class ProjectExplorer implements CustomConfigurationProvider { if (mRes && mRes.length > 5) { diagnosticCnt += 1; /* increment cnt */ const fpath = prj.ToAbsolutePath(mRes[pattern.file]); - const uri = vscode.Uri.parse(File.ToUri(fpath)); + const uri = vscode.Uri.file(fpath); const diags = Array.from(this.cppcheck_diag.get(uri) || []); const line = parseInt(mRes[pattern.line]); const col = parseInt(mRes[pattern.column]); @@ -5743,7 +6210,7 @@ export class ProjectExplorer implements CustomConfigurationProvider { if (ProjTreeItem.isFileItem(item.type)) { const file = item.val.value; - const vsUri = vscode.Uri.parse(file.ToUri()); + let isPreview = true; if (this.prev_click_info && @@ -5764,9 +6231,15 @@ export class ProjectExplorer implements CustomConfigurationProvider { // by vscode default api if (this.showBinaryFiles(file, isPreview)) return; - /* We need use 'vscode.open' command, not 'showTextDocument' API, - * because API can't open bin file */ - vscode.commands.executeCommand('vscode.open', vsUri, { preview: isPreview }); + if (item.val.isVirtualFile) { + const uri = vscode.Uri.parse(VirtualDocument.instance().getUriByPath(file.path)); + VirtualDocument.instance().updateDocument(file.path); + vscode.window.showTextDocument(uri, { preview: isPreview }); + } else { + /* We need use 'vscode.open' command, not 'showTextDocument' API, + * because API can't open bin file */ + vscode.commands.executeCommand('vscode.open', vscode.Uri.file(file.path), { preview: isPreview }); + } } catch (error) { GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); @@ -5796,7 +6269,7 @@ export class ProjectExplorer implements CustomConfigurationProvider { if (!fromelf.IsFile()) throw new Error(`Not found '${fromelf.path}' !`); cont = child_process - .execFileSync(fromelf.path, ['--text', '-e', binFile.path]) + .execFileSync(fromelf.path, ['--text', '-v', binFile.path]) .toString(); } catch (error) { const err = error; diff --git a/src/VirtualDocsProvider.ts b/src/VirtualDocsProvider.ts index fbf8bb4d..a8fe6181 100644 --- a/src/VirtualDocsProvider.ts +++ b/src/VirtualDocsProvider.ts @@ -27,17 +27,22 @@ import { File } from '../lib/node-utility/File'; let _instance: VirtualDocument | undefined; +export type VirtualDocumentContentGetter = (uri: vscode.Uri, ...args: any[]) => Promise; + export class VirtualDocument implements vscode.TextDocumentContentProvider { public static scheme = 'eide'; private onDidChangeEmitter: vscode.EventEmitter; - private docsMap: Map; + + private docsMap: Map; + private docsGetterArgs: Map; onDidChange: vscode.Event; private constructor() { this.docsMap = new Map(); + this.docsGetterArgs = new Map(); this.onDidChangeEmitter = new vscode.EventEmitter(); this.onDidChange = this.onDidChangeEmitter.event; } @@ -47,18 +52,58 @@ export class VirtualDocument implements vscode.TextDocumentContentProvider { return _instance; } - updateDocument(path: string, content: string) { - this.docsMap.set(path, content); + hasDocument(path: string): boolean { + return this.docsMap.has(path); + } + + registerDocumentGetter(path: string, getter: VirtualDocumentContentGetter, ...getterArgs: any[]) { + this.docsMap.set(path, getter); + this.docsGetterArgs.set(path, getterArgs); + } + + updateDocument(path: string, content?: string | VirtualDocumentContentGetter, ...getterArgs: any[]) { + + if (content) { + this.docsMap.set(path, content); + } else { + if (!this.docsMap.has(path)) { + return; // not has this file and not file content, exit + } + } + + this.docsGetterArgs.set(path, getterArgs); + this.onDidChangeEmitter.fire(vscode.Uri.parse(this.getUriByPath(path))); } + removeDocument(path: string) { + this.docsMap.delete(path); + this.docsGetterArgs.delete(path); + this.onDidChangeEmitter.fire(vscode.Uri.parse(this.getUriByPath(path))); + } + + getLastGetterArgs(path: string): any[] { + return this.docsGetterArgs.get(path) || []; + } + getUriByPath(path: string): string { return `${VirtualDocument.scheme}://${File.ToNoProtocolUri(path)}`; } provideTextDocumentContent(uri: vscode.Uri, token: vscode.CancellationToken): vscode.ProviderResult { - if (this.docsMap.has(uri.fsPath)) { - return this.docsMap.get(uri.fsPath); + const getter = this.docsMap.get(uri.fsPath); + if (getter) { + if (typeof getter == 'string') { + return getter; + } else { + return vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `Provide Text Document` + }, async (progress) => { + progress.report({ message: `${uri.fsPath}` }); + return await getter(uri, this.docsGetterArgs.get(uri.fsPath) || []); + }); + } } } } diff --git a/src/extension.ts b/src/extension.ts index 7ab228ed..dd8413f2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -172,6 +172,17 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.import.ext.source.struct', (item) => projectExplorer.ImportSourceFromExtProject(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.modify.exclude_list', (item) => projectExplorer.openYamlConfig(item, 'src-exc-cfg'))); + // symbol view editor commands + const virtDoc = VirtualDocument.instance(); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.sort_by_addr', + (url) => virtDoc.updateDocument(url.fsPath, undefined, 'addr', virtDoc.getLastGetterArgs(url.fsPath)[1]))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.sort_by_size', + (url) => virtDoc.updateDocument(url.fsPath, undefined, 'size', virtDoc.getLastGetterArgs(url.fsPath)[1]))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.disp_hide_no_sized', + (url) => virtDoc.updateDocument(url.fsPath, undefined, virtDoc.getLastGetterArgs(url.fsPath)[0], 'hide_no_sized'))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.disp_show_all', + (url) => virtDoc.updateDocument(url.fsPath, undefined, virtDoc.getLastGetterArgs(url.fsPath)[0], 'show_all'))); + // filesystem files subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add_file', (item) => projectExplorer.fs_folderAddFile(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add', (item) => projectExplorer.fs_folderAdd(item))); diff --git a/src/utility.ts b/src/utility.ts index f13a81a1..8ac09de2 100644 --- a/src/utility.ts +++ b/src/utility.ts @@ -26,7 +26,6 @@ import * as vscode from 'vscode'; import * as crypto from 'crypto'; import * as child_process from 'child_process'; import * as fs from 'fs'; - import * as os from 'os'; import { WorkspaceManager } from "./WorkspaceManager"; From cd353c7c7d86420d0fa4b84aae672774094182c1 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 1 Jan 2023 21:49:29 +0800 Subject: [PATCH 5/6] [new] Add 'X/O Base', 'R/O Base', 'R/W Base' options for armcc --- lang/arm.v5.verify.json | 20 +++++++++++++++++++- lang/arm.v6.verify.json | 18 ++++++++++++++++++ res/data/option.mapper.json | 18 ++++++++++++++++++ src/CodeBuilder.ts | 23 +++++++++++++++++++++++ src/EIDEProjectExplorer.ts | 4 ++++ src/KeilXmlParser.ts | 9 +++++++-- 6 files changed, 89 insertions(+), 3 deletions(-) diff --git a/lang/arm.v5.verify.json b/lang/arm.v5.verify.json index 25538164..1c89a879 100644 --- a/lang/arm.v5.verify.json +++ b/lang/arm.v5.verify.json @@ -432,6 +432,24 @@ false ] }, + "xo-base": { + "markdownDescription": "X/O Base", + "description.zh-cn": "X/O Base", + "size": "small", + "type": "string" + }, + "ro-base": { + "markdownDescription": "R/O Base", + "description.zh-cn": "R/O Base", + "size": "small", + "type": "string" + }, + "rw-base": { + "markdownDescription": "R/W Base", + "description.zh-cn": "R/W Base", + "size": "small", + "type": "string" + }, "misc-controls": { "markdownDescription": "Other Linker Options", "description.zh-cn": "链接器附加选项", @@ -448,4 +466,4 @@ } } } -} +} \ No newline at end of file diff --git a/lang/arm.v6.verify.json b/lang/arm.v6.verify.json index 9924b4b8..cea1eaf6 100644 --- a/lang/arm.v6.verify.json +++ b/lang/arm.v6.verify.json @@ -370,6 +370,24 @@ false ] }, + "xo-base": { + "markdownDescription": "X/O Base", + "description.zh-cn": "X/O Base", + "size": "small", + "type": "string" + }, + "ro-base": { + "markdownDescription": "R/O Base", + "description.zh-cn": "R/O Base", + "size": "small", + "type": "string" + }, + "rw-base": { + "markdownDescription": "R/W Base", + "description.zh-cn": "R/W Base", + "size": "small", + "type": "string" + }, "misc-controls": { "markdownDescription": "Other Linker Options", "description.zh-cn": "链接器附加选项", diff --git a/res/data/option.mapper.json b/res/data/option.mapper.json index 4fcc52ef..dc0dfb7d 100644 --- a/res/data/option.mapper.json +++ b/res/data/option.mapper.json @@ -180,6 +180,15 @@ "true": "1", "false": "0" } + }, + "xo-base": { + "keilName": "pXoBase" + }, + "ro-base": { + "keilName": "TextAddressRange" + }, + "rw-base": { + "keilName": "DataAddressRange" } } } @@ -390,6 +399,15 @@ "true": "1", "false": "0" } + }, + "xo-base": { + "keilName": "pXoBase" + }, + "ro-base": { + "keilName": "TextAddressRange" + }, + "rw-base": { + "keilName": "DataAddressRange" } } } diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts index 959cd72b..5ac52c1b 100644 --- a/src/CodeBuilder.ts +++ b/src/CodeBuilder.ts @@ -891,6 +891,7 @@ export class ARMCodeBuilder extends CodeBuilder { let scatterFilePath: string = config.compileConfig.scatterFilePath; switch (toolchain.name) { + // 'armcc' can select whether use custom linker file case 'AC5': case 'AC6': @@ -935,6 +936,28 @@ export class ARMCodeBuilder extends CodeBuilder { // set linker script options.linker['link-scatter'] = ldFileList; + // for armcc + if (['AC5', 'AC6'].includes(toolchain.name)) { + + // if no scatter, will use X/O Base, R/O Base options + if (ldFileList.length == 0) { + + let xo_base = options.linker['xo-base']?.trim(); + let ro_base = options.linker['ro-base']?.trim(); + let rw_base = options.linker['rw-base']?.trim(); + + let ld_flag: string[] = []; + + if (xo_base) ld_flag.push(`--xo-base ${xo_base}`); + if (ro_base) ld_flag.push(`--ro-base ${ro_base} --entry ${ro_base}`); + if (rw_base) ld_flag.push(`--rw-base ${rw_base}`); + + ld_flag.push('--entry Reset_Handler', '--first __Vectors'); + + options.linker['misc-controls'] = ld_flag.join(' ') + ' ' + (options.linker['misc-controls'] || ''); + } + } + if (options.afterBuildTasks === undefined) { options.afterBuildTasks = []; } diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 1ba470e7..4a669a91 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -2959,10 +2959,14 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco prjCompileOption.floatingPointHardware = keilCompileConf.floatingPointHardware || 'none'; prjCompileOption.useCustomScatterFile = keilCompileConf.useCustomScatterFile; prjCompileOption.storageLayout = keilCompileConf.storageLayout; + if (keilCompileConf.scatterFilePath) { prjCompileOption.scatterFilePath = baseInfo.rootFolder.ToRelativePath(keilCompileConf.scatterFilePath) || keilCompileConf.scatterFilePath; + } else { // if no scatter, will use X/O Base, R/O Base options, make scatterFilePath empty + prjCompileOption.scatterFilePath = ''; } + // import builder options const toolchain = ToolchainManager.getInstance().getToolchain('ARM', keilCompileConf.toolchain); const opts = mergeBuilderOpts(toolchain.getDefaultConfig(), keilCompileConf.optionsGroup[keilCompileConf.toolchain]); diff --git a/src/KeilXmlParser.ts b/src/KeilXmlParser.ts index a366ea38..b56ba1f6 100644 --- a/src/KeilXmlParser.ts +++ b/src/KeilXmlParser.ts @@ -572,7 +572,7 @@ class KeilSettingMapper { const objGroup = domainObj[groupName]; const option = objGroup.properties[key]; if (option) { - const value = option.enum[typeof val === 'boolean' ? val.toString() : val]; + const value = option.enum ? option.enum[typeof val === 'boolean' ? val.toString() : val] : val; if (value !== undefined) { const keilCategory = TargetOption[this.mapper.keilName]; keilCategory[objGroup.keilName][option.keilName] = value; @@ -592,6 +592,11 @@ class KeilSettingMapper { if (keilGroup && keilGroup[option.keilName] !== undefined) { const keilValue = keilGroup[option.keilName]; + + if (option.enum == undefined) { + return keilValue; + } + for (const opKey in option.enum) { if (option.enum[opKey] === keilValue) { if (opKey === 'true') { @@ -962,7 +967,7 @@ class ARMParser extends KeilParser { } } - //set current + // set current const toolchain = prj.getToolchain(); const mapper = new KeilSettingMapper(toolchain.name); const options: any = compileModel.getOptions(eidePath, prjConfig.config); From cef671175b71324918d3dac92bc4518f30643d24 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 1 Jan 2023 22:14:14 +0800 Subject: [PATCH 6/6] v3.10.8 update --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- src/EIDEProjectExplorer.ts | 30 +++++++++++++++++------------- src/KeilXmlParser.ts | 8 ++++++-- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index babeb73a..c8b524c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ All notable version changes will be recorded in this file. *** +### [v3.10.8] update + +**New**: + - `Project Resource`: Add `Symbol Table` virtual file in `Output Files`, click it to show `elf symbols` (support 'armcc', 'gcc', 'iar'). + - `Builder Options` : Add `X/O Base`, `R/O Base`, `R/W Base` options for armcc, and allow import them from keil project. + +**Optimize**: + - `launch.json Generator`: Don't force override 'svdPath' in launch.json config. + - `Project Resource`: Show promt when remove a filesystem source dir. + +*** + ### [v3.10.7] revision **Fix**: diff --git a/package.json b/package.json index 5d817318..893810c0 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "homepage": "https://em-ide.com", "license": "MIT", "description": "A mcu development environment for 8051/AVR/STM8/Cortex-M/RISC-V", - "version": "3.10.7", + "version": "3.10.8", "preview": false, "engines": { "vscode": "^1.67.0" diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 4a669a91..e90d88ae 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1396,19 +1396,23 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco // put virtual views { // Symbol Table - let vFile = File.fromArray([project.getRootDir().path, `${project.getUid()}.elf-symbols`]); - iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, { - label: `Symbol Table`, - value: vFile, - isVirtualFile: true, - collapsibleState: vscode.TreeItemCollapsibleState.None, - projectIndex: element.val.projectIndex, - tooltip: `Symbols Of Program`, - icon: `Table_16x.svg` - })); - if (VirtualDocument.instance().hasDocument(vFile.path) == false) { - VirtualDocument.instance().registerDocumentGetter(vFile.path, - (uri, args) => this.printProjectBinarySymbols(uri, args[0], args[1])); + // - not support sdcc, keil_c51 now ! + if (!['Keil_C51', 'SDCC'].includes(project.getToolchain().name)) { + + let vFile = File.fromArray([project.getRootDir().path, `${project.getUid()}.elf-symbols`]); + iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, { + label: `Symbol Table`, + value: vFile, + isVirtualFile: true, + collapsibleState: vscode.TreeItemCollapsibleState.None, + projectIndex: element.val.projectIndex, + tooltip: `Symbols Of Program`, + icon: `Table_16x.svg` + })); + if (VirtualDocument.instance().hasDocument(vFile.path) == false) { + VirtualDocument.instance().registerDocumentGetter(vFile.path, + (uri, args) => this.printProjectBinarySymbols(uri, args[0], args[1])); + } } } } diff --git a/src/KeilXmlParser.ts b/src/KeilXmlParser.ts index b56ba1f6..9e423c99 100644 --- a/src/KeilXmlParser.ts +++ b/src/KeilXmlParser.ts @@ -980,8 +980,12 @@ class ARMParser extends KeilParser { if (armAdsObj.LDads) { const LDads = armAdsObj.LDads; LDads.umfTarg = config.useCustomScatterFile ? '0' : '1'; - const absPath = prj.ToAbsolutePath(config.scatterFilePath); - LDads.ScatterFile = this.ToRelativePath(absPath); + if (config.scatterFilePath) { + const absPath = prj.ToAbsolutePath(config.scatterFilePath); + LDads.ScatterFile = this.ToRelativePath(absPath); + } else { + LDads.ScatterFile = ''; + } } const info = armAdsObj.ArmAdsMisc;