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

3 4 5 6 7 8
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

9 10 11 12
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

13 14 15 16 17 18
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;

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

S
Skylot 已提交
42
import static jadx.core.dex.nodes.ProcessState.LOADED;
43 44
import static jadx.core.dex.nodes.ProcessState.UNLOADED;

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

	private final DexNode dex;
49
	private final int clsDefOffset;
S
Skylot 已提交
50
	private final ClassInfo clsInfo;
51
	private AccessInfo accessFlags;
S
Skylot 已提交
52 53
	private ArgType superClass;
	private List<ArgType> interfaces;
54
	private List<GenericInfo> generics = Collections.emptyList();
S
Skylot 已提交
55

S
Skylot 已提交
56 57
	private final List<MethodNode> methods;
	private final List<FieldNode> fields;
58
	private List<ClassNode> innerClasses = Collections.emptyList();
S
Skylot 已提交
59

60 61
	// store smali
	private String smali;
62 63
	// store parent for inner classes or 'this' otherwise
	private ClassNode parentClass;
S
Skylot 已提交
64

S
Skylot 已提交
65
	private volatile ProcessState state = ProcessState.NOT_LOADED;
S
Skylot 已提交
66
	private List<ClassNode> dependencies = Collections.emptyList();
67

S
Skylot 已提交
68 69 70
	// cache maps
	private Map<MethodInfo, MethodNode> mthInfoMap = Collections.emptyMap();

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

S
Skylot 已提交
90 91
				methods = new ArrayList<>(mthsCount);
				fields = new ArrayList<>(fieldsCount);
S
Skylot 已提交
92

S
Skylot 已提交
93
				for (Method mth : clsData.getDirectMethods()) {
94
					methods.add(new MethodNode(this, mth, false));
S
Skylot 已提交
95 96
				}
				for (Method mth : clsData.getVirtualMethods()) {
97
					methods.add(new MethodNode(this, mth, true));
S
Skylot 已提交
98
				}
S
Skylot 已提交
99

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

			loadAnnotations(cls);

114 115
			parseClassSignature();
			setFieldsTypesFromSignature();
S
Skylot 已提交
116

117
			int sfIdx = cls.getSourceFileIndex();
118
			if (sfIdx != DexNode.NO_INDEX) {
119
				String fileName = dex.getString(sfIdx);
120
				addSourceFilenameAttr(fileName);
121 122
			}

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

138
	// empty synthetic class
139
	public ClassNode(DexNode dex, String name, int accessFlags) {
140
		this.dex = dex;
141
		this.clsDefOffset = 0;
142 143 144 145 146
		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);
147
		this.parentClass = this;
148 149

		dex.addClassNode(this);
150 151
	}

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

	private void loadStaticValues(ClassDef cls, List<FieldNode> staticFields) throws DecodeException {
		for (FieldNode f : staticFields) {
			if (f.getAccessFlags().isFinal()) {
166
				f.addAttr(FieldInitAttr.NULL_VALUE);
S
Skylot 已提交
167 168 169
			}
		}
		int offset = cls.getStaticValuesOffset();
170 171 172
		if (offset == 0) {
			return;
		}
173 174 175 176 177 178
		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 已提交
179 180
	}

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

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

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
	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("$")
239
					&& fileName.endsWith('$' + name)) {
240 241
				return;
			}
S
Skylot 已提交
242 243
			ClassInfo parentCls = clsInfo.getTopParentClass();
			if (parentCls != null && fileName.equals(parentCls.getShortName())) {
S
Skylot 已提交
244 245
				return;
			}
246 247 248 249
		}
		this.addAttr(new SourceFileAttr(fileName));
	}

S
Skylot 已提交
250 251 252 253
	public void loadAndProcess() {
		ProcessClass.process(this);
	}

254 255 256 257 258
	public synchronized ICodeInfo decompile() {
		ICodeCache codeCache = root().getCodeCache();
		ClassNode topParentClass = getTopParentClass();
		String clsRawName = topParentClass.getRawName();
		ICodeInfo code = codeCache.get(clsRawName);
S
Skylot 已提交
259 260 261
		if (code != null) {
			return code;
		}
262 263
		ICodeInfo codeInfo = ProcessClass.generateCode(topParentClass);
		codeCache.add(clsRawName, codeInfo);
S
Skylot 已提交
264 265 266
		return codeInfo;
	}

267 268 269 270
	public ICodeInfo getCode() {
		return decompile();
	}

S
Skylot 已提交
271
	@Override
