use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class ExceptionFixerPass method accept.
@Override
public PassResult accept(PassContext cxt) {
final AtomicInteger counter = new AtomicInteger();
for (ControlFlowGraph value : cxt.getAnalysis().getIRCache().values()) {
for (ExceptionRange<BasicBlock> range : value.getRanges()) {
if (range.getTypes().size() <= 1)
continue;
ClassNode superType = null;
for (Type type : range.getTypes()) {
ClassNode classNode = cxt.getAnalysis().getApplication().findClassNode(type.getClassName());
if (classNode == null) {
try {
classNode = ClassHelper.create(type.getClassName());
} catch (IOException e) {
continue;
}
}
if (superType == null) {
superType = classNode;
} else {
superType = cxt.getAnalysis().getApplication().getClassTree().getCommonSuperType(superType.getName(), classNode.getName());
}
}
final Set<Type> types = new HashSet<>(Collections.singleton(superType == null ? TypeUtils.OBJECT_TYPE : Type.getObjectType(superType.getName())));
range.setTypes(types);
counter.incrementAndGet();
}
}
logger.info("[*] Successfully fixed" + counter.get() + " exception ranges!");
return PassResult.with(cxt, this).finished().make();
}
use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class FieldRSADecryptionPass method accept.
@Override
public PassResult accept(PassContext pcxt) {
this.cxt = pcxt.getAnalysis();
for (MethodNode m : cxt.getIRCache().getActiveMethods()) {
ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
for (BasicBlock b : cfg.vertices()) {
for (Stmt stmt : b) {
for (Expr c : stmt.enumerateOnlyChildren()) {
if (c.getOpcode() == ARITHMETIC) {
ArithmeticExpr arith = (ArithmeticExpr) c;
if (arith.getOperator() == Operator.MUL) {
Expr l = arith.getLeft();
Expr r = arith.getRight();
if (r.getOpcode() == CONST_LOAD && l.getOpcode() == FIELD_LOAD) {
FieldLoadExpr fle = (FieldLoadExpr) l;
ConstantExpr constt = (ConstantExpr) r;
Number n = (Number) constt.getConstant();
boolean isLong = (n instanceof Long);
if (__eq(n, 1, isLong) || __eq(n, 0, isLong)) {
continue;
}
if (n instanceof Integer || n instanceof Long) {
cdecs.getNonNull(key(fle)).add(n);
}
}
}
}
}
if (stmt.getOpcode() == FIELD_STORE) {
FieldStoreStmt fss = (FieldStoreStmt) stmt;
Expr val = fss.getValueExpression();
if (bcheck1(val)) {
if (val.getOpcode() == CONST_LOAD) {
ConstantExpr c = (ConstantExpr) val;
if (c.getConstant() instanceof Integer || c.getConstant() instanceof Long) {
Number n = (Number) c.getConstant();
if (large(n, c.getConstant() instanceof Long)) {
cencs.getNonNull(key(fss)).add(n);
}
}
}
continue;
}
ArithmeticExpr ar = (ArithmeticExpr) val;
if (ar.getRight().getOpcode() == CONST_LOAD) {
ConstantExpr c = (ConstantExpr) ar.getRight();
Number n = (Number) c.getConstant();
boolean isLong = c.getConstant() instanceof Long;
if (__eq(n, 1, isLong) || __eq(n, 0, isLong)) {
continue;
}
if (ar.getOperator() == Operator.ADD) {
if (!large(n, isLong)) {
continue;
}
}
cencs.getNonNull(key(fss)).add(n);
}
}
}
for (Stmt stmt : b) {
if (stmt.getOpcode() == FIELD_STORE) {
if (key((FieldStoreStmt) stmt).equals("co.k I")) {
// System.out.println("HERE1: " + stmt);
//
// System.out.println(cfg);
}
handleFss((FieldStoreStmt) stmt);
}
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == FIELD_LOAD) {
if (key((FieldLoadExpr) e).equals("co.k I")) {
// System.out.println("HERE2: " + stmt);
}
handleFle(stmt, (FieldLoadExpr) e);
}
}
}
}
}
Set<String> keys = new HashSet<>();
keys.addAll(cencs.keySet());
keys.addAll(cdecs.keySet());
for (String k : keys) {
boolean _longint = k.endsWith("J");
Set<Number> encs = cencs.getNonNull(k);
Set<Number> decs = cdecs.getNonNull(k);
try {
Number[] pair = get_pair(encs, decs, constants.getNonNull(k), _longint);
if (pair.length != 2) {
Set<Number> extended = new HashSet<>(constants.getNonNull(k));
extended.addAll(dangerConstants.getNonNull(k));
pair = get_pair(encs, decs, extended, _longint);
}
if (pair.length != 2) {
// System.out.println("No pair for: " + k);
// System.out.println("Constants: " + constants.getNonNull(k));
// System.out.println("Dconsts : " + dangerConstants.getNonNull(k));
// System.out.println("Encs : " + encs);
// System.out.println("Decs : " + decs);
} else {
pairs.put(k, pair);
// System.out.println("for: " + k + ": " + Arrays.toString(pair));
}
} catch (IllegalStateException e) {
System.err.println();
System.err.println("Constants: " + constants.getNonNull(k));
System.out.println("Dconsts : " + dangerConstants.getNonNull(k));
System.err.println("Encs : " + encs);
System.err.println("Decs : " + decs);
System.err.println("key: " + k);
throw e;
}
}
System.out.printf(" identified %n field encoder/decoder pairs.%n", pairs.size());
transform(cxt);
return PassResult.with(pcxt, this).finished().make();
}
use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class FieldRSADecryptionPass method transform.
private void transform(AnalysisContext cxt) {
for (ClassNode cn : cxt.getApplication().iterate()) {
for (MethodNode m : cn.getMethods()) {
ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
for (BasicBlock b : cfg.vertices()) {
for (Stmt stmt : b) {
// String fsKey = "";
if (stmt.getOpcode() == Opcode.FIELD_STORE) {
FieldStoreStmt fs = (FieldStoreStmt) stmt;
// [enc, dec]
Number[] p = pairs.get(key(fs));
if (p != null) {
Expr e = fs.getValueExpression();
e.unlink();
ArithmeticExpr ae = new ArithmeticExpr(new ConstantExpr(p[1], ConstantExpr.computeType(p[1])), e, Operator.MUL);
fs.setValueExpression(ae);
// fsKey = key(fs);
}
}
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == FIELD_LOAD) {
CodeUnit par = e.getParent();
FieldLoadExpr fl = (FieldLoadExpr) e;
// [enc, dec]
Number[] p = pairs.get(key(fl));
if (p == null) {
continue;
}
if (par.getOpcode() == ARITHMETIC) {
ArithmeticExpr ae = (ArithmeticExpr) par;
if (ae.getRight().getOpcode() == CONST_LOAD) {
ConstantExpr ce = (ConstantExpr) ae.getRight();
Number cst = (Number) ce.getConstant();
Number res = __mul(cst, p[0], p[0].getClass().equals(Long.class));
// if(!__eq(res, 1, p[0].getClass().equals(Long.class))) {
// System.out.println(cst + " -> " + res);
// System.out.println(" expr: " + fl.getRootParent());
// }
par.writeAt(new ConstantExpr(res, ConstantExpr.computeType(res)), par.indexOf(ce));
continue;
}
}
ArithmeticExpr ae = new ArithmeticExpr(new ConstantExpr(p[0], ConstantExpr.computeType(p[0])), fl.copy(), Operator.MUL);
par.writeAt(ae, par.indexOf(fl));
}
}
}
}
}
}
// for(ClassNode cn : cxt.getClassTree().getClasses().values()) {
// for(MethodNode m : cn.getMethods()) {
// ControlFlowGraph cfg = cxt.getCFGS().getIR(m);
//
// for(BasicBlock b : cfg.vertices()) {
// for(Stmt stmt : b) {
// for(Expr e : stmt.enumerateOnlyChildren()) {
// if(e.getOpcode() == Opcode.ARITHMETIC) {
// ArithmeticExpr ae = (ArithmeticExpr) e;
// if(ae.getRight().getOpcode() == Opcode.CONST_LOAD) {
// ConstantExpr c = (ConstantExpr) ae.getRight();
// Object o = c.getConstant();
//
// if(o instanceof Long || o instanceof Integer) {
// Number n = (Number) o;
// if(__eq(n, 1, ae.getType().equals(DescType.LONG_TYPE))) {
// Expr l = ae.getLeft();
// l.unlink();
//
// CodeUnit aePar = ae.getParent();
// aePar.writeAt(l, aePar.indexOf(ae));
// } else if(__eq(n, 0, ae.getType().equals(DescType.LONG_TYPE))) {
// c.unlink();
//
// CodeUnit aePar = ae.getParent();
// aePar.writeAt(c, aePar.indexOf(ae));
// }
// }
// }
// }
// }
// }
// }
// }
// }
}
use of org.mapleir.ir.cfg.ControlFlowGraph 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 PassResult accept(PassContext pcxt) {
AnalysisContext cxt = pcxt.getAnalysis();
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.getName());
if (!heuristic.shouldRename(className, cn.node.access)) {
System.out.println("Heuristic bypass " + cn.getName());
}
String newName = heuristic.shouldRename(className, cn.node.access) ? RenamingUtil.createName(n) : className;
String s = RenamingUtil.getPackage(cn.getName()) + newName;
n += step;
remapping.put(cn.getName(), s);
// System.out.println(cn.getName() + " -> " + s);
cn.node.name = s;
}
for (ClassNode cn : classes) {
cn.node.superName = remapping.getOrDefault(cn.node.superName, cn.node.superName);
{
List<String> ifaces = new ArrayList<>();
for (int i = 0; i < cn.node.interfaces.size(); i++) {
String s = cn.node.interfaces.get(i);
ifaces.add(remapping.getOrDefault(s, s));
}
cn.node.interfaces = ifaces;
}
unsupported(cn.node.signature);
// unsupported(cn.sourceFile);
// unsupported(cn.sourceDebug);
cn.node.outerClass = remapping.getOrDefault(cn.node.outerClass, cn.node.outerClass);
// unsupported(cn.outerMethod);
// unsupported(cn.outerMethodDesc);
unsupported(cn.node.visibleAnnotations);
unsupported(cn.node.invisibleAnnotations);
unsupported(cn.node.visibleTypeAnnotations);
unsupported(cn.node.invisibleTypeAnnotations);
unsupported(cn.node.attrs);
unsupported(cn.node.innerClasses);
for (FieldNode f : cn.getFields()) {
unsupported(cn.node.signature);
{
Type type = Type.getType(f.node.desc);
String newType = resolveType(type, remapping);
if (newType != null) {
f.node.desc = newType;
}
}
unsupported(f.node.visibleAnnotations);
unsupported(f.node.invisibleAnnotations);
unsupported(f.node.visibleTypeAnnotations);
unsupported(f.node.invisibleTypeAnnotations);
unsupported(f.node.attrs);
}
for (MethodNode m : cn.getMethods()) {
m.node.desc = resolveMethod(m.node.desc, remapping);
unsupported(m.node.signature);
{
List<String> exceptions = new ArrayList<>();
for (int i = 0; i < m.node.exceptions.size(); i++) {
String s = m.node.exceptions.get(i);
exceptions.add(remapping.getOrDefault(s, s));
}
m.node.exceptions = exceptions;
}
unsupported(m.node.parameters);
unsupported(m.node.visibleAnnotations);
unsupported(m.node.invisibleAnnotations);
unsupported(m.node.visibleTypeAnnotations);
unsupported(m.node.invisibleTypeAnnotations);
unsupported(m.node.attrs);
unsupported(m.node.annotationDefault);
unsupported(m.node.visibleParameterAnnotations);
unsupported(m.node.invisibleParameterAnnotations);
for (TryCatchBlockNode tcbn : m.node.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.node.localVariables != null) {
m.node.localVariables.clear();
for (LocalVariableNode lvn : m.node.localVariables) {
String newDesc = resolveType(Type.getType(lvn.desc), remapping);
if (newDesc != null) {
lvn.desc = newDesc;
}
unsupported(lvn.signature);
}
}
unsupported(m.node.visibleLocalVariableAnnotations);
unsupported(m.node.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.INVOKE) {
InvocationExpr invoke = (InvocationExpr) e;
if (invoke.isDynamic())
throw new UnsupportedOperationException();
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 PassResult.with(pcxt, this).finished().make();
}
use of org.mapleir.ir.cfg.ControlFlowGraph in project maple-ir by LLVM-but-worse.
the class ConstantParameterPass method accept.
@Override
public PassResult accept(PassContext pcxt) {
AnalysisContext cxt = pcxt.getAnalysis();
Map<MethodNode, Set<MethodNode>> chainMap = new HashMap<>();
for (MethodNode mn : cxt.getIRCache().getActiveMethods()) {
makeUpChain(cxt, mn, chainMap);
}
InvocationResolver resolver = cxt.getInvocationResolver();
Map<MethodNode, List<Set<Object>>> rawConstantParameters = new HashMap<>();
Map<MethodNode, boolean[]> chainedNonConstant = new HashMap<>();
Map<MethodNode, boolean[]> specificNonConstant = new HashMap<>();
IPAnalysisVisitor vis = new IPAnalysisVisitor() {
@Override
public void postVisitMethod(IPAnalysis analysis, MethodNode m) {
int pCount = Type.getArgumentTypes(m.getDesc()).length;
/* init map entries */
if (!chainedNonConstant.containsKey(m)) {
for (MethodNode assoc : chainMap.get(m)) {
boolean[] arr = new boolean[pCount];
chainedNonConstant.put(assoc, arr);
}
for (MethodNode assoc : chainMap.get(m)) {
boolean[] arr = new boolean[pCount];
specificNonConstant.put(assoc, arr);
}
}
if (Modifier.isStatic(m.node.access)) {
if (!rawConstantParameters.containsKey(m)) {
List<Set<Object>> l = new ArrayList<>(pCount);
rawConstantParameters.put(m, l);
for (int i = 0; i < pCount; i++) {
l.add(new HashSet<>());
}
}
} else {
// TODO: cache
for (MethodNode site : resolver.resolveVirtualCalls(m, true)) {
if (!rawConstantParameters.containsKey(site)) {
List<Set<Object>> l = new ArrayList<>(pCount);
rawConstantParameters.put(site, l);
for (int i = 0; i < pCount; i++) {
l.add(new HashSet<>());
}
}
}
}
}
@Override
public void postProcessedInvocation(IPAnalysis analysis, MethodNode caller, MethodNode callee, Invocation call) {
Expr[] params = call.getParameterExprs();
for (int i = 0; i < params.length; i++) {
Expr e = params[i];
if (e.getOpcode() == Opcode.CONST_LOAD) {
if (Modifier.isStatic(callee.node.access)) {
rawConstantParameters.get(callee).get(i).add(((ConstantExpr) e).getConstant());
} else {
/* only chain callsites *can* have this input */
for (MethodNode site : resolver.resolveVirtualCalls(callee, true)) {
rawConstantParameters.get(site).get(i).add(((ConstantExpr) e).getConstant());
}
}
} else {
/* whole branch tainted */
for (MethodNode associated : chainMap.get(callee)) {
chainedNonConstant.get(associated)[i] = true;
}
/* callsites tainted */
if (Modifier.isStatic(callee.node.access)) {
specificNonConstant.get(callee)[i] = true;
} else {
/* only chain callsites *can* have this input */
for (MethodNode site : resolver.resolveVirtualCalls(callee, true)) {
specificNonConstant.get(site)[i] = true;
}
}
}
}
}
};
IPAnalysis constAnalysis = IPAnalysis.create(cxt, vis);
// ApplicationClassSource app = cxt.getApplication();
// ClassTree structures = app.getStructures();
/* remove all calls to library methods since we can't
* handle them. */
/*Iterator<Entry<MethodNode, List<Set<Object>>>> it = rawConstantParameters.entrySet().iterator();
while(it.hasNext()) {
Entry<MethodNode, List<Set<Object>>> en = it.next();
MethodNode m = en.getKey();
if(app.isLibraryClass(m.owner.getName())) {
it.remove();
continue;
}
// TODO: MUST BE CONVERTED TO ACCOUNT FOR DIRECT SUPERS, NOT ALL
superFor: for(ClassNode cn : structures.getAllParents(m.owner)) {
if(app.isLibraryClass(cn.getName())) {
for(MethodNode m1 : cn.methods) {
if(resolver.areMethodsCongruent(m1, m, Modifier.isStatic(m.node.access))) {
it.remove();
break superFor;
}
}
}
}
}*/
/* aggregate constant parameters indices with their chained
* methods such that the map contains only constant parameter
* indices that we can actually remove while keeping a valid chain.
*
* We do this as we can have methods from different branches that
* are cousin-related but have different constant parameter values.
* In these cases we can still inline the constants (different constants)
* and change the descriptions, keeping the chain. */
Map<MethodNode, boolean[]> filteredConstantParameters = new HashMap<>();
for (Entry<MethodNode, List<Set<Object>>> en : rawConstantParameters.entrySet()) {
MethodNode m = en.getKey();
List<Set<Object>> objParams = en.getValue();
boolean[] tainted = chainedNonConstant.get(m);
if (filteredConstantParameters.containsKey(m)) {
/* note: if this method is contained in the
* map all of it's cousin-reachable methods
* must also be and furthermore the dead map
* for the entire chain is the same array.
*
* we need to now merge the current dead map
* with the one specifically for this method.*/
boolean[] thisDeadMap = makeDeadMap(objParams, tainted);
boolean[] prevDeadMap = filteredConstantParameters.get(m);
if (thisDeadMap.length != prevDeadMap.length) {
throw new IllegalStateException(String.format("m: %s, chain:%s, %d:%d", m, chainMap.get(m), thisDeadMap.length, prevDeadMap.length));
}
/* each dead map contains true values for an
* index if that index is a constant parameter. */
for (int i = 0; i < prevDeadMap.length; i++) {
prevDeadMap[i] &= thisDeadMap[i];
}
} else {
boolean[] deadParams = makeDeadMap(objParams, tainted);
for (MethodNode chm : chainMap.get(m)) {
filteredConstantParameters.put(chm, deadParams);
}
}
ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
// boolean b = false;
boolean[] specificTaint = specificNonConstant.get(m);
for (int i = 0; i < objParams.size(); i++) {
Set<Object> set = objParams.get(i);
if (!specificTaint[i] && set.size() == 1) {
inlineConstant(cfg, constAnalysis.getLocalIndex(m, i), set.iterator().next());
}
}
}
Map<MethodNode, String> remap = new HashMap<>();
Set<MethodNode> toRemove = new HashSet<>();
Set<Set<MethodNode>> mustRename = new HashSet<>();
for (Entry<MethodNode, boolean[]> en : filteredConstantParameters.entrySet()) {
MethodNode m = en.getKey();
if (!remap.containsKey(m) && !toRemove.contains(m)) {
boolean[] deadMap = en.getValue();
boolean notSame = false;
for (boolean b : deadMap) {
notSame |= b;
}
if (!notSame) {
/* eliminate all branches (same congruence class) */
for (MethodNode n : chainMap.get(m)) {
toRemove.add(n);
}
continue;
}
Type[] params = Type.getArgumentTypes(m.getDesc());
Type ret = Type.getReturnType(m.getDesc());
String desc = buildDesc(params, ret, deadMap);
Set<MethodNode> conflicts = new HashSet<>();
for (MethodNode chm : chainMap.get(m)) {
remap.put(chm, desc);
if (Modifier.isStatic(m.node.access)) {
MethodNode mm = resolver.resolveStaticCall(chm.owner.getName(), chm.getName(), desc);
if (mm != null) {
conflicts.add(mm);
}
} else {
if (chm.getName().equals("<init>")) {
conflicts.addAll(resolver.resolveVirtualCalls(chm.owner.getName(), "<init>", desc, false));
} else {
conflicts.addAll(resolver.getHierarchyMethodChain(m.owner, m.getName(), desc, true));
}
}
}
if (conflicts.size() > 0) {
Set<MethodNode> chain = chainMap.get(m);
/* rename the smallest conflict set */
// if(chain.size() < conflicts.size()) {
//
// } else {
// mustRename.add(conflicts);
// }
mustRename.add(chain);
}
}
}
remap.keySet().removeAll(toRemove);
int k = RenamingUtil.numeric("aaaaa");
Map<MethodNode, String> methodNameRemap = new HashMap<>();
for (Set<MethodNode> set : mustRename) {
// MethodNode first = set.iterator().next();
// String newName = "rename_" + first.getName();
String newName = RenamingUtil.createName(k++);
System.out.printf(" renaming %s to %s%n", set, newName);
System.out.println(" recom " + computeChain(cxt, set.iterator().next()));
Set<MethodNode> s2 = new HashSet<>();
for (MethodNode m : set) {
s2.addAll(chainMap.get(m));
}
if (!s2.equals(set)) {
System.err.println(set);
System.err.println(s2);
throw new IllegalStateException();
}
for (MethodNode m : set) {
methodNameRemap.put(m, newName);
}
}
if (mustRename.size() > 0) {
MethodRenamerPass.rename(cxt, methodNameRemap, false);
}
Set<MethodNode> visitedMethods = new HashSet<>();
Set<Expr> visitedExprs = new HashSet<>();
int killedTotal = 0;
for (; ; ) {
int killedBeforePass = killedTotal;
for (Entry<MethodNode, String> en : remap.entrySet()) {
MethodNode key = en.getKey();
String newDesc = en.getValue();
if (!visitedMethods.contains(key)) {
Set<MethodNode> chain = chainMap.get(key);
/*for(MethodNode n : chain) {
if(visitedMethods.contains(n)) {
throw new IllegalStateException(String.format("Invalid transistivityr: %s in %s but not %s", n, chain, key));
}
}*/
boolean[] dead = filteredConstantParameters.get(key);
for (MethodNode n : chain) {
n.node.desc = newDesc;
/* boolean[] dead = filteredConstantParameters.get(n);
boolean[] deadM = filteredConstantParameters.get(key);
if(!Arrays.equals(dead, deadM)) {
throw new IllegalStateException(String.format("neq: %s vs %s for %s and %s", Arrays.toString(dead), Arrays.toString(deadM), n, key));
} */
demoteDeadParamters(constAnalysis, cxt.getIRCache().getFor(n), n, dead);
for (Invocation call : constAnalysis.getCallsTo(n)) {
/* since the callgrapher finds all
* the methods in a hierarchy and considers
* it as a single invocation, a certain
* invocation may be considered multiple times. */
if (visitedExprs.contains(call)) {
continue;
}
/* the invocationexpr method desc is changed implicitly
* when the new expression is created in patchCall() */
visitedExprs.add(call);
patchCall(newDesc, call, dead);
killedTotal += chain.size();
}
}
visitedMethods.addAll(chain);
}
}
if (killedBeforePass == killedTotal) {
break;
}
}
System.out.printf(" removed %d constant parameters.%n", killedTotal);
return PassResult.with(pcxt, this).finished(killedTotal).make();
}
Aggregations