Skip to content

Commit

Permalink
Consult the list of sources when submitting native breakpoints in Jav…
Browse files Browse the repository at this point in the history
…a native image.
  • Loading branch information
entlicher committed Jan 5, 2022
1 parent 5c7b739 commit af26af4
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 32 deletions.
2 changes: 1 addition & 1 deletion cpplite/cpplite.debugger/nbproject/project.xml
Expand Up @@ -75,7 +75,7 @@
<compile-dependency/>
<run-dependency>
<release-version>0</release-version>
<specification-version>0.5</specification-version>
<specification-version>0.7</specification-version>
</run-dependency>
</dependency>
<dependency>
Expand Down
Expand Up @@ -42,6 +42,7 @@
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.debugger.ActionsManager;
Expand Down Expand Up @@ -103,6 +104,8 @@ public final class CPPLiteDebugger {
private volatile CPPThread currentThread;
private volatile CPPFrame currentFrame;
private AtomicInteger exitCode = new AtomicInteger();
private String gdbVersion;
private boolean gdbVersion111; // Whether GDB version is greater than or equal to 11.1

public CPPLiteDebugger(ContextProvider contextProvider) {
this.contextProvider = contextProvider;
Expand Down Expand Up @@ -140,6 +143,49 @@ void setDebuggee(Process debuggee) {
//proxy.send(new Command("-gdb-set scheduler-locking on"));
proxy.send(new Command("-gdb-set non-stop on"));
proxy.send(new Command("-gdb-set print object on"));
try {
MIRecord versionRecord = sendAndGet("-gdb-version");
gdbVersion = versionRecord.command().getConsoleStream();
gdbVersion111 = isVersion111(gdbVersion);
} catch (InterruptedException ex) {
}
}

private static boolean isVersion111(String version) {
int i = version.indexOf("\\n");
if (i > 0) {
version = version.substring(0, i);
}
i = version.lastIndexOf(' ');
if (i < 0) {
i = 0;
} else {
i++;
}
version = version.substring(i);
i = version.indexOf('.');
String major = version.substring(0, i);
int m;
try {
m = Integer.parseInt(major);
} catch (NumberFormatException ex) {
return false;
}
if (m > 11) {
return true;
}
if (m < 11) {
return false;
}
version = version.substring(i + 1);
i = version.indexOf('.');
String minor = version.substring(0, i);
try {
m = Integer.parseInt(minor);
} catch (NumberFormatException ex) {
return false;
}
return m >= 1;
}

public void execRun() {
Expand Down Expand Up @@ -420,13 +466,7 @@ public String readMemory(String address, long offset, int length) {
}

public String getVersion() {
MIRecord versionRecord;
try {
versionRecord = sendAndGet("-gdb-version");
} catch (InterruptedException ex) {
return null;
}
return versionRecord.command().getConsoleStream();
return gdbVersion;
}

public List<Location> listLocations(String filePath) {
Expand Down Expand Up @@ -563,6 +603,53 @@ private Map<SourceInfo, List<Symbol>> listSymbols(String command) {
}
}

public List<SourceInfo> listSources(String nameRegexp) {
StringBuilder command = new StringBuilder("-file-list-exec-source-files");
if (nameRegexp != null && gdbVersion111) {
command.append(" -- ");
command.append(nameRegexp);
}
MIRecord result;
try {
result = sendAndGet(command.toString());
} catch (InterruptedException ex) {
return null;
}
MIValue allFilesValue = result.results().valueOf("files");
if (allFilesValue instanceof MITList) {
MITList allFilesList = (MITList) allFilesValue;
if (allFilesList.size() == 0) {
return Collections.emptyList();
}
// GDB interprets the nameRegexp since version 11.1
Pattern namePattern = null;
if (nameRegexp != null && !gdbVersion111) {
namePattern = Pattern.compile(nameRegexp);
}
List<SourceInfo> sources = new ArrayList<>();
for (MITListItem fileItem : allFilesList) {
if (fileItem instanceof MITList) {
MITList sourceFile = (MITList) fileItem;
String filename = sourceFile.getConstValue("filename", null);
String fullname = sourceFile.getConstValue("fullname", null);
if (namePattern != null) {
if (fullname == null || !namePattern.matcher(fullname).find()) {
continue;
}
}
SourceInfo.Builder sourceBuilder = SourceInfo.newBuilder();
sourceBuilder.fileName(filename);
sourceBuilder.fullName(fullname);
SourceInfo source = sourceBuilder.build();
sources.add(source);
}
}
return Collections.unmodifiableList(sources);
} else {
return null;
}
}

ContextProvider getContextProvider() {
return contextProvider;
}
Expand Down Expand Up @@ -808,7 +895,6 @@ public Object[] getServices () {
);
DebuggerEngine[] es = DebuggerManager.getDebuggerManager ().
startDebugging (di);
startedEngine.accept(es[0]);
Pty pty = PtySupport.allocate(ExecutionEnvironmentFactory.getLocal());
CPPLiteDebugger debugger = es[0].lookupFirst(null, CPPLiteDebugger.class);
List<String> executable = new ArrayList<>();
Expand Down Expand Up @@ -844,6 +930,7 @@ public Object[] getServices () {
}
});
debugger.setDebuggee(debuggee);
startedEngine.accept(es[0]);
AtomicInteger exitCode = debugger.exitCode;

return new Process() {
Expand Down
Expand Up @@ -257,4 +257,9 @@ public Map<SourceInfo, List<Symbol>> listVariables(String name, boolean includeN
return debugger.listVariables(name, includeNondebug, maxResults);
}

@Override
public List<SourceInfo> listSources(String nameRegexp) {
return debugger.listSources(nameRegexp);
}

}
2 changes: 1 addition & 1 deletion ide/nativeimage.api/manifest.mf
Expand Up @@ -2,5 +2,5 @@ Manifest-Version: 1.0
AutoUpdate-Show-In-Client: false
OpenIDE-Module: org.netbeans.modules.nativeimage.api/0
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/nativeimage/api/Bundle.properties
OpenIDE-Module-Specification-Version: 0.6
OpenIDE-Module-Specification-Version: 0.7

Expand Up @@ -257,6 +257,16 @@ public Map<SourceInfo, List<Symbol>> listVariables(String name, boolean includeN
return provider.listVariables(name, includeNondebug, maxResults);
}

/**
* Get a list of source paths in the debuggee.
*
* @param nameRegexp regular expression that filters the list of source paths
* @since 0.7
*/
@CheckForNull
public List<SourceInfo> listSources(String nameRegexp) {
return provider.listSources(nameRegexp);
}
/**
* A builder that creates a Native Image debugger with optional displayers.
*
Expand Down
Expand Up @@ -194,4 +194,13 @@ default Map<SourceInfo, List<Symbol>> listFunctions(String name, boolean include
default Map<SourceInfo, List<Symbol>> listVariables(String name, boolean includeNondebug, int maxResults) {
return null;
}

/**
* Provide a list of source paths in the debuggee.
*
* @since 0.7
*/
default List<SourceInfo> listSources(String nameRegexp) {
return null;
}
}
Expand Up @@ -152,8 +152,8 @@ public void finished(boolean success) {
}
}
};
Project prj = FileOwnerQuery.getOwner(toRun);
if (nativeImageFile == null) {
Project prj = FileOwnerQuery.getOwner(toRun);
class W extends Writer {
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
Expand Down
18 changes: 9 additions & 9 deletions java/java.lsp.server/vscode/package.json
Expand Up @@ -415,7 +415,7 @@
"command": "java.workspace.newproject",
"title": "New Project...",
"category": "Java",
"icon" : "$(new-folder)"
"icon": "$(new-folder)"
},
{
"command": "java.goto.super.implementation",
Expand All @@ -431,11 +431,11 @@
"command": "foundProjects.deleteEntry",
"title": "Delete"
},
{
"command": "db.add.connection",
"title": "Add Database Connection",
"category": "Database"
},
{
"command": "db.add.connection",
"title": "Add Database Connection",
"category": "Database"
},
{
"command": "nbls:Database:netbeans.db.explorer.action.Connect",
"title": "Connect to Database"
Expand Down Expand Up @@ -494,8 +494,8 @@
"command": "java.workspace.configureRunSettings",
"title": "Edit",
"icon": "$(edit)"
},
{
},
{
"command": "testing.runAll",
"title": "Run All Tests",
"category": "Test"
Expand Down Expand Up @@ -606,7 +606,7 @@
"command": "workbench.action.debug.start",
"when": "nbJavaLSReady && view == foundProjects"
}
],
],
"view/item/context": [
{
"command": "foundProjects.deleteEntry",
Expand Down
2 changes: 1 addition & 1 deletion java/java.nativeimage.debugger/nbproject/project.xml
Expand Up @@ -85,7 +85,7 @@
<compile-dependency/>
<run-dependency>
<release-version>0</release-version>
<specification-version>0.5</specification-version>
<specification-version>0.7</specification-version>
</run-dependency>
</dependency>
<dependency>
Expand Down
Expand Up @@ -25,6 +25,7 @@
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
Expand All @@ -35,6 +36,7 @@
import org.netbeans.api.debugger.jpda.JPDABreakpoint;
import org.netbeans.api.debugger.jpda.LineBreakpoint;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.modules.nativeimage.api.SourceInfo;
import org.netbeans.modules.nativeimage.api.debug.NIDebugger;
import org.netbeans.modules.nativeimage.api.debug.NILineBreakpointDescriptor;
import org.openide.filesystems.FileObject;
Expand All @@ -46,6 +48,8 @@
*/
public class JPDABreakpointsHandler extends DebuggerManagerAdapter implements PropertyChangeListener {

private static final String SOURCES_FOLDER = "sources"; // NOI18N

private final File niFileSources;
private final NIDebugger debugger;
private final Set<JPDABreakpoint> attachedBreakpoints = new HashSet<>();
Expand All @@ -62,7 +66,7 @@ public JPDABreakpointsHandler(File niFile, NIDebugger debugger) {
}

private static File getNativeSources(File niFile) {
File sources = new File(niFile.getParentFile(), "sources");
File sources = new File(niFile.getParentFile(), SOURCES_FOLDER);
if (sources.isDirectory()) {
return sources;
} else {
Expand Down Expand Up @@ -124,25 +128,26 @@ private Breakpoint added(JPDABreakpoint b) {
return null;
}
String filePath = null;
if (niFileSources != null) {
FileObject fo;
fo = URLMapper.findFileObject(url);
for (FileObject root : GlobalPathRegistry.getDefault().getSourceRoots()) {
if (FileUtil.isParentOf(root, fo)) {
String path = FileUtil.getRelativePath(root, fo);
File sourcesFile = new File(niFileSources, path);
filePath = sourcesFile.getAbsolutePath();
break;
}
String relativePath = null;
FileObject fo = URLMapper.findFileObject(url);
for (FileObject root : GlobalPathRegistry.getDefault().getSourceRoots()) {
if (FileUtil.isParentOf(root, fo)) {
relativePath = FileUtil.getRelativePath(root, fo);
break;
}
}
if (niFileSources != null && relativePath != null) {
File sourcesFile = new File(niFileSources, relativePath);
filePath = sourcesFile.getAbsolutePath();
}
if (filePath == null) {
try {
filePath = new File(url.toURI()).getAbsolutePath();
} catch (URISyntaxException ex) {
return null;
}
}
filePath = verifyFilePath(filePath, relativePath);
NILineBreakpointDescriptor niBreakpointDescriptor = NILineBreakpointDescriptor.newBuilder(filePath, lb.getLineNumber())
.condition(lb.getCondition())
.enabled(lb.isEnabled())
Expand All @@ -154,6 +159,25 @@ private Breakpoint added(JPDABreakpoint b) {
return null;
}

private String verifyFilePath(String filePath, String relativePath) {
if (relativePath != null) {
List<SourceInfo> sources = debugger.listSources(SOURCES_FOLDER + File.separator + relativePath);
if (!sources.isEmpty()) {
boolean match = false;
for (SourceInfo src : sources) {
if (filePath.equals(src.getFullName())) {
match = true;
break;
}
}
if (!match) {
filePath = sources.get(0).getFullName();
}
}
}
return filePath;
}

public void dispose() {
synchronized (attachedBreakpoints) {
for (JPDABreakpoint jb : attachedBreakpoints) {
Expand Down

0 comments on commit af26af4

Please sign in to comment.