我一直在玩ABC字节码,并希望有人可以为我清理一点混乱。我有一个简单的Flash文件,可以在舞台上放置一个剪辑,并有一个小脚本来更新它在每个帧上的位置。代码看起来像:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class RedCircle extends MovieClip
{
public function RedCircle()
{
this.addEventListener(Event.ENTER_FRAME, moveit);
}
function moveit(e:Event)
{
this.x -=1;
}
}
}
编译为:
protected package protected RedCircle
{
class RedCircle extends flash.display.MovieClip
{
static () : Void
{
getlocal_0();
pushscope();
returnvoid();
}
RedCircle () : Void
{
getlocal_0();
pushscope();
getlocal_0();
constructsuper(0);
getlocal_0();
getlex(flash.events.Event);
getproperty(ENTER_FRAME);
getlex(internal .moveit); // ###1
callpropvoid(addEventListener, 2);
returnvoid();
}
function (anonymous) (flash.events.Event param1) : Void // ###2
{
getlocal_0();
pushscope();
getlocal_0();
getlocal_0();
getproperty(x);
decrement();
setproperty(x);
returnvoid();
}
}
}
我的问题是'getlex'操作是如何工作的(我用### 1标记了它)。它传递了一个引用该类的'moveit'方法的multiname。不幸的是,方法信息中的'name'字段似乎永远不会被编译器使用。所有方法都有空字符串作为其名称(在上面显示为### 2中未命名的函数)。
flash播放器如何将多个名称链接到未命名的方法?在AVM2规范中似乎没有这方面的规定。
我知道这是可能的,因为像sothink这样的商业反编译器会设法确定方法名称。我只是不确定他们是如何做到的,或者代码是如何工作的。
答案 0 :(得分:5)
我不确定为什么你的反编译器会将该方法显示为(匿名)。
这是abcData的转储:
abcFile{
minor_version (17): 16
major_version (19): 46
constant_pool{
int_count (21): 0
[0]: zero (not included in abcFile)
uint_count (22): 0
[0]: zero (not included in abcFile)
double_count (23): 0
[0]: NaN (not included in abcFile)
string_count (24): 17
string_info[0]{
name: * (not included in abcFile)
}
string_info[1]{
size (25): 12
name (26): "flash.events"
}
string_info[2]{
size (38): 5
name (39): "Event"
}
string_info[3]{
size (44): 0
name (45): ""
}
string_info[4]{
size (45): 9
name (46): "RedCircle"
}
string_info[5]{
size (55): 13
name (56): "flash.display"
}
string_info[6]{
size (69): 9
name (70): "MovieClip"
}
string_info[7]{
size (79): 6
name (80): "moveit"
}
string_info[8]{
size (86): 11
name (87): "ENTER_FRAME"
}
string_info[9]{
size (98): 16
name (99): "addEventListener"
}
string_info[10]{
size (115): 1
name (116): "x"
}
string_info[11]{
size (117): 6
name (118): "Object"
}
string_info[12]{
size (124): 15
name (125): "EventDispatcher"
}
string_info[13]{
size (140): 13
name (141): "DisplayObject"
}
string_info[14]{
size (154): 17
name (155): "InteractiveObject"
}
string_info[15]{
size (172): 22
name (173): "DisplayObjectContainer"
}
string_info[16]{
size (195): 6
name (196): "Sprite"
}
namespace_count (202): 6
namespace_info[0]{
kind: * (not included in abcFile)
}
namespace_info[1]{
kind (203): CONSTANT_PackageNamespace
name (204): 1
}
namespace_info[2]{
kind (205): CONSTANT_PackageNamespace
name (206): 3
}
namespace_info[3]{
kind (207): CONSTANT_PackageNamespace
name (208): 5
}
namespace_info[4]{
kind (209): CONSTANT_ProtectedNamespace
name (210): 4
}
namespace_info[5]{
kind (211): CONSTANT_PackageInternalNs
name (212): 3
}
ns_set_count (213): 0
ns_set_info[0]{
ns: 0 (not included in abcFile)
}
multiname_count (214): 14
multiname_info[0]{
kind: 0 (not included in abcFile)
}
multiname_info[1]{
kind (216): CONSTANT_QName
multiname_kind_QNAME{
ns (216): 1
name (217): 2 ("Event")
}
}
multiname_info[2]{
kind (219): CONSTANT_QName
multiname_kind_QNAME{
ns (219): 2
name (220): 4 ("RedCircle")
}
}
multiname_info[3]{
kind (222): CONSTANT_QName
multiname_kind_QNAME{
ns (222): 3
name (223): 6 ("MovieClip")
}
}
multiname_info[4]{
kind (225): CONSTANT_QName
multiname_kind_QNAME{
ns (225): 5
name (226): 7 ("moveit")
}
}
multiname_info[5]{
kind (228): CONSTANT_QName
multiname_kind_QNAME{
ns (228): 2
name (229): 8 ("ENTER_FRAME")
}
}
multiname_info[6]{
kind (231): CONSTANT_QName
multiname_kind_QNAME{
ns (231): 2
name (232): 9 ("addEventListener")
}
}
multiname_info[7]{
kind (234): CONSTANT_QName
multiname_kind_QNAME{
ns (234): 2
name (235): 10 ("x")
}
}
multiname_info[8]{
kind (237): CONSTANT_QName
multiname_kind_QNAME{
ns (237): 2
name (238): 11 ("Object")
}
}
multiname_info[9]{
kind (240): CONSTANT_QName
multiname_kind_QNAME{
ns (240): 1
name (241): 12 ("EventDispatcher")
}
}
multiname_info[10]{
kind (243): CONSTANT_QName
multiname_kind_QNAME{
ns (243): 3
name (244): 13 ("DisplayObject")
}
}
multiname_info[11]{
kind (246): CONSTANT_QName
multiname_kind_QNAME{
ns (246): 3
name (247): 14 ("InteractiveObject")
}
}
multiname_info[12]{
kind (249): CONSTANT_QName
multiname_kind_QNAME{
ns (249): 3
name (250): 15 ("DisplayObjectContainer")
}
}
multiname_info[13]{
kind (252): CONSTANT_QName
multiname_kind_QNAME{
ns (252): 3
name (253): 16 ("Sprite")
}
}
}
method_count (254): 4
method_info[0]{
param_count (255): 0
return_type (256): 0
name (257): 0
flags (258): 0
NEED_ARGUMENTS (0x01): false
NEED_ACTIVATION (0x02): false
NEED_REST (0x04): false
HAS_OPTIONAL (0x08): false
SET_DXNS (0x40): false
HAS_PARAM_NAMES (0x80): false
}
method_info[1]{
param_count (259): 0
return_type (260): 0
name (261): 0
flags (262): 0
NEED_ARGUMENTS (0x01): false
NEED_ACTIVATION (0x02): false
NEED_REST (0x04): false
HAS_OPTIONAL (0x08): false
SET_DXNS (0x40): false
HAS_PARAM_NAMES (0x80): false
}
method_info[2]{
param_count (263): 1
return_type (264): 0
param_type[0] (265): 1
name (266): 0
flags (267): 0
NEED_ARGUMENTS (0x01): false
NEED_ACTIVATION (0x02): false
NEED_REST (0x04): false
HAS_OPTIONAL (0x08): false
SET_DXNS (0x40): false
HAS_PARAM_NAMES (0x80): false
}
method_info[3]{
param_count (268): 0
return_type (269): 0
name (270): 0
flags (271): 0
NEED_ARGUMENTS (0x01): false
NEED_ACTIVATION (0x02): false
NEED_REST (0x04): false
HAS_OPTIONAL (0x08): false
SET_DXNS (0x40): false
HAS_PARAM_NAMES (0x80): false
}
metadata_count (272): 0
class_count (273): 1
instance_info[0]{
name (274): 2 (RedCircle)
super_name (275): 3 (MovieClip)
flags (276): 9
CONSTANT_ClassSealed (0x01): true
CONSTANT_ClassFinal (0x02): false
CONSTANT_ClassInterface (0x04): false
CONSTANT_ClassProtectedNs (0x08): true
protectedNs (277): 4
intrf_count (278): 0
iinit (279): 1
trait_count (280): 1
traits_info[0]{
name (281): 4 (moveit)
kind (282): Trait_Method
ATTR_Final (0x1): false
ATTR_Override (0x2): false
ATTR_Metadata (0x4): false
trait_method{
disp_id (283): 0
method (284): 2
}
}
}
class_info[0]{
cinit (285): 0
trait_count (286): 0
}
script_count (287): 1
init (288): 3
trait_count (289): 1
traits_info[0]{
name (290): 2 (RedCircle)
kind (291): Trait_Class
ATTR_Metadata (0x4): false
trait_class{
slot_id (292): 1
classi (293): 0
}
}
method_body_count (294): 4
method_body_info[0]{
method (295): 0
max_stack (296): 1
local_count (297): 1
init_scope_depth (298): 9
max_scope_depth (299): 10
code_length (300): 3
208 0xD0 (301) getlocal_0
48 0x30 (302) pushscope
71 0x47 (303) returnvoid
exception_count (304): 0
trait_count (305): 0
}
method_body_info[1]{
method (306): 1
max_stack (307): 3
local_count (308): 1
init_scope_depth (309): 10
max_scope_depth (310): 11
code_length (311): 17
208 0xD0 (312) getlocal_0
48 0x30 (313) pushscope
208 0xD0 (314) getlocal_0
73 0x49 (315) constructsuper
arg_count: 0
208 0xD0 (317) getlocal_0
96 0x60 (318) getlex
index: 1 (Event)
102 0x66 (320) getproperty
index: 5 (ENTER_FRAME)
208 0xD0 (322) getlocal_0
102 0x66 (323) getproperty
index: 4 (moveit)
79 0x4F (325) callpropvoid
index: 6 (addEventListener)
arg_count: 2
71 0x47 (328) returnvoid
exception_count (329): 0
trait_count (330): 0
}
method_body_info[2]{
method (331): 2
max_stack (332): 3
local_count (333): 2
init_scope_depth (334): 10
max_scope_depth (335): 11
code_length (336): 10
208 0xD0 (337) getlocal_0
48 0x30 (338) pushscope
208 0xD0 (339) getlocal_0
208 0xD0 (340) getlocal_0
102 0x66 (341) getproperty
index: 7
147 0x93 (343) decrement
97 0x61 (344) setproperty
index: 7
71 0x47 (346) returnvoid
exception_count (347): 0
trait_count (348): 0
}
method_body_info[3]{
method (349): 3
max_stack (350): 2
local_count (351): 1
init_scope_depth (352): 1
max_scope_depth (353): 9
code_length (354): 39
208 0xD0 (355) getlocal_0
48 0x30 (356) pushscope
101 0x65 (357) getscopeobject
index: 0
96 0x60 (359) getlex
index: 8
48 0x30 (361) pushscope
96 0x60 (362) getlex
index: 9
48 0x30 (364) pushscope
96 0x60 (365) getlex
index: 10
48 0x30 (367) pushscope
96 0x60 (368) getlex
index: 11
48 0x30 (370) pushscope
96 0x60 (371) getlex
index: 12
48 0x30 (373) pushscope
96 0x60 (374) getlex
index: 13
48 0x30 (376) pushscope
96 0x60 (377) getlex
index: 3
48 0x30 (379) pushscope
96 0x60 (380) getlex
index: 3
88 0x58 (382) newclass
index: 0
29 0x1D (384) popscope
29 0x1D (385) popscope
29 0x1D (386) popscope
29 0x1D (387) popscope
29 0x1D (388) popscope
29 0x1D (389) popscope
29 0x1D (390) popscope
104 0x68 (391) initproperty
index: 2
71 0x47 (393) returnvoid
exception_count (394): 0
trait_count (395): 0
}
}
您感兴趣的是instance_info [0]。这是类的运行时实例的定义,这里将是RedCircle。实例具有各种类型的特征数组。 RedCircle有一个特质Trait_Method特征(moveit),这意味着特征引用了方法(2)。
因此,如果你跳到method_body_info [1](RedCircle的构造函数),你可以在字节323看到调用getProperty时索引为4.
102 0x66 (323) getproperty
index: 4 (moveit)
这是对多名称常量池的引用。
multiname_info[4]{
kind (225): CONSTANT_QName
multiname_kind_QNAME{
ns (225): 5
name (226): 7 ("moveit")
}
}
在调用方法时,它会在实例的特征中查找名称索引。
traits_info[0]{
name (281): 4 (moveit)
kind (282): Trait_Method
ATTR_Final (0x1): false
ATTR_Override (0x2): false
ATTR_Metadata (0x4): false
trait_method{
disp_id (283): 0
method (284): 2
}
}
然后调用相关方法。
method_info[2]{
param_count (263): 1
return_type (264): 0
param_type[0] (265): 1
name (266): 0
flags (267): 0
NEED_ARGUMENTS (0x01): false
NEED_ACTIVATION (0x02): false
NEED_REST (0x04): false
HAS_OPTIONAL (0x08): false
SET_DXNS (0x40): false
HAS_PARAM_NAMES (0x80): false
}
method_body_info[2]{
method (331): 2
max_stack (332): 3
local_count (333): 2
init_scope_depth (334): 10
max_scope_depth (335): 11
code_length (336): 10
208 0xD0 (337) getlocal_0
48 0x30 (338) pushscope
208 0xD0 (339) getlocal_0
208 0xD0 (340) getlocal_0
102 0x66 (341) getproperty
index: 7 (x)
147 0x93 (343) decrement
97 0x61 (344) setproperty
index: 7 (x)
71 0x47 (346) returnvoid
exception_count (347): 0
trait_count (348): 0
}
一个有点简化的答案,但我希望它能解决一些问题。
答案 1 :(得分:0)
我正在探索当前时刻的as3swf和as3abc库)并且在as3abc lib中提到了两次getlex:
package com.codeazur.as3abc.factories
public function create(code:int):AbstractOperation
switch (code) {//in real life this switch block is really huge
case Opcodes.GetLex: return new MultinameOperation(code);
}
和
package com.codeazur.as3abc.data.bytecode
public class Opcodes
public static const GetLex:uint = 0x60;
_opNames[ GetLex ] = "GetLex";
据我所知,它只是AVM2中的一个关键字。并且更密切地关注你的问题:我想在这里:
getlex(对象类型:flash.events.Event);
的getProperty(ENTER_FRAME);
getlex(内部.moveit);
callpropvoid(addEventListener,2);
我们可以看到一种添加事件监听器(或者我只是疯了)还有一件事需要提及:你以前的moveit
函数是唯一一个接受Event
的函数参数因此不难调用它。顺便说一句:你是如何进入AVM2的?也许这个函数是如此内部,只有当你是这个类中的实体时,它的名字才是可见的;)?
and here's a link to some avm2 bytecode from adobe
答案 2 :(得分:0)
原来,方法名称是存储在类特征中的多个名称;我正在寻找字符串表中的特征名称,而不是多名表,这一事实加剧了这个问题。糟糕。
但似乎方法名称字段在ABC文件中是多余的。