From b6b759b2866fd05d030ca65c52e0b3013e2e6956 Mon Sep 17 00:00:00 2001 From: Denys Almazov Date: Wed, 22 Apr 2026 10:47:09 +0300 Subject: [PATCH 1/3] feat: detect and use modern gdb syntax --- .../debug/gdbjtag/openocd/Configuration.java | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java index 4d2c13dd9..d3c855ea7 100644 --- a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java +++ b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java @@ -16,6 +16,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.debug.gdbjtag.core.IGDBJtagConstants; @@ -89,11 +91,17 @@ public static String[] getGdbServerCommandLineArray(ILaunchConfiguration configu return null; String executable = getGdbServerCommand(configuration, null); - if (executable == null || executable.length() == 0) + if (executable == null || executable.isEmpty()) return null; + lst.add(executable); + boolean useModernSyntax = useModernPortSyntax(executable); + String fmtGdbPort = useModernSyntax ? "gdb port %d" : "gdb_port %d"; //$NON-NLS-1$ //$NON-NLS-2$ + String fmtTelnetPort = useModernSyntax ? "telnet port %d" : "telnet_port %d"; //$NON-NLS-1$ //$NON-NLS-2$ + String fmtTclPort = useModernSyntax ? "tcl port %d" : "tcl_port %d"; //$NON-NLS-1$ //$NON-NLS-2$ + int port = PortChecker .getAvailablePort(DefaultPreferences.GDB_SERVER_GDB_PORT_NUMBER_DEFAULT); @@ -102,21 +110,21 @@ public static String[] getGdbServerCommandLineArray(ILaunchConfiguration configu configurationWorkingCopy.doSave(); lst.add("-c"); //$NON-NLS-1$ - lst.add("gdb_port " + port); //$NON-NLS-1$ + lst.add(String.format(fmtGdbPort, port)); port = PortChecker .getAvailablePort(configuration.getAttribute(ConfigurationAttributes.GDB_SERVER_TELNET_PORT_NUMBER, DefaultPreferences.GDB_SERVER_TELNET_PORT_NUMBER_DEFAULT)); lst.add("-c"); //$NON-NLS-1$ - lst.add("telnet_port " + port); //$NON-NLS-1$ + lst.add(String.format(fmtTelnetPort, port)); port = PortChecker.getAvailablePort( Integer.parseInt(configuration.getAttribute(ConfigurationAttributes.GDB_SERVER_TCL_PORT_NUMBER, DefaultPreferences.GDB_SERVER_TCL_PORT_NUMBER_DEFAULT))); lst.add("-c"); //$NON-NLS-1$ - lst.add("tcl_port " + port); //$NON-NLS-1$ + lst.add(String.format(fmtTclPort, port)); String other = configuration .getAttribute(ConfigurationAttributes.GDB_SERVER_OTHER, DefaultPreferences.GDB_SERVER_OTHER_DEFAULT) @@ -322,4 +330,34 @@ public static boolean getDoStartGdbClient(ILaunchConfiguration config) throws Co } // ------------------------------------------------------------------------ + + private static boolean useModernPortSyntax(String executablePath) + { + if (executablePath == null) + { + return false; + } + + Pattern pattern = Pattern.compile("v(\\d+)\\.(\\d+)\\.\\d+-esp32-\\d{8}"); //$NON-NLS-1$ + Matcher matcher = pattern.matcher(executablePath); + + if (matcher.find()) + { + try + { + int major = Integer.parseInt(matcher.group(1)); + int minor = Integer.parseInt(matcher.group(2)); + + if (major > 0 || (major == 0 && minor >= 12)) + { + return true; + } + } + catch (NumberFormatException e) + { + Activator.log(e); + } + } + return false; + } } From 4a4d01992141b87b1c55ef16fb39f4a3ed4460a2 Mon Sep 17 00:00:00 2001 From: Denys Almazov Date: Mon, 27 Apr 2026 10:24:23 +0300 Subject: [PATCH 2/3] feat: checking version with openocd process --- .../debug/gdbjtag/openocd/Configuration.java | 55 ++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java index d3c855ea7..f6bef1b6c 100644 --- a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java +++ b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java @@ -14,8 +14,11 @@ package com.espressif.idf.debug.gdbjtag.openocd; +import java.io.BufferedReader; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,7 +29,9 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.embedcdt.core.EclipseUtils; @@ -333,31 +338,55 @@ public static boolean getDoStartGdbClient(ILaunchConfiguration config) throws Co private static boolean useModernPortSyntax(String executablePath) { - if (executablePath == null) + if (executablePath == null || executablePath.isEmpty()) { return false; } + Pattern outputPattern = Pattern.compile("(?:Open On-Chip Debugger |v)(?\\d+)\\.(?\\d+)"); //$NON-NLS-1$ - Pattern pattern = Pattern.compile("v(\\d+)\\.(\\d+)\\.\\d+-esp32-\\d{8}"); //$NON-NLS-1$ - Matcher matcher = pattern.matcher(executablePath); - - if (matcher.find()) + try { + ProcessBuilder pb = new ProcessBuilder(executablePath, "--version"); //$NON-NLS-1$ + pb.redirectErrorStream(true); + Process process = pb.start(); + try { - int major = Integer.parseInt(matcher.group(1)); - int minor = Integer.parseInt(matcher.group(2)); - - if (major > 0 || (major == 0 && minor >= 12)) + try (BufferedReader reader = process.inputReader()) { - return true; + return reader.lines().map(outputPattern::matcher).filter(Matcher::find).findFirst().map(matcher -> { + int major = Integer.parseInt(matcher.group("major")); //$NON-NLS-1$ + int minor = Integer.parseInt(matcher.group("minor")); //$NON-NLS-1$ + return major > 0 || (major == 0 && minor >= 12); + }).orElse(false); } - } - catch (NumberFormatException e) + } finally { - Activator.log(e); + if (process.isAlive()) + { + process.destroy(); + + if (!process.waitFor(500, TimeUnit.MILLISECONDS)) + { + process.destroyForcibly(); + } + } } } + catch ( + IOException + | NumberFormatException e) + { + Activator.log(new CoreException(new Status(IStatus.WARNING, Activator.PLUGIN_ID, + "Failed to execute or parse OpenOCD version fallback for path: " + executablePath, e))); //$NON-NLS-1$ + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + Activator.log(new CoreException(new Status(IStatus.WARNING, Activator.PLUGIN_ID, + "Thread was interrupted while waiting for OpenOCD process to exit.", e))); //$NON-NLS-1$ + } + return false; } } From 5d4bbfdb225bb908ba7a4bca8c8b9a71a88f2412 Mon Sep 17 00:00:00 2001 From: Denys Almazov Date: Tue, 28 Apr 2026 11:20:31 +0300 Subject: [PATCH 3/3] fix: addressing potential hang out --- .../debug/gdbjtag/openocd/Configuration.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java index f6bef1b6c..6979b0b6c 100644 --- a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java +++ b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/Configuration.java @@ -352,6 +352,11 @@ private static boolean useModernPortSyntax(String executablePath) try { + if (!process.waitFor(2, TimeUnit.SECONDS)) + { + return false; + } + try (BufferedReader reader = process.inputReader()) { return reader.lines().map(outputPattern::matcher).filter(Matcher::find).findFirst().map(matcher -> { @@ -364,29 +369,22 @@ private static boolean useModernPortSyntax(String executablePath) { if (process.isAlive()) { - process.destroy(); - - if (!process.waitFor(500, TimeUnit.MILLISECONDS)) - { - process.destroyForcibly(); - } + process.destroyForcibly(); } } } - catch ( - IOException - | NumberFormatException e) + catch (IOException e) { Activator.log(new CoreException(new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Failed to execute or parse OpenOCD version fallback for path: " + executablePath, e))); //$NON-NLS-1$ + return false; } catch (InterruptedException e) { Thread.currentThread().interrupt(); Activator.log(new CoreException(new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Thread was interrupted while waiting for OpenOCD process to exit.", e))); //$NON-NLS-1$ + return false; } - - return false; } }