Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8281880: AsmTools driver uses wrong implementation classes #650

Closed
wants to merge 8 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 121 additions & 61 deletions test/lib/org/openjdk/asmtools/JtregDriver.java
Original file line number Diff line number Diff line change
@@ -22,9 +22,11 @@
*/
package org.openjdk.asmtools;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.InvalidPathException;
import java.nio.file.Files;
import java.io.PrintWriter;
import java.io.IOException;
@@ -50,77 +52,135 @@
*/
public class JtregDriver {

public static void main(String... args) throws IOException {
if (args.length == 0) {
throw new IllegalArgumentException("Missing asmtools command");
public static void main(String... args) throws Throwable {
// run AltLoaderMain from a class loader that prefers the modified AsmTools classes
ClassLoader loader = JtregDriver.class.getClassLoader();
Path file = Path.of(loader.getResource("org/openjdk/asmtools/JtregDriver.class").toURI());
Path root = file.getParent().getParent().getParent().getParent();
ClassLoader altLoader = new AsmToolsClassLoader(root);
Class<?> altMain = altLoader.loadClass(AltLoaderMain.class.getName());
try {
altMain.getMethod("main", String[].class).invoke(null, (Object) args);
} catch (InvocationTargetException e) {
System.out.println("Throwing " + e);
throw e.getCause();
}
String cmd = args[0];
if (!cmd.equals("jasm") && !cmd.equals("jdis") && !cmd.equals("jcoder")
&& !cmd.equals("jdec") && !cmd.equals("jcdec")) {
throw new IllegalArgumentException("Unrecognized asmtools command: " + cmd);
}
boolean isAssembler = cmd.equals("jasm") || cmd.equals("jcoder");
String srcDir = System.getProperty("test.src", ".");
String clsDir = System.getProperty("test.classes", ".");
String fileDir = isAssembler ? srcDir : clsDir;

ArrayList<String> toolArgList = new ArrayList<String>();

if (isAssembler) {
Path destPath = Paths.get(clsDir);
if (!Files.exists(destPath)) {
// jtreg creates classes dir on demand, might not have happened yet
Files.createDirectories(destPath);
}

public static class AltLoaderMain {

public static void main(String... args) throws IOException {
if (args.length == 0) {
throw new IllegalArgumentException("Missing asmtools command");
}
toolArgList.add("-d");
toolArgList.add(clsDir);
}
String cmd = args[0];
if (!cmd.equals("jasm") && !cmd.equals("jdis") && !cmd.equals("jcoder")
&& !cmd.equals("jdec") && !cmd.equals("jcdec")) {
throw new IllegalArgumentException("Unrecognized asmtools command: " + cmd);
}
boolean isAssembler = cmd.equals("jasm") || cmd.equals("jcoder");
String srcDir = System.getProperty("test.src", ".");
String clsDir = System.getProperty("test.classes", ".");
String fileDir = isAssembler ? srcDir : clsDir;

boolean isOptionArg = false; // marks an argument to a previous option
for (int i = 1; i < args.length; i++) {
String arg = args[i];
if (isOptionArg) {
isOptionArg = false; // reset for next
} else {
if (arg.equals("-d")) {
isOptionArg = true;
} else if (!arg.startsWith("-") && !arg.startsWith("/")) {
// adjust filename
arg = Paths.get(fileDir, arg).toString();
ArrayList<String> toolArgList = new ArrayList<String>();

if (isAssembler) {
Path destPath = Path.of(clsDir);
if (!Files.exists(destPath)) {
// jtreg creates classes dir on demand, might not have happened yet
Files.createDirectories(destPath);
}
toolArgList.add("-d");
toolArgList.add(clsDir);
}
toolArgList.add(arg);
}

String[] toolArgs = toolArgList.toArray(new String[0]);
boolean success = switch (cmd) {
case "jasm" -> {
PrintWriter out = new PrintWriter(System.out);
yield new org.openjdk.asmtools.jasm.Main(out, "jasm").compile(toolArgs);
}
case "jdis" -> {
PrintWriter out = new PrintWriter(new uEscWriter(System.out));
PrintWriter err = new PrintWriter(System.err);
yield new org.openjdk.asmtools.jdis.Main(out, err, "jdis").disasm(toolArgs);
boolean isOptionArg = false; // marks an argument to a previous option
for (int i = 1; i < args.length; i++) {
String arg = args[i];
if (isOptionArg) {
isOptionArg = false; // reset for next
} else {
if (arg.equals("-d")) {
isOptionArg = true;
} else if (!arg.startsWith("-") && !arg.startsWith("/")) {
// adjust filename
arg = Path.of(fileDir, arg).toString();
}
}
toolArgList.add(arg);
}
case "jcoder" -> {
PrintWriter out = new PrintWriter(System.out);
yield new org.openjdk.asmtools.jcoder.Main(out, "jcoder").compile(toolArgs);

String[] toolArgs = toolArgList.toArray(new String[0]);
boolean success = switch (cmd) {
case "jasm" -> {
PrintWriter out = new PrintWriter(System.out);
yield new org.openjdk.asmtools.jasm.Main(out, "jasm").compile(toolArgs);
}
case "jdis" -> {
PrintWriter out = new PrintWriter(new uEscWriter(System.out));
PrintWriter err = new PrintWriter(System.err);
yield new org.openjdk.asmtools.jdis.Main(out, err, "jdis").disasm(toolArgs);
}
case "jcoder" -> {
PrintWriter out = new PrintWriter(System.out);
yield new org.openjdk.asmtools.jcoder.Main(out, "jcoder").compile(toolArgs);
}
case "jdec" -> {
PrintWriter out = new PrintWriter(new uEscWriter(System.out));
PrintWriter err = new PrintWriter(System.err);
yield new org.openjdk.asmtools.jdec.Main(out, err, "jdec").decode(toolArgs);
}
case "jcdec" -> {
PrintWriter out = new PrintWriter(new uEscWriter(System.out));
yield new org.openjdk.asmtools.jcdec.Main(out, "jcdec").decode(toolArgs);
}
default -> throw new AssertionError();
};
System.out.printf("ran %s, result %s%n", cmd, success);
if (!success) {
throw new RuntimeException("asmtools execution failed");
}
case "jdec" -> {
PrintWriter out = new PrintWriter(new uEscWriter(System.out));
PrintWriter err = new PrintWriter(System.err);
yield new org.openjdk.asmtools.jdec.Main(out, err, "jdec").decode(toolArgs);
}

}

/**
* Class loader for the AsmTools classes. Allows classes colocated with
* JtregDriver to have priority over versions of the classes loaded by
* jtreg (which includes its own copy of AsmTools).
*/
private static class AsmToolsClassLoader extends ClassLoader {
private final Path root;
private final String separator;

public AsmToolsClassLoader(Path root) {
super(AsmToolsClassLoader.class.getClassLoader());
this.root = root;
this.separator = root.getFileSystem().getSeparator();
}

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (name.startsWith("org.openjdk.asmtools.")) {
Class<?> result = findClass(name);
if (resolve) resolveClass(result);
return result;
} else {
return super.loadClass(name, resolve);
}
case "jcdec" -> {
PrintWriter out = new PrintWriter(new uEscWriter(System.out));
yield new org.openjdk.asmtools.jcdec.Main(out, "jcdec").decode(toolArgs);
}

protected Class<?> findClass(String name) throws ClassNotFoundException {
String filename = name.replace(".",separator) + ".class";
try {
Path classFile = root.resolve(filename);
byte[] bytes = Files.readAllBytes(classFile);
return defineClass(name, bytes, 0, bytes.length);
} catch (InvalidPathException | IOException e) {
throw new ClassNotFoundException("can't read class " + filename, e);
}
default -> throw new AssertionError();
};
if (!success) {
throw new RuntimeException("asmtools execution failed");
}

}

}