Skip to content

Commit

Permalink
Add a parameter to exclude debug instructions from reassembled SWF
Browse files Browse the repository at this point in the history
  • Loading branch information
piepie62 committed May 12, 2022
1 parent 399dd88 commit d1e0221
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 26 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ Native/BytecodeEditor/BytecodeEditor.vcxproj.user
*.dll
AS3/bin
AS3/obj
*.ane
Binary file removed ANEBytecodeEditor.ane
Binary file not shown.
10 changes: 5 additions & 5 deletions AS3/src/com/cff/anebe/BytecodeEditor.as
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ package com.cff.anebe

// Assembles an SWF from a map of file name to file contents. If replaceSWF is unspecified, and Disassemble was called, uses
// the last SWF's data for the rest of the SWF.
public function Assemble(strings:Object, replaceSWF:ByteArray = null):ByteArray
public function Assemble(strings:Object, includeDebugInstructions:Boolean, replaceSWF:ByteArray = null):ByteArray
{
if (replaceSWF != null)
{
Expand Down Expand Up @@ -155,7 +155,7 @@ package com.cff.anebe
vec[vec.length] = str;
}

ret = extContext.call("Assemble", strings, vec);
ret = extContext.call("Assemble", strings, vec, includeDebugInstructions);

if (ret == null)
{
Expand Down Expand Up @@ -248,7 +248,7 @@ package com.cff.anebe

// Assembles an SWF from a map of file name to file contents, asynchronously. If replaceSWF is unspecified, and Disassemble was called, uses
// the last SWF's data for the rest of the SWF.
public function AssembleAsync(strings:Object, replaceSWF:ByteArray = null):void
public function AssembleAsync(strings:Object, includeDebugInstructions:Boolean, replaceSWF:ByteArray = null):void
{
if (replaceSWF != null)
{
Expand Down Expand Up @@ -310,7 +310,7 @@ package com.cff.anebe
vec[vec.length] = str;
}

ret = extContext.call("AssembleAsync", strings, vec);
ret = extContext.call("AssembleAsync", strings, vec, includeDebugInstructions);

if (ret == null)
{
Expand Down Expand Up @@ -364,4 +364,4 @@ package com.cff.anebe
}
}

}
}
19 changes: 15 additions & 4 deletions Native/BytecodeEditor/include/Assembler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Assembler
{
private:
const std::unordered_map<std::string, std::string>& strings;
bool includeDebugInstructions;

static constexpr char addUniqueMethod[] = "method";
static constexpr char addUniqueClass[] = "class";
Expand Down Expand Up @@ -1379,7 +1380,12 @@ class Assembler
OPCode(uint8_t(OPCode::OP_setlocal0) + instruction.arguments[0].uintv());
}

ret.emplace_back(std::move(instruction));
if (includeDebugInstructions || (instruction.opcode != OPCode::OP_debug &&
instruction.opcode != OPCode::OP_debugfile &&
instruction.opcode != OPCode::OP_debugline))
{
ret.emplace_back(std::move(instruction));
}
}

for (const auto& f : jumpFixups)
Expand Down Expand Up @@ -1471,7 +1477,11 @@ class Assembler
}
}

Assembler(const std::unordered_map<std::string, std::string>& strings) : strings(strings) {}
Assembler(
const std::unordered_map<std::string, std::string>& strings, bool includeDebugInstructions)
: strings(strings), includeDebugInstructions(includeDebugInstructions)
{
}

ASASM::ASProgram readProgram()
{
Expand Down Expand Up @@ -1565,14 +1575,15 @@ class Assembler
}

