ClassNode.java 11.1 KB
Newer Older
S
Skylot 已提交
1 2 3 4 5
package jadx.core.dex.nodes;

import jadx.core.Consts;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AttributeType;
6
import jadx.core.dex.attributes.LineAttrNode;
S
Skylot 已提交
7 8 9 10 11 12 13 14
import jadx.core.dex.attributes.SourceFileAttr;
import jadx.core.dex.attributes.annotations.Annotation;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.AccessInfo.AFType;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType;
1
13.beta2 已提交
15
import jadx.core.dex.instructions.args.LiteralArg;
16
import jadx.core.dex.instructions.args.PrimitiveType;
S
Skylot 已提交
17 18
import jadx.core.dex.nodes.parser.AnnotationsParser;
import jadx.core.dex.nodes.parser.FieldValueAttr;
S
Skylot 已提交
19
import jadx.core.dex.nodes.parser.SignatureParser;
S
Skylot 已提交
20 21
import jadx.core.dex.nodes.parser.StaticValuesParser;
import jadx.core.utils.exceptions.DecodeException;
S
Skylot 已提交
22
import jadx.core.utils.exceptions.JadxRuntimeException;
S
Skylot 已提交
23 24 25

import java.util.ArrayList;
import java.util.Collections;
S
Skylot 已提交
26
import java.util.LinkedHashMap;
S
Skylot 已提交
27 28 29 30 31 32 33 34 35 36 37
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.android.dx.io.ClassData;
import com.android.dx.io.ClassData.Field;
import com.android.dx.io.ClassData.Method;
import com.android.dx.io.ClassDef;

38
public class ClassNode extends LineAttrNode implements ILoadable {
S
Skylot 已提交
39
	private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class);
S
Skylot 已提交
40 41 42

	private final DexNode dex;
	private final ClassInfo clsInfo;
S
Skylot 已提交
43
	private final AccessInfo accessFlags;
44 45 46
	private ClassInfo superClass;
	private List<ClassInfo> interfaces;
	private Map<ArgType, List<ArgType>> genericMap;
S
Skylot 已提交
47

S
Skylot 已提交
48 49 50
	private final List<MethodNode> methods;
	private final List<FieldNode> fields;
	private Map<Object, FieldNode> constFields = Collections.emptyMap();
S
Skylot 已提交
51 52
	private List<ClassNode> innerClasses = Collections.emptyList();

53
	// store decompiled code
S
Skylot 已提交
54
	private CodeWriter code;
55 56
	// store parent for inner classes or 'this' otherwise
	private ClassNode parentClass;
S
Skylot 已提交
57

