2010-11-03 64 views
4

我一直在玩ABC字節碼,希望有人能爲我澄清一點困惑。我有一個簡單的Flash文件,在舞臺上放置一個剪輯,並有一個小腳本來更新它在每個幀上的位置。代碼看起來是這樣的:如何在AVM2字節碼中找到方法?

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'方法。不幸的是,方法信息中的'name'字段似乎永遠不會被編譯器使用。所有方法都有空字符串作爲其名稱(在### 2中顯示爲未命名的函數)。

Flash播放器如何將multiiname鏈接到未命名的方法?在AVM2規範中似乎沒有這方面的規定。

我知道這是可能的,因爲商業反編譯器如sothink可以設法確定方法名稱。我只是不確定他們是如何做到的,或者代碼如何工作。

回答

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 
} 

一個有點簡單的答案,但我希望它清除了一些問題。

+0

一個非常完整的答案,謝謝:) – izb 2010-11-04 10:38:30

+0

非常明確的答案。你用什麼工具以這種漂亮的格式轉儲abcData? – 2016-08-06 20:41:27

+0

@HaoNguyen我寫了我自己的工具(https://github.com/Joony/ByteMyAS)。那是6年前,我不再維護它,但代碼在那裏,如果它對你有任何用處。 – Joony 2016-08-08 09:38:56

0

我正在探索as3swf和as3abc庫正是在這個當前時刻)和getlex在as3abc lib中兩次提到:

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(internal .moveit);

callpropvoid(addEventListener,2);

,我們可以看到一種添加事件監聽器(或者也許我只是瘋了)的還有一兩件事提:你以前moveit功能是接受Event作爲參數只有一個,所以它不是很難調用它。順便說一下:你是如何進入AVM2的?也許該函數是如此的內部,只有當你是這個類中的實體時,它的名字纔是可見的;)?
and here's a link to some avm2 bytecode from adobe

0

原來,方法名稱是存儲在類特徵中的多名;由於我正在查找字符串表中的特徵名稱,而不是多表名,這一問題更加複雜了。哎呀。

似乎儘管ABC文件中的方法名稱字段是多餘的。

相關問題