1 /*
  2  * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.asmtools.jdis;
 24 
 25 import static java.lang.String.format;
 26 import static org.openjdk.asmtools.jasm.Tables.*;
 27 import static org.openjdk.asmtools.jdis.TraceUtils.mapToHexString;
 28 import static org.openjdk.asmtools.jdis.TraceUtils.traceln;
 29 
 30 import java.io.DataInputStream;
 31 import java.io.EOFException;
 32 import java.io.IOException;
 33 
 34 /**
 35  * represents one entry of StackMap attribute
 36  */
 37 class StackMapData {
 38     static int prevFramePC = 0;
 39     boolean isStackMapTable = false;
 40     StackMapFrameType stackFrameType = null;
 41     int start_pc;
 42     int[] lockMap;
 43     int[] stackMap;
 44 
 45     public StackMapData(CodeData code, DataInputStream in) throws IOException {
 46         start_pc = in.readUnsignedShort();
 47         lockMap = readMap(code, in);
 48         stackMap = readMap(code, in);
 49         traceln(2, format("stack_map_entry:pc=%d numloc=%s  numstack=%s",
 50                 start_pc, mapToHexString(lockMap), mapToHexString(stackMap)));
 51     }
 52 
 53     public StackMapData(CodeData code, DataInputStream in,
 54             boolean isStackMapTable) throws IOException {
 55         this.isStackMapTable = isStackMapTable;
 56         int ft_val = in.readUnsignedByte();
 57         StackMapFrameType frame_type = stackMapFrameType(ft_val);
 58         int offset = 0;
 59         switch (frame_type) {
 60             case SAME_FRAME:
 61                 // type is same_frame;
 62                 offset = ft_val;
 63                 traceln(2, format("same_frame=%d", ft_val));
 64                 break;
 65             case SAME_FRAME_EX:
 66                 // type is same_frame_extended;
 67                 offset = in.readUnsignedShort();
 68                 traceln(2, format("same_frame_extended=%d, offset=%d", ft_val, offset));
 69                 break;
 70             case SAME_LOCALS_1_STACK_ITEM_FRAME:
 71                 // type is same_locals_1_stack_item_frame
 72                 offset = ft_val - 64;
 73                 stackMap = readMapElements(code, in, 1);
 74                 traceln(2, format("same_locals_1_stack_item_frame=%d, offset=%d, numstack=%s",
 75                         ft_val, offset, mapToHexString(stackMap)));
 76                 break;
 77             case SAME_LOCALS_1_STACK_ITEM_EXTENDED_FRAME:
 78                 // type is same_locals_1_stack_item_frame_extended
 79                 offset = in.readUnsignedShort();
 80                 stackMap = readMapElements(code, in, 1);
 81                 traceln(2, format("same_locals_1_stack_item_frame_extended=%d, offset=%d, numstack=%s",
 82                         ft_val, offset, mapToHexString(stackMap)));
 83                 break;
 84             case CHOP_1_FRAME:
 85             case CHOP_2_FRAME:
 86             case CHOP_3_FRAME:
 87                 // type is chop_frame
 88                 offset = in.readUnsignedShort();
 89                 traceln(2, format("chop_frame=%d offset=%d", ft_val, offset));
 90                 break;
 91             case APPEND_FRAME:
 92                 // type is append_frame
 93                 offset = in.readUnsignedShort();
 94                 lockMap = readMapElements(code, in, ft_val - 251);
 95                 traceln(2, format("append_frame=%d offset=%d numlock=%s",
 96                         ft_val, offset, mapToHexString(lockMap)));
 97                 break;
 98             case FULL_FRAME:
 99                 // type is full_frame
100                 offset = in.readUnsignedShort();
101                 lockMap = readMap(code, in);
102                 stackMap = readMap(code, in);
103                 traceln(2, format("full_frame=%d offset=%d numloc=%s  numstack=%s",
104                         ft_val, offset, mapToHexString(lockMap), mapToHexString(stackMap)));
105                 break;
106             default:
107                 TraceUtils.traceln("incorrect frame_type argument");
108 
109         }
110         stackFrameType = frame_type;
111         start_pc = prevFramePC == 0 ? offset : prevFramePC + offset + 1;
112         prevFramePC = start_pc;
113     }
114 
115     private int[] readMap(CodeData code, DataInputStream in) throws IOException {
116         int num = in.readUnsignedShort();
117         return readMapElements(code, in, num);
118     }
119 
120     private int[] readMapElements(CodeData code, DataInputStream in, int num) throws IOException {
121         int[] map = new int[num];
122         for (int k = 0; k < num; k++) {
123             int mt_val = 0;
124             try {
125                 mt_val = in.readUnsignedByte();
126             } catch (EOFException eofe) {
127                 throw eofe;
128             }
129             StackMapType maptype = stackMapType(mt_val, null);
130             switch (maptype) {
131                 case ITEM_Object:
132                     mt_val = mt_val | (in.readUnsignedShort() << 8);
133                     break;
134                 case ITEM_NewObject: {
135                     int pc = in.readUnsignedShort();
136                     code.get_iAtt(pc).referred = true;
137                     mt_val = mt_val | (pc << 8);
138                     break;
139                 }
140             }
141             map[k] = mt_val;
142         }
143         return map;
144     }
145 
146 }