use of jadx.core.dex.info.FieldInfo in project jadx by skylot.
the class ShadowFieldVisitor method searchShadowedFields.
private static Map<FieldInfo, FieldFixType> searchShadowedFields(ClassNode thisCls) {
List<FieldNode> allFields = collectAllInstanceFields(thisCls);
if (allFields.isEmpty()) {
return Collections.emptyMap();
}
Map<String, List<FieldNode>> mapByName = groupByName(allFields);
mapByName.entrySet().removeIf(entry -> entry.getValue().size() == 1);
if (mapByName.isEmpty()) {
return Collections.emptyMap();
}
Map<FieldInfo, FieldFixType> fixMap = new HashMap<>();
for (List<FieldNode> fields : mapByName.values()) {
boolean fromThisCls = fields.get(0).getParentClass() == thisCls;
if (fromThisCls && fields.size() == 2) {
// only one super class contains same field => can use super
FieldNode otherField = fields.get(1);
if (otherField.getParentClass() != thisCls) {
fixMap.put(otherField.getFieldInfo(), FieldFixType.SUPER);
}
} else {
// several super classes contains same field => can't use super, need cast to exact class
for (FieldNode field : fields) {
if (field.getParentClass() != thisCls) {
fixMap.put(field.getFieldInfo(), FieldFixType.CAST);
}
}
}
}
return fixMap;
}
use of jadx.core.dex.info.FieldInfo in project jadx by skylot.
the class SimplifyVisitor method convertFieldArith.
/**
* Convert field arith operation to arith instruction
* (IPUT (ARITH (IGET, lit)) -> ARITH ((IGET)) <op>= lit))
*/
private static ArithNode convertFieldArith(MethodNode mth, InsnNode insn) {
InsnArg arg = insn.getArg(0);
if (!arg.isInsnWrap()) {
return null;
}
InsnNode wrap = ((InsnWrapArg) arg).getWrapInsn();
InsnType wrapType = wrap.getType();
if (wrapType != InsnType.ARITH && wrapType != InsnType.STR_CONCAT || !wrap.getArg(0).isInsnWrap()) {
return null;
}
InsnArg getWrap = wrap.getArg(0);
InsnNode get = ((InsnWrapArg) getWrap).getWrapInsn();
InsnType getType = get.getType();
if (getType != InsnType.IGET && getType != InsnType.SGET) {
return null;
}
FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex();
FieldInfo innerField = (FieldInfo) ((IndexInsnNode) get).getIndex();
if (!field.equals(innerField)) {
return null;
}
try {
if (getType == InsnType.IGET && insn.getType() == InsnType.IPUT) {
InsnArg reg = get.getArg(0);
InsnArg putReg = insn.getArg(1);
if (!reg.equals(putReg)) {
return null;
}
}
InsnArg fArg = getWrap.duplicate();
InsnRemover.unbindInsn(mth, get);
if (insn.getType() == InsnType.IPUT) {
InsnRemover.unbindArgUsage(mth, insn.getArg(1));
}
if (wrapType == InsnType.ARITH) {
ArithNode ar = (ArithNode) wrap;
return ArithNode.oneArgOp(ar.getOp(), fArg, ar.getArg(1));
}
int argsCount = wrap.getArgsCount();
InsnNode concat = new InsnNode(InsnType.STR_CONCAT, argsCount - 1);
for (int i = 1; i < argsCount; i++) {
concat.addArg(wrap.getArg(i));
}
return ArithNode.oneArgOp(ArithOp.ADD, fArg, InsnArg.wrapArg(concat));
} catch (Exception e) {
LOG.debug("Can't convert field arith insn: {}, mth: {}", insn, mth, e);
}
return null;
}
use of jadx.core.dex.info.FieldInfo in project jadx by skylot.
the class RenameVisitor method checkFields.
private static void checkFields(Deobfuscator deobfuscator, ClassNode cls, JadxArgs args) {
Set<String> names = new HashSet<>();
for (FieldNode field : cls.getFields()) {
FieldInfo fieldInfo = field.getFieldInfo();
String fieldName = fieldInfo.getAlias();
boolean notUnique = !names.add(fieldName);
boolean notValid = args.isRenameValid() && !NameMapper.isValidIdentifier(fieldName);
boolean notPrintable = args.isRenamePrintable() && !NameMapper.isAllCharsPrintable(fieldName);
if (notUnique || notValid || notPrintable) {
deobfuscator.forceRenameField(field);
field.addAttr(new RenameReasonAttr(field, notValid, notPrintable));
if (notUnique) {
field.addAttr(new RenameReasonAttr(field).append("collision with other field name"));
}
}
}
}
use of jadx.core.dex.info.FieldInfo in project jadx by skylot.
the class ExtractFieldInit method insnUseExcludedField.
private static boolean insnUseExcludedField(FieldInitInfo initInfo, Set<FieldInfo> excludedFields) {
if (excludedFields.isEmpty()) {
return false;
}
IndexInsnNode insn = initInfo.putInsn;
boolean staticField = insn.getType() == InsnType.SPUT;
InsnType useType = staticField ? InsnType.SGET : InsnType.IGET;
// exclude if init code use any excluded field
Boolean exclude = insn.visitInsns(innerInsn -> {
if (innerInsn.getType() == useType) {
FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) innerInsn).getIndex();
if (excludedFields.contains(fieldInfo)) {
return true;
}
}
return null;
});
return Objects.equals(exclude, Boolean.TRUE);
}
use of jadx.core.dex.info.FieldInfo in project jadx by skylot.
the class ExtractFieldInit method processFieldsDependencies.
private static List<FieldNode> processFieldsDependencies(ClassNode cls, List<FieldInitInfo> inits) {
List<FieldNode> orderedFields = Utils.collectionMap(inits, v -> v.fieldNode);
// collect dependant fields
Map<FieldNode, List<FieldNode>> deps = new HashMap<>(inits.size());
for (FieldInitInfo initInfo : inits) {
IndexInsnNode insn = initInfo.putInsn;
boolean staticField = insn.getType() == InsnType.SPUT;
InsnType useType = staticField ? InsnType.SGET : InsnType.IGET;
insn.visitInsns(subInsn -> {
if (subInsn.getType() == useType) {
FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) subInsn).getIndex();
if (fieldInfo.getDeclClass().equals(cls.getClassInfo())) {
FieldNode depField = cls.searchField(fieldInfo);
if (depField != null) {
deps.computeIfAbsent(initInfo.fieldNode, k -> new ArrayList<>()).add(depField);
}
}
}
});
}
if (deps.isEmpty()) {
return orderedFields;
}
// build new list with deps fields before usage field
List<FieldNode> result = new ArrayList<>();
for (FieldNode field : orderedFields) {
int idx = result.indexOf(field);
List<FieldNode> fieldDeps = deps.get(field);
if (fieldDeps == null) {
if (idx == -1) {
result.add(field);
}
continue;
}
if (idx == -1) {
for (FieldNode depField : fieldDeps) {
if (!result.contains(depField)) {
result.add(depField);
}
}
result.add(field);
continue;
}
for (FieldNode depField : fieldDeps) {
int depIdx = result.indexOf(depField);
if (depIdx == -1) {
result.add(idx, depField);
} else if (depIdx > idx) {
result.remove(depIdx);
result.add(idx, depField);
}
}
}
return result;
}
Aggregations