Skip to content

Commit ff0703d

Browse files
authored
Merge pull request #38 from edmcman/scalav3-new
Scala v3
2 parents c7194a6 + ee46bd5 commit ff0703d

File tree

8 files changed

+50
-92
lines changed

8 files changed

+50
-92
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ repositories {
2323
}
2424

2525
dependencies {
26-
implementation group: 'org.scala-lang', name: 'scala-compiler', version: '2.12.18'
26+
implementation group: 'org.scala-lang', name: 'scala3-compiler_3', version: '3.3.4'
2727
}
2828

2929
// Need to compile scala and java jointly so Java class can call ScalaHelper

ghidra_scripts/FuncParams.scala

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ import ghidra.app.script.GhidraScript
88

99
import ghidra.program.model.pcode._
1010

11-
class FuncParams extends GhidraScript {
11+
class FuncParams extends GhidraScript:
1212

13-
override def run() = {
13+
override def run() =
1414
println("Hello world, I'm written in Scala...!")
1515

1616
val ifc = new DecompInterface
17-
if (!ifc.openProgram(currentProgram)) {
17+
if !ifc.openProgram(currentProgram) then
1818
throw new DecompileException("Decompiler", "Unable to initialize: " + ifc.getLastMessage)
19-
}
2019

2120
val res = ifc.decompileFunction(currentProgram.getFunctionManager.getFunctionContaining(currentAddress), 60, null)
2221
val hf = res.getHighFunction
@@ -27,5 +26,3 @@ class FuncParams extends GhidraScript {
2726
.map(_.getStorage.toString).mkString(", ")
2827

2928
println(s"Function ${hf.getFunction.getName}: ${storage}")
30-
}
31-
}

ghidra_scripts/HelloWorldScript.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import ghidra.app.script.GhidraScript
77

8-
class HelloWorldScript extends GhidraScript {
8+
class HelloWorldScript extends GhidraScript:
99

10-
override def run() = println("Hello world, I'm written in Scala!")
11-
}
10+
override def run() = println("Hello world, I'm written in Scala 3!")

ghidra_scripts/InstructionOps.scala

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ import ghidra.program.model.listing.Function
77
import ghidra.program.model.address.AddressSetView
88
import ghidra.program.model.symbol.Reference
99

10-
import scala.collection.JavaConverters._
10+
import scala.jdk.CollectionConverters.*
1111

12-
class InstructionOps extends GhidraScript {
13-
14-
override def run() = {
12+
class InstructionOps extends GhidraScript:
1513

14+
override def run() =
1615

1716
println("Starting InstructionOps script")
1817

@@ -23,21 +22,19 @@ class InstructionOps extends GhidraScript {
2322

2423
val l = getCurrentProgram.getListing
2524

26-
funcs.foreach(f => {
25+
funcs.foreach(f =>
2726
println(s"Function ${f.getName}")
28-
l.getInstructions(f.getBody, true).forEach(i => {
27+
l.getInstructions(f.getBody, true).forEach(i =>
2928
val numops = i.getNumOperands
3029
println(s" Insn: ${i} has ${numops} operands")
31-
(0 to numops-1).foreach(opnum => {
30+
(0 to numops-1).foreach(opnum =>
3231
println(s" Operand ${opnum} ${i.getDefaultOperandRepresentation(opnum)}")
3332
//println(s" Operand ${opnum} is ${i.getOpObjects(opnum)}")
3433
val reftype = i.getOperandRefType(opnum)
3534
println(s" Operand ${opnum} ref type ${reftype}")
3635
val optype = i.getOperandType(opnum)
3736
val optypestr = ghidra.program.model.lang.OperandType.toString(optype)
3837
println(s" Operand ${opnum} op type ${optypestr}")
39-
})
40-
})
41-
})
42-
}
43-
}
38+
)
39+
)
40+
)

ghidra_scripts/PopularFunctions.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import ghidra.program.model.listing.Function
77
import ghidra.program.model.address.AddressSetView
88
import ghidra.program.model.symbol.Reference
99

10-
import scala.collection.JavaConverters._
10+
import scala.jdk.CollectionConverters.*
1111

12-
class PopularFunctions extends GhidraScript {
12+
class PopularFunctions extends GhidraScript:
1313

14-
override def run() = {
14+
override def run() =
1515
val p = getCurrentProgram
1616
val refmgr = p.getReferenceManager
1717
getCurrentProgram.getFunctionManager
@@ -30,5 +30,3 @@ class PopularFunctions extends GhidraScript {
3030
.sortWith(_._2 > _._2)
3131
.take(20)
3232
.foreach{case (f,cnt) => println(s"Function ${f.getName} (${f.getEntryPoint}) is referenced $cnt times")}
33-
}
34-
}

ghidra_scripts/PrintHighPCode.scala

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44

55
import ghidra.app.script.GhidraScript
66
import ghidra.app.decompiler._
7-
import scala.collection.JavaConverters._
7+
import scala.jdk.CollectionConverters.*
88

9-
class PrintHighPCode extends GhidraScript {
9+
class PrintHighPCode extends GhidraScript:
1010

11-
override def run() = {
11+
override def run() =
1212
val ifc = new DecompInterface
13-
if (!ifc.openProgram(currentProgram)) {
13+
if !ifc.openProgram(currentProgram) then
1414
throw new DecompileException("Decompiler", "Unable to initialize: " + ifc.getLastMessage)
15-
}
1615

1716
ifc.setSimplificationStyle("decompiler")
1817

@@ -21,13 +20,9 @@ class PrintHighPCode extends GhidraScript {
2120

2221
val hfblocks = hf.getBasicBlocks.asScala
2322

24-
hfblocks.foreach (block => {
23+
hfblocks.foreach (block =>
2524
println(s"Beginning of ${block.toString}")
26-
block.getIterator.asScala.foreach (inst => {
25+
block.getIterator.asScala.foreach (inst =>
2726
println(inst.toString)
28-
})
29-
})
30-
31-
}
32-
}
33-
27+
)
28+
)

src/main/java/scalascriptprovider/ScalaScriptProvider.java

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@
2626
import java.net.MalformedURLException;
2727
import java.net.URLClassLoader;
2828

29-
import scala.collection.JavaConversions;
30-
import scala.tools.nsc.MainClass;
31-
import scala.tools.nsc.Settings;
32-
import scala.tools.nsc.CompilerCommand;
29+
import scala.jdk.CollectionConverters;
3330

3431
import javax.tools.*;
3532
import javax.tools.JavaCompiler.CompilationTask;
@@ -54,7 +51,7 @@ public String getExtension() {
5451

5552
static ResourceFile getClassFileByResourceFile(ResourceFile sourceFile, String rawName) {
5653
String javaAbsolutePath = sourceFile.getAbsolutePath();
57-
String classAbsolutePath = javaAbsolutePath.replace(".java", ".class");
54+
String classAbsolutePath = javaAbsolutePath.replace(".scala", ".class");
5855

5956
return new ResourceFile(classAbsolutePath);
6057
}
@@ -90,8 +87,8 @@ public GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter write
9087
sourceFile.getName() + " does not.");
9188
}
9289
catch (ClassNotFoundException e) {
93-
throw new GhidraScriptLoadException("The class could not be found. " +
94-
"It must be the public class of the .java file: " + e.getMessage(), e);
90+
throw new GhidraScriptLoadException("The class " + e.getMessage() + " could not be found. " +
91+
"Make sure the primary class in " + sourceFile + " is named " + e.getMessage() + ".", e);
9592
}
9693
catch (NoClassDefFoundError e) {
9794
throw new GhidraScriptLoadException("The class could not be found or loaded, " +
@@ -102,6 +99,7 @@ public GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter write
10299
"Error during class initialization: " + e.getException(), e.getException());
103100
}
104101
catch (Exception e) {
102+
e.printStackTrace();
105103
throw new GhidraScriptLoadException("Unexpected error: " + e);
106104
}
107105

@@ -156,29 +154,7 @@ private boolean doCompile(ResourceFile sourceFile, final PrintWriter writer) {
156154
return helper.compile(msg -> writer.println(msg), outputDirectory, getSourcePath(), getClassPath(), sourceFile.getAbsolutePath());
157155
}
158156

159-
private List<Class<?>> getParentClasses(ResourceFile scriptSourceFile) {
160-
161-
Class<?> scriptClass = getScriptClass(scriptSourceFile);
162-
if (scriptClass == null) {
163-
return null; // special signal that there was a problem
164-
}
165-
166-
List<Class<?>> parentClasses = new ArrayList<>();
167-
Class<?> superClass = scriptClass.getSuperclass();
168-
while (superClass != null) {
169-
if (superClass.equals(GhidraScript.class)) {
170-
break; // not interested in the built-in classes
171-
}
172-
else if (superClass.equals(HeadlessScript.class)) {
173-
break; // not interested in the built-in classes
174-
}
175-
parentClasses.add(superClass);
176-
superClass = superClass.getSuperclass();
177-
}
178-
return parentClasses;
179-
}
180-
181-
private Class<?> getScriptClass(ResourceFile scriptSourceFile) {
157+
private Class<?> getScriptClass(ResourceFile scriptSourceFile) throws ClassNotFoundException {
182158
String clazzName = GhidraScriptUtil.getBaseName(scriptSourceFile);
183159
try {
184160
URL classURL = outputDir(scriptSourceFile).getFile(false).toURI().toURL();
@@ -188,6 +164,7 @@ private Class<?> getScriptClass(ResourceFile scriptSourceFile) {
188164
}
189165
catch (NoClassDefFoundError | ClassNotFoundException e) {
190166
Msg.error(this, "Unable to find class file for script file: " + scriptSourceFile, e);
167+
throw e;
191168
}
192169
catch (MalformedURLException e) {
193170
Msg.error(this, "Malformed URL exception:", e);

src/main/scala/scalascriptprovider/ScalaHelper.scala

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,29 @@
44

55
package scalascriptprovider
66

7-
import scala.tools.nsc.{MainClass, CompilerCommand, Settings}
8-
import scala.tools.nsc.reporters.StoreReporter
7+
import dotty.tools.dotc.Driver
8+
import dotty.tools.dotc.reporting.{Diagnostic, ConsoleReporter}
99
import java.util.function.Consumer
1010

11-
class ScalaHelper {
12-
def compile(errorFn: Consumer[java.lang.String], outputDirectory: String, sourcePath: String, classPath: String, sourceFileName: String): Boolean = {
13-
val settings = new Settings()
14-
15-
val args = List("-g:source",
11+
class ScalaHelper:
12+
def compile(errorFn: Consumer[java.lang.String], outputDirectory: String, sourcePath: String, classPath: String, sourceFileName: String): Boolean =
13+
val args = Array(
14+
"-g:source",
1615
"-d", outputDirectory,
1716
"-sourcepath", sourcePath,
1817
"-classpath", classPath,
19-
sourceFileName)
18+
sourceFileName
19+
)
2020

21-
val command = new CompilerCommand(args.toList, settings)
22-
val reporter = new scala.tools.nsc.reporters.StoreReporter
23-
val compiler = new scala.tools.nsc.Global(settings, reporter)
24-
val run = new compiler.Run()
25-
run.compile(command.files)
21+
val driver = new Driver
22+
val reporter = new ConsoleReporter
23+
val run = driver.process(args, reporter)
2624

27-
def infoToString(info: reporter.Info): String = {
28-
s"${info.severity}: " + scala.reflect.internal.util.Position.formatMessage(info.pos, info.msg + "\n", true) + "\n"
29-
}
25+
def diagnosticToString(diag: Diagnostic): String =
26+
s"${diag.level}: ${diag.message} at ${diag.pos.toString}\n"
3027

31-
if (reporter.hasErrors) {
28+
if reporter.hasErrors then
3229
errorFn.accept("Error(s) while compiling scala script:")
33-
reporter.infos.foreach(i => errorFn.accept (infoToString (i)))
34-
}
35-
!reporter.hasErrors
36-
}
37-
}
30+
reporter.allErrors.foreach(d => errorFn.accept(diagnosticToString(d)))
31+
32+
!reporter.hasErrors

0 commit comments

Comments
 (0)