S
Skylot 已提交
272
	public void load() {
S
Skylot 已提交
273
		for (MethodNode mth : getMethods()) {
S
Skylot 已提交
274 275
			try {
				mth.load();
276
			} catch (Exception e) {
277
				mth.addError("Method load error", e);
S
Skylot 已提交
278
			}
S
Skylot 已提交
279 280 281 282
		}
		for (ClassNode innerCls : getInnerClasses()) {
			innerCls.load();
		}
S
Skylot 已提交
283
		setState(LOADED);
S
Skylot 已提交
284 285 286 287
	}

	@Override
	public void unload() {
288 289 290 291
		methods.forEach(MethodNode::unload);
		innerClasses.forEach(ClassNode::unload);
		fields.forEach(FieldNode::unloadAttributes);
		unloadAttributes();
292
		setState(UNLOADED);
S
Skylot 已提交
293 294
	}

S
Skylot 已提交
295
	private void buildCache() {
S
Skylot 已提交
296
		mthInfoMap = new HashMap<>(methods.size());
S
Skylot 已提交
297 298 299 300 301
		for (MethodNode mth : methods) {
			mthInfoMap.put(mth.getMethodInfo(), mth);
		}
	}

S
Skylot 已提交
302 303
	@Nullable
	public ArgType getSuperClass() {
S
Skylot 已提交
304 305 306
		return superClass;
	}

S
Skylot 已提交
307
	public List<ArgType> getInterfaces() {
S
Skylot 已提交
308 309 310
		return interfaces;
	}

311 312
	public List<GenericInfo> getGenerics() {
		return generics;
313 314
	}

S
Skylot 已提交
315 316 317 318 319 320 321 322
	public List<MethodNode> getMethods() {
		return methods;
	}

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

323 324 325 326
	public FieldNode getConstField(Object obj) {
		return getConstField(obj, true);
	}

327
	@Nullable
328
	public FieldNode getConstField(Object obj, boolean searchGlobal) {
329
		return root().getConstValues().getConstField(this, obj, searchGlobal);
330 331
	}

332
	@Nullable
1
13.beta2 已提交
333
	public FieldNode getConstFieldByLiteralArg(LiteralArg arg) {
334
		return root().getConstValues().getConstFieldByLiteralArg(this, arg);
1
13.beta2 已提交
335 336
	}

S
Skylot 已提交
337
	public FieldNode searchFieldById(int id) {
338 339 340 341
		return searchField(FieldInfo.fromDex(dex, id));
	}

	public FieldNode searchField(FieldInfo field) {
S
Skylot 已提交
342
		for (FieldNode f : fields) {
343
			if (f.getFieldInfo().equals(field)) {
S
Skylot 已提交
344
				return f;
S
Skylot 已提交
345
			}
S
Skylot 已提交
346 347 348 349
		}
		return null;
	}

350 351 352 353 354 355 356 357 358
	public FieldNode searchFieldByNameAndType(FieldInfo field) {
		for (FieldNode f : fields) {
			if (f.getFieldInfo().equalsNameAndType(field)) {
				return f;
			}
		}
		return null;
	}

S
Skylot 已提交
359
	public FieldNode searchFieldByName(String name) {
S
Skylot 已提交
360
		for (FieldNode f : fields) {
S
Skylot 已提交
361
			if (f.getName().equals(name)) {
S
Skylot 已提交
362
				return f;
S
Skylot 已提交
363
			}
S
Skylot 已提交
364 365 366 367
		}
		return null;
	}

S
Skylot 已提交
368
	public MethodNode searchMethod(MethodInfo mth) {
S
Skylot 已提交
369
		return mthInfoMap.get(mth);
S
Skylot 已提交
370 371
	}

372
	public MethodNode searchMethodByShortId(String shortId) {
S
Skylot 已提交
373
		for (MethodNode m : methods) {
S
Skylot 已提交
374
			if (m.getMethodInfo().getShortId().equals(shortId)) {
S
Skylot 已提交
375
				return m;
S
Skylot 已提交
376
			}
S
Skylot 已提交
377 378 379 380
		}
		return null;
	}

381 382
	/**
	 * Return first method by original short name
383 384
	 * Note: methods are not unique by name (class can have several methods with same name but different
	 * signature)
385 386 387 388 389 390 391 392 393 394 395
	 */
	@Nullable
	public MethodNode searchMethodByShortName(String name) {
		for (MethodNode m : methods) {
			if (m.getMethodInfo().getName().equals(name)) {
				return m;
			}
		}
		return null;
	}

