2
* This file is part of SwfLib
3
* Copyright (c)2004-2006 Nicolas Cannasse
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
let s = Printf.sprintf
24
let f_int_length : (int -> int) ref = ref (fun _ -> assert false)
25
let f_int_read : (IO.input -> int) ref = ref (fun _ -> assert false)
26
let f_int_write : (unit IO.output -> int -> unit) ref = ref (fun _ _ -> assert false)
28
let int_length i = (!f_int_length) i
29
let read_int ch = (!f_int_read) ch
30
let write_int (ch : 'a IO.output) i = (!f_int_write) (Obj.magic ch) i
32
let int_index (x : 'a index) : int = Obj.magic x
33
let index_int (x : int) : 'a index = Obj.magic x
34
let int_index_nz (x : 'a index_nz) : int = Obj.magic x
35
let index_nz_int (x : int) : 'a index_nz = Obj.magic x
37
let read_index ch = index_int (read_int ch)
38
let write_index ch i = write_int ch (int_index i)
40
let read_index_nz ch = index_nz_int (read_int ch)
41
let write_index_nz ch i = write_int ch (int_index_nz i)
43
let iget (t : 'a array) (i : 'a index) : 'a =
46
let write_signed_byte = write_byte
48
let max_i24 = 1 lsl 23 - 1
51
let a = read_byte ch in
52
let b = read_byte ch in
53
let c = read_byte ch in
54
let n = a lor (b lsl 8) lor (c lsl 16) in
55
if c land 128 <> 0 then
60
let rec write_i24 ch n =
61
if n < -max_i24 || n > max_i24 then assert false;
62
let n = (if n land (1 lsl 23) <> 0 then n + (1 lsl 24) else n) in
64
write_byte ch (n lsr 8);
65
write_byte ch (n lsr 16)
68
let h = Hashtbl.create 0 in
69
let h2 = Hashtbl.create 0 in
70
List.iter (fun (o,b) -> Hashtbl.add h b o; Hashtbl.add h2 o b)
102
let length = function
120
1 + int_length (int_index f)
122
1 + int_length (int_index f)
124
1 + int_length (int_index f)
126
1 + int_length (int_index_nz f)
138
1 + int_length (int_index f)
170
| A3DebugReg (a,b,c,line) -> 1 + int_length a + int_length b + int_length c + int_length line
172
| A3GetScope n -> 1 + int_length n
173
| A3Reg n | A3SetReg n -> if n >= 1 && n <= 3 then 1 else (1 + int_length n)
174
| A3SuperCall (f,n) | A3Call (f,n) | A3New (f,n) | A3CallUnknown (f,n) | A3SuperCallUnknown(f,n) -> 1 + int_length n + int_length (int_index f)
176
| A3Next (a,b) -> 1 + int_length a + int_length b
177
| A3Switch (_,cases,_) ->
178
let ncases = List.length cases in
179
1 + 3 + int_length ncases + 3 * (ncases + 1)
182
A3Jump (kind,read_i24 ch)
185
let op = (try Some (read_byte ch) with IO.No_more_input -> None) in
191
| 0x04 -> A3GetSuper (read_index ch)
192
| 0x05 -> A3SetSuper (read_index ch)
193
| 0x08 -> A3RegReset (read_int ch)
195
| 0x0C -> jump ch J3NotLt
196
| 0x0D -> jump ch J3NotLte
197
| 0x0E -> jump ch J3NotGt
198
| 0x0F -> jump ch J3NotGte
199
| 0x10 -> jump ch J3Always
200
| 0x11 -> jump ch J3True
201
| 0x12 -> jump ch J3False
202
| 0x13 -> jump ch J3Eq
203
| 0x14 -> jump ch J3Neq
204
| 0x15 -> jump ch J3Lt
205
| 0x16 -> jump ch J3Lte
206
| 0x17 -> jump ch J3Gt
207
| 0x18 -> jump ch J3Gte
208
| 0x19 -> jump ch J3PhysEq
209
| 0x1A -> jump ch J3PhysNeq
211
let def = read_i24 ch in
216
let j = read_i24 ch in
219
let cases = loop (read_int ch) in
220
let def2 = read_i24 ch in
221
A3Switch (def,cases,def2)
226
| 0x21 -> A3Undefined
228
| 0x24 -> A3SmallInt (read_signed_byte ch)
229
| 0x25 -> A3Int (read_int ch)
235
| 0x2B -> A3CatchDone
236
| 0x2C -> A3String (read_index ch)
237
| 0x2D -> A3IntRef (read_index ch)
238
| 0x2F -> A3Float (read_index ch)
241
let r1 = read_int ch in
242
let r2 = read_int ch in
244
| 0x40 -> A3Function (read_index_nz ch)
245
| 0x41 -> A3StackCall (read_int ch)
246
| 0x42 -> A3StackNew (read_int ch)
248
let id = read_index ch in
249
let nargs = read_int ch in
250
A3SuperCall (id,nargs)
252
let id = read_index ch in
253
let nargs = read_int ch in
257
| 0x49 -> A3SuperConstr (read_int ch)
259
let id = read_index ch in
260
let nargs = read_int ch in
263
let id = read_index ch in
264
let nargs = read_int ch in
265
A3SuperCallUnknown (id,nargs)
267
let id = read_index ch in
268
let nargs = read_int ch in
269
A3CallUnknown (id,nargs)
270
| 0x55 -> A3Object (read_int ch)
271
| 0x56 -> A3Array (read_int ch)
273
| 0x58 -> A3ClassDef (read_int ch)
274
| 0x59 -> A3XmlOp1 (read_index ch)
275
| 0x5A -> A3Catch (read_int ch)
276
| 0x5D -> A3GetInf (read_index ch)
277
| 0x5E -> A3SetInf (read_index ch)
278
| 0x60 -> A3GetProp (read_index ch)
279
| 0x61 -> A3SetProp (read_index ch)
280
| 0x62 -> A3Reg (read_int ch)
281
| 0x63 -> A3SetReg (read_int ch)
282
| 0x64 -> A3GetScope0
283
| 0x65 -> A3GetScope (read_int ch)
284
| 0x66 -> A3Get (read_index ch)
285
| 0x68 -> A3Set (read_index ch)
286
| 0x6A -> A3Delete (read_index ch)
287
| 0x6C -> A3GetSlot (read_int ch)
288
| 0x6D -> A3SetSlot (read_int ch)
295
| 0x80 -> A3Cast (read_index ch)
299
| 0xB1 -> A3InstanceOf
300
| 0xC2 -> A3IncrReg (read_int ch)
309
let a = read_int ch in
310
let b = read_int ch in
311
let c = read_int ch in
312
let line = read_int ch in
313
A3DebugReg (a,b,c,line)
314
| 0xF0 -> A3DebugLine (read_int ch)
315
| 0xF1 -> A3DebugFile (read_index ch)
318
A3Op (Hashtbl.find ops op)
320
Printf.printf "Unknown opcode 0x%.2X\n" op;
321
A3Unk (char_of_int op)
325
let data = nread ch len in
326
let ch = input_string data in
328
match (try opcode ch with _ -> match acc with A3Unk '\xff' :: _ -> None | _ -> Some (A3Unk '\xff')) with
329
| None -> List.rev acc
330
| Some o -> loop (o :: acc)
334
let write ch = function
349
write_byte ch (match k with
367
| A3Switch (def,cases,def2) ->
370
write_int ch (List.length cases);
371
List.iter (write_i24 ch) cases;
387
write_signed_byte ch b
427
| A3SuperCall (f,n) ->
446
| A3SuperCallUnknown (f,n) ->
450
| A3CallUnknown (f,n) ->
485
| 1 -> write_byte ch 0xD1;
486
| 2 -> write_byte ch 0xD2;
487
| 3 -> write_byte ch 0xD3;
493
| 1 -> write_byte ch 0xD5;
494
| 2 -> write_byte ch 0xD6;
495
| 3 -> write_byte ch 0xD7;
547
| A3DebugReg (a,b,c,line) ->
560
write_byte ch (try Hashtbl.find ops_ids op with Not_found -> assert false)
564
let dump_op = function
570
| A3OBitNot -> "bitnot"
583
| A3OPhysEq -> "physeq"
590
| A3OIIncr -> "iincr"
591
| A3OIDecr -> "idecr"
593
let dump_jump = function
595
| J3NotLte -> "-nlte"
597
| J3NotGte -> "-ngte"
600
| J3False -> "-ifnot"
608
| J3PhysNeq -> "-pneq"
611
let ident n = ctx.as3_idents.(int_index n - 1) in
613
let t = ctx.as3_types.(int_index n - 1) in
615
| A3TClassInterface (Some ident,_) -> "[" ^ iget ctx.as3_idents ident ^ "]"
616
| A3TMethodVar (ident,_) -> iget ctx.as3_idents ident
617
| A3TArrayAccess idx -> "~array"
622
| A3GetSuper f -> s "super.%s" (field f)
623
| A3SetSuper f -> s "set super.%s" (field f)
624
| A3RegReset n -> s "reset %d" n
626
| A3Jump (k,n) -> s "jump%s %d" (dump_jump k) n
627
| A3Switch (def,cases,def2) -> s "switch %d [%s] %d" def (String.concat "," (List.map (s "%d") cases)) def2
629
| A3PopScope -> "popscope"
632
| A3Undefined -> "undefined"
633
| A3ForEach -> "foreach"
634
| A3SmallInt b -> s "int %d" b
635
| A3Int n -> s "int %d" n
641
| A3CatchDone -> "catch-done?"
642
| A3String n -> s "string [%s]" (ident n)
643
| A3IntRef n -> s "int [%ld]" ctx.as3_ints.(int_index n - 1)
644
| A3Float n -> s "float [%f]" ctx.as3_floats.(int_index n - 1)
646
| A3Next (r1,r2) -> s "next %d %d" r1 r2
647
| A3Function f -> s "function #%d" (int_index_nz f)
648
| A3StackCall n -> s "stackcall (%d)" n
649
| A3StackNew n -> s "stacknew (%d)" n
650
| A3SuperCall (f,n) -> s "supercall %s (%d)" (field f) n
651
| A3Call (f,n) -> s "call %s (%d)" (field f) n
652
| A3RetVoid -> "ret void"
654
| A3SuperConstr n -> s "superconstr %d" n
655
| A3New (f,n) -> s "new %s (%d)" (field f) n
656
| A3SuperCallUnknown (f,n) -> s "?supercall %s (%d)" (field f) n
657
| A3CallUnknown (f,n) -> s "?call %s (%d)" (field f) n
658
| A3Object n -> s "obj %d" n
659
| A3Array n -> s "array %d" n
660
| A3NewBlock -> "newblock"
661
| A3ClassDef n -> s "classdef %d" n
662
| A3XmlOp1 f -> s "xml1 %s" (field f)
663
| A3Catch n -> s "catch %d" n
664
| A3GetInf f -> s "iget %s" (field f)
665
| A3SetInf f -> s "iset %s" (field f)
666
| A3GetProp f -> s "getp %s" (field f)
667
| A3SetProp f -> s "setp %s" (field f)
668
| A3Reg n -> s "reg %d" n
669
| A3SetReg n -> s "setreg %d" n
670
| A3GetScope0 -> "getscope0"
671
| A3GetScope n -> s "getscope %d" n
672
| A3Get f -> s "get %s" (field f)
673
| A3Set f -> s "set %s" (field f)
674
| A3Delete f -> s "delete %s" (field f)
675
| A3GetSlot n -> s "getslot %d" n
676
| A3SetSlot n -> s "setslot %d" n
677
| A3ToXml -> "to_xml"
678
| A3ToInt -> "to_int"
679
| A3ToUInt -> "to_uint"
680
| A3ToNumber -> "to_number"
681
| A3ToBool -> "to_bool"
683
| A3Cast f -> s "cast %s" (field f)
684
| A3ToObject -> "to_obj"
685
| A3ToString -> "to_str"
686
| A3Typeof -> "typeof"
687
| A3InstanceOf -> "instanceof"
688
| A3IncrReg r -> s "incr-reg %d" r
690
| A3DebugReg (a,b,c,line) -> s ".reg %d %d %d line:%d" a b c line
691
| A3DebugLine l -> s ".line %d" l
692
| A3DebugFile f -> s ".file %s" (ident f)
693
| A3Op o -> dump_op o
694
| A3Unk x -> s "??? 0x%X" (int_of_char x)