1/* This file read a Java(TM) .class file. 2 It is not stand-alone: It depends on tons of macros, and the 3 intent is you #include this file after you've defined the macros. 4 5 Copyright (C) 1996 Free Software Foundation, Inc. 6 7This program is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12This program is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GNU CC; see the file COPYING. If not, write to 19the Free Software Foundation, 59 Temple Place - Suite 330, 20Boston, MA 02111-1307, USA. 21 22Java and all Java-based marks are trademarks or registered trademarks 23of Sun Microsystems, Inc. in the United States and other countries. 24The Free Software Foundation is independent of Sun Microsystems, Inc. */ 25 26#include "jcf.h" 27#include "zipfile.h" 28 29int 30DEFUN(get_attribute, (jcf), 31 JCF *jcf) 32{ 33 uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf)); 34 uint32 attribute_length = JCF_readu4 (jcf); 35 uint32 start_pos = JCF_TELL(jcf); 36 int name_length; 37 unsigned char *name_data; 38 JCF_FILL (jcf, (long) attribute_length); 39 if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf)) 40 return -2; 41 if (JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8) 42 return -2; 43 name_length = JPOOL_UTF_LENGTH (jcf, attribute_name); 44 name_data = JPOOL_UTF_DATA (jcf, attribute_name); 45 46#ifdef IGNORE_ATTRIBUTE 47 if (IGNORE_ATTRIBUTE (jcf, attribute_name, attribute_length)) 48 { 49 JCF_SKIP (jcf, attribute_length); 50 } 51 else 52#endif 53#ifdef HANDLE_SOURCEFILE 54 if (name_length == 10 && memcmp (name_data, "SourceFile", 10) == 0) 55 { 56 uint16 sourcefile_index = JCF_readu2 (jcf); 57 HANDLE_SOURCEFILE(sourcefile_index); 58 } 59 else 60#endif 61#ifdef HANDLE_CONSTANTVALUE 62 if (name_length == 13 && memcmp (name_data, "ConstantValue", 13) == 0) 63 { 64 uint16 constantvalue_index = JCF_readu2 (jcf); 65 if (constantvalue_index <= 0 || constantvalue_index >= JPOOL_SIZE(jcf)) 66 return -2; 67 HANDLE_CONSTANTVALUE(constantvalue_index); 68 } 69 else 70#endif 71#ifdef HANDLE_CODE_ATTRIBUTE 72 if (name_length == 4 && memcmp (name_data, "Code", 4) == 0) 73 { 74 uint16 j; 75 uint16 max_stack ATTRIBUTE_UNUSED = JCF_readu2 (jcf); 76 uint16 max_locals ATTRIBUTE_UNUSED = JCF_readu2 (jcf); 77 uint32 code_length = JCF_readu4 (jcf); 78 uint16 exception_table_length, attributes_count; 79 if (code_length + 12 > attribute_length) 80 return -1; 81 HANDLE_CODE_ATTRIBUTE(max_stack, max_locals, code_length); 82 JCF_SKIP (jcf, code_length); 83 exception_table_length = JCF_readu2 (jcf); 84 if (code_length + 8 * exception_table_length + 12 > attribute_length) 85 return -1; 86#ifdef HANDLE_EXCEPTION_TABLE 87 HANDLE_EXCEPTION_TABLE (jcf->read_ptr, exception_table_length); 88#endif 89 JCF_SKIP (jcf, 2 * 4 * exception_table_length); 90 attributes_count = JCF_readu2 (jcf); 91 for (j = 0; j < attributes_count; j++) 92 { 93 int code = get_attribute (jcf); 94 if (code != 0) 95 return code; 96 } 97 } 98 else 99#endif /* HANDLE_CODE_ATTRIBUTE */ 100#ifdef HANDLE_EXCEPTIONS_ATTRIBUTE 101 if (name_length == 10 && memcmp (name_data, "Exceptions", 10) == 0) 102 { 103 uint16 count = JCF_readu2 (jcf); 104 HANDLE_EXCEPTIONS_ATTRIBUTE (count); 105 } 106 else 107#endif 108#ifdef HANDLE_LINENUMBERTABLE_ATTRIBUTE 109 if (name_length == 15 && memcmp (name_data, "LineNumberTable", 15) == 0) 110 { 111 uint16 count = JCF_readu2 (jcf); 112 HANDLE_LINENUMBERTABLE_ATTRIBUTE (count); 113 } 114 else 115#endif 116#ifdef HANDLE_LOCALVARIABLETABLE_ATTRIBUTE 117 if (name_length == 18 && memcmp (name_data, "LocalVariableTable", 18) == 0) 118 { 119 uint16 count = JCF_readu2 (jcf); 120 HANDLE_LOCALVARIABLETABLE_ATTRIBUTE (count); 121 } 122 else 123#endif 124 { 125#ifdef PROCESS_OTHER_ATTRIBUTE 126 PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length); 127#else 128 JCF_SKIP (jcf, attribute_length); 129#endif 130 } 131 if ((long) (start_pos + attribute_length) != JCF_TELL(jcf)) 132 return -1; 133 return 0; 134} 135 136/* Read and handle the pre-amble. */ 137int 138DEFUN(jcf_parse_preamble, (jcf), 139 JCF* jcf) 140{ 141 uint32 magic = (JCF_FILL (jcf, 8), JCF_readu4 (jcf)); 142 uint16 minor_version ATTRIBUTE_UNUSED = JCF_readu2 (jcf); 143 uint16 major_version ATTRIBUTE_UNUSED = JCF_readu2 (jcf); 144#ifdef HANDLE_MAGIC 145 HANDLE_MAGIC (magic, minor_version, major_version); 146#endif 147 if (magic != 0xcafebabe) 148 return -1; 149 else 150 return 0; 151} 152 153/* Read and handle the constant pool. 154 155 Return 0 if OK. 156 Return -2 if a bad cross-reference (index of other constant) was seen. 157*/ 158int 159DEFUN(jcf_parse_constant_pool, (jcf), 160 JCF* jcf) 161{ 162 int i, n; 163 JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf)); 164 jcf->cpool.tags = ALLOC (JPOOL_SIZE (jcf)); 165 jcf->cpool.data = ALLOC (sizeof (jword) * JPOOL_SIZE (jcf)); 166 jcf->cpool.tags[0] = 0; 167#ifdef HANDLE_START_CONSTANT_POOL 168 HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf)); 169#endif 170 for (i = 1; i < (int) JPOOL_SIZE (jcf); i++) 171 { 172 int constant_kind; 173 174 /* Make sure at least 9 bytes are available. This is enough 175 for all fixed-sized constant pool entries (so we don't need many 176 more JCF_FILL calls below), but is is small enough that 177 we are guaranteed to not hit EOF (in a valid .class file). */ 178 JCF_FILL (jcf, 9); 179 constant_kind = JCF_readu (jcf); 180 jcf->cpool.tags[i] = constant_kind; 181 switch (constant_kind) 182 { 183 case CONSTANT_String: 184 case CONSTANT_Class: 185 jcf->cpool.data[i] = JCF_readu2 (jcf); 186 break; 187 case CONSTANT_Fieldref: 188 case CONSTANT_Methodref: 189 case CONSTANT_InterfaceMethodref: 190 case CONSTANT_NameAndType: 191 jcf->cpool.data[i] = JCF_readu2 (jcf); 192 jcf->cpool.data[i] |= JCF_readu2 (jcf) << 16; 193 break; 194 case CONSTANT_Integer: 195 case CONSTANT_Float: 196 jcf->cpool.data[i] = JCF_readu4 (jcf); 197 break; 198 case CONSTANT_Long: 199 case CONSTANT_Double: 200 jcf->cpool.data[i] = JCF_readu4 (jcf); 201 i++; /* These take up two spots in the constant pool */ 202 jcf->cpool.tags[i] = 0; 203 jcf->cpool.data[i] = JCF_readu4 (jcf); 204 break; 205 case CONSTANT_Utf8: 206 n = JCF_readu2 (jcf); 207 JCF_FILL (jcf, n); 208#ifdef HANDLE_CONSTANT_Utf8 209 HANDLE_CONSTANT_Utf8(jcf, i, n); 210#else 211 jcf->cpool.data[i] = JCF_TELL(jcf) - 2; 212 JCF_SKIP (jcf, n); 213#endif 214 break; 215 default: 216 return i; 217 } 218 } 219 return 0; 220} 221 222/* Read various class flags and numbers. */ 223 224void 225DEFUN(jcf_parse_class, (jcf), 226 JCF* jcf) 227{ 228 int i; 229 uint16 interfaces_count; 230 JCF_FILL (jcf, 8); 231 jcf->access_flags = JCF_readu2 (jcf); 232 jcf->this_class = JCF_readu2 (jcf); 233 jcf->super_class = JCF_readu2 (jcf); 234 interfaces_count = JCF_readu2 (jcf); 235 236#ifdef HANDLE_CLASS_INFO 237 HANDLE_CLASS_INFO(jcf->access_flags, jcf->this_class, jcf->super_class, interfaces_count); 238#endif 239 240 JCF_FILL (jcf, 2 * interfaces_count); 241 242 /* Read interfaces. */ 243 for (i = 0; i < interfaces_count; i++) 244 { 245 uint16 index ATTRIBUTE_UNUSED = JCF_readu2 (jcf); 246#ifdef HANDLE_CLASS_INTERFACE 247 HANDLE_CLASS_INTERFACE (index); 248#endif 249 } 250} 251 252/* Read fields. */ 253int 254DEFUN(jcf_parse_fields, (jcf), 255 JCF* jcf) 256{ 257 int i, j; 258 uint16 fields_count; 259 JCF_FILL (jcf, 2); 260 fields_count = JCF_readu2 (jcf); 261 262#ifdef HANDLE_START_FIELDS 263 HANDLE_START_FIELDS (fields_count); 264#endif 265 for (i = 0; i < fields_count; i++) 266 { 267 uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf)); 268 uint16 name_index = JCF_readu2 (jcf); 269 uint16 signature_index = JCF_readu2 (jcf); 270 uint16 attribute_count = JCF_readu2 (jcf); 271#ifdef HANDLE_START_FIELD 272 HANDLE_START_FIELD (access_flags, name_index, signature_index, 273 attribute_count); 274#endif 275 for (j = 0; j < attribute_count; j++) 276 { 277 int code = get_attribute (jcf); 278 if (code != 0) 279 return code; 280 } 281#ifdef HANDLE_END_FIELD 282 HANDLE_END_FIELD (); 283#endif 284 } 285#ifdef HANDLE_END_FIELDS 286 HANDLE_END_FIELDS (); 287#endif 288 return 0; 289} 290 291/* Read methods. */ 292 293int 294DEFUN(jcf_parse_one_method, (jcf), 295 JCF* jcf) 296{ 297 int i; 298 uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf)); 299 uint16 name_index = JCF_readu2 (jcf); 300 uint16 signature_index = JCF_readu2 (jcf); 301 uint16 attribute_count = JCF_readu2 (jcf); 302#ifdef HANDLE_METHOD 303 HANDLE_METHOD(access_flags, name_index, signature_index, attribute_count); 304#endif 305 for (i = 0; i < attribute_count; i++) 306 { 307 int code = get_attribute (jcf); 308 if (code != 0) 309 return code; 310 } 311#ifdef HANDLE_END_METHOD 312 HANDLE_END_METHOD (); 313#endif 314 return 0; 315} 316 317int 318DEFUN(jcf_parse_methods, (jcf), 319 JCF* jcf) 320{ 321 int i; 322 uint16 methods_count; 323 JCF_FILL (jcf, 2); 324 methods_count = JCF_readu2 (jcf); 325#ifdef HANDLE_START_METHODS 326 HANDLE_START_METHODS (methods_count); 327#endif 328 for (i = 0; i < methods_count; i++) 329 { 330 int code = jcf_parse_one_method (jcf); 331 if (code != 0) 332 return code; 333 } 334#ifdef HANDLE_END_METHODS 335 HANDLE_END_METHODS (); 336#endif 337 return 0; 338} 339 340/* Read attributes. */ 341int 342DEFUN(jcf_parse_final_attributes, (jcf), 343 JCF *jcf) 344{ 345 int i; 346 uint16 attributes_count = (JCF_FILL (jcf, 2), JCF_readu2 (jcf)); 347#ifdef START_FINAL_ATTRIBUTES 348 START_FINAL_ATTRIBUTES (attributes_count) 349#endif 350 for (i = 0; i < attributes_count; i++) 351 { 352 int code = get_attribute (jcf); 353 if (code != 0) 354 return code; 355 } 356 return 0; 357} 358 359