Skip to content

Commit 09f122c

Browse files
committed
feat: Enhance ELF symbol handling and UI improvements
- Updated symbol labels to use title case for consistency - Added hexaddr property to symbols for better address representation - Improved UI styles for better readability and consistency - Introduced new CLAUDE.md documentation for ELF symbol processing library
1 parent 3f3c19e commit 09f122c

File tree

10 files changed

+192
-110
lines changed

10 files changed

+192
-110
lines changed

src/cmds/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export let cmds: Object = {
3535
],
3636
name: 'Build',
3737
iconId: 'github-action',
38-
label: 'build',
38+
label: 'Build',
3939
isExpanded: true
4040
},
4141
Settings : {
@@ -84,7 +84,7 @@ export let cmds: Object = {
8484
],
8585
name: 'Settings',
8686
iconId: 'gear',
87-
label: 'settings',
87+
label: 'Settings',
8888
isExpanded: true
8989
},
9090
Packages : {
@@ -112,7 +112,7 @@ export let cmds: Object = {
112112
],
113113
name: 'Packages',
114114
iconId: 'extensions',
115-
label: 'packages',
115+
label: 'Packages',
116116
isExpanded: false
117117
}
118118
};

src/dock.ts

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,18 @@ class CmdTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
2020

2121
if (isRTThreadProject() !== true && isRTThreadWorksapce() !== true) {
2222
// only show Create Project and RT-Thread Setting command when not in RT-Thread project
23-
let createProject = new vscode.TreeItem("create project", vscode.TreeItemCollapsibleState.None);
23+
let createProject = new vscode.TreeItem("Create Project", vscode.TreeItemCollapsibleState.None);
2424
createProject.iconPath = new vscode.ThemeIcon("new-folder");
25-
createProject.label = "create project";
25+
createProject.label = "Create Project";
2626
createProject.command = {
2727
command: "extension.showCreateProject",
2828
title: "show create project page",
2929
arguments: [],
3030
};
3131

32-
let rtSetting = new vscode.TreeItem("rt-thread setting", vscode.TreeItemCollapsibleState.None);
32+
let rtSetting = new vscode.TreeItem("RT-Thread Setting", vscode.TreeItemCollapsibleState.None);
3333
rtSetting.iconPath = new vscode.ThemeIcon("settings-gear");
34-
rtSetting.label = "rt-thread setting";
34+
rtSetting.label = "RT-Thread Setting";
3535
rtSetting.command = {
3636
command: "extension.showSetting",
3737
title: "show rt-thread setting page",
@@ -47,35 +47,26 @@ class CmdTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
4747
arguments: [],
4848
};
4949

50-
let analyze = new vscode.TreeItem("Analyze", vscode.TreeItemCollapsibleState.None);
51-
analyze.iconPath = new vscode.ThemeIcon("search-fuzzy");
52-
analyze.label = "Analyze";
53-
analyze.command = {
54-
command: "extension.showAnalyze",
55-
title: "show Analyze page",
56-
arguments: [],
57-
};
58-
59-
return [analyze, createProject, rtSetting, about, ];
50+
return [createProject, rtSetting, about];
6051
}
6152

6253
if (!element) {
6354
let children = [];
6455

6556
// 添加创建工程项
66-
let createProject = new vscode.TreeItem("create project", vscode.TreeItemCollapsibleState.None);
57+
let createProject = new vscode.TreeItem("Create Project", vscode.TreeItemCollapsibleState.None);
6758
createProject.iconPath = new vscode.ThemeIcon("new-folder");
68-
createProject.label = "create project";
59+
createProject.label = "Create Project";
6960
createProject.command = {
7061
command: "extension.showCreateProject",
7162
title: "show create project page",
7263
arguments: [],
7364
};
7465
children.push(createProject);
7566

76-
let rtSetting = new vscode.TreeItem("rt-thread setting", vscode.TreeItemCollapsibleState.None);
67+
let rtSetting = new vscode.TreeItem("RT-Thread Setting", vscode.TreeItemCollapsibleState.None);
7768
rtSetting.iconPath = new vscode.ThemeIcon("settings-gear");
78-
rtSetting.label = "rt-thread setting";
69+
rtSetting.label = "RT-Thread Setting";
7970
rtSetting.command = {
8071
command: "extension.showSetting",
8172
title: "show rt-thread setting page",
@@ -91,6 +82,16 @@ class CmdTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
9182
children.push(item);
9283
};
9384

85+
let analyze = new vscode.TreeItem("Symbolic Analysis", vscode.TreeItemCollapsibleState.None);
86+
analyze.iconPath = new vscode.ThemeIcon("search-fuzzy");
87+
analyze.label = "Symbolic Analysis";
88+
analyze.command = {
89+
command: "extension.showAnalyze",
90+
title: "show symbolic analysis page",
91+
arguments: [],
92+
};
93+
children.push(analyze);
94+
9495
let about = new vscode.TreeItem("About", vscode.TreeItemCollapsibleState.None);
9596
about.iconPath = new vscode.ThemeIcon("info");
9697
about.label = "About";
@@ -101,15 +102,6 @@ class CmdTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
101102
};
102103
children.push(about);
103104

