diff --git a/Ghidra/Framework/SoftwareModeling/Sleigh.launch b/Ghidra/Framework/SoftwareModeling/Sleigh.launch
index b8273f84bc..e9a2b91ae5 100644
--- a/Ghidra/Framework/SoftwareModeling/Sleigh.launch
+++ b/Ghidra/Framework/SoftwareModeling/Sleigh.launch
@@ -1,27 +1,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java
index 5bca728f89..fa58559993 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java
@@ -422,7 +422,7 @@ public class SleighLanguage implements Language {
String languageName = specName + ".slaspec";
ResourceFile languageFile = new ResourceFile(slaFile.getParentFile(), languageName);
- // see gradleScripts/processorUtils.gradle for sleighArgs.txt generation
+ // see gradle/processorUtils.gradle for sleighArgs.txt generation
ResourceFile sleighArgsFile = null;
ResourceFile languageModule = Application.getModuleContainingResourceFile(languageFile);
if (languageModule != null) {
@@ -430,21 +430,23 @@ public class SleighLanguage implements Language {
sleighArgsFile = new ResourceFile(languageModule, "data/sleighArgs.txt");
}
else {
- sleighArgsFile = new ResourceFile(languageModule, "build/data/sleighArgs.txt");
+ sleighArgsFile = new ResourceFile(languageModule, "build/tmp/sleighArgs.txt");
}
}
- Map defineMap;
String[] args;
if (sleighArgsFile != null && sleighArgsFile.isFile()) {
- args = new String[] { "-i", sleighArgsFile.getAbsolutePath(),
+ String baseDir = Application.getInstallationDirectory().getAbsolutePath().replace(
+ File.separatorChar, '/');
+ if (!baseDir.endsWith("/")) {
+ baseDir += "/";
+ }
+ args = new String[] { "-DBaseDir=" + baseDir, "-i", sleighArgsFile.getAbsolutePath(),
languageFile.getAbsolutePath(), description.getSlaFile().getAbsolutePath() };
- defineMap = new HashMap<>();
}
else {
args = new String[] { languageFile.getAbsolutePath(),
description.getSlaFile().getAbsolutePath() };
- defineMap = ModuleDefinitionsMap.getModuleMap();
}
try {
@@ -454,7 +456,7 @@ public class SleighLanguage implements Language {
buf.append(" ");
}
Msg.debug(this, "Sleigh compile: " + buf);
- int returnCode = SleighCompileLauncher.runMain(args, defineMap);
+ int returnCode = SleighCompileLauncher.runMain(args);
if (returnCode != 0) {
throw new SleighException("Errors compiling " + languageFile.getAbsolutePath() +
" -- please check log messages for details");
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
index 185a19c166..6defc9f5d9 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
@@ -1688,6 +1688,6 @@ public class SleighCompile extends SleighBase {
* @throws RecognitionException
*/
public static void main(String[] args) throws JDOMException, IOException, RecognitionException {
- System.exit(SleighCompileLauncher.runMain(args, new HashMap()));
+ System.exit(SleighCompileLauncher.runMain(args));
}
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java
index 0321cdef5a..109eabfeb7 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java
@@ -71,24 +71,24 @@ public class SleighCompileLauncher implements GhidraLaunchable {
ApplicationConfiguration configuration = new ApplicationConfiguration();
Application.initializeApplication(layout, configuration);
- System.exit(runMain(args, new HashMap()));
+ System.exit(runMain(args));
}
/**
* Execute the Sleigh compiler process
*
* @param args sleigh compiler command line arguments
- * @param preprocs additional preprocessor macro
* @return exit code (TODO: exit codes are not well defined)
* @throws JDOMException
* @throws IOException
* @throws RecognitionException
*/
- public static int runMain(String[] args, Map preprocs)
+ public static int runMain(String[] args)
throws JDOMException, IOException, RecognitionException {
int retval;
String filein = null;
String fileout = null;
+ Map preprocs = new HashMap<>();
SleighCompile.yydebug = false;
boolean allMode = false;
@@ -218,8 +218,8 @@ public class SleighCompileLauncher implements GhidraLaunchable {
System.out.println("Compiling " + input + ":");
SleighCompile compiler = new SleighCompile();
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
- allCollisionWarning,
- allNopWarning, deadTempWarning, unusedFieldWarning, enforceLocalKeyWord);
+ allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
+ enforceLocalKeyWord);
String outname = input.getName().replace(".slaspec", ".sla");
File output = new File(input.getParent(), outname);
@@ -247,8 +247,8 @@ public class SleighCompileLauncher implements GhidraLaunchable {
// single file compile
SleighCompile compiler = new SleighCompile();
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
- allCollisionWarning, allNopWarning,
- deadTempWarning, unusedFieldWarning, enforceLocalKeyWord);
+ allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
+ enforceLocalKeyWord);
if (i == args.length) {
Msg.error(SleighCompile.class, "Missing input file name");
return 1;
@@ -418,6 +418,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
return 4;
}
catch (PreprocessorException e) {
+ Msg.error(SleighCompile.class, e.getMessage());
Msg.error(SleighCompile.class, "Errors during preprocessing, halting compilation");
return 5;
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/test.slow/java/ghidra/pcodeCPort/slgh_compile/regression/SleighCompileRegressionTest.java b/Ghidra/Framework/SoftwareModeling/src/test.slow/java/ghidra/pcodeCPort/slgh_compile/regression/SleighCompileRegressionTest.java
index c12b655c92..6fe4024ff5 100644
--- a/Ghidra/Framework/SoftwareModeling/src/test.slow/java/ghidra/pcodeCPort/slgh_compile/regression/SleighCompileRegressionTest.java
+++ b/Ghidra/Framework/SoftwareModeling/src/test.slow/java/ghidra/pcodeCPort/slgh_compile/regression/SleighCompileRegressionTest.java
@@ -16,7 +16,7 @@
*/
package ghidra.pcodeCPort.slgh_compile.regression;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.io.*;
import java.util.*;
@@ -167,11 +167,9 @@ public class SleighCompileRegressionTest extends AbstractGenericTest {
private int runActualCompiler(File inputFile, File actualFile)
throws JDOMException, IOException, RecognitionException {
- return SleighCompileLauncher.runMain(
- new String[] { "-DMIPS=../../../../../../ghidra/Ghidra/Processors/MIPS",
- "-D8051=../../../../../../ghidra/Ghidra/Processors/8051",
- inputFile.getAbsolutePath(), actualFile.getAbsolutePath() },
- new HashMap());
+ return SleighCompileLauncher.runMain(new String[] { "-DBaseDir=../../../../../../",
+ "-DMIPS=ghidra/Ghidra/Processors/MIPS", "-D8051=ghidra/Ghidra/Processors/8051",
+ inputFile.getAbsolutePath(), actualFile.getAbsolutePath() });
}
private static final Pattern SPACEMATCH = Pattern.compile("^\\s*\\s*$");
diff --git a/Ghidra/Processors/AARCH64/build.gradle b/Ghidra/Processors/AARCH64/build.gradle
index b581cbf7f4..5b7ba0fbb8 100644
--- a/Ghidra/Processors/AARCH64/build.gradle
+++ b/Ghidra/Processors/AARCH64/build.gradle
@@ -7,9 +7,9 @@ apply plugin: 'eclipse'
eclipse.project.name = 'Processors AARCH64'
-sleighCompile {
- args '-l'
-}
+sleighCompileOptions = [
+ '-l'
+]
dependencies {
compile project(':Base')
diff --git a/Ghidra/Processors/Atmel/build.gradle b/Ghidra/Processors/Atmel/build.gradle
index fdc360695f..efc171ec2a 100644
--- a/Ghidra/Processors/Atmel/build.gradle
+++ b/Ghidra/Processors/Atmel/build.gradle
@@ -10,6 +10,6 @@ dependencies {
compile project(':Base')
}
-sleighCompile {
- // args '-l'
-}
+sleighCompileOptions = [
+ // '-l'
+]
diff --git a/Ghidra/Processors/Dalvik/build.gradle b/Ghidra/Processors/Dalvik/build.gradle
index 153d8ad9d6..ad5025cd4f 100644
--- a/Ghidra/Processors/Dalvik/build.gradle
+++ b/Ghidra/Processors/Dalvik/build.gradle
@@ -7,9 +7,9 @@ apply plugin: 'eclipse'
eclipse.project.name = 'Processors Dalvik'
-sleighCompile {
- args '-l'
-}
+sleighCompileOptions = [
+ '-l'
+]
dependencies {
compile project(':Base')
diff --git a/Ghidra/Processors/HCS08/build.gradle b/Ghidra/Processors/HCS08/build.gradle
index 533dc86462..1179f4c831 100644
--- a/Ghidra/Processors/HCS08/build.gradle
+++ b/Ghidra/Processors/HCS08/build.gradle
@@ -3,6 +3,6 @@ apply from: "$rootProject.projectDir/gradle/processorProject.gradle"
apply plugin: 'eclipse'
eclipse.project.name = 'Processors HCS08'
-sleighCompile {
- args '-l'
-}
\ No newline at end of file
+sleighCompileOptions = [
+ '-l'
+]
\ No newline at end of file
diff --git a/Ghidra/Processors/HCS12/build.gradle b/Ghidra/Processors/HCS12/build.gradle
index 05c969dca1..ee75031265 100644
--- a/Ghidra/Processors/HCS12/build.gradle
+++ b/Ghidra/Processors/HCS12/build.gradle
@@ -6,9 +6,9 @@ apply plugin: 'eclipse'
eclipse.project.name = 'Processors HCS12'
-sleighCompile {
- args '-l'
-}
+sleighCompileOptions = [
+ '-l'
+]
dependencies {
compile project(':Base')
diff --git a/Ghidra/Processors/MCS96/build.gradle b/Ghidra/Processors/MCS96/build.gradle
index b98931b14f..5a07259134 100644
--- a/Ghidra/Processors/MCS96/build.gradle
+++ b/Ghidra/Processors/MCS96/build.gradle
@@ -3,7 +3,6 @@ apply from: "$rootProject.projectDir/gradle/processorProject.gradle"
apply plugin: 'eclipse'
eclipse.project.name = 'Processors MCS96'
-
-sleighCompile {
- args '-l'
-}
\ No newline at end of file
+sleighCompileOptions = [
+ '-l'
+]
\ No newline at end of file
diff --git a/Ghidra/Processors/MIPS/build.gradle b/Ghidra/Processors/MIPS/build.gradle
index e27b475e1f..55ce8fe56b 100644
--- a/Ghidra/Processors/MIPS/build.gradle
+++ b/Ghidra/Processors/MIPS/build.gradle
@@ -10,6 +10,6 @@ dependencies {
compile project(':Base')
}
-sleighCompile {
- args '-l'
-}
+sleighCompileOptions = [
+ '-l'
+]
diff --git a/GhidraBuild/BuildFiles/sleighDevBuild.template b/GhidraBuild/BuildFiles/sleighDevBuild.template
index d81928bd61..49635752eb 100644
--- a/GhidraBuild/BuildFiles/sleighDevBuild.template
+++ b/GhidraBuild/BuildFiles/sleighDevBuild.template
@@ -1,14 +1,17 @@
@@ -46,8 +49,9 @@
fork="true"
failonerror="true">
+
-
+
diff --git a/GhidraBuild/BuildFiles/sleighDistBuild.template b/GhidraBuild/BuildFiles/sleighDistBuild.template
index ec9976b7c3..c47a3fedef 100644
--- a/GhidraBuild/BuildFiles/sleighDistBuild.template
+++ b/GhidraBuild/BuildFiles/sleighDistBuild.template
@@ -1,13 +1,16 @@
@@ -39,6 +42,7 @@
fork="true"
failonerror="true">
+
diff --git a/gradle/processorProject.gradle b/gradle/processorProject.gradle
index 9346ef53b6..09aa2edfad 100644
--- a/gradle/processorProject.gradle
+++ b/gradle/processorProject.gradle
@@ -7,8 +7,6 @@
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
*****************************************************************************************/
-
-
/*****************************************************************************************
*
* Create a configuration so the a dependency can be declared on the the software modeling
@@ -26,21 +24,71 @@ dependencies {
/*****************************************************************************************
*
- * Task to write sleigh compiler args to build/data/sleighArgs.txt for use with sleigh
- * external sleigh compiler.
+ * Sleigh compile options to be written to sleighArgs.txt in support of the following
+ * use cases:
+ * - Ant build using data/build.xml (development and distribution)
+ * - Eclipse Sleigh launcher (development only)
+ * - Ghidra runtime language rebuild (SleighLanguage.reloadLanguage; development and distribution)
+ * - Distribution build (sleighCompile task; development layout)
+ *
+ * This list may be added to or replaced by a specific processor project/module.
+ *
+ * Example: MIPS processor module dependency within a slaspec specified as:
+ *
+ * @include "$(BaseDir)$(MIPS)/data/language/maips.sinc
+ *
+ * with the corresponding MIPS definition specified within the sleighCompileOptions
+ * list specified within the module's build.gradle file:
+ *
+ * sleighCompileOptions.add "-DMIPS=%%MIPS%%"
+ * -or-
+ * sleighCompileOptions = [
+ * "-l",
+ * "-DMIPS=%%MIPS%%"
+ * ]
+ *
+ *****************************************************************************************/
+ ext.sleighCompileOptions = [ ]
+
+ /*****************************************************************************************
+ *
+ * Check for invalid sleighCompileOptions
+ *
+ *****************************************************************************************/
+ def checkSleighCompileOptions() {
+ sleighCompileOptions.each { a ->
+ def arg = a.trim()
+ assert !(arg.startsWith("-a") || arg.startsWith("-i")) : "Invalid sleighCompileOption: ${arg}"
+ }
+ }
+
+/*****************************************************************************************
+ *
+ * Task to write sleigh compiler args for use with sleigh compiler.
+ * Due to the possible presence of module dependency paths two different sleighArgs.txt
+ * files are produced: one for development layout (build/tmp/sleighArgs.txt) and
+ * one for distribution layout ([build/]data/sleighArgs.txt). When invoking the
+ * Sleigh compiler and using a sleighArgs.txt file the appropriate 'BaseDir' property
+ * must be specified. Withing a distribution install 'BaseDir' must specifiy the
+ * path to the install directory while in a development layout 'BaseDir' must specify
+ * the repos root directory which contains the 'ghidra' repo directory.
*
*****************************************************************************************/
task saveSleighArgs {
def sleighArgsFile = file("build/data/sleighArgs.txt")
- outputs.files sleighArgsFile
+ def sleighArgsDevFile = file("build/tmp/sleighArgs.txt")
+ outputs.files sleighArgsFile, sleighArgsDevFile
outputs.upToDateWhen { false }
doLast {
+ checkSleighCompileOptions()
sleighArgsFile.withWriter { out->
- project.sleighCompile.args.each { a->
- // don't save -a option
- if (!"-a".equals(a)) {
- out.println a
- }
+ sleighCompileOptions.each { a->
+ out.println resolveSleighArg(a, false)
+ }
+ }
+ sleighArgsDevFile.withWriter { out->
+ sleighCompileOptions.each { a->
+ out.println resolveSleighArg(a, true)
}
}
}
@@ -50,6 +98,7 @@ rootProject.prepDev.dependsOn(saveSleighArgs)
apply plugin: 'base'
clean {
delete file("build/data/sleighArgs.txt")
+ delete file("build/tmp/sleighArgs.txt")
}
/*****************************************************************************************
@@ -94,6 +143,7 @@ rootProject.assembleDistribution {
*
*****************************************************************************************/
task sleighCompile (type: JavaExec) {
+ dependsOn saveSleighArgs
group = rootProject.GHIDRA_GROUP
description " Compiles all the sleigh languages. [processorUtils.gradle]\n"
@@ -104,7 +154,12 @@ task sleighCompile (type: JavaExec) {
// Delay adding the directory argument until the first part of the execution phase, so
// that any extra args added by a project override will be added to the arg list before
// these arguments.
+ // NOTE: projects should no longer add arguments to this task and should instead
+ // add such args to the sleighCompileOptions list.
doFirst {
+ args "-i"
+ args "./build/tmp/sleighArgs.txt"
+ args "-DBaseDir=${getProjectReposRootPath()}"
args '-a'
args './data/languages'
}
@@ -115,11 +170,9 @@ task sleighCompile (type: JavaExec) {
// The task that copies the common files to the distribution folder must depend on
// the sleigh tasks before executing.
rootProject.assembleDistribution.dependsOn sleighCompile
-rootProject.assembleDistribution.dependsOn saveSleighArgs
// Add in this projects sleighCompile to the allSleighCompile task
rootProject.allSleighCompile.dependsOn sleighCompile
-rootProject.allSleighCompile.dependsOn saveSleighArgs
/*****************************************************************************************
*
@@ -154,3 +207,55 @@ sleighCompile.outputs.files (taskOutputs)
// define the sleigh compile inputs to saveSleighArgs to limit task creation to language modules
saveSleighArgs.inputs.files (taskInputs)
+
+/*****************************************************************************************
+ *
+ * Gets the absolute repos root directory path with a trailing File separator.
+ * This path may be used for specifying 'BaseDir' to the sleigh compiler within a
+ * development layout.
+ *
+ *****************************************************************************************/
+def getProjectReposRootPath() {
+ return rootProject.projectDir.getParent() + File.separator
+}
+
+/*****************************************************************************************
+ *
+ * Filter a sleigh compiler argument replacing any project/module reference of the form
+ * %%MODULE%% witha that MODULE's relative path. If useDevPath is true the path will
+ * include the containing repo directory (e.g., ghidra/Ghidra/...), otherwise the
+ * path should start at the application root 'Ghidra/'. Only a single replacement per
+ * arg is supported.
+ *
+ * This mechanism relies on the relative depth of a language module project within a
+ * repository directory hierarchy. In general language module projects must reside
+ * within the directory Ghidra/Processors.
+ *
+ *****************************************************************************************/
+def resolveSleighArg(String arg, boolean useDevPath) {
+ arg = arg.trim()
+ int index = arg.indexOf("%%")
+ if (index < 0) {
+ return arg
+ }
+ String newArg = arg.substring(0, index)
+ String tail = arg.substring(index+2)
+ index = tail.indexOf("%%")
+ assert index > 0 : "Badly formed sleigh path-replacment option: ${arg}"
+ String moduleName = tail.substring(0, index)
+ tail = tail.substring(index+2)
+ def moduleProject = project(":${moduleName}")
+ def modulePath
+ if (useDevPath) {
+ // first path element is the containing repo directory
+ modulePath = moduleProject.projectDir.absolutePath
+ modulePath = modulePath.substring(getProjectReposRootPath().length())
+ }
+ else {
+ // first path element is the Ghidra directory
+ modulePath = getZipPath(moduleProject)
+ }
+ newArg += modulePath
+ newArg += tail
+ return newArg
+}
\ No newline at end of file