use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class EnumVisitor method convertToEnum.
private boolean convertToEnum(ClassNode cls) {
if (!cls.isEnum()) {
return false;
}
MethodNode classInitMth = cls.getClassInitMth();
if (classInitMth == null) {
cls.addWarnComment("Enum class init method not found");
return false;
}
if (classInitMth.getBasicBlocks().isEmpty()) {
return false;
}
ArgType clsType = cls.getClassInfo().getType();
// search "$VALUES" field (holds all enum values)
List<FieldNode> valuesCandidates = cls.getFields().stream().filter(f -> f.getAccessFlags().isStatic()).filter(f -> f.getType().isArray()).filter(f -> Objects.equals(f.getType().getArrayRootElement(), clsType)).collect(Collectors.toList());
if (valuesCandidates.isEmpty()) {
return false;
}
if (valuesCandidates.size() > 1) {
valuesCandidates.removeIf(f -> !f.getAccessFlags().isSynthetic());
}
if (valuesCandidates.size() > 1) {
Optional<FieldNode> valuesOpt = valuesCandidates.stream().filter(f -> f.getName().equals("$VALUES")).findAny();
if (valuesOpt.isPresent()) {
valuesCandidates.clear();
valuesCandidates.add(valuesOpt.get());
}
}
if (valuesCandidates.size() != 1) {
cls.addWarnComment("Found several \"values\" enum fields: " + valuesCandidates);
return false;
}
FieldNode valuesField = valuesCandidates.get(0);
List<InsnNode> toRemove = new ArrayList<>();
// search "$VALUES" array init and collect enum fields
BlockInsnPair valuesInitPair = getValuesInitInsn(classInitMth, valuesField);
if (valuesInitPair == null) {
return false;
}
BlockNode staticBlock = valuesInitPair.getBlock();
InsnNode valuesInitInsn = valuesInitPair.getInsn();
List<EnumField> enumFields = null;
InsnArg arrArg = valuesInitInsn.getArg(0);
if (arrArg.isInsnWrap()) {
InsnNode wrappedInsn = ((InsnWrapArg) arrArg).getWrapInsn();
enumFields = extractEnumFieldsFromInsn(cls, staticBlock, wrappedInsn, toRemove);
}
if (enumFields == null) {
return false;
}
toRemove.add(valuesInitInsn);
// all checks complete, perform transform
EnumClassAttr attr = new EnumClassAttr(enumFields);
attr.setStaticMethod(classInitMth);
cls.addAttr(attr);
for (EnumField enumField : attr.getFields()) {
ConstructorInsn co = enumField.getConstrInsn();
FieldNode fieldNode = enumField.getField();
// use string arg from the constructor as enum field name
String name = getConstString(cls.root(), co.getArg(0));
if (name != null && !fieldNode.getAlias().equals(name) && NameMapper.isValidAndPrintable(name) && cls.root().getArgs().isRenameValid()) {
fieldNode.getFieldInfo().setAlias(name);
}
fieldNode.add(AFlag.DONT_GENERATE);
processConstructorInsn(cls, enumField, classInitMth, staticBlock, toRemove);
}
valuesField.add(AFlag.DONT_GENERATE);
InsnRemover.removeAllAndUnbind(classInitMth, staticBlock, toRemove);
if (classInitMth.countInsns() == 0) {
classInitMth.add(AFlag.DONT_GENERATE);
} else if (!toRemove.isEmpty()) {
CodeShrinkVisitor.shrinkMethod(classInitMth);
}
removeEnumMethods(cls, clsType, valuesField);
return true;
}
use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class PrepareForCodeGen method checkEncodedValue.
@SuppressWarnings("unchecked")
private void checkEncodedValue(MethodNode mth, EncodedValue encodedValue) {
switch(encodedValue.getType()) {
case ENCODED_FIELD:
Object fieldData = encodedValue.getValue();
FieldInfo fieldInfo;
if (fieldData instanceof IFieldRef) {
fieldInfo = FieldInfo.fromRef(mth.root(), (IFieldRef) fieldData);
} else {
fieldInfo = (FieldInfo) fieldData;
}
FieldNode fieldNode = mth.root().resolveField(fieldInfo);
if (fieldNode != null) {
fieldNode.addUseIn(mth);
}
break;
case ENCODED_ANNOTATION:
IAnnotation annotation = (IAnnotation) encodedValue.getValue();
annotation.getValues().forEach((k, v) -> checkEncodedValue(mth, v));
break;
case ENCODED_ARRAY:
List<EncodedValue> valueList = (List<EncodedValue>) encodedValue.getValue();
valueList.forEach(v -> checkEncodedValue(mth, v));
break;
}
}
use of jadx.core.dex.nodes.FieldNode 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.nodes.FieldNode in project jadx by skylot.
the class RenameVisitor method processRootPackages.
private static void processRootPackages(Deobfuscator deobfuscator, RootNode root, List<ClassNode> classes) {
Set<String> rootPkgs = collectRootPkgs(classes);
root.getCacheStorage().setRootPkgs(rootPkgs);
if (root.getArgs().isRenameValid()) {
// rename field if collide with any root package
for (ClassNode cls : classes) {
for (FieldNode field : cls.getFields()) {
if (rootPkgs.contains(field.getAlias())) {
deobfuscator.forceRenameField(field);
field.addAttr(new RenameReasonAttr("collision with root package name"));
}
}
}
}
}
use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class DebugController method updateAllFields.
private void updateAllFields(FrameNode frame) {
List<FieldNode> fldNodes = Collections.emptyList();
String clsSig = frame.getClsSig();
if (clsSig != null) {
ClassNode clsNode = DbgUtils.getClassNodeBySig(clsSig, debuggerPanel.getMainWindow());
if (clsNode != null) {
fldNodes = clsNode.getFields();
}
}
try {
long thisID = debugger.getThisID(frame.getThreadID(), frame.getFrame().getID());
List<RuntimeField> flds = debugger.getAllFieldsSync(frame.getClsID());
List<FieldTreeNode> nodes = new ArrayList<>(flds.size());
for (RuntimeField fld : flds) {
FieldTreeNode fldNode = new FieldTreeNode(fld, thisID);
fldNodes.stream().filter(f -> f.getName().equals(fldNode.getName())).findFirst().ifPresent(smaliFld -> fldNode.setAlias(smaliFld.getAlias()));
nodes.add(fldNode);
}
debuggerPanel.updateThisFieldNodes(nodes);
frame.setFieldNodes(nodes);
if (thisID > 0 && nodes.size() > 0) {
lazyQueue.execute(() -> updateAllFieldValues(thisID, frame));
}
} catch (SmaliDebuggerException e) {
logErr(e);
}
}
Aggregations