S
Skylot 已提交
396
	public MethodNode searchMethodById(int id) {
397
		return searchMethodByShortId(MethodInfo.fromDex(dex, id).getShortId());
S
Skylot 已提交
398 399
	}

400 401 402 403
	public ClassNode getParentClass() {
		if (parentClass == null) {
			if (clsInfo.isInner()) {
				ClassNode parent = dex().resolveClass(clsInfo.getParentClass());
404
				parentClass = parent == null ? this : parent;
405 406 407 408 409 410 411
			} else {
				parentClass = this;
			}
		}
		return parentClass;
	}

412 413
	public ClassNode getTopParentClass() {
		ClassNode parent = getParentClass();
414
		return parent == this ? this : parent.getTopParentClass();
415 416
	}

417 418 419 420 421 422 423 424 425 426 427
	public boolean hasNotGeneratedParent() {
		if (contains(AFlag.DONT_GENERATE)) {
			return true;
		}
		ClassNode parent = getParentClass();
		if (parent == this) {
			return false;
		}
		return parent.hasNotGeneratedParent();
	}

S
Skylot 已提交
428 429 430 431 432
	public List<ClassNode> getInnerClasses() {
		return innerClasses;
	}

	public void addInnerClass(ClassNode cls) {
433 434 435
		if (innerClasses.isEmpty()) {
			innerClasses = new ArrayList<>(5);
		}
S
Skylot 已提交
436
		innerClasses.add(cls);
437
		cls.parentClass = this;
S
Skylot 已提交
438 439
	}

440
	public boolean isEnum() {
S
Skylot 已提交
441 442 443
		return getAccessFlags().isEnum()
				&& getSuperClass() != null
				&& getSuperClass().getObject().equals(ArgType.ENUM.getObject());
444 445
	}

S
Skylot 已提交
446
	public boolean isAnonymous() {
447
		return contains(AFlag.ANONYMOUS_CLASS);
448 449
	}

450 451
	@Nullable
	public MethodNode getClassInitMth() {
452
		return searchMethodByShortId("<clinit>()V");
453 454 455
	}

	@Nullable
S
Skylot 已提交
456 457
	public MethodNode getDefaultConstructor() {
		for (MethodNode mth : methods) {
458
			if (mth.isDefaultConstructor()) {
S
Skylot 已提交
459
				return mth;
S
Skylot 已提交
460 461
			}
		}
S
Skylot 已提交
462
		return null;
S
Skylot 已提交
463 464
	}

465
	@Override
S
Skylot 已提交
466 467 468 469
	public AccessInfo getAccessFlags() {
		return accessFlags;
	}

470 471 472 473 474
	@Override
	public void setAccessFlags(AccessInfo accessFlags) {
		this.accessFlags = accessFlags;
	}

475
	@Override
S
Skylot 已提交
476 477 478 479
	public DexNode dex() {
		return dex;
	}

480 481 482 483 484
	@Override
	public RootNode root() {
		return dex.root();
	}

485 486 487 488 489
	@Override
	public String typeName() {
		return "class";
	}

S
Skylot 已提交
490 491 492 493 494 495 496
	public String getRawName() {
		return clsInfo.getRawName();
	}

	/**
	 * Internal class info (don't use in code generation and external api).
	 */
S
Skylot 已提交
497 498 499 500 501
	public ClassInfo getClassInfo() {
		return clsInfo;
	}

	public String getShortName() {
502
		return clsInfo.getAliasShortName();
S
Skylot 已提交
503 504 505
	}

	public String getFullName() {
506
		return clsInfo.getAliasFullName();
S
Skylot 已提交
507 508 509
	}

	public String getPackage() {
510
		return clsInfo.getAliasPkg();
511 512
	}

513
	public String getSmali() {
514 515 516
		if (smali == null) {
			smali = SmaliUtils.getSmaliCode(dex, clsDefOffset);
		}
517 518 519
		return smali;
	}

520 521 522 523 524 525 526 527
	public ProcessState getState() {
		return state;
	}

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

S
Skylot 已提交
528
	public List<ClassNode> getDependencies() {
529 530 531
		return dependencies;
	}

S
Skylot 已提交
532 533 534 535
	public void setDependencies(List<ClassNode> dependencies) {
		this.dependencies = dependencies;
	}

536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
	@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 已提交
553 554
	@Override
	public String toString() {
S
Skylot 已提交
555
		return clsInfo.getFullName();
S
Skylot 已提交
556
	}
557

S
Skylot 已提交
558
}