use of org.mapleir.app.service.ApplicationClassSource in project maple-ir by LLVM-but-worse.
the class Boot method dumpJar.
private static void dumpJar(ApplicationClassSource app, SingleJarDownloader<ClassNode> dl, PassGroup masterGroup, String outputFile) throws IOException {
(new CompleteResolvingJarDumper(dl.getJarContents(), app) {
@Override
public int dumpResource(JarOutputStream out, String name, byte[] file) throws IOException {
// }
if (name.equals("META-INF/MANIFEST.MF")) {
ClassRenamerPass renamer = (ClassRenamerPass) masterGroup.getPass(e -> e.is(ClassRenamerPass.class));
if (renamer != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(baos));
BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(file)));
String line;
while ((line = br.readLine()) != null) {
String[] parts = line.split(": ", 2);
if (parts.length != 2) {
bw.write(line);
continue;
}
if (parts[0].equals("Main-Class")) {
String newMain = renamer.getRemappedName(parts[1].replace(".", "/")).replace("/", ".");
LOGGER.info(String.format("%s -> %s%n", parts[1], newMain));
parts[1] = newMain;
}
bw.write(parts[0]);
bw.write(": ");
bw.write(parts[1]);
bw.write(System.lineSeparator());
}
br.close();
bw.close();
file = baos.toByteArray();
}
}
return super.dumpResource(out, name, file);
}
}).dump(new File(outputFile));
}
use of org.mapleir.app.service.ApplicationClassSource in project maple-ir by LLVM-but-worse.
the class Boot method main.
public static void main(String[] args) throws Exception {
sections = new LinkedList<>();
logging = true;
File rtjar = new File("res/rt.jar");
// Load input jar
File f = locateRevFile(135);
// File f = new File("res/allatori6.1san.jar");
section("Preparing to run on " + f.getAbsolutePath());
SingleJarDownloader<ClassNode> dl = new SingleJarDownloader<>(new JarInfo(f));
dl.download();
String name = f.getName().substring(0, f.getName().length() - 4);
// ApplicationClassSource app = new ApplicationClassSource(name, dl.getJarContents().getClassContents());
//
ApplicationClassSource app = new ApplicationClassSource("test", ClassHelper.parseClasses(CGExample.class));
// app.addLibraries(new InstalledRuntimeClassSource(app));
app.addLibraries(rt(app, rtjar), new InstalledRuntimeClassSource(app));
section("Initialising context.");
AnalysisContext cxt = new BasicAnalysisContext.BasicContextBuilder().setApplication(app).setInvocationResolver(new DefaultInvocationResolver(app)).setCache(new IRCache(ControlFlowGraphBuilder::build)).setApplicationContext(new SimpleApplicationContext(app)).build();
section("Expanding callgraph and generating cfgs.");
IRCallTracer tracer = new IRCallTracer(cxt);
for (MethodNode m : cxt.getApplicationContext().getEntryPoints()) {
// System.out.println(m);
tracer.trace(m);
if (m.instructions.size() > 500 && m.instructions.size() < 100) {
System.out.println(m);
System.out.println(cxt.getIRCache().get(m));
}
}
for (ClassNode cn : app.iterate()) {
TabbedStringWriter sw = new TabbedStringWriter();
sw.setTabString(" ");
IPropertyDictionary settings = PropertyHelper.createDictionary();
// settings.put(new BooleanProperty(ASMPrinter.PROP_ACCESS_FLAG_SAFE, true));
ClassPrinter cp = new ClassPrinter(sw, settings, new FieldNodePrinter(sw, settings), new MethodNodePrinter(sw, settings) {
@Override
protected ControlFlowGraph getCfg(MethodNode mn) {
return cxt.getIRCache().getFor(mn);
}
});
cp.print(cn);
System.out.println(sw.toString());
}
section0("...generated " + cxt.getIRCache().size() + " cfgs in %fs.%n", "Preparing to transform.");
// do passes
PassGroup masterGroup = new PassGroup("MasterController");
for (IPass p : getTransformationPasses()) {
masterGroup.add(p);
}
run(cxt, masterGroup);
// for(MethodNode m : cxt.getIRCache().getActiveMethods()) {
// if(m.instructions.size() > 100 && m.instructions.size() < 500) {
// System.out.println(cxt.getIRCache().get(m));
// }
// }
section("Retranslating SSA IR to standard flavour.");
for (Entry<MethodNode, ControlFlowGraph> e : cxt.getIRCache().entrySet()) {
MethodNode mn = e.getKey();
ControlFlowGraph cfg = e.getValue();
BoissinotDestructor.leaveSSA(cfg);
cfg.getLocals().realloc(cfg);
(new ControlFlowGraphDumper(cfg, mn)).dump();
}
section("Rewriting jar.");
// dumpJar(app, dl, masterGroup, "out/osb5.jar");
section("Finished.");
}
use of org.mapleir.app.service.ApplicationClassSource in project maple-ir by LLVM-but-worse.
the class MethodRenamerPass method accept.
@Override
public int accept(AnalysisContext cxt, IPass prev, List<IPass> completed) {
ApplicationClassSource source = cxt.getApplication();
InvocationResolver resolver = cxt.getInvocationResolver();
Map<MethodNode, String> remapped = new HashMap<>();
int totalMethods = 0;
for (ClassNode cn : source.iterate()) {
totalMethods += cn.methods.size();
}
int i = RenamingUtil.computeMinimum(totalMethods);
for (ClassNode cn : source.iterate()) {
for (MethodNode m : cn.methods) {
if (!heuristic.shouldRename(m.name, m.access)) {
// System.out.println("Heuristic bypass meth " + m.name);
continue;
}
if (remapped.containsKey(m)) {
continue;
}
if (Modifier.isStatic(m.access)) {
if (!m.name.equals("<clinit>") && !SimpleApplicationContext.isMainMethod(m)) {
String newName = RenamingUtil.createName(i++);
remapped.put(m, newName);
}
} else {
if (!m.name.equals("<init>")) {
// Set<ClassNode> classes = source.getStructures().dfsTree(m.owner, true, true, true);
// Set<MethodNode> methods = getVirtualMethods(cxt, classes, m.name, m.desc);
Set<MethodNode> methods = resolver.getHierarchyMethodChain(m.owner, m.name, m.desc, true);
if (canRename(cxt, methods)) {
String newName = RenamingUtil.createName(i++);
for (MethodNode o : methods) {
// Set<MethodNode> s2 = InvocationResolver.getHierarchyMethodChain(cxt, o.owner, o.name, m.desc, true);
/*if(!methods.equals(s2)) {
System.err.printf("m: %s%n", m);
System.err.printf("o: %s%n", o);
System.err.println("this ms::");
for(MethodNode s : methods) {
System.err.printf(" %s%n", s);
}
System.err.println("o ms::");
for(MethodNode s : s2) {
System.err.printf(" %s%n", s);
}
throw new IllegalStateException();
}*/
/*if(remapped.containsKey(o)) {
System.err.printf("m: %s%n", m);
System.err.printf("o: %s%n", o);
System.err.println("this ms::");
for(MethodNode s : methods) {
System.err.printf(" %s%n", s);
}
System.err.println("o ms::");
for(MethodNode s : InvocationResolver.getHierarchyMethodChain(cxt, o.owner, o.name, m.desc, true)) {
System.err.printf(" %s%n", s);
}
System.err.println(" o debugset::");
for(MethodNode s : debugMap.get(o)) {
System.err.printf(" %s%n", s);
}
System.err.printf("on: %s%n", remapped.get(o));
System.err.printf("nn: %s%n", newName);
throw new IllegalStateException();
}*/
remapped.put(o, newName);
}
/*for(MethodNode hm : methods) {
debugMap.put(hm, methods);
}*/
} else {
System.out.println(" can't rename: " + methods);
}
}
}
}
}
rename(cxt, remapped, true);
System.out.printf(" Remapped %d/%d methods.%n", remapped.size(), totalMethods);
return remapped.size();
}
use of org.mapleir.app.service.ApplicationClassSource in project maple-ir by LLVM-but-worse.
the class MethodRenamerPass method rename.
public static void rename(AnalysisContext cxt, Map<MethodNode, String> remapped, boolean warn) {
ApplicationClassSource source = cxt.getApplication();
InvocationResolver resolver = cxt.getInvocationResolver();
for (ClassNode cn : source.iterate()) {
{
if (cn.outerMethod != null) {
// ClassNode owner = tree.getClass(cn.outerClass);
System.out.println("Outer: " + cn.outerClass + "." + cn.outerMethod + " " + cn.outerMethodDesc);
cn.outerClass = null;
cn.outerMethod = null;
cn.outerMethodDesc = null;
// System.out.println(owner.name);
// do {
// for(MethodNode m : owner.methods) {
// System.out.println(m);
// if(m.name.equals(cn.outerMethod) && m.desc.equals(cn.outerMethodDesc)) {
// System.out.println("m: " + m);
// }
// }
// owner = tree.getClass(owner.superName);
// System.out.println(cn.superName);
// System.out.println(owner);
// } while(owner != null);
}
}
Set<Expr> visited = new HashSet<>();
for (MethodNode m : cn.methods) {
ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
for (BasicBlock b : cfg.vertices()) {
for (Stmt stmt : b) {
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == Opcode.INVOKE) {
InvocationExpr invoke = (InvocationExpr) e;
if (visited.contains(invoke)) {
throw new RuntimeException(invoke.toString());
}
visited.add(invoke);
if (invoke.getOwner().startsWith("[")) {
System.err.println(" ignore array object invoke: " + invoke + ", owner: " + invoke.getOwner());
continue;
}
if (invoke.isStatic()) {
MethodNode site = resolver.resolveStaticCall(invoke.getOwner(), invoke.getName(), invoke.getDesc());
if (site != null) {
if (remapped.containsKey(site)) {
invoke.setName(remapped.get(site));
} else {
if (warn && mustMark(source, invoke.getOwner())) {
System.err.println(" invalid site(s): " + invoke);
}
}
} else {
if (mustMark(source, invoke.getOwner())) {
System.err.printf(" can't resolve(s) %s ; %s.%s %s%n", invoke, invoke.getOwner(), invoke.getName(), invoke.getDesc());
if (invoke.getOwner().equals("hey")) {
for (MethodNode mm : cxt.getApplication().findClassNode(invoke.getOwner()).methods) {
System.out.println(mm);
}
throw new UnsupportedOperationException();
}
}
}
} else {
// Set<MethodNode> sites = resolver.resolveVirtualCalls(invoke.getOwner(), invoke.getName(), invoke.getDesc());
// Set<ClassNode> classes = source.getStructures().dfsTree(cn, true, true, true);
// Set<MethodNode> sites = getVirtualMethods(cxt, classes, invoke.getName(), invoke.getDesc());
Set<MethodNode> sites = resolver.getHierarchyMethodChain(source.findClassNode(invoke.getOwner()), invoke.getName(), invoke.getDesc(), true);
if (sites.size() > 0) {
/* all of the sites must be linked by the same name,
* so we can use any to find the new name. */
boolean anyContains = false;
boolean allContains = true;
for (MethodNode s : sites) {
anyContains |= remapped.containsKey(s);
allContains &= remapped.containsKey(s);
}
if (anyContains && !allContains) {
System.err.println("mismatch: ");
// System.err.println(classes);
System.err.println(sites);
throw new RuntimeException();
}
MethodNode site = sites.iterator().next();
if (remapped.containsKey(site)) {
invoke.setName(remapped.get(site));
} else {
if (warn && !site.name.equals("<init>") && canRename(cxt, sites)) {
System.err.println(" invalid site(v): " + invoke + ", " + sites);
}
}
} else {
if (mustMark(source, invoke.getOwner())) {
System.err.println(" can't resolve(v) " + invoke + ", owner: " + invoke.getOwner() + " desc " + invoke.getDesc());
// System.err.println(" classes: " + classes);
}
}
}
} else if (e.getOpcode() == Opcode.DYNAMIC_INVOKE) {
throw new UnsupportedOperationException();
}
}
}
}
}
}
/* Rename the methods after as we need to resolve
* them using the old names during the invocation
* analysis above. */
for (Entry<MethodNode, String> e : remapped.entrySet()) {
// System.out.printf("%s -> %s%n", e.getKey(), e.getValue());
e.getKey().name = e.getValue();
}
}
use of org.mapleir.app.service.ApplicationClassSource in project maple-ir by LLVM-but-worse.
the class ClassRenamerPass method accept.
/*private String getClassName(String name) {
int i = name.lastIndexOf('/');
if(i == -1) {
return name;
} else {
return name.substring(i + 1, name.length());
}
}*/
@Override
public int accept(AnalysisContext cxt, IPass prev, List<IPass> completed) {
ApplicationClassSource source = cxt.getApplication();
Collection<ClassNode> classes = CollectionUtils.collate(source.iterator());
// int min = RenamingUtil.computeMinimum(classes.size());
int n = RenamingUtil.numeric("aaa");
int step = 27;
for (ClassNode cn : classes) {
String className = RenamingUtil.getClassName(cn.name);
if (!heuristic.shouldRename(className, cn.access)) {
System.out.println("Heuristic bypass " + cn.name);
}
String newName = heuristic.shouldRename(className, cn.access) ? RenamingUtil.createName(n) : className;
String s = RenamingUtil.getPackage(cn.name) + newName;
n += step;
remapping.put(cn.name, s);
// System.out.println(cn.name + " -> " + s);
cn.name = s;
}
for (ClassNode cn : classes) {
cn.superName = remapping.getOrDefault(cn.superName, cn.superName);
{
List<String> ifaces = new ArrayList<>();
for (int i = 0; i < cn.interfaces.size(); i++) {
String s = cn.interfaces.get(i);
ifaces.add(remapping.getOrDefault(s, s));
}
cn.interfaces = ifaces;
}
unsupported(cn.signature);
// unsupported(cn.sourceFile);
// unsupported(cn.sourceDebug);
cn.outerClass = remapping.getOrDefault(cn.outerClass, cn.outerClass);
// unsupported(cn.outerMethod);
// unsupported(cn.outerMethodDesc);
unsupported(cn.visibleAnnotations);
unsupported(cn.invisibleAnnotations);
unsupported(cn.visibleTypeAnnotations);
unsupported(cn.invisibleTypeAnnotations);
unsupported(cn.attrs);
unsupported(cn.innerClasses);
for (FieldNode f : cn.fields) {
unsupported(cn.signature);
{
Type type = Type.getType(f.desc);
String newType = resolveType(type, remapping);
if (newType != null) {
f.desc = newType;
}
}
unsupported(f.visibleAnnotations);
unsupported(f.invisibleAnnotations);
unsupported(f.visibleTypeAnnotations);
unsupported(f.invisibleTypeAnnotations);
unsupported(f.attrs);
}
for (MethodNode m : cn.methods) {
m.desc = resolveMethod(m.desc, remapping);
unsupported(m.signature);
{
List<String> exceptions = new ArrayList<>();
for (int i = 0; i < m.exceptions.size(); i++) {
String s = m.exceptions.get(i);
exceptions.add(remapping.getOrDefault(s, s));
}
m.exceptions = exceptions;
}
unsupported(m.parameters);
unsupported(m.visibleAnnotations);
unsupported(m.invisibleAnnotations);
unsupported(m.visibleTypeAnnotations);
unsupported(m.invisibleTypeAnnotations);
unsupported(m.attrs);
unsupported(m.annotationDefault);
unsupported(m.visibleParameterAnnotations);
unsupported(m.invisibleParameterAnnotations);
for (TryCatchBlockNode tcbn : m.tryCatchBlocks) {
tcbn.type = remapping.getOrDefault(tcbn.type, tcbn.type);
}
ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
for (ExceptionRange<BasicBlock> er : cfg.getRanges()) {
Set<Type> newTypeSet = new HashSet<>();
for (Type t : er.getTypes()) {
// FIXME:
String s = t.getInternalName();
if (remapping.containsKey(s)) {
newTypeSet.add(Type.getType("L" + remapping.get(s) + ";"));
} else {
newTypeSet.add(t);
}
}
er.setTypes(newTypeSet);
}
if (m.localVariables != null) {
m.localVariables.clear();
for (LocalVariableNode lvn : m.localVariables) {
String newDesc = resolveType(Type.getType(lvn.desc), remapping);
if (newDesc != null) {
lvn.desc = newDesc;
}
unsupported(lvn.signature);
}
}
unsupported(m.visibleLocalVariableAnnotations);
unsupported(m.invisibleLocalVariableAnnotations);
for (BasicBlock b : cfg.vertices()) {
for (Stmt stmt : b) {
if (stmt.getOpcode() == Opcode.FIELD_STORE) {
FieldStoreStmt fs = (FieldStoreStmt) stmt;
String owner = fs.getOwner();
fs.setOwner(remapping.getOrDefault(owner, owner));
{
Type type = Type.getType(fs.getDesc());
String newType = resolveType(type, remapping);
if (newType != null) {
fs.setDesc(newType);
}
}
} else if (stmt.getOpcode() == Opcode.RETURN) {
ReturnStmt ret = (ReturnStmt) stmt;
String newType = resolveType(ret.getType(), remapping);
if (newType != null) {
ret.setType(Type.getType(newType));
}
} else if (stmt instanceof AbstractCopyStmt) {
AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
VarExpr v = copy.getVariable();
String newType = resolveType(v.getType(), remapping);
if (newType != null) {
v.setType(Type.getType(newType));
}
}
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == Opcode.CAST) {
CastExpr cast = (CastExpr) e;
String newType = resolveType(cast.getType(), remapping);
if (newType != null) {
cast.setType(Type.getType(newType));
}
} else if (e.getOpcode() == Opcode.CATCH) {
CaughtExceptionExpr caught = (CaughtExceptionExpr) e;
String newType = resolveType(caught.getType(), remapping);
if (newType != null) {
caught.setType(Type.getType(newType));
}
} else if (e.getOpcode() == Opcode.DYNAMIC_INVOKE) {
throw new UnsupportedOperationException();
} else if (e.getOpcode() == Opcode.INVOKE) {
InvocationExpr invoke = (InvocationExpr) e;
invoke.setOwner(remapping.getOrDefault(invoke.getOwner(), invoke.getOwner()));
invoke.setDesc(resolveMethod(invoke.getDesc(), remapping));
} else if (e.getOpcode() == Opcode.FIELD_LOAD) {
FieldLoadExpr fl = (FieldLoadExpr) e;
fl.setOwner(remapping.getOrDefault(fl.getOwner(), fl.getOwner()));
String newType = resolveType(fl.getType(), remapping);
if (newType != null) {
fl.setDesc(newType);
}
} else if (e.getOpcode() == Opcode.INIT_OBJ) {
InitialisedObjectExpr init = (InitialisedObjectExpr) e;
init.setOwner(remapping.getOrDefault(init.getOwner(), init.getOwner()));
init.setDesc(resolveMethod(init.getDesc(), remapping));
} else if (e.getOpcode() == Opcode.INSTANCEOF) {
InstanceofExpr inst = (InstanceofExpr) e;
String newType = resolveType(inst.getCheckType(), remapping);
if (newType != null) {
inst.setCheckType(Type.getType(newType));
}
} else if (e.getOpcode() == Opcode.NEW_ARRAY) {
NewArrayExpr na = (NewArrayExpr) e;
String newType = resolveType(na.getType(), remapping);
if (newType != null) {
na.setType(Type.getType(newType));
}
} else if (e.getOpcode() == Opcode.ALLOC_OBJ) {
AllocObjectExpr uninit = (AllocObjectExpr) e;
String newType = resolveType(uninit.getType(), remapping);
if (newType != null) {
uninit.setType(Type.getType(newType));
}
} else if (e.getOpcode() == Opcode.LOCAL_LOAD) {
VarExpr v = (VarExpr) e;
String newType = resolveType(v.getType(), remapping);
if (newType != null) {
v.setType(Type.getType(newType));
}
} else if (e.getOpcode() == Opcode.CONST_LOAD) {
ConstantExpr c = (ConstantExpr) e;
Object cst = c.getConstant();
if (cst instanceof Type) {
Type t = (Type) cst;
if (t.getSort() == Type.OBJECT) {
String newType = resolveType(t, remapping);
if (newType != null) {
c.setConstant(Type.getType(newType));
}
} else {
throw new UnsupportedOperationException(String.format("Unsupported ctype %s (%d)", t, t.getSort()));
}
}
}
}
}
}
}
}
source.rebuildTable();
return classes.size();
}
Aggregations