From 2fd7ccf7a1def37977c2fe0be1564961875b7a9b Mon Sep 17 00:00:00 2001 From: Chris Feger Date: Fri, 10 Feb 2023 23:02:19 -0700 Subject: [PATCH] Use strings for namespace disambiguation in AS3 Also cleans up memory rather than leaking it now --- ANEBytecodeEditorSWC.as3proj | 93 +++++++++++ AS3/src/com/cff/anebe/ir/ASNamespace.as | 10 +- .../anebe/ir/namespaces/ExplicitNamespace.as | 6 +- .../anebe/ir/namespaces/NormalNamespace.as | 6 +- .../anebe/ir/namespaces/PackageInternalNs.as | 6 +- .../anebe/ir/namespaces/PackageNamespace.as | 6 +- .../anebe/ir/namespaces/PrivateNamespace.as | 6 +- .../anebe/ir/namespaces/ProtectedNamespace.as | 6 +- .../anebe/ir/namespaces/StaticProtectedNs.as | 6 +- Native/BytecodeEditor/BytecodeEditor.vcxproj | 2 + Native/BytecodeEditor/include/ABC/ABCFile.hpp | 2 +- .../BytecodeEditor/include/ABC/ABCReader.hpp | 2 +- .../BytecodeEditor/include/ABC/ABCWriter.hpp | 2 +- Native/BytecodeEditor/include/ABC/Class.hpp | 2 +- Native/BytecodeEditor/include/ABC/Error.hpp | 2 +- .../include/ABC/ExceptionInfo.hpp | 2 +- .../BytecodeEditor/include/ABC/Instance.hpp | 2 +- .../include/ABC/Instruction.hpp | 2 +- Native/BytecodeEditor/include/ABC/Label.hpp | 4 +- .../BytecodeEditor/include/ABC/Metadata.hpp | 2 +- .../BytecodeEditor/include/ABC/MethodBody.hpp | 2 +- .../BytecodeEditor/include/ABC/MethodInfo.hpp | 2 +- .../BytecodeEditor/include/ABC/Multiname.hpp | 2 +- .../BytecodeEditor/include/ABC/Namespace.hpp | 2 +- .../include/ABC/OptionDetail.hpp | 2 +- Native/BytecodeEditor/include/ABC/Script.hpp | 2 +- .../BytecodeEditor/include/ABC/TraitsInfo.hpp | 2 +- .../BytecodeEditor/include/ANEFunctions.hpp | 6 +- .../BytecodeEditor/include/ANEFunctions.tcc | 20 ++- .../include/ASASM/ASProgram.hpp | 4 +- .../BytecodeEditor/include/ASASM/AStoABC.hpp | 42 ++--- .../include/ASASM/Exception.hpp | 2 +- .../include/ASASM/Instruction.hpp | 22 +-- .../include/ASASM/MethodBody.hpp | 2 +- .../include/ASASM/Namespace.hpp | 4 + Native/BytecodeEditor/include/Assembler.hpp | 28 ++-- .../BytecodeEditor/include/BytecodeEditor.hpp | 32 +++- .../BytecodeEditor/include/Disassembler.hpp | 14 +- .../include/utils/ANEFunctionContext.hpp | 23 +++ .../BytecodeEditor/include/utils/ANEUtils.hpp | 24 --- .../include/utils/RefBuilder.hpp | 80 +++++++--- .../include/utils/StringUtils.hpp | 10 +- .../include/utils/ValuePool.hpp | 4 +- .../include/utils/generic_hash.hpp | 35 ++++ .../source/ANEBytecodeEditor.cpp | 150 +++++++++--------- .../source/ANEBytecodeEditorFunctions.cpp | 42 +++-- .../BytecodeEditor/source/ASASM/ASProgram.cpp | 30 ++-- .../BytecodeEditor/source/ASTypeFunctions.cpp | 55 ++++--- .../BytecodeEditor/source/BytecodeEditor.cpp | 49 ++++-- .../BytecodeEditor/source/Test.cpp.disabled | 4 +- .../BytecodeEditor/source/utils/ANEUtils.cpp | 111 +++++++++---- 51 files changed, 638 insertions(+), 338 deletions(-) create mode 100644 ANEBytecodeEditorSWC.as3proj create mode 100644 Native/BytecodeEditor/include/utils/ANEFunctionContext.hpp create mode 100644 Native/BytecodeEditor/include/utils/generic_hash.hpp diff --git a/ANEBytecodeEditorSWC.as3proj b/ANEBytecodeEditorSWC.as3proj new file mode 100644 index 0000000..2da0727 --- /dev/null +++ b/ANEBytecodeEditorSWC.as3proj @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "$(BaseDir)\Tools\swcbuild\swcbuild.exe" "$(ProjectPath)" "-compiler=$(CompilerPath)" "-debug=$(BuildConfig)" "-library=C:\Program Files (x86)\FlashDevelop\Library" -asdoc=true -keep-asdoc=false + + + + + + + + \ No newline at end of file diff --git a/AS3/src/com/cff/anebe/ir/ASNamespace.as b/AS3/src/com/cff/anebe/ir/ASNamespace.as index 61cc028..e7d5ee0 100644 --- a/AS3/src/com/cff/anebe/ir/ASNamespace.as +++ b/AS3/src/com/cff/anebe/ir/ASNamespace.as @@ -12,8 +12,8 @@ package com.cff.anebe.ir /** Namespace name. */ public var name:String; - /** If there are multiple namespaces with the same name, disambiguates them. This should only very rarely be non-zero. */ - public var id:int = 0; + /** If there are multiple namespaces with the same name, disambiguates them. This should only very rarely be non-null. */ + public var secondaryName:String; /** Type string for private namespaces */ public static const TYPE_PRIVATE:String = "PrivateNamespace"; @@ -40,13 +40,13 @@ package com.cff.anebe.ir * Builds an ASNamespace from scratch. Should probably not be used; see instead helper functions in the package com.cff.anebe.ir.namespaces * @param type Namespace type * @param name Namespace name - * @param id Disambiguation ID + * @param secondaryName Namespace secondary name, if disambiguation is required */ - public function ASNamespace(type:String, name:String, id:int = 0) + public function ASNamespace(type:String, name:String, secondaryName:String = null) { this.type = type; this.name = name; - this.id = id; + this.secondaryName = secondaryName; } } } diff --git a/AS3/src/com/cff/anebe/ir/namespaces/ExplicitNamespace.as b/AS3/src/com/cff/anebe/ir/namespaces/ExplicitNamespace.as index 545e114..fce15a2 100644 --- a/AS3/src/com/cff/anebe/ir/namespaces/ExplicitNamespace.as +++ b/AS3/src/com/cff/anebe/ir/namespaces/ExplicitNamespace.as @@ -5,11 +5,11 @@ package com.cff.anebe.ir.namespaces /** * Builds an ASNamespace that represents an ExplicitNamespace * @param name Name of the namespace - * @param id If there are multiple of the same namespace name and type, disambiguates between them; should almost always be zero + * @param disambiguator If there are multiple of the same namespace name and type, disambiguates between them; should almost always be null * @return Built ASNamespace */ - public function ExplicitNamespace(name:String, id:int = 0):ASNamespace + public function ExplicitNamespace(name:String, disambiguator:String = null):ASNamespace { - return new ASNamespace(ASNamespace.TYPE_EXPLICIT, name, id); + return new ASNamespace(ASNamespace.TYPE_EXPLICIT, name, disambiguator); } } diff --git a/AS3/src/com/cff/anebe/ir/namespaces/NormalNamespace.as b/AS3/src/com/cff/anebe/ir/namespaces/NormalNamespace.as index 6e156a8..b519ce8 100644 --- a/AS3/src/com/cff/anebe/ir/namespaces/NormalNamespace.as +++ b/AS3/src/com/cff/anebe/ir/namespaces/NormalNamespace.as @@ -5,11 +5,11 @@ package com.cff.anebe.ir.namespaces /** * Builds an ASNamespace that represents a Namespace * @param name Name of the namespace - * @param id If there are multiple of the same namespace name and type, disambiguates between them; should almost always be zero + * @param disambiguator If there are multiple of the same namespace name and type, disambiguates between them; should almost always be null * @return Built ASNamespace */ - public function NormalNamespace(name:String, id:int = 0):ASNamespace + public function NormalNamespace(name:String, disambiguator:String = null):ASNamespace { - return new ASNamespace(ASNamespace.TYPE_NORMAL, name, id); + return new ASNamespace(ASNamespace.TYPE_NORMAL, name, disambiguator); } } diff --git a/AS3/src/com/cff/anebe/ir/namespaces/PackageInternalNs.as b/AS3/src/com/cff/anebe/ir/namespaces/PackageInternalNs.as index 7de0240..7a1caa6 100644 --- a/AS3/src/com/cff/anebe/ir/namespaces/PackageInternalNs.as +++ b/AS3/src/com/cff/anebe/ir/namespaces/PackageInternalNs.as @@ -5,11 +5,11 @@ package com.cff.anebe.ir.namespaces /** * Builds an ASNamespace that represents a PackageInternalNs * @param name Name of the namespace - * @param id If there are multiple of the same namespace name and type, disambiguates between them; should almost always be zero + * @param disambiguator If there are multiple of the same namespace name and type, disambiguates between them; should almost always be null * @return Built ASNamespace */ - public function PackageInternalNs(name:String, id:int = 0):ASNamespace + public function PackageInternalNs(name:String, disambiguator:String = null):ASNamespace { - return new ASNamespace(ASNamespace.TYPE_PACKAGEINTERNAL, name, id); + return new ASNamespace(ASNamespace.TYPE_PACKAGEINTERNAL, name, disambiguator); } } diff --git a/AS3/src/com/cff/anebe/ir/namespaces/PackageNamespace.as b/AS3/src/com/cff/anebe/ir/namespaces/PackageNamespace.as index 7814e98..1747810 100644 --- a/AS3/src/com/cff/anebe/ir/namespaces/PackageNamespace.as +++ b/AS3/src/com/cff/anebe/ir/namespaces/PackageNamespace.as @@ -5,11 +5,11 @@ package com.cff.anebe.ir.namespaces /** * Builds an ASNamespace that represents a PackageNamespace * @param name Name of the namespace - * @param id If there are multiple of the same namespace name and type, disambiguates between them; should almost always be zero + * @param disambiguator If there are multiple of the same namespace name and type, disambiguates between them; should almost always be null * @return Built ASNamespace */ - public function PackageNamespace(name:String, id:int = 0):ASNamespace + public function PackageNamespace(name:String, disambiguator:String = null):ASNamespace { - return new ASNamespace(ASNamespace.TYPE_PACKAGE, name, id); + return new ASNamespace(ASNamespace.TYPE_PACKAGE, name, disambiguator); } } diff --git a/AS3/src/com/cff/anebe/ir/namespaces/PrivateNamespace.as b/AS3/src/com/cff/anebe/ir/namespaces/PrivateNamespace.as index 98d9a10..a5f726b 100644 --- a/AS3/src/com/cff/anebe/ir/namespaces/PrivateNamespace.as +++ b/AS3/src/com/cff/anebe/ir/namespaces/PrivateNamespace.as @@ -5,11 +5,11 @@ package com.cff.anebe.ir.namespaces /** * Builds an ASNamespace that represents an PrivateNamespace * @param name Name of the namespace - * @param id If there are multiple of the same namespace name and type, disambiguates between them; should almost always be zero + * @param disambiguator If there are multiple of the same namespace name and type, disambiguates between them; should almost always be null * @return Built ASNamespace */ - public function PrivateNamespace(name:String, id:int = 0):ASNamespace + public function PrivateNamespace(name:String, disambiguator:String = null):ASNamespace { - return new ASNamespace(ASNamespace.TYPE_PRIVATE, name, id); + return new ASNamespace(ASNamespace.TYPE_PRIVATE, name, disambiguator); } } diff --git a/AS3/src/com/cff/anebe/ir/namespaces/ProtectedNamespace.as b/AS3/src/com/cff/anebe/ir/namespaces/ProtectedNamespace.as index bd72a08..b04ef2d 100644 --- a/AS3/src/com/cff/anebe/ir/namespaces/ProtectedNamespace.as +++ b/AS3/src/com/cff/anebe/ir/namespaces/ProtectedNamespace.as @@ -5,11 +5,11 @@ package com.cff.anebe.ir.namespaces /** * Builds an ASNamespace that represents a ProtectedNamespace * @param name Name of the namespace - * @param id If there are multiple of the same namespace name and type, disambiguates between them; should almost always be zero + * @param disambiguator If there are multiple of the same namespace name and type, disambiguates between them; should almost always be null * @return Built ASNamespace */ - public function ProtectedNamespace(name:String, id:int = 0):ASNamespace + public function ProtectedNamespace(name:String, disambiguator:String = null):ASNamespace { - return new ASNamespace(ASNamespace.TYPE_PROTECTED, name, id); + return new ASNamespace(ASNamespace.TYPE_PROTECTED, name, disambiguator); } } diff --git a/AS3/src/com/cff/anebe/ir/namespaces/StaticProtectedNs.as b/AS3/src/com/cff/anebe/ir/namespaces/StaticProtectedNs.as index 099c2a6..674850e 100644 --- a/AS3/src/com/cff/anebe/ir/namespaces/StaticProtectedNs.as +++ b/AS3/src/com/cff/anebe/ir/namespaces/StaticProtectedNs.as @@ -5,11 +5,11 @@ package com.cff.anebe.ir.namespaces /** * Builds an ASNamespace that represents a StaticProtectedNs * @param name Name of the namespace - * @param id If there are multiple of the same namespace name and type, disambiguates between them; should almost always be zero + * @param disambiguator If there are multiple of the same namespace name and type, disambiguates between them; should almost always be null * @return Built ASNamespace */ - public function StaticProtectedNs(name:String, id:int = 0):ASNamespace + public function StaticProtectedNs(name:String, disambiguator:String = null):ASNamespace { - return new ASNamespace(ASNamespace.TYPE_STATICPROTECTED, name, id); + return new ASNamespace(ASNamespace.TYPE_STATICPROTECTED, name, disambiguator); } } diff --git a/Native/BytecodeEditor/BytecodeEditor.vcxproj b/Native/BytecodeEditor/BytecodeEditor.vcxproj index 110217b..b8a7904 100644 --- a/Native/BytecodeEditor/BytecodeEditor.vcxproj +++ b/Native/BytecodeEditor/BytecodeEditor.vcxproj @@ -160,8 +160,10 @@ + + diff --git a/Native/BytecodeEditor/include/ABC/ABCFile.hpp b/Native/BytecodeEditor/include/ABC/ABCFile.hpp index 8d2d688..ae0d347 100644 --- a/Native/BytecodeEditor/include/ABC/ABCFile.hpp +++ b/Native/BytecodeEditor/include/ABC/ABCFile.hpp @@ -11,7 +11,7 @@ #include #include -namespace ABC +namespace SWFABC { struct ABCFile { diff --git a/Native/BytecodeEditor/include/ABC/ABCReader.hpp b/Native/BytecodeEditor/include/ABC/ABCReader.hpp index fe6e36f..17821fc 100644 --- a/Native/BytecodeEditor/include/ABC/ABCReader.hpp +++ b/Native/BytecodeEditor/include/ABC/ABCReader.hpp @@ -32,7 +32,7 @@ #include #include -namespace ABC +namespace SWFABC { class ABCReader { diff --git a/Native/BytecodeEditor/include/ABC/ABCWriter.hpp b/Native/BytecodeEditor/include/ABC/ABCWriter.hpp index 90f0ca1..0938bba 100644 --- a/Native/BytecodeEditor/include/ABC/ABCWriter.hpp +++ b/Native/BytecodeEditor/include/ABC/ABCWriter.hpp @@ -30,7 +30,7 @@ #include #include -namespace ABC +namespace SWFABC { class ABCWriter { diff --git a/Native/BytecodeEditor/include/ABC/Class.hpp b/Native/BytecodeEditor/include/ABC/Class.hpp index 360dfff..750a085 100644 --- a/Native/BytecodeEditor/include/ABC/Class.hpp +++ b/Native/BytecodeEditor/include/ABC/Class.hpp @@ -4,7 +4,7 @@ #include #include -namespace ABC +namespace SWFABC { struct Class { diff --git a/Native/BytecodeEditor/include/ABC/Error.hpp b/Native/BytecodeEditor/include/ABC/Error.hpp index 38076ed..6eb6c32 100644 --- a/Native/BytecodeEditor/include/ABC/Error.hpp +++ b/Native/BytecodeEditor/include/ABC/Error.hpp @@ -3,7 +3,7 @@ #include "ABC/Label.hpp" #include -namespace ABC +namespace SWFABC { struct Error { diff --git a/Native/BytecodeEditor/include/ABC/ExceptionInfo.hpp b/Native/BytecodeEditor/include/ABC/ExceptionInfo.hpp index 036ad68..78b52dc 100644 --- a/Native/BytecodeEditor/include/ABC/ExceptionInfo.hpp +++ b/Native/BytecodeEditor/include/ABC/ExceptionInfo.hpp @@ -3,7 +3,7 @@ #include "ABC/Label.hpp" #include -namespace ABC +namespace SWFABC { struct ExceptionInfo { diff --git a/Native/BytecodeEditor/include/ABC/Instance.hpp b/Native/BytecodeEditor/include/ABC/Instance.hpp index f860554..305e2ec 100644 --- a/Native/BytecodeEditor/include/ABC/Instance.hpp +++ b/Native/BytecodeEditor/include/ABC/Instance.hpp @@ -4,7 +4,7 @@ #include #include -namespace ABC +namespace SWFABC { struct Instance { diff --git a/Native/BytecodeEditor/include/ABC/Instruction.hpp b/Native/BytecodeEditor/include/ABC/Instruction.hpp index 1b5a738..a99f868 100644 --- a/Native/BytecodeEditor/include/ABC/Instruction.hpp +++ b/Native/BytecodeEditor/include/ABC/Instruction.hpp @@ -6,7 +6,7 @@ #include #include -namespace ABC +namespace SWFABC { struct Instruction { diff --git a/Native/BytecodeEditor/include/ABC/Label.hpp b/Native/BytecodeEditor/include/ABC/Label.hpp index 59260b3..5a69d11 100644 --- a/Native/BytecodeEditor/include/ABC/Label.hpp +++ b/Native/BytecodeEditor/include/ABC/Label.hpp @@ -1,9 +1,9 @@ #pragma once -#include #include +#include -namespace ABC +namespace SWFABC { struct Label { diff --git a/Native/BytecodeEditor/include/ABC/Metadata.hpp b/Native/BytecodeEditor/include/ABC/Metadata.hpp index adb5621..dda9d7e 100644 --- a/Native/BytecodeEditor/include/ABC/Metadata.hpp +++ b/Native/BytecodeEditor/include/ABC/Metadata.hpp @@ -3,7 +3,7 @@ #include #include -namespace ABC +namespace SWFABC { struct Metadata { diff --git a/Native/BytecodeEditor/include/ABC/MethodBody.hpp b/Native/BytecodeEditor/include/ABC/MethodBody.hpp index 25a40c7..2d9d812 100644 --- a/Native/BytecodeEditor/include/ABC/MethodBody.hpp +++ b/Native/BytecodeEditor/include/ABC/MethodBody.hpp @@ -7,7 +7,7 @@ #include #include -namespace ABC +namespace SWFABC { struct MethodBody { diff --git a/Native/BytecodeEditor/include/ABC/MethodInfo.hpp b/Native/BytecodeEditor/include/ABC/MethodInfo.hpp index 671e5e0..de137fe 100644 --- a/Native/BytecodeEditor/include/ABC/MethodInfo.hpp +++ b/Native/BytecodeEditor/include/ABC/MethodInfo.hpp @@ -4,7 +4,7 @@ #include #include -namespace ABC +namespace SWFABC { struct MethodInfo { diff --git a/Native/BytecodeEditor/include/ABC/Multiname.hpp b/Native/BytecodeEditor/include/ABC/Multiname.hpp index 913b801..a6b1eca 100644 --- a/Native/BytecodeEditor/include/ABC/Multiname.hpp +++ b/Native/BytecodeEditor/include/ABC/Multiname.hpp @@ -5,7 +5,7 @@ #include #include -namespace ABC +namespace SWFABC { struct Multiname { diff --git a/Native/BytecodeEditor/include/ABC/Namespace.hpp b/Native/BytecodeEditor/include/ABC/Namespace.hpp index b31c650..73e28d0 100644 --- a/Native/BytecodeEditor/include/ABC/Namespace.hpp +++ b/Native/BytecodeEditor/include/ABC/Namespace.hpp @@ -3,7 +3,7 @@ #include "enums/ABCType.hpp" #include -namespace ABC +namespace SWFABC { struct Namespace { diff --git a/Native/BytecodeEditor/include/ABC/OptionDetail.hpp b/Native/BytecodeEditor/include/ABC/OptionDetail.hpp index b1d06a5..2883809 100644 --- a/Native/BytecodeEditor/include/ABC/OptionDetail.hpp +++ b/Native/BytecodeEditor/include/ABC/OptionDetail.hpp @@ -3,7 +3,7 @@ #include "enums/ABCType.hpp" #include -namespace ABC +namespace SWFABC { struct OptionDetail { diff --git a/Native/BytecodeEditor/include/ABC/Script.hpp b/Native/BytecodeEditor/include/ABC/Script.hpp index 204bed7..dfaeefe 100644 --- a/Native/BytecodeEditor/include/ABC/Script.hpp +++ b/Native/BytecodeEditor/include/ABC/Script.hpp @@ -4,7 +4,7 @@ #include #include -namespace ABC +namespace SWFABC { struct Script { diff --git a/Native/BytecodeEditor/include/ABC/TraitsInfo.hpp b/Native/BytecodeEditor/include/ABC/TraitsInfo.hpp index 9c8c62f..3126757 100644 --- a/Native/BytecodeEditor/include/ABC/TraitsInfo.hpp +++ b/Native/BytecodeEditor/include/ABC/TraitsInfo.hpp @@ -5,7 +5,7 @@ #include #include -namespace ABC +namespace SWFABC { struct TraitsInfo { diff --git a/Native/BytecodeEditor/include/ANEFunctions.hpp b/Native/BytecodeEditor/include/ANEFunctions.hpp index 325d102..7cda36f 100644 --- a/Native/BytecodeEditor/include/ANEFunctions.hpp +++ b/Native/BytecodeEditor/include/ANEFunctions.hpp @@ -1,6 +1,7 @@ #pragma once #include "BytecodeEditor.hpp" +#include "utils/ANEFunctionContext.hpp" #include "utils/ANEUtils.hpp" #include #include @@ -9,14 +10,15 @@ #include -inline ASASM::Class* classPointerHelper = nullptr; -inline ASASM::Script* scriptPointerHelper = nullptr; +inline std::optional nextObjectContext; template &&, bool)> FREObject Assemble(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); template FREObject TransparentZeroArg(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); +template +FREObject CheckAssemblyValid(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); #include "ANEFunctions.tcc" diff --git a/Native/BytecodeEditor/include/ANEFunctions.tcc b/Native/BytecodeEditor/include/ANEFunctions.tcc index 66bebad..3a3f538 100644 --- a/Native/BytecodeEditor/include/ANEFunctions.tcc +++ b/Native/BytecodeEditor/include/ANEFunctions.tcc @@ -8,7 +8,7 @@ #include -#define GET_EDITOR() BytecodeEditor* editor = reinterpret_cast(funcData) +#define GET_EDITOR() BytecodeEditor& editor = *static_cast(funcData)->editor template &&, bool)> @@ -68,7 +68,7 @@ FREObject Assemble(FREContext, void* funcData, uint32_t argc, FREObject argv[]) FAIL(std::string("Exception occurred while converting strings: ") + e.what()); } - return (editor->*Assembler)(std::move(strings), includeDebugInstructions); + return (editor.*Assembler)(std::move(strings), includeDebugInstructions); } template @@ -78,7 +78,21 @@ FREObject TransparentZeroArg(FREContext, void* funcData, uint32_t argc, FREObjec GET_EDITOR(); - return (editor->*Function)(); + return (editor.*Function)(); +} + +template +FREObject CheckAssemblyValid(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) +{ + ANEFunctionContext& context = *static_cast(funcData); + BytecodeEditor& editor = *context.editor; + + if (editor.partialAssembly.get() != context.objectData->program) + { + FAIL("Invalid instance: underlying data has been disposed of"); + } + + return Function(ctx, funcData, argc, argv); } #undef GET_EDITOR diff --git a/Native/BytecodeEditor/include/ASASM/ASProgram.hpp b/Native/BytecodeEditor/include/ASASM/ASProgram.hpp index 366b592..96c9424 100644 --- a/Native/BytecodeEditor/include/ASASM/ASProgram.hpp +++ b/Native/BytecodeEditor/include/ASASM/ASProgram.hpp @@ -29,7 +29,7 @@ namespace ASASM std::vector> orphanClasses; std::vector> orphanMethods; - static ASProgram fromABC(const ABC::ABCFile& abc); - ABC::ABCFile toABC(); + static ASProgram fromABC(const SWFABC::ABCFile& abc); + SWFABC::ABCFile toABC(); }; } diff --git a/Native/BytecodeEditor/include/ASASM/AStoABC.hpp b/Native/BytecodeEditor/include/ASASM/AStoABC.hpp index 80f42b8..4f94fa2 100644 --- a/Native/BytecodeEditor/include/ASASM/AStoABC.hpp +++ b/Native/BytecodeEditor/include/ASASM/AStoABC.hpp @@ -30,7 +30,7 @@ namespace ASASM ValuePool, false> classes; ValuePool, false> methods; - ABC::ABCFile abc; + SWFABC::ABCFile abc; void visitInt(int64_t v) { ints.add(v); } @@ -476,8 +476,8 @@ namespace ASASM abc.multinames.reserve(multinames.values.size()); for (size_t i = 1; i < multinames.values.size(); i++) { - ABC::Multiname& multiname = abc.multinames.emplace_back(); - multiname.kind = multinames.values[i].kind; + SWFABC::Multiname& multiname = abc.multinames.emplace_back(); + multiname.kind = multinames.values[i].kind; switch (multinames.values[i].kind) { case ABCType::QName: @@ -507,7 +507,7 @@ namespace ASASM break; case ABCType::TypeName: { - ABC::Multiname::_Typename tn = { + SWFABC::Multiname::_Typename tn = { .name = multinames.get(multinames.values[i].Typename().name()), .params = std::vector( multinames.values[i].Typename().params().size())}; @@ -527,7 +527,7 @@ namespace ASASM abc.metadata.reserve(metadatas.values.size()); for (size_t i = 0; i < metadatas.values.size(); i++) { - ABC::Metadata& metadata = abc.metadata.emplace_back( + SWFABC::Metadata& metadata = abc.metadata.emplace_back( strings.get(metadatas.values[i].name), std::vector>(metadatas.values[i].data.size())); for (size_t j = 0; j < metadatas.values[i].data.size(); j++) @@ -542,7 +542,7 @@ namespace ASASM abc.methods.reserve(methods.values.size()); for (size_t i = 0; i < methods.values.size(); i++) { - ABC::MethodInfo& info = abc.methods.emplace_back(); + SWFABC::MethodInfo& info = abc.methods.emplace_back(); info.paramTypes.reserve(methods.values[i]->paramTypes.size()); for (const auto& paramType : methods.values[i]->paramTypes) @@ -572,7 +572,7 @@ namespace ASASM abc.instances.reserve(classes.values.size()); for (size_t i = 0; i < classes.values.size(); i++) { - ABC::Instance& instance = abc.instances.emplace_back(); + SWFABC::Instance& instance = abc.instances.emplace_back(); instance.name = multinames.get(classes.values[i]->instance.name); instance.superName = multinames.get(classes.values[i]->instance.superName); @@ -604,12 +604,12 @@ namespace ASASM abc.bodies.reserve(bodies.size()); for (size_t i = 0; i < bodies.size(); i++) { - ABC::MethodBody& body = abc.bodies.emplace_back(); - body.method = methods.get(bodies[i].method.lock()); - body.maxStack = bodies[i].maxStack; - body.localCount = bodies[i].localCount; - body.initScopeDepth = bodies[i].initScopeDepth; - body.maxScopeDepth = bodies[i].maxScopeDepth; + SWFABC::MethodBody& body = abc.bodies.emplace_back(); + body.method = methods.get(bodies[i].method.lock()); + body.maxStack = bodies[i].maxStack; + body.localCount = bodies[i].localCount; + body.initScopeDepth = bodies[i].initScopeDepth; + body.maxScopeDepth = bodies[i].maxScopeDepth; body.instructions.reserve(bodies[i].instructions.size()); for (size_t j = 0; j < bodies[i].instructions.size(); j++) { @@ -625,15 +625,15 @@ namespace ASASM } } - std::vector convertTraits(const std::vector& traits) + std::vector convertTraits(const std::vector& traits) { - std::vector ret; + std::vector ret; ret.reserve(traits.size()); for (const auto& oTrait : traits) { - ABC::TraitsInfo& nTrait = ret.emplace_back(); - nTrait.name = multinames.get(oTrait.name); + SWFABC::TraitsInfo& nTrait = ret.emplace_back(); + nTrait.name = multinames.get(oTrait.name); nTrait.kind(oTrait.kind); nTrait.attr(oTrait.attributes); switch (oTrait.kind) @@ -671,15 +671,15 @@ namespace ASASM return ret; } - ABC::Instruction convertInstruction(const ASASM::Instruction& instruction) + SWFABC::Instruction convertInstruction(const ASASM::Instruction& instruction) { - ABC::Instruction ret; + SWFABC::Instruction ret; ret.opcode = instruction.opcode; ret.arguments.reserve(instruction.arguments.size()); for (size_t i = 0; i < OPCode_Info[(uint8_t)instruction.opcode].second.size(); i++) { - ABC::Instruction::Argument& newArg = ret.arguments.emplace_back(); + SWFABC::Instruction::Argument& newArg = ret.arguments.emplace_back(); switch (OPCode_Info[(uint8_t)instruction.opcode].second[i]) { case OPCodeArgumentType::Unknown: @@ -747,7 +747,7 @@ namespace ASASM case OPCodeArgumentType::SwitchTargets: newArg.switchTargets( - std::vector(instruction.arguments[i].switchTargets())); + std::vector(instruction.arguments[i].switchTargets())); break; } } diff --git a/Native/BytecodeEditor/include/ASASM/Exception.hpp b/Native/BytecodeEditor/include/ASASM/Exception.hpp index ecf62a1..65a267f 100644 --- a/Native/BytecodeEditor/include/ASASM/Exception.hpp +++ b/Native/BytecodeEditor/include/ASASM/Exception.hpp @@ -7,7 +7,7 @@ namespace ASASM { struct Exception { - ABC::Label from, to, target; + SWFABC::Label from, to, target; Multiname excType; Multiname varName; diff --git a/Native/BytecodeEditor/include/ASASM/Instruction.hpp b/Native/BytecodeEditor/include/ASASM/Instruction.hpp index 7ff5e10..cb87fd7 100644 --- a/Native/BytecodeEditor/include/ASASM/Instruction.hpp +++ b/Native/BytecodeEditor/include/ASASM/Instruction.hpp @@ -23,8 +23,8 @@ namespace ASASM { private: std::variant, std::shared_ptr, ABC::Label, - std::vector> + Namespace, Multiname, std::shared_ptr, std::shared_ptr, + SWFABC::Label, std::vector> data; public: @@ -100,26 +100,26 @@ namespace ASASM void methodv(std::shared_ptr v) { data = v; } - [[nodiscard]] ABC::Label& jumpTarget() { return std::get(data); } + [[nodiscard]] SWFABC::Label& jumpTarget() { return std::get(data); } - [[nodiscard]] const ABC::Label& jumpTarget() const + [[nodiscard]] const SWFABC::Label& jumpTarget() const { - return std::get(data); + return std::get(data); } - void jumpTarget(const ABC::Label& v) { data = v; } + void jumpTarget(const SWFABC::Label& v) { data = v; } - [[nodiscard]] std::vector& switchTargets() + [[nodiscard]] std::vector& switchTargets() { - return std::get>(data); + return std::get>(data); } - [[nodiscard]] const std::vector& switchTargets() const + [[nodiscard]] const std::vector& switchTargets() const { - return std::get>(data); + return std::get>(data); } - void switchTargets(const std::vector& v) { data = v; } + void switchTargets(const std::vector& v) { data = v; } auto operator<=>(const Argument& other) const noexcept { diff --git a/Native/BytecodeEditor/include/ASASM/MethodBody.hpp b/Native/BytecodeEditor/include/ASASM/MethodBody.hpp index 771640e..451fbf6 100644 --- a/Native/BytecodeEditor/include/ASASM/MethodBody.hpp +++ b/Native/BytecodeEditor/include/ASASM/MethodBody.hpp @@ -25,7 +25,7 @@ namespace ASASM std::vector exceptions; std::vector traits; - std::vector errors; + std::vector errors; auto operator<=>(const MethodBody&) const noexcept = default; bool operator==(const MethodBody&) const noexcept = default; diff --git a/Native/BytecodeEditor/include/ASASM/Namespace.hpp b/Native/BytecodeEditor/include/ASASM/Namespace.hpp index b51c661..def6c78 100644 --- a/Native/BytecodeEditor/include/ASASM/Namespace.hpp +++ b/Native/BytecodeEditor/include/ASASM/Namespace.hpp @@ -1,6 +1,7 @@ #pragma once #include "enums/ABCType.hpp" +#include "utils/generic_hash.hpp" #include #include @@ -18,3 +19,6 @@ namespace ASASM bool operator==(const Namespace&) const noexcept = default; }; } + +DEFINE_HASH( + ASASM::Namespace, &ASASM::Namespace::kind, &ASASM::Namespace::name, &ASASM::Namespace::id); diff --git a/Native/BytecodeEditor/include/Assembler.hpp b/Native/BytecodeEditor/include/Assembler.hpp index 88599f5..27c95cd 100644 --- a/Native/BytecodeEditor/include/Assembler.hpp +++ b/Native/BytecodeEditor/include/Assembler.hpp @@ -137,7 +137,7 @@ class Assembler } std::unordered_map vars; - std::unordered_map namespaceLabels; + std::vector namespaceLabels; uint32_t sourceVersion = 1; void handlePreprocessor() @@ -424,7 +424,7 @@ class Assembler template void mustBeSet(const char* name, const T& obj) { - using comp = std::remove_cvref_t; + using comp = std::remove_cvref_t; if constexpr (std::is_same_v, comp>) { if (obj == nullptr) @@ -612,10 +612,10 @@ class Assembler const std::string w = readWord(); if (w == "null") { - return ABC::ABCFile::NULL_INT; + return SWFABC::ABCFile::NULL_INT; } const int64_t ret = strtoll(w.c_str(), nullptr, 0); - if (ret < ABC::ABCFile::MIN_INT || ret > ABC::ABCFile::MAX_INT) + if (ret < SWFABC::ABCFile::MIN_INT || ret > SWFABC::ABCFile::MAX_INT) { throw StringException("Int out of bounds"); } @@ -627,10 +627,10 @@ class Assembler const std::string w = readWord(); if (w == "null") { - return ABC::ABCFile::NULL_UINT; + return SWFABC::ABCFile::NULL_UINT; } const uint64_t ret = strtoull(w.c_str(), nullptr, 0); - if (ret > ABC::ABCFile::MAX_UINT) + if (ret > SWFABC::ABCFile::MAX_UINT) { throw StringException("UInt out of bounds"); } @@ -642,7 +642,7 @@ class Assembler const std::string w = readWord(); if (w == "null") { - return ABC::ABCFile::NULL_DOUBLE; + return SWFABC::ABCFile::NULL_DOUBLE; } return strtod(w.c_str(), nullptr); } @@ -720,13 +720,15 @@ class Assembler { skipChar(); std::string s = readString(); - if (namespaceLabels.contains(s)) + auto found = std::find(namespaceLabels.begin(), namespaceLabels.end(), s); + if (found != namespaceLabels.end()) { - id = namespaceLabels.at(s); + id = std::distance(namespaceLabels.begin(), found) + 1; } else { - id = namespaceLabels[s] = namespaceLabels.size() + 1; + namespaceLabels.emplace_back(std::move(s)); + id = namespaceLabels.size(); } } expectSymbol(')'); @@ -1221,7 +1223,7 @@ class Assembler } } - ABC::Label parseLabel( + SWFABC::Label parseLabel( const std::string& label, const std::unordered_map& labels) { std::string name = label; @@ -1246,7 +1248,7 @@ class Assembler throw StringException("Unknown label " + name); } - return ABC::Label{labels.at(name), offset, 0}; + return SWFABC::Label{labels.at(name), offset, 0}; } std::vector readInstructions( @@ -1359,7 +1361,7 @@ class Assembler std::vector switchTargetLabels = readList<'[', ']', false>([this] { return readWord(); }); instruction.arguments[i].switchTargets( - std::vector(switchTargetLabels.size())); + std::vector(switchTargetLabels.size())); for (size_t li = 0; li < switchTargetLabels.size(); li++) { switchFixups.emplace_back( diff --git a/Native/BytecodeEditor/include/BytecodeEditor.hpp b/Native/BytecodeEditor/include/BytecodeEditor.hpp index 13c8dba..52c27ea 100644 --- a/Native/BytecodeEditor/include/BytecodeEditor.hpp +++ b/Native/BytecodeEditor/include/BytecodeEditor.hpp @@ -3,6 +3,7 @@ #include "ASASM/ASProgram.hpp" #include "SWF/SWFFile.hpp" #include "utils/ANEUtils.hpp" +#include "utils/RefBuilder.hpp" #include #include #include @@ -15,7 +16,7 @@ #include -class BytecodeEditor +class BytecodeEditor : public std::enable_shared_from_this { private: FREContext ctx; @@ -28,9 +29,9 @@ class BytecodeEditor std::vector> m_taskResult; - std::unique_ptr partialAssembly; - public: + std::unique_ptr> partialAssembly; + BytecodeEditor(FREContext ctx) noexcept : ctx(ctx) {} FREObject disassemble(); @@ -67,4 +68,29 @@ class BytecodeEditor } FREObject taskResult(); + + std::shared_ptr ConvertClass(FREObject o) const; + FREObject ConvertClass(ASASM::Class& c) const; + ASASM::Namespace ConvertNamespace(FREObject o) const; + FREObject ConvertNamespace(const ASASM::Namespace& o) const; + ASASM::Multiname ConvertMultiname(FREObject o) const; + FREObject ConvertMultiname(const ASASM::Multiname& o) const; + ASASM::Trait ConvertTrait(FREObject o) const; + FREObject ConvertTrait(const ASASM::Trait& t) const; + std::shared_ptr ConvertMethod(FREObject o) const; + FREObject ConvertMethod(const ASASM::Method& m) const; + ASASM::MethodBody ConvertMethodBody(FREObject o) const; + FREObject ConvertMethodBody(const ASASM::MethodBody& b) const; + ASASM::Exception ConvertException(FREObject o, const std::vector& allInstrs) const; + FREObject ConvertException( + const ASASM::Exception& e, const std::vector& allInstrs) const; + SWFABC::Error ConvertError(FREObject o, const std::vector& allInstrs) const; + FREObject ConvertError(const SWFABC::Error& e, const std::vector& allInstrs) const; + SWFABC::Label ConvertLabel(FREObject o, const std::vector& allInstrs) const; + FREObject ConvertLabel(const SWFABC::Label& l, const std::vector& allInstrs) const; + ASASM::Instruction ConvertInstruction( + FREObject o, const std::vector& allInstrs) const; + std::pair ConvertInstruction(const ASASM::Instruction& i) const; + ASASM::Value ConvertValue(FREObject o) const; + FREObject ConvertValue(const ASASM::Value& v) const; }; diff --git a/Native/BytecodeEditor/include/Disassembler.hpp b/Native/BytecodeEditor/include/Disassembler.hpp index fe81142..bf352a5 100644 --- a/Native/BytecodeEditor/include/Disassembler.hpp +++ b/Native/BytecodeEditor/include/Disassembler.hpp @@ -123,7 +123,7 @@ class Disassembler void dumpInt(StringBuilder& sb, int64_t v) { - if (v == ABC::ABCFile::NULL_INT) + if (v == SWFABC::ABCFile::NULL_INT) { sb << "null"; } @@ -135,7 +135,7 @@ class Disassembler void dumpUInt(StringBuilder& sb, uint64_t v) { - if (v == ABC::ABCFile::NULL_UINT) + if (v == SWFABC::ABCFile::NULL_UINT) { sb << "null"; } @@ -147,7 +147,7 @@ class Disassembler void dumpDouble(StringBuilder& sb, double v) { - if (std::isnan(v)) // v == ABC::ABCFile::NULL_DOUBLE + if (std::isnan(v)) // v == SWFABC::ABCFile::NULL_DOUBLE { sb << "null"; return; @@ -628,10 +628,10 @@ class Disassembler sb.newLine(); } - for (const auto& interface : instance.interfaces) + for (const auto& iface : instance.interfaces) { sb << "implements "; - dumpMultiname(sb, interface); + dumpMultiname(sb, iface); sb.newLine(); } @@ -672,7 +672,7 @@ class Disassembler sb.newLine(); } - void dumpLabel(StringBuilder& sb, const ABC::Label& label) + void dumpLabel(StringBuilder& sb, const SWFABC::Label& label) { sb << 'L'; sb.write(label.index); @@ -739,7 +739,7 @@ class Disassembler } void dumpInstructions(StringBuilder& sb, const std::vector& instructions, - std::vector& labels, const std::vector& errors) + std::vector& labels, const std::vector& errors) { for (const auto& instruction : instructions) { diff --git a/Native/BytecodeEditor/include/utils/ANEFunctionContext.hpp b/Native/BytecodeEditor/include/utils/ANEFunctionContext.hpp new file mode 100644 index 0000000..e3d3950 --- /dev/null +++ b/Native/BytecodeEditor/include/utils/ANEFunctionContext.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ASASM/ASProgram.hpp" +#include "ASASM/Class.hpp" +#include "ASASM/Script.hpp" +#include "BytecodeEditor.hpp" +#include +#include +#include + +struct ANEFunctionContext +{ + std::shared_ptr editor; + std::unique_ptr functions; + + struct ObjectData + { + std::variant object; + std::pair* program; + }; + + std::optional objectData; +}; diff --git a/Native/BytecodeEditor/include/utils/ANEUtils.hpp b/Native/BytecodeEditor/include/utils/ANEUtils.hpp index 6c246b1..34226f9 100644 --- a/Native/BytecodeEditor/include/utils/ANEUtils.hpp +++ b/Native/BytecodeEditor/include/utils/ANEUtils.hpp @@ -165,30 +165,6 @@ inline FREResult ANECallObjectMethod( return FRECallObjectMethod(o, (const uint8_t*)m, c, v, r, e); } -std::shared_ptr ConvertClass(FREObject o); -FREObject ConvertClass(const std::shared_ptr& c); - -ASASM::Namespace ConvertNamespace(FREObject o); -FREObject ConvertNamespace(const ASASM::Namespace& o); -ASASM::Multiname ConvertMultiname(FREObject o); -FREObject ConvertMultiname(const ASASM::Multiname& o); -ASASM::Trait ConvertTrait(FREObject o); -FREObject ConvertTrait(const ASASM::Trait& t); -std::shared_ptr ConvertMethod(FREObject o); -FREObject ConvertMethod(const ASASM::Method& m); -ASASM::MethodBody ConvertMethodBody(FREObject o); -FREObject ConvertMethodBody(const ASASM::MethodBody& b); -ASASM::Exception ConvertException(FREObject o, const std::vector& allInstrs); -FREObject ConvertException(const ASASM::Exception& e, const std::vector& allInstrs); -ABC::Error ConvertError(FREObject o, const std::vector& allInstrs); -FREObject ConvertError(const ABC::Error& e, const std::vector& allInstrs); -ABC::Label ConvertLabel(FREObject o, const std::vector& allInstrs); -FREObject ConvertLabel(const ABC::Label& l, const std::vector& allInstrs); -ASASM::Instruction ConvertInstruction(FREObject o, const std::vector& allInstrs); -std::pair ConvertInstruction(const ASASM::Instruction& i); -ASASM::Value ConvertValue(FREObject o); -FREObject ConvertValue(const ASASM::Value& v); - #undef FAIL_RETURN #define FAIL_RETURN(x) return x diff --git a/Native/BytecodeEditor/include/utils/RefBuilder.hpp b/Native/BytecodeEditor/include/utils/RefBuilder.hpp index 1618dd3..58230ca 100644 --- a/Native/BytecodeEditor/include/utils/RefBuilder.hpp +++ b/Native/BytecodeEditor/include/utils/RefBuilder.hpp @@ -11,22 +11,25 @@ #include #include #include +#include #include -bool nsSimilar(const ASASM::Namespace& ns1, const ASASM::Namespace& ns2) +class RefBuilder : public ASASM::ASTraitsVisitor { - if (ns1.kind == ABCType::PrivateNamespace || ns2.kind == ABCType::PrivateNamespace) +private: + static bool nsSimilar(const ASASM::Namespace& ns1, const ASASM::Namespace& ns2) { - return ns1.kind == ns2.kind && ns1.id == ns2.id; + if (ns1.kind == ABCType::PrivateNamespace || ns2.kind == ABCType::PrivateNamespace) + { + return ns1.kind == ns2.kind && ns1.id == ns2.id; + } + // ignore ns kind in other cases + return ns1.name == ns2.name; } - // ignore ns kind in other cases - return ns1.name == ns2.name; -} -class RefBuilder : public ASASM::ASTraitsVisitor -{ -private: - std::array>, + std::list> homonymData; + std::array>>, ABCTypeMap.GetEntries().size()> homonyms; @@ -37,14 +40,41 @@ class RefBuilder : public ASASM::ASTraitsVisitor public: bool hasHomonyms(const ASASM::Namespace& ns) const { - return homonyms[(uint8_t)ns.kind].contains(ns.name) && - homonyms[(uint8_t)ns.kind].at(ns.name).size() > 1; + if (auto found = homonyms[(uint8_t)ns.kind].find(ns.name); + found != homonyms[(uint8_t)ns.kind].end()) + { + return found->second.get().size() > 1; + } + else + { + return false; + } } void addHomonym(const ASASM::Namespace& ns) { assert(!homonymsBuilt); - homonyms[(uint8_t)ns.kind][ns.name][ns.id] = true; + if (auto found = homonyms[(uint8_t)ns.kind].find(ns.name); + found != homonyms[(uint8_t)ns.kind].end()) + { + found->second.get().emplace(ns); + } + else + { + homonyms[(uint8_t)ns.kind].emplace(ns.name, homonymData.emplace_back()); + homonymData.back().emplace(ns); + } + } + + std::optional>> getHomonyms( + const ASASM::Namespace& ns) const + { + if (auto found = homonyms[(uint8_t)ns.kind].find(ns.name); + found != homonyms[(uint8_t)ns.kind].end()) + { + return found->second; + } + return std::nullopt; } /// Represents a link in a "context chain", which represents the context in which an object @@ -222,8 +252,8 @@ class RefBuilder : public ASASM::ASTraitsVisitor const auto& ns = multiname.qname().ns; if (ns.kind == ABCType::PrivateNamespace) { - auto ctx = refs.namespaces[(uint8_t)ns.kind].getContext( - refs, (uint32_t)ns.id); + auto ctx = + refs.namespaces[(uint8_t)ns.kind].getContext(refs, ns.id); if (!multiname.qname().name.empty()) { ctx.emplace_back(multiname.qname().name); @@ -498,20 +528,20 @@ class RefBuilder : public ASASM::ASTraitsVisitor assert(!coagulated); assert(!contextsSealed); - if (!contextSets.contains(obj)) + if (auto found = contextSets.find(obj); found != contextSets.end()) { - contextSets[obj][(uint8_t)priority].emplace_back(context); - return true; - } - else - { - auto& pet = contextSets.at(obj)[(uint8_t)priority]; + auto& pet = found->second[(uint8_t)priority]; if (pet.size() == 0 || pet[pet.size() - 1] != context) { pet.emplace_back(context); } return false; } + else + { + contextSets[obj][(uint8_t)priority].emplace_back(context); + return true; + } } bool addIfNew(T obj, const std::vector& context, ContextPriority priority) @@ -661,7 +691,7 @@ class RefBuilder : public ASASM::ASTraitsVisitor } }; - std::array, ABCTypeMap.GetEntries().size()> namespaces; + std::array, ABCTypeMap.GetEntries().size()> namespaces; ContextSet objects, scripts; RefBuilder(const ASASM::ASProgram& as) : ASTraitsVisitor(as) {} @@ -749,7 +779,7 @@ class RefBuilder : public ASASM::ASTraitsVisitor } } - for (size_t i = 0; i < possibleOrphanPrivateNamespaces.size(); i++) + for (int i = 0; i < (int)possibleOrphanPrivateNamespaces.size(); i++) { if (!namespaces[(uint8_t)ABCType::PrivateNamespace].isAdded(i)) { @@ -825,7 +855,7 @@ class RefBuilder : public ASASM::ASTraitsVisitor popContext(); } - std::unordered_map possibleOrphanPrivateNamespaces; + std::unordered_map possibleOrphanPrivateNamespaces; void visitNamespace(const ASASM::Namespace& ns, ContextPriority priority) { diff --git a/Native/BytecodeEditor/include/utils/StringUtils.hpp b/Native/BytecodeEditor/include/utils/StringUtils.hpp index aa6f6d8..ef86ad4 100644 --- a/Native/BytecodeEditor/include/utils/StringUtils.hpp +++ b/Native/BytecodeEditor/include/utils/StringUtils.hpp @@ -5,7 +5,7 @@ namespace StringUtils { - std::vector split(std::string_view s, std::string_view delimiter) + constexpr std::vector split(std::string_view s, std::string_view delimiter) { std::vector ret; if (delimiter.size() == 0) @@ -29,7 +29,7 @@ namespace StringUtils return ret; } - std::string join(const std::string_view* s, size_t len, std::string_view joiner) + constexpr std::string join(const std::string_view* s, size_t len, std::string_view joiner) { if (len == 0) { @@ -54,7 +54,7 @@ namespace StringUtils return ret; } - std::string join(const std::string* s, size_t len, std::string_view joiner) + constexpr std::string join(const std::string* s, size_t len, std::string_view joiner) { if (len == 0) { @@ -79,12 +79,12 @@ namespace StringUtils return ret; } - std::string join(const std::vector& s, std::string_view joiner) + constexpr std::string join(const std::vector& s, std::string_view joiner) { return join(s.data(), s.size(), joiner); } - std::string join(const std::vector& s, std::string_view joiner) + constexpr std::string join(const std::vector& s, std::string_view joiner) { return join(s.data(), s.size(), joiner); } diff --git a/Native/BytecodeEditor/include/utils/ValuePool.hpp b/Native/BytecodeEditor/include/utils/ValuePool.hpp index 95bd670..077d31f 100644 --- a/Native/BytecodeEditor/include/utils/ValuePool.hpp +++ b/Native/BytecodeEditor/include/utils/ValuePool.hpp @@ -61,11 +61,11 @@ class ValuePool : private ValuePoolBase std::is_same_v>); if constexpr (std::is_same_v) { - return v == ABC::ABCFile::NULL_UINT; + return v == SWFABC::ABCFile::NULL_UINT; } else if constexpr (std::is_same_v) { - return v == ABC::ABCFile::NULL_INT; + return v == SWFABC::ABCFile::NULL_INT; } else if constexpr (std::is_same_v) { diff --git a/Native/BytecodeEditor/include/utils/generic_hash.hpp b/Native/BytecodeEditor/include/utils/generic_hash.hpp new file mode 100644 index 0000000..2e6194d --- /dev/null +++ b/Native/BytecodeEditor/include/utils/generic_hash.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +template + requires requires(T v) { + v.*MemberPointer; + std::hash>{}(v.*MemberPointer); + } +constexpr size_t generic_hash(const T& val) noexcept +{ + static constexpr auto hash_combine = [](size_t seed, size_t value) + { return seed ^ value + 0x9e3779b9 + (seed << 6) + (seed >> 2); }; + + if constexpr (sizeof...(MemberPointers) == 0) + { + return std::hash>{}(val.*MemberPointer); + } + else + { + return hash_combine( + std::hash>{}(val.*MemberPointer), + generic_hash(val)); + } +} + +#define DEFINE_HASH(Type, ...) \ + template <> \ + struct std::hash \ + { \ + size_t operator()(const Type& v) const noexcept \ + { \ + return generic_hash(v); \ + } \ + } diff --git a/Native/BytecodeEditor/source/ANEBytecodeEditor.cpp b/Native/BytecodeEditor/source/ANEBytecodeEditor.cpp index c44659b..5b16fe1 100644 --- a/Native/BytecodeEditor/source/ANEBytecodeEditor.cpp +++ b/Native/BytecodeEditor/source/ANEBytecodeEditor.cpp @@ -1,6 +1,7 @@ #include "ANEBytecodeEditor.hpp" #include "ANEFunctions.hpp" #include "BytecodeEditor.hpp" +#include "utils/ANEFunctionContext.hpp" #include "utils/ANEUtils.hpp" #include @@ -14,101 +15,104 @@ void ContextInitializer(void*, const uint8_t* ctxTypeRaw, FREContext ctx, uint32 { std::string_view ctxType = reinterpret_cast(ctxTypeRaw); + ANEFunctionContext* context = new ANEFunctionContext; + #define TZA TransparentZeroArg #define BE BytecodeEditor +#define CAV CheckAssemblyValid if (ctxType == "BytecodeEditor"sv) { - BytecodeEditor* editorForContext = new BytecodeEditor(ctx); - FRENamedFunction* ANEBE_functions = new FRENamedFunction[]{ - {(const uint8_t*)"Disassemble", editorForContext, &TZA<&BE::disassemble> }, - {(const uint8_t*)"Assemble", editorForContext, &Assemble<&BE::assemble> }, - {(const uint8_t*)"PartialAssemble", editorForContext, &Assemble<&BE::partialAssemble>}, - {(const uint8_t*)"FinishAssemble", editorForContext, &TZA<&BE::finishAssemble> }, - {(const uint8_t*)"DisassembleAsync", editorForContext, &TZA<&BE::disassembleAsync> }, - {(const uint8_t*)"AssembleAsync", editorForContext, &Assemble<&BE::assembleAsync> }, - {(const uint8_t*)"PartialAssembleAsync", editorForContext, - &Assemble<&BE::partialAssembleAsync> }, - {(const uint8_t*)"FinishAssembleAsync", editorForContext, - &TZA<&BE::finishAssembleAsync> }, - {(const uint8_t*)"AsyncTaskResult", editorForContext, &TZA<&BE::taskResult> }, - {(const uint8_t*)"SetCurrentSWF", editorForContext, &SetCurrentSWF }, - {(const uint8_t*)"Cleanup", editorForContext, &Cleanup }, - {(const uint8_t*)"GetClass", editorForContext, &GetClass }, - {(const uint8_t*)"GetScript", editorForContext, &GetScript }, - }; - *functions = ANEBE_functions; + context->editor = std::shared_ptr(new BytecodeEditor(ctx)); + context->functions = std::unique_ptr(new FRENamedFunction[]{ + {(const uint8_t*)"Disassemble", context, &TZA<&BE::disassemble> }, + {(const uint8_t*)"Assemble", context, &Assemble<&BE::assemble> }, + {(const uint8_t*)"PartialAssemble", context, &Assemble<&BE::partialAssemble> }, + {(const uint8_t*)"FinishAssemble", context, &TZA<&BE::finishAssemble> }, + {(const uint8_t*)"DisassembleAsync", context, &TZA<&BE::disassembleAsync> }, + {(const uint8_t*)"AssembleAsync", context, &Assemble<&BE::assembleAsync> }, + {(const uint8_t*)"PartialAssembleAsync", context, &Assemble<&BE::partialAssembleAsync>}, + {(const uint8_t*)"FinishAssembleAsync", context, &TZA<&BE::finishAssembleAsync> }, + {(const uint8_t*)"AsyncTaskResult", context, &TZA<&BE::taskResult> }, + {(const uint8_t*)"SetCurrentSWF", context, &SetCurrentSWF }, + {(const uint8_t*)"Cleanup", context, &Cleanup }, + {(const uint8_t*)"GetClass", context, &GetClass }, + {(const uint8_t*)"GetScript", context, &GetScript }, + }); + + *functions = context->functions.get(); *numFunctions = 13; - FRESetContextNativeData(ctx, (void*)ANEBE_functions); } else if (ctxType == "SWFIntrospector"sv) { - BytecodeEditor* editorForContext = new BytecodeEditor(ctx); - FRENamedFunction* ANEBE_functions = new FRENamedFunction[]{ - {(const uint8_t*)"SetCurrentSWF", editorForContext, &SetCurrentSWF }, - {(const uint8_t*)"BeginIntrospection", editorForContext, &TZA<&BE::beginIntrospection>}, - {(const uint8_t*)"GetClass", editorForContext, &GetROClass }, - {(const uint8_t*)"GetScript", editorForContext, &GetROScript }, - }; - *functions = ANEBE_functions; - *numFunctions = 4; - FRESetContextNativeData(ctx, (void*)ANEBE_functions); + context->editor = std::shared_ptr(new BytecodeEditor(ctx)); + context->functions = std::unique_ptr(new FRENamedFunction[]{ + {(const uint8_t*)"SetCurrentSWF", context, &SetCurrentSWF }, + {(const uint8_t*)"BeginIntrospection", context, &TZA<&BE::beginIntrospection>}, + {(const uint8_t*)"GetClass", context, &GetROClass }, + {(const uint8_t*)"GetScript", context, &GetROScript }, + }); + *functions = context->functions.get(); + *numFunctions = 4; } else if (ctxType == "Class"sv) { - FRENamedFunction* CLASS_functions = new FRENamedFunction[]{ - {(const uint8_t*)"GetStaticTrait", classPointerHelper, &ASClass::GetStaticTrait }, - {(const uint8_t*)"SetStaticTrait", classPointerHelper, &ASClass::SetStaticTrait }, - {(const uint8_t*)"DeleteStaticTrait", classPointerHelper, &ASClass::DeleteStaticTrait}, - {(const uint8_t*)"GetInstanceTrait", classPointerHelper, &ASClass::GetInstanceTrait }, - {(const uint8_t*)"SetInstanceTrait", classPointerHelper, &ASClass::SetInstanceTrait }, - {(const uint8_t*)"DeleteInstanceTrait", classPointerHelper, - &ASClass::DeleteInstanceTrait }, - {(const uint8_t*)"GetStaticConstructor", classPointerHelper, - &ASClass::GetStaticConstructor }, - {(const uint8_t*)"SetStaticConstructor", classPointerHelper, - &ASClass::SetStaticConstructor }, - {(const uint8_t*)"GetConstructor", classPointerHelper, &ASClass::GetConstructor }, - {(const uint8_t*)"SetConstructor", classPointerHelper, &ASClass::SetConstructor }, - {(const uint8_t*)"GetInterfaces", classPointerHelper, &ASClass::GetInterfaces }, - {(const uint8_t*)"SetInterfaces", classPointerHelper, &ASClass::SetInterfaces }, - {(const uint8_t*)"GetSuperclass", classPointerHelper, &ASClass::GetSuperclass }, - {(const uint8_t*)"SetSuperclass", classPointerHelper, &ASClass::SetSuperclass }, - {(const uint8_t*)"GetFlags", classPointerHelper, &ASClass::GetFlags }, - {(const uint8_t*)"SetFlags", classPointerHelper, &ASClass::SetFlags }, - {(const uint8_t*)"GetProtectedNamespace", classPointerHelper, - &ASClass::GetProtectedNamespace }, - {(const uint8_t*)"SetProtectedNamespace", classPointerHelper, - &ASClass::SetProtectedNamespace }, - {(const uint8_t*)"ConvertClassHelper", classPointerHelper, - &ASClass::ConvertClassHelper } - }; - classPointerHelper = nullptr; - *functions = CLASS_functions; - *numFunctions = 19; - FRESetContextNativeData(ctx, (void*)CLASS_functions); + context->editor = nextObjectContext->editor; + context->functions = std::unique_ptr(new FRENamedFunction[]{ + {(const uint8_t*)"GetStaticTrait", context, &CAV<&ASClass::GetStaticTrait> }, + {(const uint8_t*)"SetStaticTrait", context, &CAV<&ASClass::SetStaticTrait> }, + {(const uint8_t*)"DeleteStaticTrait", context, &CAV<&ASClass::DeleteStaticTrait> }, + {(const uint8_t*)"GetInstanceTrait", context, &CAV<&ASClass::GetInstanceTrait> }, + {(const uint8_t*)"SetInstanceTrait", context, &CAV<&ASClass::SetInstanceTrait> }, + {(const uint8_t*)"DeleteInstanceTrait", context, &CAV<&ASClass::DeleteInstanceTrait> }, + {(const uint8_t*)"GetStaticConstructor", context, &CAV<&ASClass::GetStaticConstructor>}, + {(const uint8_t*)"SetStaticConstructor", context, &CAV<&ASClass::SetStaticConstructor>}, + {(const uint8_t*)"GetConstructor", context, &CAV<&ASClass::GetConstructor> }, + {(const uint8_t*)"SetConstructor", context, &CAV<&ASClass::SetConstructor> }, + {(const uint8_t*)"GetInterfaces", context, &CAV<&ASClass::GetInterfaces> }, + {(const uint8_t*)"SetInterfaces", context, &CAV<&ASClass::SetInterfaces> }, + {(const uint8_t*)"GetSuperclass", context, &CAV<&ASClass::GetSuperclass> }, + {(const uint8_t*)"SetSuperclass", context, &CAV<&ASClass::SetSuperclass> }, + {(const uint8_t*)"GetFlags", context, &CAV<&ASClass::GetFlags> }, + {(const uint8_t*)"SetFlags", context, &CAV<&ASClass::SetFlags> }, + {(const uint8_t*)"GetProtectedNamespace", context, + &CAV<&ASClass::GetProtectedNamespace> }, + {(const uint8_t*)"SetProtectedNamespace", context, + &CAV<&ASClass::SetProtectedNamespace> }, + {(const uint8_t*)"ConvertClassHelper", context, &CAV<&ASClass::ConvertClassHelper> } + }); + context->objectData = { + nextObjectContext->objectData->object, context->editor->partialAssembly.get()}; + nextObjectContext = std::nullopt; + *functions = context->functions.get(); + *numFunctions = 19; + FRESetContextNativeData(ctx, context); } else if (ctxType == "Script"sv) { - FRENamedFunction* SCRIPT_functions = new FRENamedFunction[]{ - {(const uint8_t*)"GetTrait", scriptPointerHelper, &ASScript::GetTrait }, - {(const uint8_t*)"SetTrait", scriptPointerHelper, &ASScript::SetTrait }, - {(const uint8_t*)"DeleteTrait", scriptPointerHelper, &ASScript::DeleteTrait }, - {(const uint8_t*)"GetInitializer", scriptPointerHelper, &ASScript::GetInitializer}, - {(const uint8_t*)"SetInitializer", scriptPointerHelper, &ASScript::SetInitializer}, - }; - scriptPointerHelper = nullptr; - *functions = SCRIPT_functions; - *numFunctions = 5; - FRESetContextNativeData(ctx, (void*)SCRIPT_functions); + context->editor = nextObjectContext->editor; + context->functions = std::unique_ptr(new FRENamedFunction[]{ + {(const uint8_t*)"GetTrait", context, &CAV<&ASScript::GetTrait> }, + {(const uint8_t*)"SetTrait", context, &CAV<&ASScript::SetTrait> }, + {(const uint8_t*)"DeleteTrait", context, &CAV<&ASScript::DeleteTrait> }, + {(const uint8_t*)"GetInitializer", context, &CAV<&ASScript::GetInitializer>}, + {(const uint8_t*)"SetInitializer", context, &CAV<&ASScript::SetInitializer>}, + }); + context->objectData = { + nextObjectContext->objectData->object, context->editor->partialAssembly.get()}; + nextObjectContext = std::nullopt; + *functions = context->functions.get(); + *numFunctions = 5; + FRESetContextNativeData(ctx, context); } + FRESetContextNativeData(ctx, context); } void ContextFinalizer(FREContext ctx) { void* d; FREGetContextNativeData(ctx, &d); - delete[] static_cast(d); + delete static_cast(d); } extern "C" EXPORT void ExtInitializerANEBytecodeEditor(void** extDataToSet, diff --git a/Native/BytecodeEditor/source/ANEBytecodeEditorFunctions.cpp b/Native/BytecodeEditor/source/ANEBytecodeEditorFunctions.cpp index 8f23b91..1f001f8 100644 --- a/Native/BytecodeEditor/source/ANEBytecodeEditorFunctions.cpp +++ b/Native/BytecodeEditor/source/ANEBytecodeEditorFunctions.cpp @@ -1,6 +1,6 @@ #include "ANEFunctions.hpp" -#define GET_EDITOR() BytecodeEditor* editor = reinterpret_cast(funcData) +#define GET_EDITOR() BytecodeEditor& editor = *static_cast(funcData)->editor FREObject SetCurrentSWF(FREContext, void* funcData, uint32_t argc, FREObject argv[]) { @@ -19,7 +19,7 @@ FREObject SetCurrentSWF(FREContext, void* funcData, uint32_t argc, FREObject arg try { - editor->setSWF(SWF::SWFFile(std::move(data))); + editor.setSWF(SWF::SWFFile(std::move(data))); } catch (std::exception& e) { @@ -37,7 +37,7 @@ FREObject Cleanup(FREContext, void* funcData, uint32_t argc, FREObject[]) GET_EDITOR(); - editor->cleanup(); + editor.cleanup(); return nullptr; } @@ -48,15 +48,18 @@ FREObject GetClass(FREContext, void* funcData, uint32_t argc, FREObject argv[]) GET_EDITOR(); - ASASM::Multiname name = ConvertMultiname(argv[0]); + ASASM::Multiname name = editor.ConvertMultiname(argv[0]); - classPointerHelper = editor->getClass(name); + ASASM::Class* clazz = editor.getClass(name); - if (classPointerHelper == nullptr) + if (clazz == nullptr) { FAIL("Class not found"); } + nextObjectContext = ANEFunctionContext{ + editor.shared_from_this(), nullptr, ANEFunctionContext::ObjectData{clazz}}; + FREObject ret; DO_OR_FAIL("Could not build com.cff.anebe.ir.ASClass", ANENewObject("com.cff.anebe.ir.ASClass", 0, nullptr, &ret, nullptr)); @@ -70,15 +73,18 @@ FREObject GetScript(FREContext, void* funcData, uint32_t argc, FREObject argv[]) GET_EDITOR(); - ASASM::Multiname name = ConvertMultiname(argv[0]); + ASASM::Multiname name = editor.ConvertMultiname(argv[0]); - scriptPointerHelper = editor->getScript(name); + ASASM::Script* script = editor.getScript(name); - if (scriptPointerHelper == nullptr) + if (script == nullptr) { FAIL("Script not found"); } + nextObjectContext = ANEFunctionContext{ + editor.shared_from_this(), nullptr, ANEFunctionContext::ObjectData{script}}; + FREObject ret; DO_OR_FAIL("Could not build com.cff.anebe.ir.ASScript", ANENewObject("com.cff.anebe.ir.ASScript", 0, nullptr, &ret, nullptr)); @@ -92,15 +98,18 @@ FREObject GetROClass(FREContext, void* funcData, uint32_t argc, FREObject argv[] GET_EDITOR(); - ASASM::Multiname name = ConvertMultiname(argv[0]); + ASASM::Multiname name = editor.ConvertMultiname(argv[0]); - classPointerHelper = editor->getClass(name); + ASASM::Class* clazz = editor.getClass(name); - if (classPointerHelper == nullptr) + if (clazz == nullptr) { FAIL("Class not found"); } + nextObjectContext = ANEFunctionContext{ + editor.shared_from_this(), nullptr, ANEFunctionContext::ObjectData{clazz}}; + FREObject ret; DO_OR_FAIL("Could not build com.cff.anebe.ir.ASClass", ANENewObject("com.cff.anebe.ir.ASReadOnlyClass", 0, nullptr, &ret, nullptr)); @@ -114,15 +123,18 @@ FREObject GetROScript(FREContext, void* funcData, uint32_t argc, FREObject argv[ GET_EDITOR(); - ASASM::Multiname name = ConvertMultiname(argv[0]); + ASASM::Multiname name = editor.ConvertMultiname(argv[0]); - scriptPointerHelper = editor->getScript(name); + ASASM::Script* script = editor.getScript(name); - if (scriptPointerHelper == nullptr) + if (script == nullptr) { FAIL("Script not found"); } + nextObjectContext = ANEFunctionContext{ + editor.shared_from_this(), nullptr, ANEFunctionContext::ObjectData{script}}; + FREObject ret; DO_OR_FAIL("Could not build com.cff.anebe.ir.ASScript", ANENewObject("com.cff.anebe.ir.ASReadOnlyScript", 0, nullptr, &ret, nullptr)); diff --git a/Native/BytecodeEditor/source/ASASM/ASProgram.cpp b/Native/BytecodeEditor/source/ASASM/ASProgram.cpp index ca12050..d2ab9ff 100644 --- a/Native/BytecodeEditor/source/ASASM/ASProgram.cpp +++ b/Native/BytecodeEditor/source/ASASM/ASProgram.cpp @@ -1,7 +1,7 @@ #include "ASASM/ASProgram.hpp" #include "ASASM/AStoABC.hpp" -ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) +ASASM::ASProgram ASASM::ASProgram::fromABC(const SWFABC::ABCFile& abc) { ASProgram asp; @@ -69,7 +69,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto convertNamespace = [&](const ABC::Namespace& ns, int id) { + const auto convertNamespace = [&](const SWFABC::Namespace& ns, int id) { return Namespace{ns.kind, abc.strings[ns.name], id}; }; @@ -83,7 +83,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto convertMultiname = [&](const ABC::Multiname& multiname) + const auto convertMultiname = [&](const SWFABC::Multiname& multiname) { Multiname ret; ret.kind = multiname.kind; @@ -120,7 +120,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto postConvertMultiname = [&](const ABC::Multiname& multiname, Multiname& edit) + const auto postConvertMultiname = [&](const SWFABC::Multiname& multiname, Multiname& edit) { if (multiname.kind == ABCType::TypeName) { @@ -135,7 +135,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) } }; - const auto convertMethod = [&](const ABC::MethodInfo& method, int id) + const auto convertMethod = [&](const SWFABC::MethodInfo& method, int id) { std::shared_ptr ret = std::make_shared(); ret->paramTypes.reserve(method.paramTypes.size()); @@ -160,7 +160,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto convertMetadata = [&](const ABC::Metadata& metadata) + const auto convertMetadata = [&](const SWFABC::Metadata& metadata) { Metadata ret; ret.name = abc.strings[metadata.name]; @@ -172,7 +172,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto convertTraits = [&](const std::vector& traits) + const auto convertTraits = [&](const std::vector& traits) { std::vector ret; ret.reserve(traits.size()); @@ -217,7 +217,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto convertInstance = [&](const ABC::Instance& instance) + const auto convertInstance = [&](const SWFABC::Instance& instance) { Instance ret; ret.name = multinames[instance.name]; @@ -234,18 +234,18 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto convertClass = [&](const ABC::Class& clazz, uint32_t i) + const auto convertClass = [&](const SWFABC::Class& clazz, uint32_t i) { classSet[i] = true; - return std::shared_ptr( - new Class(std::move(getMethod(clazz.cinit)), convertTraits(clazz.traits), std::move(instances[i]))); + return std::shared_ptr(new Class(std::move(getMethod(clazz.cinit)), + convertTraits(clazz.traits), std::move(instances[i]))); }; - const auto convertScript = [&](const ABC::Script& script) { + const auto convertScript = [&](const SWFABC::Script& script) { return Script{getMethod(script.sinit), convertTraits(script.traits)}; }; - const auto convertInstruction = [&](const ABC::Instruction instruction) + const auto convertInstruction = [&](const SWFABC::Instruction instruction) { Instruction ret; ret.opcode = instruction.opcode; @@ -320,7 +320,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return ret; }; - const auto convertBody = [&](const ABC::MethodBody& body) + const auto convertBody = [&](const SWFABC::MethodBody& body) { MethodBody ret; ret.method = methods[body.method]; @@ -431,7 +431,7 @@ ASASM::ASProgram ASASM::ASProgram::fromABC(const ABC::ABCFile& abc) return asp; } -ABC::ABCFile ASASM::ASProgram::toABC() +SWFABC::ABCFile ASASM::ASProgram::toABC() { return AStoABC(*this).abc; } diff --git a/Native/BytecodeEditor/source/ASTypeFunctions.cpp b/Native/BytecodeEditor/source/ASTypeFunctions.cpp index fa36ef2..e2020a0 100644 --- a/Native/BytecodeEditor/source/ASTypeFunctions.cpp +++ b/Native/BytecodeEditor/source/ASTypeFunctions.cpp @@ -1,7 +1,12 @@ #include "ANEFunctions.hpp" #include "enums/InstanceFlags.hpp" +#include -#define GET_TYPE(type) type& clazz = *reinterpret_cast(funcData) +using namespace std::string_view_literals; + +#define GET_TYPE(type) \ + type& clazz = *std::get(static_cast(funcData)->objectData->object) +#define GET_EDITOR() BytecodeEditor& editor = *static_cast(funcData)->editor #define SUCCEED_VOID() \ FREObject ret; \ @@ -16,10 +21,11 @@ namespace CHECK_ARGC(2); GET_TYPE(T); + GET_EDITOR(); try { - ASASM::Multiname name = ConvertMultiname(argv[0]); + ASASM::Multiname name = editor.ConvertMultiname(argv[0]); bool favorSetter = CHECK_OBJECT(argv[1]); @@ -39,7 +45,7 @@ namespace if (found.size() == 1) { - return ConvertTrait(*found[0]); + return editor.ConvertTrait(*found[0]); } else if (found.size() == 2) { @@ -47,22 +53,22 @@ namespace { if (favorSetter) { - return ConvertTrait(*found[1]); + return editor.ConvertTrait(*found[1]); } else { - return ConvertTrait(*found[0]); + return editor.ConvertTrait(*found[0]); } } else { if (favorSetter) { - return ConvertTrait(*found[0]); + return editor.ConvertTrait(*found[0]); } else { - return ConvertTrait(*found[1]); + return editor.ConvertTrait(*found[1]); } } } @@ -93,10 +99,11 @@ namespace CHECK_ARGC(1); GET_TYPE(T); + GET_EDITOR(); try { - ASASM::Trait value = ConvertTrait(argv[0]); + ASASM::Trait value = editor.ConvertTrait(argv[0]); SmallTrivialVector found{}; @@ -200,10 +207,11 @@ namespace CHECK_ARGC(2); GET_TYPE(T); + GET_EDITOR(); try { - ASASM::Multiname name = ConvertMultiname(argv[0]); + ASASM::Multiname name = editor.ConvertMultiname(argv[0]); bool favorSetter = CHECK_OBJECT(argv[1]); @@ -282,10 +290,11 @@ namespace CHECK_ARGC(0); GET_TYPE(T); + GET_EDITOR(); try { - return ConvertMethod(*std::invoke(accessor, clazz)); + return editor.ConvertMethod(*std::invoke(accessor, clazz)); } catch (FREObject o) { @@ -311,10 +320,11 @@ namespace CHECK_ARGC(1); GET_TYPE(T); + GET_EDITOR(); try { - std::invoke(accessor, clazz) = ConvertMethod(argv[0]); + std::invoke(accessor, clazz) = editor.ConvertMethod(argv[0]); } catch (FREObject o) { @@ -411,6 +421,7 @@ namespace ASClass CHECK_ARGC(0); GET_TYPE(ASASM::Class); + GET_EDITOR(); try { @@ -422,7 +433,8 @@ namespace ASClass for (size_t i = 0; i < clazz.instance.interfaces.size(); i++) { DO_OR_FAIL("Couldn't set interface vector entry", - FRESetArrayElementAt(ret, i, ConvertMultiname(clazz.instance.interfaces[i]))); + FRESetArrayElementAt( + ret, i, editor.ConvertMultiname(clazz.instance.interfaces[i]))); } return ret; } @@ -449,6 +461,7 @@ namespace ASClass CHECK_ARGC(1); GET_TYPE(ASASM::Class); + GET_EDITOR(); try { @@ -460,7 +473,7 @@ namespace ASClass FREObject mname; DO_OR_FAIL("Couldn't get interface vector element", FREGetArrayElementAt(argv[0], i, &mname)); - newMultinames.emplace_back(ConvertMultiname(mname)); + newMultinames.emplace_back(editor.ConvertMultiname(mname)); } clazz.instance.interfaces = newMultinames; @@ -490,10 +503,11 @@ namespace ASClass CHECK_ARGC(0); GET_TYPE(ASASM::Class); + GET_EDITOR(); try { - return ConvertMultiname(clazz.instance.superName); + return editor.ConvertMultiname(clazz.instance.superName); } catch (FREObject o) { @@ -518,10 +532,11 @@ namespace ASClass CHECK_ARGC(1); GET_TYPE(ASASM::Class); + GET_EDITOR(); try { - clazz.instance.superName = ConvertMultiname(argv[0]); + clazz.instance.superName = editor.ConvertMultiname(argv[0]); } catch (FREObject o) { @@ -634,10 +649,11 @@ namespace ASClass CHECK_ARGC(0); GET_TYPE(ASASM::Class); + GET_EDITOR(); try { - return ConvertNamespace(clazz.instance.protectedNs); + return editor.ConvertNamespace(clazz.instance.protectedNs); } catch (FREObject o) { @@ -662,10 +678,11 @@ namespace ASClass CHECK_ARGC(1); GET_TYPE(ASASM::Class); + GET_EDITOR(); try { - clazz.instance.protectedNs = ConvertNamespace(argv[0]); + clazz.instance.protectedNs = editor.ConvertNamespace(argv[0]); } catch (FREObject o) { @@ -692,8 +709,10 @@ namespace ASClass CHECK_ARGC(0); GET_TYPE(ASASM::Class); + GET_EDITOR(); - classPointerHelper = &clazz; + nextObjectContext = ANEFunctionContext{ + editor.shared_from_this(), nullptr, ANEFunctionContext::ObjectData{&clazz}}; return nullptr; } diff --git a/Native/BytecodeEditor/source/BytecodeEditor.cpp b/Native/BytecodeEditor/source/BytecodeEditor.cpp index 7961f08..af3e812 100644 --- a/Native/BytecodeEditor/source/BytecodeEditor.cpp +++ b/Native/BytecodeEditor/source/BytecodeEditor.cpp @@ -31,7 +31,7 @@ FREObject BytecodeEditor::disassemble() try { auto strings = Disassembler::Disassembler( - ASASM::ASProgram::fromABC(ABC::ABCReader(currentSWF->abcData()).abc())) + ASASM::ASProgram::fromABC(SWFABC::ABCReader(currentSWF->abcData()).abc())) .disassemble(); FREObject ret; @@ -68,7 +68,8 @@ FREObject BytecodeEditor::assemble( try { std::vector data = std::move( - ABC::ABCWriter(Assembler::assemble(strings, includeDebugInstructions).toABC()).data()); + SWFABC::ABCWriter(Assembler::assemble(strings, includeDebugInstructions).toABC()) + .data()); currentSWF->replaceABCData(data.data(), data.size()); @@ -115,7 +116,7 @@ FREObject BytecodeEditor::disassembleAsync() try { SUCCEED_ASYNC(Disassembler::Disassembler( - ASASM::ASProgram::fromABC(ABC::ABCReader(currentSWF->abcData()).abc())) + ASASM::ASProgram::fromABC(SWFABC::ABCReader(currentSWF->abcData()).abc())) .disassemble()); } catch (const std::exception& e) @@ -146,9 +147,9 @@ FREObject BytecodeEditor::assembleAsync( } try { - std::vector data = std::move( - ABC::ABCWriter(Assembler::assemble(strings, includeDebugInstructions).toABC()) - .data()); + std::vector data = std::move(SWFABC::ABCWriter( + Assembler::assemble(strings, includeDebugInstructions).toABC()) + .data()); SUCCEED_ASYNC(data); } @@ -173,8 +174,11 @@ FREObject BytecodeEditor::partialAssemble( try { - this->partialAssembly = std::make_unique( - Assembler::assemble(strings, includeDebugInstructions)); + auto assembled = Assembler::assemble(strings, includeDebugInstructions); + RefBuilder rb(assembled); + rb.run(); + this->partialAssembly = std::make_unique>( + std::move(assembled), std::move(rb)); } catch (const std::exception& e) { @@ -199,8 +203,11 @@ FREObject BytecodeEditor::partialAssembleAsync( { try { - this->partialAssembly = std::make_unique( - Assembler::assemble(strings, includeDebugInstructions)); + auto assembled = Assembler::assemble(strings, includeDebugInstructions); + RefBuilder rb(assembled); + rb.run(); + this->partialAssembly = std::make_unique>( + std::move(assembled), std::move(rb)); SUCCEED_ASYNC_WITHMESSAGE("PartialSuccess"); } @@ -233,8 +240,9 @@ FREObject BytecodeEditor::finishAssemble() try { - std::vector data = std::move(ABC::ABCWriter(partialAssembly->toABC()).data()); - partialAssembly = nullptr; + std::vector data = + std::move(SWFABC::ABCWriter(partialAssembly->first.toABC()).data()); + partialAssembly = nullptr; currentSWF->replaceABCData(data.data(), data.size()); @@ -284,7 +292,7 @@ FREObject BytecodeEditor::finishAssembleAsync() try { std::vector data = - std::move(ABC::ABCWriter(partialAssembly->toABC()).data()); + std::move(SWFABC::ABCWriter(partialAssembly->first.toABC()).data()); partialAssembly = nullptr; @@ -294,6 +302,10 @@ FREObject BytecodeEditor::finishAssembleAsync() { FAIL_ASYNC(std::string("Exception while finishing assembly: ") + e.what()); } + catch (...) + { + FAIL_ASYNC("AAAA"); + } }); FREObject ret; @@ -315,8 +327,11 @@ FREObject BytecodeEditor::beginIntrospection() try { - this->partialAssembly = std::make_unique( - ASASM::ASProgram::fromABC(ABC::ABCReader(currentSWF->abcData()).abc())); + auto assembled = ASASM::ASProgram::fromABC(SWFABC::ABCReader(currentSWF->abcData()).abc()); + RefBuilder rb(assembled); + rb.run(); + this->partialAssembly = std::make_unique>( + std::move(assembled), std::move(rb)); currentSWF = std::nullopt; } @@ -332,7 +347,7 @@ FREObject BytecodeEditor::beginIntrospection() ASASM::Class* BytecodeEditor::getClass(const ASASM::Multiname& className) const { - for (const auto& script : partialAssembly->scripts) + for (const auto& script : partialAssembly->first.scripts) { for (const auto& trait : script.traits) { @@ -348,7 +363,7 @@ ASASM::Class* BytecodeEditor::getClass(const ASASM::Multiname& className) const ASASM::Script* BytecodeEditor::getScript(const ASASM::Multiname& traitName) const { - for (auto& script : partialAssembly->scripts) + for (auto& script : partialAssembly->first.scripts) { for (const auto& trait : script.traits) { diff --git a/Native/BytecodeEditor/source/Test.cpp.disabled b/Native/BytecodeEditor/source/Test.cpp.disabled index 46a25ee..f203cac 100644 --- a/Native/BytecodeEditor/source/Test.cpp.disabled +++ b/Native/BytecodeEditor/source/Test.cpp.disabled @@ -32,7 +32,7 @@ void testdisassemble() auto abcData = swf.abcData(); - ABC::ABCReader reader(abcData.first, abcData.second); + SWFABC::ABCReader reader(abcData.first, abcData.second); const auto& abc = reader.abc(); ASASM::ASProgram program = ASASM::ASProgram::fromABC(abc); disassembled = Disassembler(program).disassemble(); @@ -79,7 +79,7 @@ void testreassemble() } std::vector abcData = - std::move(ABC::ABCWriter(Assembler::assemble(asasmFiles).toABC()).data()); + std::move(SWFABC::ABCWriter(Assembler::assemble(asasmFiles).toABC()).data()); file = fopen("test.swf", "rb"); fseek(file, 0, SEEK_END); diff --git a/Native/BytecodeEditor/source/utils/ANEUtils.cpp b/Native/BytecodeEditor/source/utils/ANEUtils.cpp index 9149b9e..f5d3a28 100644 --- a/Native/BytecodeEditor/source/utils/ANEUtils.cpp +++ b/Native/BytecodeEditor/source/utils/ANEUtils.cpp @@ -5,18 +5,19 @@ #undef FAIL_RETURN #define FAIL_RETURN(x) throw x -std::shared_ptr ConvertClass(FREObject o) +std::shared_ptr BytecodeEditor::ConvertClass(FREObject o) const { FREObject dummy; DO_OR_FAIL("Could not get class's native pointer", ANECallObjectMethod(o, "setNativePointerForConversion", 0, nullptr, &dummy, nullptr)); - return classPointerHelper->shared_from_this(); + return std::get(nextObjectContext->objectData->object)->shared_from_this(); } -FREObject ConvertClass(ASASM::Class& clazz) +FREObject BytecodeEditor::ConvertClass(ASASM::Class& clazz) const { - classPointerHelper = &clazz; + nextObjectContext = ANEFunctionContext{const_cast(this)->shared_from_this(), + nullptr, ANEFunctionContext::ObjectData{&clazz}}; FREObject ret; DO_OR_FAIL("Could not build com.cff.anebe.ir.ASClass", @@ -25,21 +26,56 @@ FREObject ConvertClass(ASASM::Class& clazz) return ret; } -ASASM::Namespace ConvertNamespace(FREObject o) +ASASM::Namespace BytecodeEditor::ConvertNamespace(FREObject o) const { - return ASASM::Namespace{ABCTypeMap.Find(CheckMember(o, "type"))->get(), - std::string(CheckMember(o, "name")), - CheckMember(o, "id")}; + ASASM::Namespace ret{ABCTypeMap.Find(CheckMember(o, "type"))->get(), + std::string(CheckMember(o, "name"))}; + + FREObject disambiguatorObj = GetMember(o, "secondaryName"); + FREObjectType objType; + DO_OR_FAIL("Could not get multiname type", FREGetObjectType(disambiguatorObj, &objType)); + + auto homonyms = partialAssembly->second.getHomonyms(ret); + + if (objType == FRE_TYPE_NULL) + { + if (homonyms) + { + ret.id = homonyms->get().begin()->id; + } + return ret; + } + + std::string_view disambiguator = CheckMember(o, "secondaryName"); + + if (homonyms) + { + for (const auto& homonym : homonyms->get()) + { + if (partialAssembly->second.namespaces[(uint8_t)homonym.kind].getName(homonym.id) == + disambiguator) + { + ret.id = homonym.id; + break; + } + } + } + + return ret; } -FREObject ConvertNamespace(const ASASM::Namespace& n) +FREObject BytecodeEditor::ConvertNamespace(const ASASM::Namespace& n) const { - FREObject name = FREString(n.name); - FREObject kind = FREString(ABCTypeMap.ReverseFind(n.kind)->get()); - FREObject id; - DO_OR_FAIL("Could not convert namespace ID", FRENewObjectFromInt32(n.id, &id)); + FREObject name = FREString(n.name); + FREObject kind = FREString(ABCTypeMap.ReverseFind(n.kind)->get()); + FREObject disambiguator = nullptr; + if (partialAssembly->second.hasHomonyms(n)) + { + disambiguator = + FREString(partialAssembly->second.namespaces[(uint8_t)n.kind].getName(n.id)); + } - FREObject args[] = {kind, name, id}; + FREObject args[] = {kind, name, disambiguator}; FREObject ret; DO_OR_FAIL("Could not create com.cff.anebe.ir.ASNamespace", @@ -48,7 +84,7 @@ FREObject ConvertNamespace(const ASASM::Namespace& n) return ret; } -ASASM::Multiname ConvertMultiname(FREObject o) +ASASM::Multiname BytecodeEditor::ConvertMultiname(FREObject o) const { ASASM::Multiname ret; @@ -155,7 +191,7 @@ ASASM::Multiname ConvertMultiname(FREObject o) return ret; } -FREObject ConvertMultiname(const ASASM::Multiname& m) +FREObject BytecodeEditor::ConvertMultiname(const ASASM::Multiname& m) const { if (m.kind == ABCType::Void) { @@ -250,7 +286,7 @@ FREObject ConvertMultiname(const ASASM::Multiname& m) return ret; } -FREObject ConvertTrait(const ASASM::Trait& t) +FREObject BytecodeEditor::ConvertTrait(const ASASM::Trait& t) const { FREObject kind = FREString(TraitKindMap.ReverseFind(t.kind)->get()); FREObject traitName = ConvertMultiname(t.name); @@ -346,7 +382,7 @@ FREObject ConvertTrait(const ASASM::Trait& t) return ret; } -ASASM::Trait ConvertTrait(FREObject o) +ASASM::Trait BytecodeEditor::ConvertTrait(FREObject o) const { TraitKind kind; if (auto found = TraitKindMap.Find(CheckMember(o, "kind")); found) @@ -437,7 +473,7 @@ ASASM::Trait ConvertTrait(FREObject o) return ret; } -FREObject ConvertMethod(const ASASM::Method& m) +FREObject BytecodeEditor::ConvertMethod(const ASASM::Method& m) const { FREObject paramTypes; DO_OR_FAIL("Could not create method paramTypes array", @@ -495,7 +531,7 @@ FREObject ConvertMethod(const ASASM::Method& m) return ret; } -std::shared_ptr ConvertMethod(FREObject o) +std::shared_ptr BytecodeEditor::ConvertMethod(FREObject o) const { std::shared_ptr ret = std::make_shared(); @@ -564,7 +600,7 @@ std::shared_ptr ConvertMethod(FREObject o) return ret; } -FREObject ConvertMethodBody(const ASASM::MethodBody& b) +FREObject BytecodeEditor::ConvertMethodBody(const ASASM::MethodBody& b) const { FREObject maxStack; DO_OR_FAIL("Could not create body max stack", FRENewObjectFromUint32(b.maxStack, &maxStack)); @@ -693,7 +729,7 @@ FREObject ConvertMethodBody(const ASASM::MethodBody& b) return ret; } -ASASM::MethodBody ConvertMethodBody(FREObject o) +ASASM::MethodBody BytecodeEditor::ConvertMethodBody(FREObject o) const { ASASM::MethodBody body; body.maxStack = CheckMember(o, "maxStack"); @@ -754,7 +790,8 @@ ASASM::MethodBody ConvertMethodBody(FREObject o) return body; } -FREObject ConvertException(const ASASM::Exception& e, const std::vector& allInstrs) +FREObject BytecodeEditor::ConvertException( + const ASASM::Exception& e, const std::vector& allInstrs) const { FREObject from = ConvertLabel(e.from, allInstrs); FREObject to = ConvertLabel(e.to, allInstrs); @@ -770,7 +807,8 @@ FREObject ConvertException(const ASASM::Exception& e, const std::vector& allInstrs) +ASASM::Exception BytecodeEditor::ConvertException( + FREObject o, const std::vector& allInstrs) const { return {ConvertLabel(CheckMember(o, "from"), allInstrs), ConvertLabel(CheckMember(o, "to"), allInstrs), @@ -779,7 +817,8 @@ ASASM::Exception ConvertException(FREObject o, const std::vector& all ConvertMultiname(GetMember(o, "exceptionName"))}; } -FREObject ConvertError(const ABC::Error& e, const std::vector& allInstrs) +FREObject BytecodeEditor::ConvertError( + const SWFABC::Error& e, const std::vector& allInstrs) const { FREObject args[] = {ConvertLabel(e.loc, allInstrs), FREString(e.message)}; @@ -789,13 +828,15 @@ FREObject ConvertError(const ABC::Error& e, const std::vector& allIns return ret; } -ABC::Error ConvertError(FREObject o, const std::vector& allInstrs) +SWFABC::Error BytecodeEditor::ConvertError( + FREObject o, const std::vector& allInstrs) const { return {ConvertLabel(CheckMember(o, "loc"), allInstrs), std::string(CheckMember(o, "message"))}; } -FREObject ConvertLabel(const ABC::Label& l, const std::vector& allInstrs) +FREObject BytecodeEditor::ConvertLabel( + const SWFABC::Label& l, const std::vector& allInstrs) const { if (l.index + l.offset >= allInstrs.size()) { @@ -804,17 +845,19 @@ FREObject ConvertLabel(const ABC::Label& l, const std::vector& allIns return allInstrs[l.index + l.offset]; } -ABC::Label ConvertLabel(FREObject o, const std::vector& allInstrs) +SWFABC::Label BytecodeEditor::ConvertLabel( + FREObject o, const std::vector& allInstrs) const { if (auto found = std::ranges::find(allInstrs, o); found != allInstrs.end()) { - return ABC::Label{.index = (uint32_t)std::distance(allInstrs.begin(), found)}; + return SWFABC::Label{.index = (uint32_t)std::distance(allInstrs.begin(), found)}; } FAIL("Could not find target instruction in full instruction list"); } -ASASM::Instruction ConvertInstruction(FREObject o, const std::vector& allInstrs) +ASASM::Instruction BytecodeEditor::ConvertInstruction( + FREObject o, const std::vector& allInstrs) const { ASASM::Instruction ret; if (auto found = OPCodeMap.Find(CheckMember(o, "opcode")); found) @@ -995,7 +1038,7 @@ ASASM::Instruction ConvertInstruction(FREObject o, const std::vector& CHECK_OBJECT(argO, "args[" + std::to_string(i) + "]"), &targetLen)); - arg.switchTargets(std::vector(targetLen)); + arg.switchTargets(std::vector(targetLen)); for (size_t j = 0; j < targetLen; j++) { FREObject target; @@ -1013,7 +1056,7 @@ ASASM::Instruction ConvertInstruction(FREObject o, const std::vector& return ret; } -std::pair ConvertInstruction(const ASASM::Instruction& instr) +std::pair BytecodeEditor::ConvertInstruction(const ASASM::Instruction& instr) const { bool requiresFixup = false; @@ -1140,7 +1183,7 @@ std::pair ConvertInstruction(const ASASM::Instruction& instr) return {ret, requiresFixup}; } -FREObject ConvertValue(const ASASM::Value& v) +FREObject BytecodeEditor::ConvertValue(const ASASM::Value& v) const { FREObject value; switch (v.vkind) @@ -1190,7 +1233,7 @@ FREObject ConvertValue(const ASASM::Value& v) return ret; } -ASASM::Value ConvertValue(FREObject o) +ASASM::Value BytecodeEditor::ConvertValue(FREObject o) const { ASASM::Value ret;