ClassNode.java 12.7 KB
Newer Older
S
Skylot 已提交
1 2
package jadx.core.dex.nodes;

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.android.dex.ClassData;
import com.android.dex.ClassData.Field;
import com.android.dex.ClassData.Method;
import com.android.dex.ClassDef;
import com.android.dex.Dex;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

S
Skylot 已提交
20 21
import jadx.core.Consts;
import jadx.core.codegen.CodeWriter;
22
import jadx.core.dex.attributes.AFlag;
S
Skylot 已提交
23
import jadx.core.dex.attributes.annotations.Annotation;
S
Skylot 已提交
24 25
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.attributes.nodes.SourceFileAttr;
S
Skylot 已提交
26 27 28 29 30 31
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 已提交
32
import jadx.core.dex.instructions.args.LiteralArg;
S
Skylot 已提交
33
import jadx.core.dex.nodes.parser.AnnotationsParser;
34
import jadx.core.dex.nodes.parser.FieldInitAttr;
S
Skylot 已提交
35
import jadx.core.dex.nodes.parser.SignatureParser;
S
Skylot 已提交
36 37
import jadx.core.dex.nodes.parser.StaticValuesParser;
import jadx.core.utils.exceptions.DecodeException;
S
Skylot 已提交
38
import jadx.core.utils.exceptions.JadxRuntimeException;
S
Skylot 已提交
39

40 41
import static jadx.core.dex.nodes.ProcessState.UNLOADED;

42
public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
S
Skylot 已提交
43
	private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class);
S
Skylot 已提交
44 45 46

	private final DexNode dex;
	private final ClassInfo clsInfo;
47
	private AccessInfo accessFlags;
S
Skylot 已提交
48 49
	private ArgType superClass;
	private List<ArgType> interfaces;
50
	private Map<ArgType, List<ArgType>> genericMap;
S
Skylot 已提交
51

S
Skylot 已提交
52 53
	private final List<MethodNode> methods;
	private final List<FieldNode> fields;
54
	private List<ClassNode> innerClasses = new ArrayList<>();
S
Skylot 已提交
55

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

61
	private ProcessState state = ProcessState.NOT_LOADED;
S
Skylot 已提交
62
	private final Set<ClassNode> dependencies = new HashSet<>();
63

S
Skylot 已提交
64 65 66
	// cache maps
	private Map<MethodInfo, MethodNode> mthInfoMap = Collections.emptyMap();

