From 1a8ec9e809639a8b11e5ba675f4939f8884b6f29 Mon Sep 17 00:00:00 2001 From: katherine-hough <32645020+katherine-hough@users.noreply.github.com> Date: Sun, 26 Nov 2023 13:10:48 -0500 Subject: [PATCH] * Started working on Jar driver --- Phosphor/pom.xml | 36 ++----- .../columbia/cs/psl/phosphor/OptionsUtil.java | 88 ----------------- .../cs/psl/phosphor/PhosphorOption.java | 95 +++++++++++++++---- .../src/main/resources/META-INF/MANIFEST.MF | 5 - .../swe/phosphor/instrument/Instrumenter.java | 46 ++++----- .../instrument/PhosphorInstrumentation.java | 23 ++++- .../instrument/PhosphorInstrumenter.java | 25 +++-- pom.xml | 2 +- 8 files changed, 144 insertions(+), 176 deletions(-) delete mode 100644 Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/OptionsUtil.java delete mode 100644 Phosphor/src/main/resources/META-INF/MANIFEST.MF diff --git a/Phosphor/pom.xml b/Phosphor/pom.xml index 9d0ef5706..db28b1a93 100644 --- a/Phosphor/pom.xml +++ b/Phosphor/pom.xml @@ -17,37 +17,19 @@ maven-jar-plugin - src/main/resources/META-INF/MANIFEST.MF + + + edu.columbia.cs.psl.phosphor.Java8PreMain + + true + - - java/ - sun/ - + true - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - none - true - 8 - sun.*:java.* - - - - attach-javadoc - - jar - - - - org.codehaus.mojo exec-maven-plugin - 1.6.0 generate-stubs @@ -95,7 +77,8 @@ - edu/columbia/cs/psl/phosphor/org/objectweb/asm/tree/FrameNode.class + + edu/columbia/cs/psl/phosphor/org/objectweb/asm/tree/FrameNode.class @@ -109,6 +92,7 @@ + true true true diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/OptionsUtil.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/OptionsUtil.java deleted file mode 100644 index 0bd356470..000000000 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/OptionsUtil.java +++ /dev/null @@ -1,88 +0,0 @@ -package edu.columbia.cs.psl.phosphor; - -import edu.columbia.cs.psl.phosphor.struct.SinglyLinkedList; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; - -import java.util.*; - -public class OptionsUtil { - /** - * Creates a standardized copy of the specified properties where each Phosphor option without an argument is mapped - * to either true or not present in the properties, each Phosphor option with an argument is either mapped to a - * non-null, non-empty string or not present in properties, and no other keys are present in the properties. - * - * @param properties properties to be standardized - * @return a standardized copy of properties - */ - private static Properties standardize(Properties properties) { - Properties result = new Properties(); - Map phosphorOptionMap = createOptionMap(); - for (String key : properties.stringPropertyNames()) { - String value = properties.getProperty(key); - if (phosphorOptionMap.containsKey(key)) { - Option option = phosphorOptionMap.get(key); - if (option.hasArg() && value != null && !value.isEmpty()) { - result.setProperty(option.getOpt(), value); - } else if (!option.hasArg() && (value == null || value.isEmpty() || "true".equalsIgnoreCase(value))) { - result.setProperty(option.getOpt(), "true"); - } - } else { - throw new IllegalArgumentException("Unknown option: " + key); - } - } - return result; - } - - /** - * @return a mapping from the names of configuration options available in Phosphor to an instance of - * org.apache.commons.cli.Option that represents that configuration option - */ - private static Map createOptionMap() { - Map map = new HashMap<>(); - Options options = PhosphorOption.createOptions(false); - for (Option option : options.getOptions()) { - map.put(option.getOpt(), option); - if (option.hasLongOpt()) { - map.put(option.getLongOpt(), option); - } - } - return map; - } - - public static String[] createPhosphorMainArguments(Properties properties) { - properties = standardize(properties); - SinglyLinkedList arguments = new SinglyLinkedList<>(); - Set propNames = properties.stringPropertyNames(); - for (String propName : propNames) { - arguments.addLast("-" + propName); - if (!"true".equals(properties.getProperty(propName))) { - arguments.addLast(properties.getProperty(propName)); - } - } - arguments.addLast("temp/"); - arguments.addLast("temp2/"); - return arguments.toArray(new String[0]); - } - - public static Set> getConfigurationClasses(Properties properties) { - Set> classes = new HashSet<>(); - Options options = PhosphorOption.createOptions(false); - for (Option option : options.getOptions()) { - if (option.getType().equals(Class.class)) { - String key = option.getOpt(); - if (properties.containsKey(key)) { - try { - Class clazz = Class.forName(properties.getProperty(key)); - classes.add(clazz); - } catch (ReflectiveOperationException e) { - String message = - String.format("Failed to create %s class: %s", key, properties.getProperty(key)); - throw new IllegalArgumentException(message, e); - } - } - } - } - return classes; - } -} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java index 3087b1809..522fd76fa 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java @@ -7,9 +7,10 @@ import org.apache.commons.cli.*; import org.objectweb.asm.ClassVisitor; +import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.util.EnumMap; +import java.util.*; public enum PhosphorOption { @@ -369,42 +370,94 @@ public static Options createOptions(boolean forRuntimeInst) { } } } - for(OptionGroup group : groupMap.values()) { + for (OptionGroup group : groupMap.values()) { options.addOptionGroup(group); } return options; } - public static CommandLine configure(boolean forRuntimeInst, String[] args) { - CommandLineParser parser = new DefaultParser(); - Options options = createOptions(forRuntimeInst); + public static CommandLine configure(boolean isRuntime, String[] args) { + String commandSynopsis = "java -jar phosphor.jar [OPTIONS] "; + Options options = createOptions(isRuntime); CommandLine line; try { - line = parser.parse(options, args); - } catch(org.apache.commons.cli.ParseException exp) { - if(forRuntimeInst) { - System.err.println(exp.getMessage()); + line = new DefaultParser().parse(options, args); + } catch (ParseException e) { + if (isRuntime) { + System.err.println(e.getMessage()); return null; } - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("java -jar phosphor.jar [OPTIONS] [input] [output]", options); - System.err.println(exp.getMessage()); - if(exp.getMessage().contains("-multiTaint")) { - System.err.println("Note: the -multiTaint option has been removed, and is now enabled by default (int tags no longer exist)"); - } - return null; + new HelpFormatter().printHelp(commandSynopsis, options); + throw new IllegalArgumentException(e); } - if(!forRuntimeInst && (line.hasOption("help") || line.getArgs().length != 2)) { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("java -jar phosphor.jar [OPTIONS] [input] [output]", options); + if (!isRuntime && line.hasOption("help")) { + new HelpFormatter().printHelp(commandSynopsis, options); return null; } - for(PhosphorOption phosphorOption : values()) { - phosphorOption.configure(forRuntimeInst, line.hasOption(phosphorOption.optionName), line); + if (!isRuntime && line.getArgs().length != 2) { + new HelpFormatter().printHelp(commandSynopsis, options); + throw new IllegalArgumentException("Missing command line arguments"); + } + for (PhosphorOption phosphorOption : values()) { + phosphorOption.configure(isRuntime, line.hasOption(phosphorOption.optionName), line); } return line; } + public static Set> getClassOptionValues(CommandLine line) { + // This method should not be called from instrumented JVMs. + // Therefore, the use of JCL classes is acceptable. + Set> classes = new HashSet<>(); + for (Option option : line.getOptions()) { + if (option.getType().equals(Class.class)) { + if (line.hasOption(option.getOpt())) { + try { + classes.add((Class) line.getParsedOptionValue(option.getOpt())); + } catch (ParseException e) { + throw new IllegalArgumentException( + "Failed to process " + option.getOpt() + ": " + line.getOptionValue(option.getOpt())); + } + } + } + } + return classes; + } + + public static CommandLine configure(Properties properties, File source, File destination) { + // This method should not be called from instrumented JVMs. + // Therefore, the use of JCL classes is acceptable. + List arguments = new LinkedList<>(); + for (String key : properties.stringPropertyNames()) { + String value = properties.getProperty(key); + if (value == null || value.isEmpty() || value.equals("true")) { + arguments.add("-" + key); + } else if (!value.equals("false")) { + arguments.add("-" + key); + arguments.add(value); + } + } + arguments.add(source.getAbsolutePath()); + arguments.add(destination.getAbsolutePath()); + return configure(false, arguments.toArray(new String[0])); + } + + public static Properties toProperties(CommandLine line) { + // This method should not be called from instrumented JVMs. + // Therefore, the use of JCL classes is acceptable. + Properties properties = new Properties(); + for (Option option : line.getOptions()) { + String key = option.getOpt(); + if (line.hasOption(key)) { + String value = line.getOptionValue(key); + if (value == null) { + value = "true"; + } + properties.put(key, value); + } + } + return properties; + } + private enum PhosphorOptionGroup { GENERAL, CONTROL_PROPAGATION } diff --git a/Phosphor/src/main/resources/META-INF/MANIFEST.MF b/Phosphor/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index f8fd3bc8e..000000000 --- a/Phosphor/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -Created-By: 1.6.0_06 (Sun Microsystems Inc.) -Main-Class: edu.columbia.cs.psl.phosphor.Instrumenter -Premain-Class: edu.columbia.cs.psl.phosphor.Java8PreMain -Can-Retransform-Classes: true diff --git a/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/Instrumenter.java b/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/Instrumenter.java index 87e645525..cb7158a3e 100644 --- a/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/Instrumenter.java +++ b/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/Instrumenter.java @@ -27,14 +27,14 @@ public Instrumenter(Instrumentation instrumentation, boolean verbose) { this.verbose = verbose; } - public void process(File source, File target) throws IOException, InterruptedException, ExecutionException { + public void process(File source, File destination) throws IOException, InterruptedException, ExecutionException { if (!source.exists()) { throw new IllegalArgumentException("Source file not found: " + source); } else if (!source.isDirectory() && !isClass(source.getName()) && !isArchive(source.getName())) { throw new IllegalArgumentException("Unknown source file type: " + source); } Queue> futures = new LinkedList<>(); - processFile(futures, source, target); + processFile(futures, source, destination); while (!futures.isEmpty()) { futures.poll().get(); } @@ -51,9 +51,9 @@ public void process(File source, File target) throws IOException, InterruptedExc } } - private void instrumentClass(File source, File target) { + private void instrumentClass(File source, File destination) { try (InputStream input = Files.newInputStream(source.toPath()); - OutputStream output = Files.newOutputStream(target.toPath())) { + OutputStream output = Files.newOutputStream(destination.toPath())) { instrumentClass(InstrumentUtil.readAllBytes(input), output); } catch (Throwable t) { errors.add(t); @@ -69,27 +69,27 @@ private void instrumentClass(byte[] classFileBuffer, OutputStream output) throws } } - private void processFile(Collection> futures, File source, File target) + private void processFile(Collection> futures, File source, File destination) throws IOException, InterruptedException { if (source.isDirectory()) { - InstrumentUtil.ensureDirectory(target); + InstrumentUtil.ensureDirectory(destination); for (File child : Objects.requireNonNull(source.listFiles())) { - processFile(futures, child, new File(target, child.getName())); + processFile(futures, child, new File(destination, child.getName())); } } else if (isClass(source.getName())) { - futures.add(executor.submit(() -> instrumentClass(source, target), null)); + futures.add(executor.submit(() -> instrumentClass(source, destination), null)); } else if (isArchive(source.getName())) { - processZip(Files.newInputStream(source.toPath()), Files.newOutputStream(target.toPath())); + processZip(Files.newInputStream(source.toPath()), Files.newOutputStream(destination.toPath())); } else { - if (copy(source, target)) { - if (source.canExecute() && !target.setExecutable(true)) { - errors.add(new IOException("Failed to set execute permission for: " + target)); + if (copy(source, destination)) { + if (source.canExecute() && !destination.setExecutable(true)) { + errors.add(new IOException("Failed to set execute permission for: " + destination)); } - if (source.canRead() && !target.setReadable(true)) { - errors.add(new IOException("Failed to set read permission for: " + target)); + if (source.canRead() && !destination.setReadable(true)) { + errors.add(new IOException("Failed to set read permission for: " + destination)); } - if (source.canWrite() && !target.setWritable(true)) { - errors.add(new IOException("Failed to set write permission for: " + target)); + if (source.canWrite() && !destination.setWritable(true)) { + errors.add(new IOException("Failed to set write permission for: " + destination)); } } } @@ -144,9 +144,9 @@ private void writeZipResults(OutputStream out, List> futures) } } - private boolean copy(File source, File target) { + private boolean copy(File source, File destination) { try (InputStream in = Files.newInputStream(source.toPath()); - OutputStream out = Files.newOutputStream(target.toPath())) { + OutputStream out = Files.newOutputStream(destination.toPath())) { InstrumentUtil.copy(in, out); return true; } catch (IOException e) { @@ -193,14 +193,14 @@ public ZipResult(ZipEntry entry, byte[] buffer) throws IOException, InterruptedE public static long instrument( File source, - File target, + File destination, Properties options, Instrumentation instrumentation, boolean verbose, String modules) throws IOException { - if (target.exists()) { - throw new IllegalArgumentException("Target location for instrumentation already exists."); + if (destination.exists()) { + throw new IllegalArgumentException("Destination location for instrumentation already exists."); } if (!source.exists()) { throw new IllegalArgumentException("Source location not found: " + source); @@ -208,9 +208,9 @@ public static long instrument( long startTime = System.currentTimeMillis(); try { if (InstrumentUtil.isModularJvm(source)) { - JLinkInvoker.invoke(source, target, instrumentation, options, modules); + JLinkInvoker.invoke(source, destination, instrumentation, options, modules); } else { - new Instrumenter(instrumentation, verbose).process(source, target); + new Instrumenter(instrumentation, verbose).process(source, destination); } return System.currentTimeMillis() - startTime; } catch (IOException | InterruptedException | ExecutionException e) { diff --git a/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumentation.java b/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumentation.java index e7b0de35b..6494fe1e2 100644 --- a/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumentation.java +++ b/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumentation.java @@ -1,7 +1,11 @@ package edu.gmu.swe.phosphor.instrument; -import edu.columbia.cs.psl.phosphor.*; +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.PhosphorOption; +import edu.columbia.cs.psl.phosphor.PhosphorPatcher; +import edu.columbia.cs.psl.phosphor.PreMain; import edu.columbia.cs.psl.phosphor.instrumenter.TaintTrackingClassVisitor; +import edu.columbia.cs.psl.phosphor.org.apache.commons.cli.CommandLine; import java.io.File; import java.io.IOException; @@ -25,16 +29,25 @@ public class PhosphorInstrumentation implements Instrumentation { @Override public void configure(File source, Properties options) throws IOException { - options.put("java8", String.valueOf(!InstrumentUtil.isModularJvm(source))); - String[] arguments = OptionsUtil.createPhosphorMainArguments(options); + options.remove("help"); + CommandLine line = PhosphorOption.configure(options, source, new File("temp/")); + assert line != null; + initialize(line); + } + + public void initialize(CommandLine line) throws IOException { + File source = new File(line.getArgs()[0]); + Set> configurationClasses = PhosphorOption.getClassOptionValues(line); + if (InstrumentUtil.isJavaHome(source)) { + Configuration.IS_JAVA_8 = !InstrumentUtil.isModularJvm(source); + } setUpClassLoader(source); - PhosphorOption.configure(false, arguments); Configuration.init(); TaintTrackingClassVisitor.IS_RUNTIME_INST = false; transformer = new PreMain.PCLoggingTransformer(); classPathElements = new HashSet<>(); classPathElements.add(InstrumentUtil.getClassPathElement(PreMain.class)); - OptionsUtil.getConfigurationClasses(options).stream() + configurationClasses.stream() .map(InstrumentUtil::getClassPathElement) .forEach(classPathElements::add); } diff --git a/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumenter.java b/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumenter.java index 1f4715bc7..d59e92dc0 100644 --- a/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumenter.java +++ b/phosphor-instrument-jigsaw/src/main/java/edu/gmu/swe/phosphor/instrument/PhosphorInstrumenter.java @@ -1,5 +1,9 @@ package edu.gmu.swe.phosphor.instrument; +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.PhosphorOption; +import edu.columbia.cs.psl.phosphor.org.apache.commons.cli.CommandLine; + import java.io.File; import java.io.IOException; @@ -9,13 +13,20 @@ private PhosphorInstrumenter() { } public static void main(String[] args) throws IOException { - // TODO + PhosphorInstrumentation instrumentation = new PhosphorInstrumentation(); + CommandLine line = PhosphorOption.configure(false, args); + if(line == null) { + // The "help" option was specified + return; + } File source = new File(args[0]); - File target = new File(args[1]); - boolean verbose = Boolean.parseBoolean(args[2]); - String modules = args[3]; - System.out.printf("Instrumenting %s to %s%n", source, target); - long elapsedTime = Instrumenter.instrument(source, target, null, null, verbose, modules); - System.out.printf("Finished generation after %dms%n", elapsedTime); + File destination = new File(args[1]); + instrumentation.initialize(line); + boolean verbose = !Configuration.QUIET_MODE; + String modules = line.hasOption("jvmModules") ? line.getOptionValue("jvmModules") : "ALL-MODULE-PATH"; + System.out.printf("Instrumenting %s to %s%n", source, destination); + long elapsedTime = Instrumenter.instrument(source, destination, PhosphorOption.toProperties(line), + instrumentation, verbose, modules); + System.out.printf("Finished instrumentation after %dms%n", elapsedTime); } } diff --git a/pom.xml b/pom.xml index d0b6e72e4..15275c612 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ MIT License - http://www.opensource.org/licenses/mit-license.php + https://www.opensource.org/licenses/mit-license.php repo