Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
/*******************************************************************************
* Copyright 2021 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
* Copyright 2021-2026 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
* Use is subject to license terms.
*******************************************************************************/
package com.espressif.idf.ui.handlers;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
Expand Down Expand Up @@ -41,6 +44,8 @@
*/
public class HeapDumpAnalysisHandler extends AbstractHandler
{
private static final Pattern CORE_SUFFIX = Pattern.compile("(?i)^(.+\\.svdat)_core\\d+$"); //$NON-NLS-1$
private static final String FILE_URL_PREFIX = "file://"; //$NON-NLS-1$
Comment on lines +47 to +48

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

while IFS= read -r script; do
  ast-grep outline "$script" --lang python
  rg -n -C 4 'file:|urlparse|url2pathname|unquote|Path\(' "$script"
done < <(fd -a '^sysviewtrace_proc\.py$' .)

Repository: espressif/idf-eclipse-plugin

Length of output: 218


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Find target files"
fd -a 'HeapDumpAnalysisHandler\.java|sysviewtrace_proc\.py' .

echo
echo "Handler outline"
handler="$(fd 'HeapDumpAnalysisHandler\.java' . | head -n 1)"
if [ -n "${handler:-}" ]; then
  ast-grep outline "$handler" --lang java
  echo
  echo "Relevant handler excerpt"
  sed -n '1,180p' "$handler" | cat -n
fi

echo
echo "Python matches"
while IFS= read -r script; do
  printf '\n=== %s ===\n' "$script"
  ast-grep outline "$script" --lang python || true
  rg -n -C 4 'file:|urlparse|url2pathname|unquote|Path\(|sys.argv|argparse|sysview|trace' "$script" || true
done < <(fd -a '^sysviewtrace_proc\.py$' .)

Repository: espressif/idf-eclipse-plugin

Length of output: 8081


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from urllib.parse import urlparse, unquote
import re

def build_current(path):
    return "file://" + path.replace("\\", "/")

examples = [
    r"C:\project\build\a svdat",
    r"C:\project\build\trace#1.svdat",
    r"C:\project\build\trace?1.svdat",
    r"C:\project\build\trace%1.svdat",
    r"/unix/path/trace.svdat",
]

for path in examples:
    url = build_current(path)
    p = urlparse(url)
    print(path, "=>", url)
    print("  scheme=", p.scheme, "netloc=", p.netloc, "path=", p.path, "fragment=", p.fragment, "query=", p.query)
    print("  decoded_path=", unquote(p.path))
print()
print("Current regex matches:", re.match(r"(?i)file://(/?:|)(C?:)?/.+", "file://C:/foo/svdat").group() if re.match(r"(?i)file://(/?:|)(C?:)?/.+", "file://C:/foo/svdat") else None)
PY

echo
echo "Search for sysviewtrace_proc references"
rg -n "sysviewtrace_proc|IDF_Sysview.*|sysview.*trace|file://|urlparse|unquote|Path\\(" . || true

Repository: espressif/idf-eclipse-plugin

Length of output: 50384


Serialize the trace path with a standard file-URI API.

toFileUrl() builds raw file:// strings, so Windows paths like file://C:/... put C: in the URI authority, and URI-reserved characters such as #, ?, %, or spaces split the path incorrectly. sysviewtrace_proc.py receives the wrong trace argument and can fail conversion. Use File.toURI().toASCIIString() or an equivalent API to serialize the path.

Also applies to: bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/HeapDumpAnalysisHandler.java:135-137

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/HeapDumpAnalysisHandler.java`
around lines 47 - 48, Update toFileUrl() to serialize trace file paths through
the standard File URI API, using File.toURI().toASCIIString() or an equivalent.
Remove the raw FILE_URL_PREFIX concatenation so Windows drive letters and
URI-reserved characters are encoded correctly before passing the trace path to
sysviewtrace_proc.py.


@Override
public Object execute(ExecutionEvent event) throws ExecutionException
Expand All @@ -52,37 +57,91 @@ public Object execute(ExecutionEvent event) throws ExecutionException
messageConsoleStream.println("App Context Null"); //$NON-NLS-1$
return null;
}

// get the selected dumpFile

IResource dumpFile = EclipseHandler.getSelectedResource((IEvaluationContext) event.getApplicationContext());
IProject selectedProject = dumpFile.getProject();
IFile elfSymbolsFile = selectedProject.getFolder("build").getFile(selectedProject.getName().concat(".elf")); //$NON-NLS-1$ //$NON-NLS-2$

List<String> commands = new ArrayList<String>();
List<String> commands = new ArrayList<>();
commands.add(IDFUtil.getIDFPythonEnvPath());
commands.add(IDFUtil.getIDFSysviewTraceScriptFile().getAbsolutePath());
commands.add("-j"); //$NON-NLS-1$
commands.add("-b"); //$NON-NLS-1$
commands.add(elfSymbolsFile.getRawLocation().toOSString());
commands.add("file://".concat(dumpFile.getRawLocation().toString())); //$NON-NLS-1$
commands.addAll(resolveTraceSources(dumpFile));

messageConsoleStream.println("Commands Prepared"); //$NON-NLS-1$
for (String command : commands)
{
messageConsoleStream.print(command);
messageConsoleStream.print(" "); //$NON-NLS-1$
}

Map<String, String> envMap = new IDFEnvironmentVariables().getSystemEnvMap();
Path pathToProject = new Path(selectedProject.getLocation().toString());
String jsonOutput = runCommand(commands, pathToProject, envMap);
FileUtil.writeFile(selectedProject, "build/dump.json", jsonOutput, false); //$NON-NLS-1$
messageConsoleStream.println();
messageConsoleStream.println(jsonOutput);

if (!isJsonOutput(jsonOutput))
{
Logger.log("Heap dump analysis failed; skipping editor launch"); //$NON-NLS-1$
return null;
}

FileUtil.writeFile(selectedProject, "build/dump.json", jsonOutput, false); //$NON-NLS-1$
launchEditor(selectedProject.getFile("build/dump.json")); //$NON-NLS-1$
return null;
}

/**
* Prefer OpenOCD per-core dumps ({@code *.svdat_core0}, {@code *_core1}, …) when present. Passing those with a
* {@code file://} URL avoids the Windows multicore-split bug in {@code sysviewtrace_proc.py}. Falls back to the
* selected file when no core siblings exist.
*/
static List<String> resolveTraceSources(IResource dumpFile)
{
File selected = dumpFile.getRawLocation().toFile();
File directory = selected.getParentFile();
String baseName = stripCoreSuffix(selected.getName());

List<String> coreSources = new ArrayList<>();
for (int core = 0;; core++)
{
File coreFile = new File(directory, baseName + "_core" + core); //$NON-NLS-1$
if (!coreFile.isFile())
{
break;
}
coreSources.add(toFileUrl(coreFile));
}

if (!coreSources.isEmpty())
{
return coreSources;
}

List<String> single = new ArrayList<>(1);
single.add(toFileUrl(selected));
return single;
}

private static String stripCoreSuffix(String fileName)
{
Matcher matcher = CORE_SUFFIX.matcher(fileName);
return matcher.matches() ? matcher.group(1) : fileName;
}

private static String toFileUrl(File file)
{
return FILE_URL_PREFIX + file.getAbsolutePath().replace('\\', '/');
}

private static boolean isJsonOutput(String output)
{
return output != null && output.trim().startsWith("{"); //$NON-NLS-1$
Comment on lines +140 to +142

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Parse the complete output before writing dump.json.

Line 142 accepts malformed output such as {error or {} diagnostic. Lines 92-93 then persist invalid analysis data and open the editor. Parse the complete string as JSON and require an object root before writing the file or launching the editor.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/HeapDumpAnalysisHandler.java`
around lines 140 - 142, Update isJsonOutput in HeapDumpAnalysisHandler to parse
the complete output as JSON and return true only when parsing succeeds with an
object root, rather than checking whether trimmed text starts with "{". Ensure
the dump-writing and editor-launch flow uses this validation so malformed or
trailing diagnostic output is not persisted or opened.

}

private void launchEditor(IFile jsonDumpFile)
{
FileEditorInput editorInput = new FileEditorInput(jsonDumpFile);
Expand Down Expand Up @@ -117,7 +176,6 @@ private String runCommand(List<String> arguments, Path workDir, Map<String, Stri
return IDFCorePlugin.errorStatus("Status can't be null", null).toString(); //$NON-NLS-1$
}

// process export command output
exportCmdOp = status.getMessage();
Logger.log(exportCmdOp);
}
Expand Down
Loading