67
	public ClassNode(DexNode dex, ClassDef cls) {
S
Skylot 已提交
68 69 70
		this.dex = dex;
		this.clsInfo = ClassInfo.fromDex(dex, cls.getTypeIndex());
		try {
S
Skylot 已提交
71 72 73
			if (cls.getSupertypeIndex() == DexNode.NO_INDEX) {
				this.superClass = null;
			} else {
S
Skylot 已提交
74
				this.superClass = dex.getType(cls.getSupertypeIndex());
S
Skylot 已提交
75
			}
S
Skylot 已提交
76
			this.interfaces = new ArrayList<>(cls.getInterfaces().length);
S
Skylot 已提交
77
			for (short interfaceIdx : cls.getInterfaces()) {
D
Donlon 已提交
78
				this.interfaces.add(dex.getType(interfaceIdx));
S
Skylot 已提交
79
			}
S
Skylot 已提交
80
			if (cls.getClassDataOffset() != 0) {
S
Skylot 已提交
81
				ClassData clsData = dex.readClassData(cls);
S
Skylot 已提交
82 83
				int mthsCount = clsData.getDirectMethods().length + clsData.getVirtualMethods().length;
				int fieldsCount = clsData.getStaticFields().length + clsData.getInstanceFields().length;
S
Skylot 已提交
84

S
Skylot 已提交
85 86
				methods = new ArrayList<>(mthsCount);
				fields = new ArrayList<>(fieldsCount);
S
Skylot 已提交
87

S
Skylot 已提交
88
				for (Method mth : clsData.getDirectMethods()) {
89
					methods.add(new MethodNode(this, mth, false));
S
Skylot 已提交
90 91
				}
				for (Method mth : clsData.getVirtualMethods()) {
92
					methods.add(new MethodNode(this, mth, true));
S
Skylot 已提交
93
				}
S
Skylot 已提交
94

S
Skylot 已提交
95
				for (Field f : clsData.getStaticFields()) {
S
Skylot 已提交
96
					fields.add(new FieldNode(this, f));
S
Skylot 已提交
97
				}
S
Skylot 已提交
98
				loadStaticValues(cls, fields);
S
Skylot 已提交
99
				for (Field f : clsData.getInstanceFields()) {
S
Skylot 已提交
100
					fields.add(new FieldNode(this, f));
S
Skylot 已提交
101 102 103 104
				}
			} else {
				methods = Collections.emptyList();
				fields = Collections.emptyList();
S
Skylot 已提交
105 106 107 108
			}

			loadAnnotations(cls);

109 110
			parseClassSignature();
			setFieldsTypesFromSignature();
S
Skylot 已提交
111

112
			int sfIdx = cls.getSourceFileIndex();
113
			if (sfIdx != DexNode.NO_INDEX) {
114
				String fileName = dex.getString(sfIdx);
115
				addSourceFilenameAttr(fileName);
116 117
			}

S
Skylot 已提交
118
			// restore original access flags from dalvik annotation if present
119
			int accFlagsValue;
S
Skylot 已提交
120
			Annotation a = getAnnotation(Consts.DALVIK_INNER_CLASS);
S
Skylot 已提交
121
			if (a != null) {
122
				accFlagsValue = (Integer) a.getValues().get("accessFlags");
S
Skylot 已提交
123
			} else {
124
				accFlagsValue = cls.getAccessFlags();
S
Skylot 已提交
125
			}
S
Skylot 已提交
126
			this.accessFlags = new AccessInfo(accFlagsValue, AFType.CLASS);
127
			markAnonymousClass(this);
S
Skylot 已提交
128
			buildCache();
S
Skylot 已提交
129
		} catch (Exception e) {
130
			throw new JadxRuntimeException("Error decode class: " + clsInfo, e);
S
Skylot 已提交
131 132 133
		}
	}

134
	// empty synthetic class
135
	public ClassNode(DexNode dex, String name, int accessFlags) {
136
		this.dex = dex;
137 138 139 140 141
		this.clsInfo = ClassInfo.fromName(dex.root(), name);
		this.interfaces = new ArrayList<>();
		this.methods = new ArrayList<>();
		this.fields = new ArrayList<>();
		this.accessFlags = new AccessInfo(accessFlags, AFType.CLASS);
142
		this.parentClass = this;
143 144

		dex.addClassNode(this);
145 146
	}

S
Skylot 已提交
147 148 149 150
	private void loadAnnotations(ClassDef cls) {
		int offset = cls.getAnnotationsOffset();
		if (offset != 0) {
			try {
S
Skylot 已提交
151
				new AnnotationsParser(this).parse(offset);
152
			} catch (Exception e) {
S
Skylot 已提交
153
				LOG.error("Error parsing annotations in {}", this, e);
S
Skylot 已提交
154 155 156 157 158 159 160
			}
		}
	}

	private void loadStaticValues(ClassDef cls, List<FieldNode> staticFields) throws DecodeException {
		for (FieldNode f : staticFields) {
			if (f.getAccessFlags().isFinal()) {
161
				f.addAttr(FieldInitAttr.NULL_VALUE);
S
Skylot 已提交
162 163 164
			}
		}
		int offset = cls.getStaticValuesOffset();
165 166 167
		if (offset == 0) {
			return;
		}
168 169 170 171 172 173
		Dex.Section section = dex.openSection(offset);
		StaticValuesParser parser = new StaticValuesParser(dex, section);
		parser.processFields(staticFields);

		// process const fields
		root().getConstValues().processConstFields(this, staticFields);
S
Skylot 已提交
174 175
	}

