7 Commits
4 changed files with 114 additions and 67 deletions
+36
View File
@@ -0,0 +1,36 @@
RABCDAsm Changelog
==================
RABCDAsm v1.3 (2010.11.11)
--------------------------
* Fixed double precision problem
* This also fixes problems with illegal default values for function
parameters (default values for integer parameters are stored as doubles,
which might become out-of-range due to inadequate double precision)
* Added Changelog
* Documentation markdown fixes
RABCDAsm v1.2 (2010.11.06)
--------------------------
* Fixed ref generation for orphan objects which were only referenced
by other orphans
* Better error handling in `abcexport`; warn when no DoABC tags found
* Documentation updates
RABCDAsm v1.1 (2010.06.30)
--------------------------
* Private namespaces are now referenced by auto-generated names
* Use `:` to delimit namespace and name in QNames for consistency
* Warning: this breaks compatibility with v1.0 disassemblies
* Fixed relative include paths
* Add optional byte offsets to labels, which allows lossless representation
of jumps inside instructions and outside the function bounds
* Documentation updates
RABCDAsm v1.0 (2010.05.05)
--------------------------
* Initial release.
+49 -48
View File
@@ -1,7 +1,7 @@
Robust ABC (ActionScript Bytecode) [Dis-]Assembler
==================================================
[RABCDAsm][] is a collection of utilities including an ActionScript
[RABCDAsm][] is a collection of utilities including an ActionScript 3
assembler/disassembler, and a few tools to manipulate SWF files.
These are:
@@ -31,7 +31,7 @@ Motivation and goals
--------------------
This package was created due to lack of similar software out there.
Particularly, I needed an utility which would allow me to edit ActionScript
Particularly, I needed an utility which would allow me to edit ActionScript 3
bytecode with the following properties:
1. Speed. Less waiting means more productivity. `rabcasm` can assemble large
@@ -102,6 +102,9 @@ To assemble the `.asasm` files back, and update the SWF file:
rabcasm file0/file0.main.asasm
abcreplace file0.swf 0 file0/file0.main.abc
The second `abcreplace` argument represents the index of the ABC block in the
SWF file, and corresponds to the number in the filename created by `abcexport`.
Syntax
======
@@ -294,9 +297,9 @@ be instantiated in two ways:
although variables are defined using a string syntax, they are not
inserted as a string using this syntax. Thus, the code:
#set str "Hello, world!"
...
pushstring $str
#set str "Hello, world!"
...
pushstring $str
will expand to `pushstring Hello, world!`, which will result in an error.
To correct the problem, add escaped quotes around the variable contents
@@ -311,20 +314,20 @@ be instantiated in two ways:
Here's an example of how to use the above features to create a macro which
logs a string literal and the contents of a register:
#set log "
findpropstrict QName(PackageNamespace(\"\"), \"log\")
pushstring $\"1\"
getlocal $2
callpropvoid QName(PackageNamespace(\"\"), \"log\"), 2
"
; ...
pushbyte 2
pushbyte 2
add_i
setlocal1
#call $"log"("two plus two equals", "1")
#set log "
findpropstrict QName(PackageNamespace(\"\"), \"log\")
pushstring $\"1\"
getlocal $2
callpropvoid QName(PackageNamespace(\"\"), \"log\"), 2
"
; ...
pushbyte 2
pushbyte 2
add_i
setlocal1
#call $"log"("two plus two equals", "1")
Highlighting
------------
@@ -344,19 +347,19 @@ instead of indexes, allowing easy manipulation without having to worry about
record order or constant pools. Conversion between various states is done as
follows:
file.abc
| ^
ABCReader | | ABCWriter
v |
ABCFile
| ^
ABCtoAS | | AStoABC
v |
ASProgram
| ^
Disassembler | | Assembler
v |
file.asasm
file.abc
| ^
------ ABCReader | | ABCWriter ----
/ v | \
/ ABCFile \
/ | ^ \
rabcdasm---------- ABCtoAS | | AStoABC --------rabcasm
\ v | /
\ ASProgram /
\ | ^ /
--- Disassembler | | Assembler ----
v |
file.asasm
`AStoABC` will rebuild the constant pools, in a manner similar to Adobe's
compilers (reverse-sorted by reference count). The exact order will almost
@@ -394,19 +397,19 @@ RABCDAsm users.
placed in the `OnBeforeResponse` function) will automatically save all SWF
files while preserving the directory structure.
if (oSession.oResponse.headers.ExistsAndContains("Content-Type",
"application/x-shockwave-flash")) {
// Set desired path here
var path:String = "C:\\Temp\\FiddlerCapture\\" +
oSession.host + oSession.PathAndQuery;
if (path.Contains('?'))
path = path.Substring(0, path.IndexOf('?'));
var dir:String = Path.GetDirectoryName(path);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
oSession.utilDecodeResponse();
oSession.SaveResponseBody(path);
}
if (oSession.oResponse.headers.ExistsAndContains("Content-Type",
"application/x-shockwave-flash")) {
// Set desired path here
var path:String = "C:\\Temp\\FiddlerCapture\\" +
oSession.host + oSession.PathAndQuery;
if (path.Contains('?'))
path = path.Substring(0, path.IndexOf('?'));
var dir:String = Path.GetDirectoryName(path);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
oSession.utilDecodeResponse();
oSession.SaveResponseBody(path);
}
Once you have edited a SWF file, you can use Fiddler's [AutoResponder][] to
replace the original file with your modified version.
@@ -420,8 +423,6 @@ Limitations
* Metadata is currently ignored. I haven't noticed any metadata blocks in any
SWF files I've disassembled.
* Floating point numbers may not be disassembled with adequate precision.
* `rabcasm` may create a broken file due to not ordering classes by ancestry.
The problem originates from the fact that a class's ancestors (extended
@@ -432,7 +433,7 @@ Limitations
of order. This results in a file that, when opened, will fail to load with
an error message similar to:
`VerifyError: Error #1014: Class AncestorClassName could not be found.`
VerifyError: Error #1014: Class AncestorClassName could not be found.
The simple work-around is to re-order the classes as they are declared in
the `.main.asasm` file, and place ancestors before descendants.
+22 -16
View File
@@ -21,6 +21,7 @@ module abcexport;
import std.file;
import std.path;
import std.string;
import std.stdio;
import swffile;
void main(string[] args)
@@ -28,22 +29,27 @@ void main(string[] args)
if (args.length == 1)
throw new Exception("No file specified");
foreach (arg; args[1..$])
{
scope swf = SWFFile.read(cast(ubyte[])read(arg));
uint count;
foreach (ref tag; swf.tags)
if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2))
{
ubyte[] abc;
if (tag.type == TagType.DoABC)
abc = tag.data;
else
try
{
scope swf = SWFFile.read(cast(ubyte[])read(arg));
uint count = 0;
foreach (ref tag; swf.tags)
if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2))
{
auto p = tag.data.ptr+4; // skip flags
while (*p++) {} // skip name
abc = tag.data[p-tag.data.ptr..$];
ubyte[] abc;
if (tag.type == TagType.DoABC)
abc = tag.data;
else
{
auto p = tag.data.ptr+4; // skip flags
while (*p++) {} // skip name
abc = tag.data[p-tag.data.ptr..$];
}
write(getName(arg) ~ .toString(count++) ~ ".abc", abc);
}
write(getName(arg) ~ .toString(count++) ~ ".abc", abc);
}
}
if (count == 0)
throw new Exception("No DoABC tags found");
}
catch (Object o)
writefln("Error while processing %s: %s", arg, o);
}
+7 -3
View File
@@ -109,6 +109,10 @@ final class RefBuilder : ASTraitsVisitor
{
foreach (i, ref v; as.scripts)
addMethod(v.sinit, "script" ~ .toString(i) ~ "_sinit");
foreach (vclass; as.orphanClasses)
addClass(vclass, "orphan");
foreach (method; as.orphanMethods)
addMethod(method, "orphan");
super.run();
}
@@ -257,9 +261,9 @@ final class RefBuilder : ASTraitsVisitor
return uniqueName;
}
void addClass(ASProgram.Class vclass)
void addClass(ASProgram.Class vclass, string field = null)
{
addObject(vclass, classByName, string.init);
addObject(vclass, classByName, field);
addMethod(vclass.cinit, "cinit");
addMethod(vclass.instance.iinit, "iinit");
}
@@ -412,7 +416,7 @@ final class Disassembler
if (v == ABCFile.NULL_DOUBLE)
sb ~= "null";
else
sb ~= .toString(v);
sb ~= format("%.18g", v);
}
void dumpString(StringBuilder sb, string str)