public:
static ASASM::ASProgram assemble(const std::unordered_map<std::string, std::string>& strings)
static ASASM::ASProgram assemble(
const std::unordered_map<std::string, std::string>& strings, bool includeDebugInstructions)
{
if (!strings.contains("main.asasm"))
{
throw StringException("Assembly start (main.asasm) not found");
}

Assembler assembler(strings);
Assembler assembler(strings, includeDebugInstructions);

std::shared_ptr<SourceFile> mainFile =
std::make_shared<SourceFile>("main.asasm", strings.at("main.asasm"));
Expand Down
7 changes: 4 additions & 3 deletions Native/BytecodeEditor/include/BytecodeEditor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <thread>
#include <unordered_map>
#include <variant>
#include <vector>

class BytecodeEditor
{
Expand All @@ -28,8 +29,8 @@ class BytecodeEditor
FREObject disassemble();
FREObject disassembleAsync();

FREObject assemble(std::unordered_map<std::string, std::string>&& data);
FREObject assembleAsync(std::unordered_map<std::string, std::string>&& data);
FREObject assemble(std::unordered_map<std::string, std::string>&& data, bool includeDebugInstructions);
FREObject assembleAsync(std::unordered_map<std::string, std::string>&& data, bool includeDebugInstructions);

void setSWF(SWF::SWFFile&& file) { currentSWF = std::move(file); }

Expand All @@ -39,7 +40,7 @@ class BytecodeEditor
{
runningTask.join();
}
currentSWF = std::nullopt;
currentSWF = std::nullopt;
m_taskResult = std::monostate{};
}

Expand Down
30 changes: 24 additions & 6 deletions Native/BytecodeEditor/source/ANEBytecodeEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ FREObject Disassemble(FREContext ctx, void* funcData, uint32_t argc, FREObject a

FREObject Assemble(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
if (argc != 2)
if (argc != 3)
{
FAIL("argc should be 2");
FAIL("argc should be 3");
}

GET_EDITOR(ctx);
Expand All @@ -49,6 +49,11 @@ FREObject Assemble(FREContext ctx, void* funcData, uint32_t argc, FREObject argv
{
FAIL("argv[1] is not a vector");
}
DO_OR_FAIL("Failed to get argv[2] type", FREGetObjectType(argv[2], &type));
if (type != FRE_TYPE_BOOLEAN)
{
FAIL("argv[2] is not a boolean");
}

uint32_t vecSize;
DO_OR_FAIL("Failed to get argv[1] size", FREGetArrayLength(argv[1], &vecSize));
Expand All @@ -72,7 +77,11 @@ FREObject Assemble(FREContext ctx, void* funcData, uint32_t argc, FREObject argv
strings.emplace(key, val);
}

return editor->assemble(std::move(strings));
uint32_t includeDebugInstructions;
DO_OR_FAIL("Failed to get argv[2]'s boolean value",
FREGetObjectAsBool(argv[2], &includeDebugInstructions));

return editor->assemble(std::move(strings), includeDebugInstructions != 0);
}

FREObject DisassembleAsync(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
Expand All @@ -89,9 +98,9 @@ FREObject DisassembleAsync(FREContext ctx, void* funcData, uint32_t argc, FREObj

FREObject AssembleAsync(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
if (argc != 2)
if (argc != 3)
{
FAIL("argc should be 2");
FAIL("argc should be 3");
}

GET_EDITOR(ctx);
Expand All @@ -107,6 +116,11 @@ FREObject AssembleAsync(FREContext ctx, void* funcData, uint32_t argc, FREObject
{
FAIL("argv[1] is not a vector");
}
DO_OR_FAIL("Failed to get argv[2] type", FREGetObjectType(argv[2], &type));
if (type != FRE_TYPE_BOOLEAN)
{
FAIL("argv[2] is not a boolean");
}

uint32_t vecSize;
DO_OR_FAIL("Failed to get argv[1] size", FREGetArrayLength(argv[1], &vecSize));
Expand All @@ -130,7 +144,11 @@ FREObject AssembleAsync(FREContext ctx, void* funcData, uint32_t argc, FREObject
strings.emplace(key, val);
}

return editor->assembleAsync(std::move(strings));
uint32_t includeDebugInstructions;
DO_OR_FAIL("Failed to get argv[2]'s boolean value",
FREGetObjectAsBool(argv[2], &includeDebugInstructions));

return editor->assembleAsync(std::move(strings), includeDebugInstructions != 0);
}

FREObject AsyncTaskResult(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
Expand Down
19 changes: 11 additions & 8 deletions Native/BytecodeEditor/source/BytecodeEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ FREObject BytecodeEditor::disassemble()
}
}

FREObject BytecodeEditor::assemble(std::unordered_map<std::string, std::string>&& strings)
FREObject BytecodeEditor::assemble(
std::unordered_map<std::string, std::string>&& strings, bool includeDebugInstructions)
{
if (runningTask.joinable())
{
Expand All @@ -62,8 +63,8 @@ FREObject BytecodeEditor::assemble(std::unordered_map<std::string, std::string>&
{
FAIL("No SWF data specified to reassemble");
}
std::vector<uint8_t> data =
std::move(ABC::ABCWriter(Assembler::assemble(strings).toABC()).data());
std::vector<uint8_t> data = std::move(
ABC::ABCWriter(Assembler::assemble(strings, includeDebugInstructions).toABC()).data());

currentSWF->replaceABCData(data.data(), data.size());

Expand Down Expand Up @@ -117,22 +118,24 @@ FREObject BytecodeEditor::disassembleAsync()
return ret;
}

FREObject BytecodeEditor::assembleAsync(std::unordered_map<std::string, std::string>&& strings)
FREObject BytecodeEditor::assembleAsync(
std::unordered_map<std::string, std::string>&& strings, bool includeDebugInstructions)
{
if (runningTask.joinable())
{
FAIL("Already running a task");
}

runningTask = std::jthread([this, strings = std::move(strings)] {
runningTask = std::jthread([this, strings = std::move(strings), includeDebugInstructions] {
if (!currentSWF)
{
FAIL_ASYNC("No SWF data specified to reassemble");
}
try
{
std::vector<uint8_t> data =
std::move(ABC::ABCWriter(Assembler::assemble(strings).toABC()).data());
std::vector<uint8_t> data = std::move(
ABC::ABCWriter(Assembler::assemble(strings, includeDebugInstructions).toABC())
.data());

currentSWF->replaceABCData(data.data(), data.size());

Expand Down Expand Up @@ -225,4 +228,4 @@ FREObject BytecodeEditor::taskResult()
default:
FAIL("Invalid task result index");
}
}
}

0 comments on commit d1e0221

Please sign in to comment.