176
	private void parseClassSignature() {
S
Skylot 已提交
177 178
		SignatureParser sp = SignatureParser.fromNode(this);
		if (sp == null) {
179
			return;
S
Skylot 已提交
180
		}
S
Skylot 已提交
181 182 183 184
		try {
			// parse class generic map
			genericMap = sp.consumeGenericMap();
			// parse super class signature
S
Skylot 已提交
185
			superClass = sp.consumeType();
S
Skylot 已提交
186 187 188 189
			// parse interfaces signatures
			for (int i = 0; i < interfaces.size(); i++) {
				ArgType type = sp.consumeType();
				if (type != null) {
S
Skylot 已提交
190
					interfaces.set(i, type);
S
Skylot 已提交
191 192
				} else {
					break;
193 194
				}
			}
195
		} catch (Exception e) {
S
Skylot 已提交
196
			LOG.error("Class signature parse error: {}", this, e);
197 198 199 200 201
		}
	}

	private void setFieldsTypesFromSignature() {
		for (FieldNode field : fields) {
202 203 204
			try {
				SignatureParser sp = SignatureParser.fromNode(field);
				if (sp != null) {
S
Skylot 已提交
205 206 207 208
					ArgType gType = sp.consumeType();
					if (gType != null) {
						field.setType(gType);
					}
S
Skylot 已提交
209
				}
210 211
			} catch (Exception e) {
				LOG.error("Field signature parse error: {}.{}", this.getFullName(), field.getName(), e);
S
Skylot 已提交
212
			}
213 214 215
		}
	}

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
	private void addSourceFilenameAttr(String fileName) {
		if (fileName == null) {
			return;
		}
		if (fileName.endsWith(".java")) {
			fileName = fileName.substring(0, fileName.length() - 5);
		}
		if (fileName.isEmpty()
				|| fileName.equals("SourceFile")
				|| fileName.equals("\"")) {
			return;
		}
		if (clsInfo != null) {
			String name = clsInfo.getShortName();
			if (fileName.equals(name)) {
				return;
			}
			if (fileName.contains("$")
					&& fileName.endsWith("$" + name)) {
				return;
			}
S
Skylot 已提交
237 238 239 240
			ClassInfo parentClass = clsInfo.getTopParentClass();
			if (parentClass != null && fileName.equals(parentClass.getShortName())) {
				return;
			}
241 242 243 244
		}
		this.addAttr(new SourceFileAttr(fileName));
	}

S
Skylot 已提交
245
	@Override
S
Skylot 已提交
246
	public void load() {
S
Skylot 已提交
247
		for (MethodNode mth : getMethods()) {
S
Skylot 已提交
248 249
			try {
				mth.load();
250
			} catch (Exception e) {
251
				mth.addError("Method load error", e);
S
Skylot 已提交
252
			}
S
Skylot 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266
		}
		for (ClassNode innerCls : getInnerClasses()) {
			innerCls.load();
		}
	}

	@Override
	public void unload() {
		for (MethodNode mth : getMethods()) {
			mth.unload();
		}
		for (ClassNode innerCls : getInnerClasses()) {
			innerCls.unload();
		}
267
		setState(UNLOADED);
S
Skylot 已提交
268 269
	}

S
Skylot 已提交
270
	private void buildCache() {
S
Skylot 已提交
271
		mthInfoMap = new HashMap<>(methods.size());
S
Skylot 已提交
272 273 274 275 276
		for (MethodNode mth : methods) {
			mthInfoMap.put(mth.getMethodInfo(), mth);
		}
	}

S
Skylot 已提交
277 278
	@Nullable
	public ArgType getSuperClass() {
S
Skylot 已提交
279 280 281
		return superClass;
	}

S
Skylot 已提交
282
	public List<ArgType> getInterfaces() {
S
Skylot 已提交
283 284 285
		return interfaces;
	}

286 287 288 289
	public Map<ArgType, List<ArgType>> getGenericMap() {
		return genericMap;
	}