S
Skylot 已提交
58 59 60 61
	public ClassNode(DexNode dex, ClassDef cls) throws DecodeException {
		this.dex = dex;
		this.clsInfo = ClassInfo.fromDex(dex, cls.getTypeIndex());
		try {
S
Skylot 已提交
62 63 64 65 66
			if (cls.getSupertypeIndex() == DexNode.NO_INDEX) {
				this.superClass = null;
			} else {
				this.superClass = ClassInfo.fromDex(dex, cls.getSupertypeIndex());
			}
S
Skylot 已提交
67 68 69 70
			this.interfaces = new ArrayList<ClassInfo>(cls.getInterfaces().length);
			for (short interfaceIdx : cls.getInterfaces()) {
				this.interfaces.add(ClassInfo.fromDex(dex, interfaceIdx));
			}
S
Skylot 已提交
71
			if (cls.getClassDataOffset() != 0) {
S
Skylot 已提交
72
				ClassData clsData = dex.readClassData(cls);
S
Skylot 已提交
73 74
				int mthsCount = clsData.getDirectMethods().length + clsData.getVirtualMethods().length;
				int fieldsCount = clsData.getStaticFields().length + clsData.getInstanceFields().length;
S
Skylot 已提交
75

S
Skylot 已提交
76 77
				methods = new ArrayList<MethodNode>(mthsCount);
				fields = new ArrayList<FieldNode>(fieldsCount);
S
Skylot 已提交
78

S
Skylot 已提交
79 80 81 82
				for (Method mth : clsData.getDirectMethods()) {
					methods.add(new MethodNode(this, mth));
				}
				for (Method mth : clsData.getVirtualMethods()) {
S
Skylot 已提交
83
					methods.add(new MethodNode(this, mth));
S
Skylot 已提交
84
				}
S
Skylot 已提交
85

S
Skylot 已提交
86
				for (Field f : clsData.getStaticFields()) {
S
Skylot 已提交
87
					fields.add(new FieldNode(this, f));
S
Skylot 已提交
88
				}
S
Skylot 已提交
89
				loadStaticValues(cls, fields);
S
Skylot 已提交
90
				for (Field f : clsData.getInstanceFields()) {
S
Skylot 已提交
91
					fields.add(new FieldNode(this, f));
S
Skylot 已提交
92 93 94 95
				}
			} else {
				methods = Collections.emptyList();
				fields = Collections.emptyList();
S
Skylot 已提交
96 97 98 99
			}

			loadAnnotations(cls);

100 101
			parseClassSignature();
			setFieldsTypesFromSignature();
S
Skylot 已提交
102

103
			int sfIdx = cls.getSourceFileIndex();
104
			if (sfIdx != DexNode.NO_INDEX) {
105
				String fileName = dex.getString(sfIdx);
106
				if (!this.getFullName().contains(fileName.replace(".java", ""))) {
107
					this.getAttributes().add(new SourceFileAttr(fileName));
S
Skylot 已提交
108
					LOG.debug("Class '{}' compiled from '{}'", this, fileName);
109 110 111
				}
			}

S
Skylot 已提交
112
			// restore original access flags from dalvik annotation if present
113
			int accFlagsValue;
114
			Annotation a = getAttributes().getAnnotation(Consts.DALVIK_INNER_CLASS);
S
Skylot 已提交
115
			if (a != null) {
116
				accFlagsValue = (Integer) a.getValues().get("accessFlags");
S
Skylot 已提交
117
			} else {
118
				accFlagsValue = cls.getAccessFlags();
S
Skylot 已提交
119
			}
S
Skylot 已提交
120 121 122 123 124 125 126 127 128 129 130
			this.accessFlags = new AccessInfo(accFlagsValue, AFType.CLASS);

		} catch (Exception e) {
			throw new DecodeException("Error decode class: " + getFullName(), e);
		}
	}

	private void loadAnnotations(ClassDef cls) {
		int offset = cls.getAnnotationsOffset();
		if (offset != 0) {
			try {
S
Skylot 已提交
131
				new AnnotationsParser(this).parse(offset);
S
Skylot 已提交
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
			} catch (DecodeException e) {
				LOG.error("Error parsing annotations in " + this, e);
			}
		}
	}

	private void loadStaticValues(ClassDef cls, List<FieldNode> staticFields) throws DecodeException {
		for (FieldNode f : staticFields) {
			if (f.getAccessFlags().isFinal()) {
				FieldValueAttr nullValue = new FieldValueAttr(null);
				f.getAttributes().add(nullValue);
			}
		}

		int offset = cls.getStaticValuesOffset();
		if (offset != 0) {
			StaticValuesParser parser = new StaticValuesParser(dex, dex.openSection(offset));
S
Skylot 已提交
149 150
			int count = parser.processFields(staticFields);
			constFields = new LinkedHashMap<Object, FieldNode>(count);
S
Skylot 已提交
151
			for (FieldNode f : staticFields) {
152 153
				AccessInfo accFlags = f.getAccessFlags();
				if (accFlags.isStatic() && accFlags.isFinal()) {
S
Skylot 已提交
154 155
					FieldValueAttr fv = (FieldValueAttr) f.getAttributes().get(AttributeType.FIELD_VALUE);
					if (fv != null && fv.getValue() != null) {
156
						if (accFlags.isPublic()) {
157
							dex.getConstFields().put(fv.getValue(), f);
158 159
						}
						constFields.put(fv.getValue(), f);
S
Skylot 已提交
160 161 162 163 164 165
					}
				}
			}
		}
	}

