enable debugging of SWF file, from commandline

This commit is contained in:
Jindra Petřík
2015-10-24 19:13:36 +02:00
parent eab1e53e2a
commit b9c289464d
3 changed files with 202 additions and 0 deletions

View File

@@ -80,10 +80,14 @@ import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag;
import com.jpexs.decompiler.flash.tags.EnableDebuggerTag;
import com.jpexs.decompiler.flash.tags.EndTag;
import com.jpexs.decompiler.flash.tags.ExportAssetsTag;
import com.jpexs.decompiler.flash.tags.FileAttributesTag;
import com.jpexs.decompiler.flash.tags.JPEGTablesTag;
import com.jpexs.decompiler.flash.tags.MetadataTag;
import com.jpexs.decompiler.flash.tags.ProtectTag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SymbolClassTag;
@@ -3086,4 +3090,51 @@ public final class SWF implements SWFContainerItem, Timelined {
}
}
}
/**
* Enables debugging. Adds tags to enable debugging and injects debugline
* and debugfile instructions to AS3 code
*
* @param injectCode Modify AS3 code with debugfile / debugline ?
*/
public void enableDebugging(boolean injectCode) {
if (injectCode) {
List<ScriptPack> packs = getAS3Packs();
for (ScriptPack s : packs) {
if (s.isSimple) {
s.injectDebugInfo();
}
}
}
int pos = 0;
for (int i = 0; i < tags.size(); i++) {
Tag t = tags.get(i);
if (t instanceof MetadataTag) {
pos = i + 1;
}
if (t instanceof FileAttributesTag) {
pos = i + 1;
}
if (version >= 6 && (t instanceof EnableDebugger2Tag)) {
return;
}
if (version == 5 && (t instanceof EnableDebuggerTag)) {
return;
}
if (version < 5 && (t instanceof ProtectTag)) {
return;
}
}
if (version >= 6) {
tags.add(pos, new EnableDebugger2Tag(this));
} else if (version == 5) {
tags.add(pos, new EnableDebuggerTag(this));
} else {
tags.add(pos, new ProtectTag(this));
}
}
}

View File

@@ -17,11 +17,18 @@
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConvertException;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.types.ConvertData;
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.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
@@ -29,6 +36,8 @@ import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings;
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.ScopeStack;
@@ -40,8 +49,14 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -293,4 +308,86 @@ public class ScriptPack extends AS3ClassTreeItem {
public boolean isModified() {
return abc.script_info.get(scriptIndex).isModified();
}
/**
* Injects debugfile, debugline instructions into the code
*
* Based on idea of Jacob Thompson
* http://securityevaluators.com/knowledge/flash/
*/
public void injectDebugInfo() {
Map<Integer, Map<Integer, Integer>> bodyToPosToLine = new HashMap<>();
try {
CachedDecompilation decompiled = SWF.getCached(this);
int line = 1;
String txt = decompiled.text;
txt = txt.replace("\r", "");
for (int i = 0; i < txt.length(); i++) {
if (txt.charAt(i) == '\n') {
line++;
}
Highlighting cls = Highlighting.searchPos(decompiled.classHilights, i);
if (cls == null) {
continue;
}
Highlighting trt = Highlighting.searchPos(decompiled.traitHilights, i);
if (trt == null) {
continue;
}
Highlighting method = Highlighting.searchPos(decompiled.methodHilights, i);
if (method == null) {
continue;
}
Highlighting instr = Highlighting.searchPos(decompiled.instructionHilights, i);
if (instr == null) {
continue;
}
int classIndex = (int) cls.getProperties().index;
int methodIndex = (int) method.getProperties().index;
int bodyIndex = abc.findBodyIndex(methodIndex);
if (bodyIndex == -1) {
continue;
}
long instrOffset = instr.getProperties().offset;
int traitIndex = (int) trt.getProperties().index;
Trait trait = abc.findTraitByTraitId(classIndex, traitIndex);
if (((trait instanceof TraitMethodGetterSetter) && (((TraitMethodGetterSetter) trait).method_info != methodIndex))
|| ((trait instanceof TraitFunction) && (((TraitFunction) trait).method_info != methodIndex))) {
continue; //inner anonymous function - ignore. TODO: make work
}
int pos = -1;
try {
abc.bodies.get(bodyIndex).getCode().adr2pos(instrOffset);
} catch (ConvertException cex) {
//ignore
}
if (pos == -1) {
continue;
}
if (!bodyToPosToLine.containsKey(bodyIndex)) {
bodyToPosToLine.put(bodyIndex, new HashMap<>());
}
bodyToPosToLine.get(bodyIndex).put(pos, line);
}
} catch (InterruptedException ex) {
Logger.getLogger(ScriptPack.class.getName()).log(Level.SEVERE, "Cannot decompile", ex);
}
String filename = path.toString().replace('.', '/') + ".as";
for (int bodyIndex : bodyToPosToLine.keySet()) {
MethodBody b = abc.bodies.get(bodyIndex);
b.insertInstruction(0, new AVM2Instruction(0, AVM2Instructions.DebugFile, new int[]{abc.constants.getStringId(filename, true)}), true);
List<Integer> pos = new ArrayList<>(bodyToPosToLine.get(bodyIndex).keySet());
Collections.sort(pos);
Collections.reverse(pos);
for (int i : pos) {
int line = bodyToPosToLine.get(bodyIndex).get(i);
b.insertInstruction(i, new AVM2Instruction(0, AVM2Instructions.DebugLine, new int[]{line}));
}
}
((Tag) abc.parentTag).setModified(true);
}
}