S
Skylot 已提交
290 291 292 293 294 295 296 297
	public List<MethodNode> getMethods() {
		return methods;
	}

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

298 299 300 301
	public FieldNode getConstField(Object obj) {
		return getConstField(obj, true);
	}

302
	@Nullable
303
	public FieldNode getConstField(Object obj, boolean searchGlobal) {
304
		return root().getConstValues().getConstField(this, obj, searchGlobal);
305 306
	}

307
	@Nullable
1
13.beta2 已提交
308
	public FieldNode getConstFieldByLiteralArg(LiteralArg arg) {
309
		return root().getConstValues().getConstFieldByLiteralArg(this, arg);
1
13.beta2 已提交
310 311
	}

S
Skylot 已提交
312
	public FieldNode searchFieldById(int id) {
313 314 315 316
		return searchField(FieldInfo.fromDex(dex, id));
	}

	public FieldNode searchField(FieldInfo field) {
S
Skylot 已提交
317
		for (FieldNode f : fields) {
318
			if (f.getFieldInfo().equals(field)) {
S
Skylot 已提交
319
				return f;
S
Skylot 已提交
320
			}
S
Skylot 已提交
321 322 323 324
		}
		return null;
	}

325 326 327 328 329 330 331 332 333
	public FieldNode searchFieldByNameAndType(FieldInfo field) {
		for (FieldNode f : fields) {
			if (f.getFieldInfo().equalsNameAndType(field)) {
				return f;
			}
		}
		return null;
	}

S
Skylot 已提交
334
	public FieldNode searchFieldByName(String name) {
S
Skylot 已提交
335
		for (FieldNode f : fields) {
S
Skylot 已提交
336
			if (f.getName().equals(name)) {
S
Skylot 已提交
337
				return f;
S
Skylot 已提交
338
			}
S
Skylot 已提交
339 340 341 342
		}
		return null;
	}

S
Skylot 已提交
343
	public MethodNode searchMethod(MethodInfo mth) {
S
Skylot 已提交
344
		return mthInfoMap.get(mth);
S
Skylot 已提交
345 346 347
	}

	public MethodNode searchMethodByName(String shortId) {
S
Skylot 已提交
348
		for (MethodNode m : methods) {
S
Skylot 已提交
349
			if (m.getMethodInfo().getShortId().equals(shortId)) {
S
Skylot 已提交
350
				return m;
S
Skylot 已提交
351
			}
S
Skylot 已提交
352 353 354 355 356
		}
		return null;
	}

	public MethodNode searchMethodById(int id) {
S
Skylot 已提交
357
		return searchMethodByName(MethodInfo.fromDex(dex, id).getShortId());
S
Skylot 已提交
358 359
	}

360 361 362 363
	public ClassNode getParentClass() {
		if (parentClass == null) {
			if (clsInfo.isInner()) {
				ClassNode parent = dex().resolveClass(clsInfo.getParentClass());
364
				parentClass = parent == null ? this : parent;
365 366 367 368 369 370 371
			} else {
				parentClass = this;
			}
		}
		return parentClass;
	}

372 373
	public ClassNode getTopParentClass() {
		ClassNode parent = getParentClass();
374
		return parent == this ? this : parent.getTopParentClass();
375 376
	}

S
Skylot 已提交
377 378 379 380 381 382
	public List<ClassNode> getInnerClasses() {
		return innerClasses;
	}

	public void addInnerClass(ClassNode cls) {
		innerClasses.add(cls);
383
		cls.parentClass = this;
S
Skylot 已提交
384 385
	}

386
	public boolean isEnum() {
S
Skylot 已提交
387 388 389
		return getAccessFlags().isEnum()
				&& getSuperClass() != null
				&& getSuperClass().getObject().equals(ArgType.ENUM.getObject());
390 391
	}

