I’ve been playing around with ABC bytecode and was hoping someone could clear up a point of confusion for me. I have a simple flash file that places a clip on the stage and has a tiny script to update its position on each frame. The code looks something like:
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;
}
}
}
Which compiles to something like:
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();
}
}
}
My question is how does the ‘getlex’ operation work (I’ve marked it with ###1). It is passed a multiname which references the ‘moveit’ method of the class. Unfortunately, the ‘name’ field in method info seems never ever to get used by the compiler. All methods have the empty string as its name (Shown above as the unnamed function at ###2).
How does the flash player link the multiname to the unnamed method? There appears to be no provision for this in the AVM2 spec.
I know it’s possible because commercial decompilers like sothink manage to determine the method name. I’m just not sure how they do it, or how the code could ever work.
I’m not sure why your decompiler shows the method as (anonymous).
Here is a dump of the abcData:
What you’re interested in here is instance_info[0]. This is the definition of a run-time instance of a class, which would be RedCircle here. Instances have an array of Traits of various types. RedCircle has one trait (moveit) of kind Trait_Method which means the trait has a reference to a method (2).
So if you skip to method_body_info[1] (the constructor of RedCircle) you can see at byte 323 that getProperty is called with an index of 4.
Which is a reference to the multiname constant pool.
When it comes to calling the method it looks up the name index in the traits for the instance.
Then calls the relevant method.
A somewhat simplified answer, but I hope it clears up a few issues.