{
+
+ public MIFileListExecSourceFiles(IDMContext ctx) {
+ super(ctx, "-file-list-exec-source-files"); //$NON-NLS-1$
+ }
+
+ @Override
+ public MiSourceFilesInfo getResult(MIOutput out) {
+ return new MiSourceFilesInfo(out);
+ }
+}
\ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MiSourceFilesInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MiSourceFilesInfo.java
new file mode 100644
index 00000000000..f1441cfde0a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MiSourceFilesInfo.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2018 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham (Kichwa Coders) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.mi.service.command.output;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Example output is:
+ *
+ *
+ * (gdb) -file-list-exec-source-files
+ * ^done,files=[{file=foo.c,fullname=/home/foo.c},
+ * {file=/home/bar.c,fullname=/home/bar.c},
+ * {file=gdb_could_not_find_fullpath.c}]
+ *
+ *
+ * @since 5.8
+ */
+public class MiSourceFilesInfo extends MIInfo {
+
+ private SourceFileInfo[] sourceFileInfos;
+
+ public MiSourceFilesInfo(MIOutput record) {
+ super(record);
+ parse();
+ if (sourceFileInfos == null) {
+ sourceFileInfos = new SourceFileInfo[0];
+ }
+ }
+
+ /**
+ * Returns array of source files infos
+ *
+ * @return
+ */
+ public SourceFileInfo[] getSourceFiles() {
+ return sourceFileInfos;
+ }
+
+ private void parse() {
+ if (isDone()) {
+ MIOutput out = getMIOutput();
+ MIResultRecord rr = out.getMIResultRecord();
+ if (rr != null) {
+ MIResult[] results = rr.getMIResults();
+ for (int i = 0; i < results.length; i++) {
+ String var = results[i].getVariable();
+ if (var.equals("files")) { //$NON-NLS-1$
+ MIValue value = results[i].getMIValue();
+ if (value instanceof MIList) {
+ parseResults((MIList) value);
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ private void parseResults(MIList list) {
+ MIValue[] miValues = list.getMIValues();
+ List infos = new LinkedList<>();
+ if (miValues != null) {
+ for (MIValue miValue : miValues) {
+ if (miValue instanceof MITuple) {
+ MITuple miTuple = (MITuple) miValue;
+ SourceFileInfo info = new SourceFileInfo();
+ info.parse(miTuple.getMIResults());
+ infos.add(info);
+ }
+ }
+ }
+ sourceFileInfos = infos.toArray(new SourceFileInfo[infos.size()]);
+ }
+
+ public static class SourceFileInfo {
+ private String file;
+ private String fullname;
+
+ public void setFile(String file) {
+ this.file = file;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public void setFullName(String fullname) {
+ this.fullname = fullname;
+ }
+
+ public String getFullName() {
+ return fullname;
+ }
+
+ private void parse(MIResult[] results) {
+ for (MIResult result : results) {
+ String variable = result.getVariable();
+ MIValue miVal = result.getMIValue();
+ if (!(miVal instanceof MIConst)) {
+ continue;
+ }
+ String value = ((MIConst) miVal).getCString();
+ switch (variable) {
+ case "file": //$NON-NLS-1$
+ file = value;
+ break;
+ case "fullname": //$NON-NLS-1$
+ fullname = value;
+ break;
+ }
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((file == null) ? 0 : file.hashCode());
+ result = prime * result + ((fullname == null) ? 0 : fullname.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SourceFileInfo other = (SourceFileInfo) obj;
+ if (file == null) {
+ if (other.file != null)
+ return false;
+ } else if (!file.equals(other.file))
+ return false;
+ if (fullname == null) {
+ if (other.fullname != null)
+ return false;
+ } else if (!fullname.equals(other.fullname))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "SourceFileInfo [file=" + file + ", fullname=" + fullname + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java
index 0a97f39caf7..43af9dbbc2f 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2016 Ericsson and others.
+ * Copyright (c) 2007, 2018 Ericsson and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -67,6 +67,8 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo;
import org.eclipse.cdt.dsf.gdb.service.IGDBMemory2;
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
@@ -107,6 +109,8 @@ public class SyncUtil {
private static ISourceLookup fSourceLookup;
+ private static IDebugSourceFiles fDebugSourceFiles;
+
// Static list of register names as obtained directly from GDB.
// We make it static, key'ed on each version of gdb, so it does not
// get re-set for every test.
@@ -128,7 +132,7 @@ public class SyncUtil {
fMemory = tracker.getService(IMemory.class);
fCommandFactory = fGdbControl.getCommandFactory();
fSourceLookup = tracker.getService(ISourceLookup.class);
-
+ fDebugSourceFiles = tracker.getService(IDebugSourceFiles.class);
tracker.dispose();
};
fSession.getExecutor().submit(runnable).get();
@@ -979,4 +983,21 @@ public class SyncUtil {
return query.get();
}
+
+ /**
+ * Get the sources from the debugger.
+ *
+ * Wrapper around
+ * {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)}
+ */
+ public static IDebugSourceFileInfo[] getSources(IDMContext ctx) throws Exception {
+ Query query = new Query() {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ fDebugSourceFiles.getSources(ctx, rm);
+ }
+ };
+ fDebugSourceFiles.getExecutor().execute(query);
+ return query.get();
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java
index c4bb8c8d648..94c20e34cbc 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2016 Kichwa Coders and others.
+ * Copyright (c) 2015, 2018 Kichwa Coders and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -54,6 +54,8 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
import org.eclipse.cdt.dsf.debug.sourcelookup.DsfSourceLookupDirector;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
@@ -1157,4 +1159,58 @@ public class SourceLookupTest extends BaseParametrizedTestCase {
*/
waitUntil("Timeout waiting for launches to terminate", () -> launch1.isTerminated() && launch2.isTerminated());
}
+
+ /**
+ * Helper method that actually performs the test/assertions for
+ * {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)} tests.
+ */
+ private void testGetSourcesListInner(String path) throws Throwable {
+ IDebugSourceFileInfo[] sources = SyncUtil.getSources(SyncUtil.getContainerContext());
+ String expectedPath = Paths.get(path, SOURCE_NAME).toString();
+ boolean anyMatch = Arrays.asList(sources).stream().anyMatch(source -> {
+ return source.getPath().equals(expectedPath);
+ });
+ assertTrue(anyMatch);
+ }
+
+ /**
+ * Test for {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)}
+ * with source path substitution on. Therefore make sure there is an entry
+ * for the resolved source path of {@value #SOURCE_NAME}
+ */
+ private void testGetSourcesList(String execName) throws Throwable {
+ doMappingAndLaunch(execName, true);
+ testGetSourcesListInner(SOURCE_ABSPATH);
+ }
+
+ /**
+ * Test for {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)}
+ * with no source path substitution on. Therefore make sure there is an entry
+ * for the build path of {@value #SOURCE_NAME}
+ */
+ @Test
+ public void testGetSourcesListNoSourceLookup() throws Throwable {
+ doLaunch(EXEC_PATH + EXEC_AC_NAME);
+ testGetSourcesListInner(BUILD_ABSPATH);
+ }
+
+ @Test
+ public void testGetSourcesListAC() throws Throwable {
+ testGetSourcesList(EXEC_AC_NAME);
+ }
+
+ @Test
+ public void testGetSourcesListAN() throws Throwable {
+ testGetSourcesList(EXEC_AN_NAME);
+ }
+
+ @Test
+ public void testGetSourcesListRC() throws Throwable {
+ testGetSourcesList(EXEC_RC_NAME);
+ }
+
+ @Test
+ public void testGetSourcesListRN() throws Throwable {
+ testGetSourcesList(EXEC_RN_NAME);
+ }
}