S
Skylot 已提交
392
	public boolean isAnonymous() {
S
Skylot 已提交
393
		return clsInfo.isInner()
S
Skylot 已提交
394
				&& clsInfo.getAlias().getShortName().startsWith(Consts.ANONYMOUS_CLASS_PREFIX)
S
Skylot 已提交
395
				&& getDefaultConstructor() != null;
S
Skylot 已提交
396 397
	}

398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
	public boolean isLambdaCls() {
		return accessFlags.isSynthetic() && accessFlags.isFinal()
				&& clsInfo.getType().getObject().contains(".-$$Lambda$")
				&& countStaticFields() == 0;
	}

	private int countStaticFields() {
		int c = 0;
		for (FieldNode field : fields) {
			if (field.getAccessFlags().isStatic()) {
				c++;
			}
		}
		return c;
	}

	private static void markAnonymousClass(ClassNode cls) {
		if (cls.isAnonymous() || cls.isLambdaCls()) {
			cls.add(AFlag.ANONYMOUS_CLASS);
			cls.add(AFlag.DONT_GENERATE);
		}
	}

421 422 423 424 425 426
	@Nullable
	public MethodNode getClassInitMth() {
		return searchMethodByName("<clinit>()V");
	}

	@Nullable
S
Skylot 已提交
427 428
	public MethodNode getDefaultConstructor() {
		for (MethodNode mth : methods) {
429
			if (mth.isDefaultConstructor()) {
S
Skylot 已提交
430
				return mth;
S
Skylot 已提交
431 432
			}
		}
S
Skylot 已提交
433
		return null;
S
Skylot 已提交
434 435
	}

436
	@Override
S
Skylot 已提交
437 438 439 440
	public AccessInfo getAccessFlags() {
		return accessFlags;
	}

441 442 443 444 445
	@Override
	public void setAccessFlags(AccessInfo accessFlags) {
		this.accessFlags = accessFlags;
	}

446
	@Override
S
Skylot 已提交
447 448 449 450
	public DexNode dex() {
		return dex;
	}

451 452 453 454 455
	@Override
	public RootNode root() {
		return dex.root();
	}

456 457 458 459 460
	@Override
	public String typeName() {
		return "class";
	}

S
Skylot 已提交
461 462 463 464 465 466 467
	public String getRawName() {
		return clsInfo.getRawName();
	}

	/**
	 * Internal class info (don't use in code generation and external api).
	 */
S
Skylot 已提交
468 469 470 471
	public ClassInfo getClassInfo() {
		return clsInfo;
	}

S
Skylot 已提交
472 473 474 475 476 477 478
	/**
	 * Class info for external usage (code generation and external api).
	 */
	public ClassInfo getAlias() {
		return clsInfo.getAlias();
	}

S
Skylot 已提交
479
	public String getShortName() {
S
Skylot 已提交
480
		return clsInfo.getAlias().getShortName();
S
Skylot 已提交
481 482 483
	}

	public String getFullName() {
S
Skylot 已提交
484
		return clsInfo.getAlias().getFullName();
S
Skylot 已提交
485 486 487
	}

	public String getPackage() {
S
Skylot 已提交
488
		return clsInfo.getAlias().getPackage();
489 490
	}

S
Skylot 已提交
491 492 493 494 495 496 497 498
	public void setCode(CodeWriter code) {
		this.code = code;
	}

	public CodeWriter getCode() {
		return code;
	}

499 500 501 502 503 504 505 506 507 508 509 510
	public ProcessState getState() {
		return state;
	}

	public void setState(ProcessState state) {
		this.state = state;
	}

	public Set<ClassNode> getDependencies() {
		return dependencies;
	}

511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
	@Override
	public int hashCode() {
		return clsInfo.hashCode();
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}
		if (o instanceof ClassNode) {
			ClassNode other = (ClassNode) o;
			return clsInfo.equals(other.clsInfo);
		}
		return false;
	}

S
Skylot 已提交
528 529
	@Override
	public String toString() {
S
Skylot 已提交
530
		return clsInfo.getFullName();
S
Skylot 已提交
531 532
	}
}