home *** CD-ROM | disk | FTP | other *** search
/ Hacker / Hacker.iso / HACKER / DECOMP / DECAF / bytecode.adb < prev    next >
Encoding:
Text File  |  1996-09-19  |  12.9 KB  |  354 lines

  1. --
  2. -- Copyright (C) 1996 Ada Resource Association (ARA), Columbus, Ohio.
  3. -- Author: Gilles Demailly
  4. --
  5. --
  6. -- Permission to use, copy, modify, and distribute this software and its
  7. -- documentation for any purpose and without fee is hereby granted,
  8. -- provided that the above copyright and authorship notice appear in all
  9. -- copies and that both that copyright notice and this permission notice
  10. -- appear in supporting documentation.
  11. -- 
  12. -- The ARA makes no representations about the suitability of this software
  13. -- for any purpose.  It is provided "as is" without express
  14. -- or implied warranty.
  15. -- 
  16.  
  17. with Ada.Unchecked_Conversion;
  18. with Ada.Text_Io;
  19. with Unsigned_16_Io;
  20. with Unsigned_8_Io;
  21. with Unsigned_32_Io;
  22. with Integer_32_Io;
  23.  
  24. package body ByteCode is
  25.  
  26.    -- This package can not be understood without the followin document :
  27.    --    The Java Virtual Machine Specification
  28.    --    (Release 1.0 Beta - Draft - August 21, 1995)
  29.  
  30.    -- type Operands and Constant Instructions_Operands are
  31.    -- used to get how many operands each instruction needs
  32.    -------------------------------------------------------
  33.    type Operands is array (ByteCode) of Unsigned_32;
  34.  
  35.    -- Operands number of all Java bytecodes
  36.    ----------------------------------------
  37.    Instructions_Operands : Operands :=
  38.       (0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 0 to 9
  39.        0, 0, 0, 0, 0, 0, 1, 2, 1, 2,   -- 10 to 19
  40.        2, 1, 1, 1, 1 ,1, 0, 0, 0, 0,   -- 20 to 29
  41.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 30 to 39
  42.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 40 to 49
  43.        0, 0, 0, 0, 1, 1, 1, 1, 1, 0,   -- 50 to 59
  44.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 60 to 69
  45.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 70 to 79
  46.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 80 to 89
  47.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 90 to 99
  48.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 100 to 109
  49.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 110 to 119
  50.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 120 to 129
  51.        0, 0, 2, 0, 0, 0, 0, 0, 0, 0,   -- 130 to 139
  52.        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   -- 140 to 149
  53.        0, 0, 0, 2, 2, 2, 2, 2, 2, 2,   -- 150 to 159
  54.        2, 2, 2, 2, 2, 2, 2, 2, 2, 1,   -- 160 to 169
  55.        0, 0, 0, 0, 0, 0, 0, 0, 2, 2,   -- 170 to 179
  56.        2, 2, 2, 2, 2, 4, 2, 1, 2,      -- 180 to 189 (except 186)
  57.        0, 0, 2, 2, 0, 0, 1, 3, 2, 2,   -- 190 to 199
  58.        4, 4, 0, 2);                    -- 200, 201, 202, 209
  59.  
  60.    -- Instanciation of Enumeration_Io for ByteCode instructions display
  61.    --------------------------------------------------------------------
  62.    package ByteCode_Io is new Ada.Text_Io.Enumeration_Io (ByteCode);
  63.  
  64.    -- Conversion of a byte to a ByteCode 
  65.    -------------------------------------
  66.    function Coded is new Ada.Unchecked_Conversion
  67.                             (Byte_Utilities.Byte, ByteCode);
  68.  
  69.    -- return a ByteCode from a Byte
  70.    -- may raise E_Unknown_ByteCode
  71.    --------------------------------
  72.    function To_Bytecode 
  73.                (From : Byte_Utilities.Byte)
  74.             return ByteCode is
  75.    begin
  76.       if From > 209 or else
  77.          From = 186 or else
  78.          (From > 202 and then From < 209) then
  79.          raise E_Unkown_ByteCode;
  80.       else
  81.          return Coded (From);
  82.       end if;
  83.    exception
  84.       when others =>
  85.          raise E_Unkown_ByteCode;
  86.    end To_Bytecode;
  87.  
  88.  
  89.    function Operands_Number
  90.                (Code : ByteCode)
  91.             return Unsigned_32 is
  92.    begin
  93.       return Instructions_Operands (Code);
  94.    end Operands_Number;
  95.  
  96.    
  97.    procedure Display (Index   : in out Unsigned_32;
  98.                       Bytes   : in Byte_Utilities.Acc_Bytes;
  99.                       Context : in CP.Acc_CP_Infos) is
  100.       Instruction   : ByteCode;
  101.       
  102.       -- this a one Integer_8 argument instruction, displays it
  103.       ---------------------------------------------------------
  104.       procedure Display_Integer_8 is
  105.          Arg : Integer_8 := Byte_Utilities.Get_Integer_8 (Bytes, Index +1);
  106.       begin
  107.          Ada.Text_Io.Put (Integer_8'Image (Arg));
  108.       end Display_Integer_8;
  109.  
  110.       -- this a one Unsigned_8 argument instruction, displays it
  111.       ---------------------------------------------------------
  112.       procedure Display_Unsigned_8 is
  113.          Arg : Unsigned_8 := Bytes (Index +1);
  114.       begin
  115.          Ada.Text_Io.Put (Unsigned_8'Image (Arg));
  116.       end Display_Unsigned_8;
  117.  
  118.       -- this a one Unsigned_8 argument followed by 
  119.       -- an Integer_8 argument instruction, displays them
  120.       ---------------------------------------------------
  121.       procedure Display_Couple is
  122.          Arg : Unsigned_8 := Bytes (Index +1);
  123.          Val : Integer_8 := Byte_Utilities.Get_Integer_8 (Bytes, Index +2);
  124.       begin
  125.          Ada.Text_Io.Put (Unsigned_8'Image (Arg));
  126.          Ada.Text_Io.Put (Integer_8'Image (Val));
  127.       end Display_Couple;
  128.       
  129.       -- this a one Integer_16 argument instruction, displays it
  130.       ----------------------------------------------------------
  131.       procedure Display_Integer_16 is
  132.          Arg : Integer_16 := Byte_Utilities.Get_Integer_16 (Bytes, Index +1);
  133.       begin
  134.          Ada.Text_Io.Put (Integer_16'Image (Arg));
  135.       end Display_Integer_16;
  136.  
  137.       -- this a one Integer_16 argument instruction with offset, displays it
  138.       ----------------------------------------------------------------------
  139.       procedure Display_Integer_16_Offset is
  140.          Initial_Offset : Integer_16 := Integer_16 (Index - 1);
  141.          Arg : Integer_16 := Byte_Utilities.Get_Integer_16 (Bytes, Index +1);
  142.       begin
  143.          Ada.Text_Io.Put (Integer_16'Image (Arg + Initial_Offset));
  144.       end Display_Integer_16_Offset;
  145.  
  146.       -- this a one Unsigned_16 argument instruction, displays it
  147.       -----------------------------------------------------------
  148.       procedure Display_Unsigned_16 is
  149.          Arg : Unsigned_16 := Byte_Utilities.Get_Unsigned_16 (Bytes, Index +1);
  150.       begin
  151.          Ada.Text_Io.Put (Unsigned_16'Image (Arg));
  152.       end Display_Unsigned_16;
  153.  
  154.       -- this a one Integer_32 argument instruction, displays it
  155.       ----------------------------------------------------------
  156.       procedure Display_Integer_32 is
  157.          Initial_Offset : Integer_32 := Integer_32 (Index - 1);
  158.          Arg : Integer_32 := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  159.       begin
  160.          Ada.Text_Io.Put (Integer_32'Image (Arg + Initial_Offset));
  161.       end Display_Integer_32;
  162.       
  163.       -- Display contents of Constant Pool with 8 bits index
  164.       ------------------------------------------------------
  165.       procedure Display_CP_8 is
  166.       begin
  167.          Ada.Text_Io.Put ("#");
  168.          Unsigned_8_Io.Put (Item => Bytes (Index + 1), Width => 0);
  169.          Ada.Text_Io.Put (" ");
  170.          CP.Display (Context (Unsigned_16(Bytes (Index + 1))), Context);
  171.       end Display_CP_8;
  172.       
  173.       -- Display contents of Constant Pool with 16 bits index
  174.       -------------------------------------------------------
  175.       procedure Display_CP_16 is
  176.          Arg : Unsigned_16 := Byte_Utilities.Get_Unsigned_16 (Bytes, Index + 1);
  177.       begin
  178.          Ada.Text_Io.Put ("#");
  179.          Unsigned_16_Io.Put (Item => Arg, Width => 0);
  180.          Ada.Text_Io.Put (" ");
  181.          CP.Display (Context (Arg), Context);
  182.       end Display_CP_16;
  183.  
  184.       -- Display instruction LookUpSwitch
  185.       -- since this instruction has a variable number of arguments
  186.       -- Index is incremented during this displaying process
  187.       ------------------------------------------------------------
  188.       procedure LookUpSwitch_Display is
  189.          Initial_Offset : Integer_32 := Integer_32 (Index - 1);
  190.          Default_Offset : Integer_32;
  191.          NbPairs        : Integer_32;
  192.          Pair_Match     : Integer_32;
  193.          Pair_Offset    : Integer_32;
  194.       begin
  195.          while (Index mod 4) /= 0 loop
  196.             Index := Index + 1;
  197.          end loop;
  198.          Default_Offset := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  199.          Index := Index + 4;
  200.          NbPairs := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  201.          Index := Index + 4;
  202.          Integer_32_Io.Put (Item => NbPairs, Width => 0);
  203.          Ada.Text_Io.Put (": default=");
  204.          Integer_32_Io.Put
  205.             (Item => Default_Offset + Initial_Offset, Width => 0);
  206.          for I in 1 .. NbPairs loop
  207.             Ada.Text_Io.New_Line;
  208.             Pair_Match := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  209.             Index := Index + 4;
  210.             Pair_Offset := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  211.             Index := Index + 4;
  212.             Integer_32_Io.Put (Item => Pair_Match, Width => 16);
  213.             Ada.Text_Io.Put (": ");
  214.             Integer_32_Io.Put
  215.                (Item => Pair_Offset + Initial_Offset, Width => 0);
  216.          end loop;
  217.       end LookUpSwitch_Display;
  218.  
  219.       -- Display instruction TableSwitch
  220.       -- since this instruction has a variable number of arguments
  221.       -- Index is incremented during this displaying process
  222.       ------------------------------------------------------------
  223.       procedure TableSwitch_Display is
  224.          Initial_Offset : Integer_32 := Integer_32 (Index - 1);
  225.          Default_Offset : Integer_32;
  226.          Low_Value      : Integer_32;
  227.          High_Value     : Integer_32;
  228.          Jump_Offset    : Integer_32;
  229.       begin
  230.          while (Index mod 4) /= 0 loop
  231.             Index := Index + 1;
  232.          end loop;
  233.          Default_Offset := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  234.          Index := Index + 4;
  235.          Low_Value := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  236.          Index := Index + 4;
  237.          High_Value := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  238.          Index := Index + 4;
  239.          Integer_32_Io.Put (Item => Low_Value, Width => 0);
  240.          Ada.Text_Io.Put (" to ");
  241.          Integer_32_Io.Put (Item => High_Value, Width => 0);
  242.          Ada.Text_Io.Put (": default=");
  243.          Integer_32_Io.Put
  244.             (Item => Default_Offset + Initial_Offset, Width => 0);
  245.          for I in Low_Value .. High_Value loop
  246.             Ada.Text_Io.New_Line;
  247.             Jump_Offset := Byte_Utilities.Get_Integer_32 (Bytes, Index +1);
  248.             Index := Index + 4;
  249.             Integer_32_Io.Put (Item => I, Width => 16);
  250.             Ada.Text_Io.Put (": ");
  251.             Integer_32_Io.Put
  252.                (Item => Jump_Offset + Initial_Offset, Width => 0);
  253.          end loop;
  254.       end TableSwitch_Display;
  255.       
  256.    begin
  257.    
  258.       -- get the ByteCode and display it
  259.       ----------------------------------
  260.       Instruction := To_Bytecode (Bytes (Index));
  261.       Unsigned_32_Io.Put (Item => Index - 1, Width => 9);
  262.       Ada.Text_Io.Put (" : ");
  263.       ByteCode_Io.Put (Item => Instruction);
  264.       Ada.Text_Io.Put (" ");
  265.       
  266.       -- Instruction operands display dispatching
  267.       -------------------------------------------
  268.       case Instruction is
  269.       
  270.          when Bipush =>
  271.             Display_Integer_8;
  272.             
  273.          when Iload | Lload |
  274.               Fload | Dload | 
  275.               Aload | 
  276.               Istore | Lstore |
  277.               Fstore | Dstore |
  278.               Astore | Wide |
  279.               Newarray |
  280.               Ret =>
  281.             Display_Unsigned_8;
  282.             
  283.          when Sipush =>
  284.             Display_Integer_16;
  285.             
  286.          when Ifeq | Ifnull | Iflt |
  287.               Ifle | Ifne | Ifnonnull |
  288.               Ifgt | Ifge | If_icmpeq |
  289.               If_icmpne | If_icmplt |
  290.               If_icmpgt | If_icmple |
  291.               If_icmpge | If_acmpeq |
  292.               If_acmpne | Gotoo | Jsr  =>
  293.             Display_Integer_16_Offset;
  294.             
  295.          when Ret_w           =>
  296.             Display_Unsigned_16;
  297.             
  298.          when Ldc1            =>
  299.             Display_CP_8;
  300.             
  301.          when Ldc2 | Ldc2w |
  302.               Putfield | Getfield | 
  303.               Putstatic | Getstatic |
  304.               Invokevirtual | 
  305.               Invokenonvirtual | 
  306.               Invokestatic |
  307.               Anewarray |
  308.               New_object |
  309.               Checkcast |
  310.               Instanceof      =>   
  311.             Display_CP_16;
  312.             
  313.          when Invokeinterface =>
  314.             Ada.Text_Io.Put
  315.                ("(args" & 
  316.                 Unsigned_8'Image (Bytes (Index + 3)) & ") ");
  317.             Display_CP_16;
  318.             
  319.          when Multianewarray  =>
  320.             Display_CP_16;
  321.             Ada.Text_Io.Put (" dim:" & Unsigned_8'Image (Bytes (Index + 3)));
  322.             
  323.          when Goto_w | Jsr_w  =>
  324.             Display_Integer_32;
  325.             
  326.          when Iinc   =>
  327.             Display_Couple;
  328.                 
  329.          when Lookupswitch    =>
  330.             LookUpSwitch_Display;
  331.  
  332.          when Tableswitch     =>
  333.             TableSwitch_Display;
  334.             
  335.          when others =>
  336.             -- for the many instructions which don't get any parameter
  337.             null;
  338.       end case;
  339.       Ada.Text_Io.New_Line;
  340.       
  341.       -- increments Index to the next Instruction
  342.       -------------------------------------------
  343.       Index := Index + 1 + Operands_Number (Instruction);
  344.       
  345.    end Display;
  346.  
  347. begin
  348.  
  349.    -- Set setting to lowercase for ByteCode instructions display
  350.    -------------------------------------------------------------
  351.    ByteCode_Io.Default_Setting := Ada.Text_Io.Lower_Case;
  352.    
  353. end ByteCode;
  354.