104-
let analyze = new vscode.TreeItem("Analyze", vscode.TreeItemCollapsibleState.None);
105-
analyze.iconPath = new vscode.ThemeIcon("info");
106-
analyze.label = "Analyze";
107-
analyze.command = {
108-
command: "extension.showAnalyze",
109-
title: "show analyze page",
110-
arguments: [],
111-
};
112-
children.push(analyze);
113105

114106
return children;
115107
} else {

src/utils/elf/CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- 这是一个elf符号处理的库,使用typescript方式编写,分析rtthread.elf,rtthread.map文件,并返回相关符号信息。

src/utils/elf/elf-analyzer.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ describe('ElfAnalyzer', () => {
7373
expect(symbol).toHaveProperty('name');
7474
expect(symbol).toHaveProperty('type');
7575
expect(symbol).toHaveProperty('address');
76+
expect(symbol).toHaveProperty('hexaddr');
7677
expect(symbol).toHaveProperty('size');
7778

7879
expect(typeof symbol.name).toBe('string');
7980
expect(typeof symbol.type).toBe('string');
8081
expect(typeof symbol.address).toBe('number');
82+
expect(typeof symbol.hexaddr).toBe('string');
8183
expect(typeof symbol.size).toBe('number');
8284
});
8385
});
@@ -140,6 +142,7 @@ describe('ElfAnalyzer', () => {
140142
symbols.forEach(symbol => {
141143
expect(symbol.address).toBeGreaterThanOrEqual(0);
142144
expect(Number.isInteger(symbol.address)).toBe(true);
145+
expect(symbol.hexaddr).toMatch(/^0x[0-9a-f]+$/i);
143146
});
144147
});
145148
});