166
	private void parseClassSignature() {
S
Skylot 已提交
167 168
		SignatureParser sp = SignatureParser.fromNode(this);
		if (sp == null) {
169
			return;
S
Skylot 已提交
170
		}
S
Skylot 已提交
171 172 173 174 175 176 177 178 179 180 181 182
		try {
			// parse class generic map
			genericMap = sp.consumeGenericMap();
			// parse super class signature
			superClass = ClassInfo.fromType(sp.consumeType());
			// parse interfaces signatures
			for (int i = 0; i < interfaces.size(); i++) {
				ArgType type = sp.consumeType();
				if (type != null) {
					interfaces.set(i, ClassInfo.fromType(type));
				} else {
					break;
183 184
				}
			}
S
Skylot 已提交
185 186
		} catch (JadxRuntimeException e) {
			LOG.error("Class signature parse error: " + this, e);
187 188 189 190 191
		}
	}

	private void setFieldsTypesFromSignature() {
		for (FieldNode field : fields) {
S
Skylot 已提交
192 193 194 195 196 197 198 199 200
			SignatureParser sp = SignatureParser.fromNode(field);
			if (sp != null) {
				try {
					ArgType gType = sp.consumeType();
					if (gType != null) {
						field.setType(gType);
					}
				} catch (JadxRuntimeException e) {
					LOG.error("Field signature parse error: " + field, e);
S
Skylot 已提交
201 202
				}
			}
203 204 205
		}
	}

S
Skylot 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	@Override
	public void load() throws DecodeException {
		for (MethodNode mth : getMethods()) {
			mth.load();
		}
		for (ClassNode innerCls : getInnerClasses()) {
			innerCls.load();
		}
	}

	@Override
	public void unload() {
		for (MethodNode mth : getMethods()) {
			mth.unload();
		}
		for (ClassNode innerCls : getInnerClasses()) {
			innerCls.unload();
		}
	}

	public ClassInfo getSuperClass() {
		return superClass;
	}

	public List<ClassInfo> getInterfaces() {
		return interfaces;
	}

234 235 236 237
	public Map<ArgType, List<ArgType>> getGenericMap() {
		return genericMap;
	}

S
Skylot 已提交
238 239 240 241 242 243 244 245
	public List<MethodNode> getMethods() {
		return methods;
	}

	public List<FieldNode> getFields() {
		return fields;
	}

246 247 248 249 250
	public FieldNode getConstField(Object obj) {
		return getConstField(obj, true);
	}

	public FieldNode getConstField(Object obj, boolean searchGlobal) {
251 252 253
		ClassNode cn = this;
		FieldNode field;
		do {
254
			field = cn.constFields.get(obj);
255 256
		}
		while (field == null
257 258
				&& (cn.clsInfo.getParentClass() != null)
				&& (cn = dex.resolveClass(cn.clsInfo.getParentClass())) != null);
259

260 261 262
		if (field == null && searchGlobal) {
			field = dex.getConstFields().get(obj);
		}
263 264 265
		return field;
	}

1
13.beta2 已提交
266
	public FieldNode getConstFieldByLiteralArg(LiteralArg arg) {
267 268 269 270
		PrimitiveType type = arg.getType().getPrimitiveType();
		if (type == null) {
			return null;
		}
1
13.beta2 已提交
271
		long literal = arg.getLiteral();
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
		switch (type) {
			case BOOLEAN:
				return getConstField(literal == 1, false);
			case CHAR:
				return getConstField((char) literal, Math.abs(literal) > 1);
			case BYTE:
				return getConstField((byte) literal, Math.abs(literal) > 1);
			case SHORT:
				return getConstField((short) literal, Math.abs(literal) > 1);
			case INT:
				return getConstField((int) literal, Math.abs(literal) > 1);
			case LONG:
				return getConstField(literal, Math.abs(literal) > 1);
			case FLOAT:
				return getConstField(Float.intBitsToFloat((int) literal), true);
			case DOUBLE:
				return getConstField(Double.longBitsToDouble(literal), true);
1
13.beta2 已提交
289 290 291 292
		}
		return null;
	}

S
Skylot 已提交
293 294 295
	public FieldNode searchFieldById(int id) {
		String name = FieldInfo.getNameById(dex, id);
		for (FieldNode f : fields) {
S
Skylot 已提交
296
			if (f.getName().equals(name)) {
S
Skylot 已提交
297
				return f;
S
Skylot 已提交
298
			}
S
Skylot 已提交
299 300 301 302 303
		}
		return null;
	}

	public FieldNode searchField(FieldInfo field) {
S
Skylot 已提交
304 305 306 307
		return searchFieldByName(field.getName());
	}

	public FieldNode searchFieldByName(String name) {
S
Skylot 已提交
308
		for (FieldNode f : fields) {
S
Skylot 已提交
309
			if (f.getName().equals(name)) {
S
Skylot 已提交
310
				return f;
S
Skylot 已提交
311
			}
S
Skylot 已提交
312 313 314 315
		}
		return null;
	}

