mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-26 11:20:54 +00:00
Import/Usage parsing separated to one class
Class for generating linker reports from SWF files (similar to -link-report option in Flex) Generating linker report from commandline
This commit is contained in:
@@ -42,6 +42,7 @@ import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
|
||||
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.NulWriter;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
@@ -169,117 +170,6 @@ public abstract class Trait implements Cloneable, Serializable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void parseImportsUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
|
||||
if (m != null) {
|
||||
if (m.kind == Multiname.TYPENAME) {
|
||||
if (m.qname_index != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (Integer i : m.params) {
|
||||
if (i != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Namespace ns = m.getNamespace(abc.constants);
|
||||
String name = m.getName(abc.constants, fullyQualifiedNames, true);
|
||||
NamespaceSet nss = m.getNamespaceSet(abc.constants);
|
||||
if (ns != null) {
|
||||
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
|
||||
}
|
||||
if (nss != null) {
|
||||
for (int n : nss.namespaces) {
|
||||
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
|
||||
Namespace ns = abc.constants.getNamespace(namespace_index);
|
||||
|
||||
if (ns.kind == Namespace.KIND_NAMESPACE) {
|
||||
String nsVal = ns.getName(abc.constants).toRawString();
|
||||
for (ABCContainerTag abcTag : abc.getAbcTags()) {
|
||||
DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal);
|
||||
if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) {
|
||||
return true; //handled, but import/use not added
|
||||
}
|
||||
if (!nsimport.isEmpty()) {
|
||||
|
||||
if (!nsimport.getWithoutLast().equals(ignorePackage) && !imports.contains(nsimport)) {
|
||||
imports.add(nsimport);
|
||||
}
|
||||
if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
|
||||
return true;
|
||||
}
|
||||
if (!uses.contains(nsimport.getLast())) {
|
||||
uses.add(nsimport.getLast());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void parseImportsUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
|
||||
Namespace ns = abc.constants.getNamespace(namespace_index);
|
||||
if (name.isEmpty()) {
|
||||
name = "*";
|
||||
}
|
||||
DottedChain newimport = ns.getName(abc.constants);
|
||||
|
||||
if (parseUsagesFromNS(ignoredCustom, abc, imports, uses, namespace_index, ignorePackage, name)) {
|
||||
return;
|
||||
} else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
|
||||
return;
|
||||
}
|
||||
newimport = newimport.add(name);
|
||||
if (!imports.contains(newimport)) {
|
||||
DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.'));
|
||||
if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always
|
||||
return;
|
||||
}
|
||||
if (!pkg.equals(ignorePackage)) {
|
||||
imports.add(newimport);
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
protected void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
|
||||
if (m != null) {
|
||||
if (m.kind == Multiname.TYPENAME) {
|
||||
if (m.qname_index != 0) {
|
||||
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (Integer i : m.params) {
|
||||
if (i != 0) {
|
||||
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Namespace ns = m.getNamespace(abc.constants);
|
||||
String name = m.getName(abc.constants, fullyQualifiedNames, false);
|
||||
NamespaceSet nss = m.getNamespaceSet(abc.constants);
|
||||
if (ns != null) {
|
||||
parseUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
|
||||
}
|
||||
if (nss != null) {
|
||||
if (nss.namespaces.length == 1) {
|
||||
parseUsagesFromNS(ignoredCustom, abc, imports, uses, nss.namespaces[0], ignorePackage, name);
|
||||
} else {
|
||||
for (int n : nss.namespaces) {
|
||||
parseUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected DottedChain getPackage(ABC abc) {
|
||||
return getName(abc).getNamespace(abc.constants).getName(abc.constants);
|
||||
}
|
||||
@@ -291,7 +181,7 @@ public abstract class Trait implements Cloneable, Serializable {
|
||||
ignoredCustom = n.getName(abc.constants).toRawString();
|
||||
}
|
||||
}
|
||||
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames);
|
||||
ImportsUsagesParser.parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
|
||||
private static final String[] builtInClasses = {"ArgumentError", "arguments", "Array", "Boolean", "Class", "Date", "DefinitionError", "Error", "EvalError", "Function", "int", "JSON", "Math", "Namespace", "Number", "Object", "QName", "RangeError", "ReferenceError", "RegExp", "SecurityError", "String", "SyntaxError", "TypeError", "uint", "URIError", "VerifyError", "XML", "XMLList"};
|
||||
@@ -375,64 +265,6 @@ public abstract class Trait implements Cloneable, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
protected void parseImportsUsagesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> visitedMethods) {
|
||||
if ((method_index < 0) || (method_index >= abc.method_info.size())) {
|
||||
return;
|
||||
}
|
||||
visitedMethods.add(method_index);
|
||||
if (abc.method_info.get(method_index).ret_type != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (int t : abc.method_info.get(method_index).param_types) {
|
||||
if (t != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
MethodBody body = abc.findBody(method_index);
|
||||
if (body != null) {
|
||||
body.traits.getImportsUsages(ignoredCustom, abc, imports, uses, ignorePackage, fullyQualifiedNames);
|
||||
for (ABCException ex : body.exceptions) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (AVM2Instruction ins : body.getCode().code) {
|
||||
if (ins.definition instanceof AlchemyTypeIns) {
|
||||
DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName);
|
||||
if (!imports.contains(nimport)) {
|
||||
imports.add(nimport);
|
||||
}
|
||||
}
|
||||
if (ins.definition instanceof NewFunctionIns) {
|
||||
if (ins.operands[0] != method_index) {
|
||||
if (!visitedMethods.contains(ins.operands[0])) {
|
||||
parseImportsUsagesFromMethodInfo(ignoredCustom, abc, ins.operands[0], imports, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ins.definition instanceof FindPropertyStrictIns)
|
||||
|| (ins.definition instanceof FindPropertyIns)
|
||||
|| (ins.definition instanceof GetLexIns)
|
||||
|| (ins.definition instanceof CoerceIns)
|
||||
|| (ins.definition instanceof AsTypeIns)) {
|
||||
int m = ins.operands[0];
|
||||
if (m != 0) {
|
||||
if (m < abc.constants.getMultinameCount()) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < ins.definition.operands.length; k++) {
|
||||
if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
|
||||
int multinameIndex = ins.operands[k];
|
||||
if (multinameIndex < abc.constants.getMultinameCount()) {
|
||||
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final GraphTextWriter getMetaData(Trait parent, ConvertData convertData, ABC abc, GraphTextWriter writer) {
|
||||
List<Entry<String, Map<String, String>>> md = getMetaDataTable(parent, convertData, abc);
|
||||
for (Entry<String, Map<String, String>> en : md) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.NulWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
@@ -84,26 +85,26 @@ public class TraitClass extends Trait implements TraitWithSlot {
|
||||
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
|
||||
DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name
|
||||
|
||||
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
|
||||
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
|
||||
|
||||
if (instanceInfo.super_index > 0) {
|
||||
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames);
|
||||
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames);
|
||||
}
|
||||
for (int i : instanceInfo.interfaces) {
|
||||
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames);
|
||||
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames);
|
||||
}
|
||||
|
||||
//static
|
||||
classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
|
||||
|
||||
//static initializer
|
||||
parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
|
||||
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
|
||||
|
||||
//instance
|
||||
instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
|
||||
|
||||
//instance initializer
|
||||
parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
|
||||
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.types.ConvertData;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.NulWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
|
||||
@@ -130,7 +131,7 @@ public class TraitFunction extends Trait implements TraitWithSlot {
|
||||
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
|
||||
//if (method_info != 0)
|
||||
{
|
||||
parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
|
||||
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.NulWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
|
||||
@@ -72,7 +73,7 @@ public class TraitMethodGetterSetter extends Trait {
|
||||
}
|
||||
//if (method_info != 0)
|
||||
{
|
||||
parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
|
||||
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.abc.types.ValueKind;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.NulWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
|
||||
@@ -201,7 +202,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
|
||||
ignorePackage = getPackage(abc);
|
||||
}
|
||||
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
|
||||
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames);
|
||||
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.script;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.AlchemyTypeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.types.ABCException;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import java.util.List;
|
||||
|
||||
public class ImportsUsagesParser {
|
||||
|
||||
public static void parseImportsUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
|
||||
Namespace ns = abc.constants.getNamespace(namespace_index);
|
||||
if (name.isEmpty()) {
|
||||
name = "*";
|
||||
}
|
||||
DottedChain newimport = ns.getName(abc.constants);
|
||||
|
||||
if (parseUsagesFromNS(ignoredCustom, abc, imports, uses, namespace_index, ignorePackage, name)) {
|
||||
return;
|
||||
} else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
|
||||
return;
|
||||
}
|
||||
newimport = newimport.add(name);
|
||||
if (!imports.contains(newimport)) {
|
||||
DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.'));
|
||||
if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always
|
||||
return;
|
||||
}
|
||||
if (!pkg.equals(ignorePackage)) {
|
||||
imports.add(newimport);
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
public static void parseImportsUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
|
||||
if (m != null) {
|
||||
if (m.kind == Multiname.TYPENAME) {
|
||||
if (m.qname_index != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (Integer i : m.params) {
|
||||
if (i != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Namespace ns = m.getNamespace(abc.constants);
|
||||
String name = m.getName(abc.constants, fullyQualifiedNames, true);
|
||||
NamespaceSet nss = m.getNamespaceSet(abc.constants);
|
||||
if (ns != null) {
|
||||
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
|
||||
}
|
||||
if (nss != null) {
|
||||
for (int n : nss.namespaces) {
|
||||
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void parseImportsUsagesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> visitedMethods) {
|
||||
if ((method_index < 0) || (method_index >= abc.method_info.size())) {
|
||||
return;
|
||||
}
|
||||
visitedMethods.add(method_index);
|
||||
if (abc.method_info.get(method_index).ret_type != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (int t : abc.method_info.get(method_index).param_types) {
|
||||
if (t != 0) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
MethodBody body = abc.findBody(method_index);
|
||||
if (body != null) {
|
||||
body.traits.getImportsUsages(ignoredCustom, abc, imports, uses, ignorePackage, fullyQualifiedNames);
|
||||
for (ABCException ex : body.exceptions) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (AVM2Instruction ins : body.getCode().code) {
|
||||
if (ins.definition instanceof AlchemyTypeIns) {
|
||||
DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName);
|
||||
if (!imports.contains(nimport)) {
|
||||
imports.add(nimport);
|
||||
}
|
||||
}
|
||||
if (ins.definition instanceof NewFunctionIns) {
|
||||
if (ins.operands[0] != method_index) {
|
||||
if (!visitedMethods.contains(ins.operands[0])) {
|
||||
parseImportsUsagesFromMethodInfo(ignoredCustom, abc, ins.operands[0], imports, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ins.definition instanceof FindPropertyStrictIns)
|
||||
|| (ins.definition instanceof FindPropertyIns)
|
||||
|| (ins.definition instanceof GetLexIns)
|
||||
|| (ins.definition instanceof CoerceIns)
|
||||
|| (ins.definition instanceof AsTypeIns)) {
|
||||
int m = ins.operands[0];
|
||||
if (m != 0) {
|
||||
if (m < abc.constants.getMultinameCount()) {
|
||||
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < ins.definition.operands.length; k++) {
|
||||
if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
|
||||
int multinameIndex = ins.operands[k];
|
||||
if (multinameIndex < abc.constants.getMultinameCount()) {
|
||||
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
|
||||
if (m != null) {
|
||||
if (m.kind == Multiname.TYPENAME) {
|
||||
if (m.qname_index != 0) {
|
||||
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
for (Integer i : m.params) {
|
||||
if (i != 0) {
|
||||
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Namespace ns = m.getNamespace(abc.constants);
|
||||
String name = m.getName(abc.constants, fullyQualifiedNames, false);
|
||||
NamespaceSet nss = m.getNamespaceSet(abc.constants);
|
||||
if (ns != null) {
|
||||
parseUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
|
||||
}
|
||||
if (nss != null) {
|
||||
if (nss.namespaces.length == 1) {
|
||||
parseUsagesFromNS(ignoredCustom, abc, imports, uses, nss.namespaces[0], ignorePackage, name);
|
||||
} else {
|
||||
for (int n : nss.namespaces) {
|
||||
parseUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
|
||||
Namespace ns = abc.constants.getNamespace(namespace_index);
|
||||
|
||||
if (ns.kind == Namespace.KIND_NAMESPACE) {
|
||||
String nsVal = ns.getName(abc.constants).toRawString();
|
||||
for (ABCContainerTag abcTag : abc.getAbcTags()) {
|
||||
DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal);
|
||||
if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) {
|
||||
return true; //handled, but import/use not added
|
||||
}
|
||||
if (!nsimport.isEmpty()) {
|
||||
|
||||
if (!nsimport.getWithoutLast().equals(ignorePackage) && !imports.contains(nsimport)) {
|
||||
imports.add(nsimport);
|
||||
}
|
||||
if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
|
||||
return true;
|
||||
}
|
||||
if (!uses.contains(nsimport.getLast())) {
|
||||
uses.add(nsimport.getLast());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.script;
|
||||
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.types.ClassInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
|
||||
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Class LinkReportExporter - generates Linker reports similar to Flex
|
||||
* -link-report, but for SWF files
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class LinkReportExporter {
|
||||
|
||||
private String newLineChar = "\n";
|
||||
private String indentStr = " ";
|
||||
|
||||
/**
|
||||
* Constructs reporter with LF as newline, two spaces as indent
|
||||
*/
|
||||
public LinkReportExporter() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs reporter with custom newline char, two spaces as indent
|
||||
*
|
||||
* @param newLineChar
|
||||
*/
|
||||
public LinkReportExporter(String newLineChar) {
|
||||
this.newLineChar = newLineChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs reporter with custom newline char and indent string
|
||||
*
|
||||
* @param newLineChar
|
||||
* @param indentStr
|
||||
*/
|
||||
public LinkReportExporter(String newLineChar, String indentStr) {
|
||||
this.newLineChar = newLineChar;
|
||||
this.indentStr = indentStr;
|
||||
|
||||
}
|
||||
|
||||
private String indent(int cnt) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
sb.append(indentStr);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String generateReport(SWF swf, List<ScriptPack> as3scripts, EventListener evl) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Set<String> extDeps = new HashSet<>();
|
||||
sb.append("<report>").append(newLineChar);
|
||||
sb.append(indent(1)).append("<scripts>").append(newLineChar);
|
||||
List<ScriptPack> revList = new ArrayList<>(as3scripts);
|
||||
Collections.reverse(revList);
|
||||
|
||||
List<DottedChain> existingObjects = new ArrayList<>();
|
||||
for (ScriptPack sp : as3scripts) {
|
||||
existingObjects.add(sp.getClassPath().packageStr.add(sp.getClassPath().className));
|
||||
}
|
||||
|
||||
for (ScriptPack sp : revList) {
|
||||
String scriptName = "script" + sp.scriptIndex;
|
||||
sb.append(indent(2)).append("<script name=\"").append(scriptName).append("\">").append(newLineChar);
|
||||
//TODO: additional atributes - mod="1469951734131" size="525" optimizedsize="508
|
||||
ScriptInfo script = sp.abc.script_info.get(sp.scriptIndex);
|
||||
for (int traitIndex : sp.traitIndices) {
|
||||
Trait trait = script.traits.traits.get(traitIndex);
|
||||
sb.append(reportTrait(extDeps, existingObjects, swf, sp.abc, trait));
|
||||
}
|
||||
//how about script_init method(?)
|
||||
sb.append(indent(2)).append("</script>").append(newLineChar);
|
||||
}
|
||||
sb.append(indent(1)).append("</scripts>").append(newLineChar);
|
||||
sb.append("</report>").append(newLineChar);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String multiNameToId(ABC abc, Multiname multiName) {
|
||||
Namespace ns = multiName.getNamespace(abc.constants);
|
||||
NamespaceSet nss = multiName.getNamespaceSet(abc.constants);
|
||||
if (nss != null && nss.namespaces.length == 1) {
|
||||
ns = abc.constants.getNamespace(nss.namespaces[0]);
|
||||
}
|
||||
String pkgName = ns == null ? "" : ns.getName(abc.constants).toRawString();
|
||||
String clsName = multiName.getName(abc.constants, new ArrayList<>(), true);
|
||||
return pkgName.isEmpty() ? clsName : pkgName + ":" + clsName;
|
||||
}
|
||||
|
||||
private String dottedChainToId(DottedChain dc) {
|
||||
if (dc.getWithoutLast().isEmpty()) {
|
||||
return dc.getLast();
|
||||
}
|
||||
return dc.getWithoutLast().toRawString() + ":" + dc.getLast();
|
||||
}
|
||||
|
||||
private String reportTrait(Set<String> externalDefs, List<DottedChain> existingObjects, SWF swf, ABC abc, Trait t) {
|
||||
//TODO: handle externalDefs - <external-defs> <ext id="..." /> </external-defs>
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (t instanceof TraitClass) {
|
||||
TraitClass tc = (TraitClass) t;
|
||||
sb.append(indent(3)).append("<def id=\"").append(multiNameToId(abc, tc.getName(abc))).append("\" />").append(newLineChar);
|
||||
ClassInfo ci = abc.class_info.get(tc.class_info);
|
||||
InstanceInfo ii = abc.instance_info.get(tc.class_info);
|
||||
|
||||
Set<String> allDeps = new HashSet<>();
|
||||
|
||||
String superPre;
|
||||
if (ii.super_index != 0) {
|
||||
superPre = multiNameToId(abc, abc.constants.getMultiname(ii.super_index));
|
||||
} else {
|
||||
superPre = "Object";
|
||||
}
|
||||
allDeps.add(superPre);
|
||||
sb.append(indent(3)).append("<pre id=\"").append(superPre).append("\" />").append(newLineChar);
|
||||
|
||||
for (int iface : ii.interfaces) {
|
||||
String ifacePre = multiNameToId(abc, abc.constants.getMultiname(iface));
|
||||
allDeps.add(ifacePre);
|
||||
sb.append(indent(3)).append("<pre id=\"").append(ifacePre).append("\" />").append(newLineChar);
|
||||
}
|
||||
|
||||
for (Trait ct : ci.static_traits.traits) {
|
||||
reportTrait(externalDefs, existingObjects, swf, abc, ct);
|
||||
}
|
||||
for (Trait it : ii.instance_traits.traits) {
|
||||
reportTrait(externalDefs, existingObjects, swf, abc, it);
|
||||
}
|
||||
List<DottedChain> imports = new ArrayList<>();
|
||||
List<String> uses = new ArrayList<>();
|
||||
|
||||
sb.append(indent(3)).append("<dep id=\"AS3\" />").append(newLineChar); //Automatic
|
||||
|
||||
getImportsUsagesFromClass(tc.class_info, null, abc, imports, uses, new DottedChain("FAKE!PACKAGE") /*do not skip any package*/, new ArrayList<>());
|
||||
for (DottedChain dc : imports) {
|
||||
if (!"*".equals(dc.getLast())) {
|
||||
//some toplevel "imports" can be only method calls
|
||||
if (dc.getWithoutLast().isEmpty() && !existingObjects.contains(dc)) {
|
||||
continue;
|
||||
}
|
||||
String dep = dottedChainToId(dc);
|
||||
if (!allDeps.contains(dep)) {
|
||||
sb.append(indent(3)).append("<dep id=\"").append(dep).append("\" />").append(newLineChar);
|
||||
allDeps.add(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void getImportsUsagesFromClass(int class_info, String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignoredPackage, List<DottedChain> fullyQualifiedNames) {
|
||||
ClassInfo classInfo = abc.class_info.get(class_info);
|
||||
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
|
||||
|
||||
//static initializer
|
||||
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, ignoredPackage, fullyQualifiedNames, new ArrayList<>());
|
||||
|
||||
//instance initializer
|
||||
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, ignoredPackage, fullyQualifiedNames, new ArrayList<>());
|
||||
|
||||
//static
|
||||
classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, ignoredPackage, fullyQualifiedNames);
|
||||
|
||||
//instance
|
||||
instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, ignoredPackage, fullyQualifiedNames);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user