src/utils/elf/elf-parser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,12 @@ export class ElfParser {
214214
const type = this.getSymbolType(entry.info);
215215
const sectionName = this.getSectionNameByIndex(entry.shndx);
216216

217+
const address = Number(entry.value);
217218
symbols.push({
218219
name,
219220
type,
220-
address: Number(entry.value),
221+
address,
222+
hexaddr: '0x' + address.toString(16),
221223
size,
222224
section: sectionName
223225
});

src/utils/elf/handleElf.ts

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -10,86 +10,86 @@ const SYMBOLS_BY_SECTION_FROM_ELF = "symbolsBySectionFromElf";
1010
// Test the analyzer with local files
1111
export async function handleElf(context: vscode.ExtensionContext, panel: vscode.WebviewPanel) {
1212

13-
// 1. 先判断是否存在工作区
14-
if (!vscode.workspace.workspaceFolders) {
15-
// 提示用户打开工作区
16-
vscode.window.showErrorMessage('请先打开一个项目文件夹或工作区!');
17-
return;
18-
}
19-
const projectPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
20-
const elfPath = path.join(projectPath, 'rtthread.elf');
21-
const mapPath = path.join(projectPath, 'rtthread.map');
13+
// 1. 先判断是否存在工作区
14+
if (!vscode.workspace.workspaceFolders) {
15+
// 提示用户打开工作区
16+
vscode.window.showErrorMessage('请先打开一个项目文件夹或工作区!');
17+
return;
18+
}
19+
const projectPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
20+
const elfPath = path.join(projectPath, 'rtthread.elf');
21+
const mapPath = path.join(projectPath, 'rtthread.map');
2222

23-
// Check if files exist
24-
const elfExists = fs.existsSync(elfPath);
25-
const mapExists = fs.existsSync(mapPath);
23+
// Check if files exist
24+
const elfExists = fs.existsSync(elfPath);
25+
const mapExists = fs.existsSync(mapPath);
2626

27-
if (!elfExists && !mapExists) {
28-
console.log('\nPlease place rtthread.elf and/or rtthread.map in the current directory to test.');
29-
vscode.window.showInformationMessage('ELF 或 MAP 文件不存在!请检查当前目录下是否存在 rtthread.elf 和 rtthread.map 文件');
30-
return;
31-
}
27+
if (!elfExists && !mapExists) {
28+
console.log('\nPlease place rtthread.elf and/or rtthread.map in the current directory to test.');
29+
vscode.window.showInformationMessage('ELF 或 MAP 文件不存在!请检查当前目录下是否存在 rtthread.elf 和 rtthread.map 文件');
30+
return;
31+
}
3232

33-
try {
34-
const analyzer = new ElfAnalyzer(
35-
elfExists ? elfPath : undefined,
36-
mapExists ? mapPath : undefined
37-
);
33+
try {
34+
const analyzer = new ElfAnalyzer(
35+
elfExists ? elfPath : undefined,
36+
mapExists ? mapPath : undefined
37+
);
3838

39-
// Test getSections
40-
const sections = analyzer.getSections();
41-
const postSections = [];
42-
for(let i = 0; i < sections.length; i++) {
43-
const section = sections[i];
44-
const symbols = analyzer.getSymbolsBySection(section.name);
45-
if(symbols.length > 0) {
46-
postSections.push(section);
47-
}
48-
}
49-
console.log('\n=== Sections (Top 5) ===', postSections);
50-
panel.webview.postMessage({ eventName: SECTIONS, data: postSections, from: 'extension' });
39+
// Test getSections
40+
const sections = analyzer.getSections();
41+
const postSections = [];
42+
for (let i = 0; i < sections.length; i++) {
43+
const section = sections[i];
44+
const symbols = analyzer.getSymbolsBySection(section.name);
45+
if (symbols.length > 0) {
46+
postSections.push(section);
47+
}
48+
}
49+
console.log('\n=== Sections (Top 5) ===', postSections);
50+
panel.webview.postMessage({ eventName: SECTIONS, data: postSections, from: 'extension' });
5151

52-
// 监听 Webview 发送的消息
53-
panel.webview.onDidReceiveMessage(
54-
(message) => {
55-
// 根据消息中的 command 处理不同逻辑
56-
switch (message.eventName) {
57-
case SYMBOLS_BY_SECTION:
58-
const symbols = analyzer.getSymbolsBySection(message.sectionName);
59-
panel.webview.postMessage({ eventName: SYMBOLS_BY_SECTION_FROM_ELF, data: symbols, from: 'extension' });
60-
default:
61-
break;
52+
// 监听 Webview 发送的消息
53+
panel.webview.onDidReceiveMessage(
54+
(message) => {
55+
// 根据消息中的 command 处理不同逻辑
56+
switch (message.eventName) {
57+
case SYMBOLS_BY_SECTION:
58+
const symbols = analyzer.getSymbolsBySection(message.sectionName);
59+
panel.webview.postMessage({ eventName: SYMBOLS_BY_SECTION_FROM_ELF, data: symbols, from: 'extension' });
60+
default:
61+
break;
62+
}
63+
},
64+
undefined, // 可选的错误处理
65+
);
66+
67+
// Test getSymbolsBySection
68+
if (elfExists) {
69+
const sections = analyzer.getSections();
70+
const textSection = sections.find(s => s.name === '.text');
71+
if (textSection) {
72+
const textSymbols = analyzer.getSymbolsBySection('.text');
73+
}
6274
}
63-
},
64-
undefined, // 可选的错误处理
65-
);
6675

67-
// Test getSymbolsBySection
68-
if (elfExists) {
69-
const sections = analyzer.getSections();
70-
const textSection = sections.find(s => s.name === '.text');
71-
if (textSection) {
72-
const textSymbols = analyzer.getSymbolsBySection('.text');
73-
}
74-
}
76+
// Test getSymbols by object (if MAP file available)
77+
if (mapExists) {
78+
const allSymbols = analyzer.getAllSymbols();
79+
const uniqueObjects = new Set(allSymbols.map(s => s.object).filter(o => o));
80+
const firstObject = Array.from(uniqueObjects)[0];
7581

76-
// Test getSymbols by object (if MAP file available)
77-
if (mapExists) {
78-
const allSymbols = analyzer.getAllSymbols();
79-
const uniqueObjects = new Set(allSymbols.map(s => s.object).filter(o => o));
80-
const firstObject = Array.from(uniqueObjects)[0];
82+
if (firstObject) {
83+
console.log(`\n=== Symbols in ${firstObject} (Top 5) ===`);
84+
const objectSymbols = analyzer.getSymbols(firstObject);
85+
console.log(`Found ${objectSymbols.length} symbols:`);
86+
objectSymbols.slice(0, 5).forEach(symbol => {
87+
console.log(` ${symbol.name}: size=${symbol.size}, addr=${symbol.hexaddr}`);
88+
});
89+
}
90+
}
8191

82-
if (firstObject) {
83-
console.log(`\n=== Symbols in ${firstObject} (Top 5) ===`);
84-
const objectSymbols = analyzer.getSymbols(firstObject);
85-
console.log(`Found ${objectSymbols.length} symbols:`);
86-
objectSymbols.slice(0, 5).forEach(symbol => {
87-
console.log(` ${symbol.name}: size=${symbol.size}, addr=0x${symbol.address.toString(16)}`);
88-
});
89-
}
92+
} catch (error) {
93+
console.error('Error during analysis:', error);
9094
}
91-
92-
} catch (error) {
93-
console.error('Error during analysis:', error);
94-
}
9595
}

src/utils/elf/map-parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export class MapParser {
4545
name,
4646
type: 'UNKNOWN',
4747
address,
48+
hexaddr: '0x' + address.toString(16),
4849
size,
4950
object: currentObject || undefined
5051
});
@@ -66,6 +67,7 @@ export class MapParser {
6667
name,
6768
type: 'UNKNOWN',
6869
address,
70+
hexaddr: '0x' + address.toString(16),
6971
size,
7072
object: currentObject || undefined
7173
});

src/utils/elf/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface Symbol {
99
name: string;
1010
type: string;
1111
address: number;
12+
hexaddr: string;
1213
size: number;
1314
section?: string;
1415
object?: string;

0 commit comments

Comments
 (0)