S
Skylot 已提交
316 317
	public MethodNode searchMethod(MethodInfo mth) {
		for (MethodNode m : methods) {
S
Skylot 已提交
318
			if (m.getMethodInfo().equals(mth)) {
S
Skylot 已提交
319
				return m;
S
Skylot 已提交
320
			}
S
Skylot 已提交
321 322 323 324 325
		}
		return null;
	}

	public MethodNode searchMethodByName(String shortId) {
S
Skylot 已提交
326
		for (MethodNode m : methods) {
S
Skylot 已提交
327
			if (m.getMethodInfo().getShortId().equals(shortId)) {
S
Skylot 已提交
328
				return m;
S
Skylot 已提交
329
			}
S
Skylot 已提交
330 331 332 333 334
		}
		return null;
	}

	public MethodNode searchMethodById(int id) {
S
Skylot 已提交
335
		return searchMethodByName(MethodInfo.fromDex(dex, id).getShortId());
S
Skylot 已提交
336 337
	}

338 339 340 341 342 343 344 345 346 347 348 349 350
	public ClassNode getParentClass() {
		if (parentClass == null) {
			if (clsInfo.isInner()) {
				ClassNode parent = dex().resolveClass(clsInfo.getParentClass());
				parent = parent == null ? this : parent;
				parentClass = parent;
			} else {
				parentClass = this;
			}
		}
		return parentClass;
	}

S
Skylot 已提交
351 352 353 354 355
	public List<ClassNode> getInnerClasses() {
		return innerClasses;
	}

	public void addInnerClass(ClassNode cls) {
S
Skylot 已提交
356
		if (innerClasses.isEmpty()) {
S
Skylot 已提交
357
			innerClasses = new ArrayList<ClassNode>(3);
S
Skylot 已提交
358
		}
S
Skylot 已提交
359 360 361
		innerClasses.add(cls);
	}

362 363 364 365
	public boolean isEnum() {
		return getAccessFlags().isEnum() && getSuperClass().getFullName().equals(Consts.CLASS_ENUM);
	}

S
Skylot 已提交
366
	public boolean isAnonymous() {
S
Skylot 已提交
367 368 369
		return clsInfo.isInner()
				&& getShortName().startsWith(Consts.ANONYMOUS_CLASS_PREFIX)
				&& getDefaultConstructor() != null;
S
Skylot 已提交
370 371 372 373 374 375
	}

	public MethodNode getDefaultConstructor() {
		for (MethodNode mth : methods) {
			if (mth.getAccessFlags().isConstructor()
					&& mth.getMethodInfo().isConstructor()
S
Skylot 已提交
376
					&& (mth.getMethodInfo().getArgsCount() == 0
S
Skylot 已提交
377
					|| (mth.getArguments(false) != null && mth.getArguments(false).isEmpty()))) {
S
Skylot 已提交
378
				return mth;
S
Skylot 已提交
379 380
			}
		}
S
Skylot 已提交
381
		return null;
S
Skylot 已提交
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
	}

	public AccessInfo getAccessFlags() {
		return accessFlags;
	}

	public DexNode dex() {
		return dex;
	}

	public ClassInfo getClassInfo() {
		return clsInfo;
	}

	public String getShortName() {
		return clsInfo.getShortName();
	}

	public String getFullName() {
		return clsInfo.getFullName();
	}

	public String getPackage() {
		return clsInfo.getPackage();
	}

408 409 410 411
	public String getRawName() {
		return clsInfo.getRawName();
	}

S
Skylot 已提交
412 413 414 415 416 417 418 419
	public void setCode(CodeWriter code) {
		this.code = code;
	}

	public CodeWriter getCode() {
		return code;
	}

S
Skylot 已提交
420 421 422 423 424
	@Override
	public String toString() {
		return getFullName();
	}
}