OLD | NEW |
(Empty) | |
| 1 // Copyright 2001,2007 Alan Donovan. All rights reserved. |
| 2 // |
| 3 // Author: Alan Donovan <adonovan@google.com> |
| 4 // |
| 5 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 // you may not use this file except in compliance with the License. |
| 7 // You may obtain a copy of the License at |
| 8 // |
| 9 // http://www.apache.org/licenses/LICENSE-2.0 |
| 10 // |
| 11 // Unless required by applicable law or agreed to in writing, software |
| 12 // distributed under the License is distributed on an "AS IS" BASIS, |
| 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 // See the License for the specific language governing permissions and |
| 15 // limitations under the License. |
| 16 // |
| 17 // classfile.cc -- classfile parsing and stripping. |
| 18 // |
| 19 |
| 20 // TODO(adonovan) don't pass pointers by reference; this is not |
| 21 // compatible with Google C++ style. |
| 22 |
| 23 // See README.txt for details. |
| 24 // |
| 25 // For definition of JVM class file format, see: |
| 26 // Java SE 8 Edition: |
| 27 // http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4 |
| 28 |
| 29 #define __STDC_FORMAT_MACROS 1 |
| 30 #define __STDC_LIMIT_MACROS 1 |
| 31 #include <inttypes.h> // for PRIx32 |
| 32 #include <stddef.h> |
| 33 #include <stdio.h> |
| 34 #include <stdlib.h> |
| 35 #include <string.h> |
| 36 |
| 37 #include <string> |
| 38 #include <vector> |
| 39 |
| 40 #include "third_party/ijar/common.h" |
| 41 |
| 42 namespace devtools_ijar { |
| 43 |
| 44 // See Table 4.3 in JVM Spec. |
| 45 enum CONSTANT { |
| 46 CONSTANT_Class = 7, |
| 47 CONSTANT_FieldRef = 9, |
| 48 CONSTANT_Methodref = 10, |
| 49 CONSTANT_Interfacemethodref = 11, |
| 50 CONSTANT_String = 8, |
| 51 CONSTANT_Integer = 3, |
| 52 CONSTANT_Float = 4, |
| 53 CONSTANT_Long = 5, |
| 54 CONSTANT_Double = 6, |
| 55 CONSTANT_NameAndType = 12, |
| 56 CONSTANT_Utf8 = 1, |
| 57 CONSTANT_MethodHandle = 15, |
| 58 CONSTANT_MethodType = 16, |
| 59 CONSTANT_InvokeDynamic = 18 |
| 60 }; |
| 61 |
| 62 // See Tables 4.1, 4.4, 4.5 in JVM Spec. |
| 63 enum ACCESS { |
| 64 ACC_PUBLIC = 0x0001, |
| 65 ACC_PRIVATE = 0x0002, |
| 66 ACC_PROTECTED = 0x0004, |
| 67 ACC_STATIC = 0x0008, |
| 68 ACC_FINAL = 0x0010, |
| 69 ACC_SYNCHRONIZED = 0x0020, |
| 70 ACC_VOLATILE = 0x0040, |
| 71 ACC_TRANSIENT = 0x0080, |
| 72 ACC_INTERFACE = 0x0200, |
| 73 ACC_ABSTRACT = 0x0400 |
| 74 }; |
| 75 |
| 76 // See Table 4.7.20-A in Java 8 JVM Spec. |
| 77 enum TARGET_TYPE { |
| 78 // Targets for type parameter declarations (ElementType.TYPE_PARAMETER): |
| 79 CLASS_TYPE_PARAMETER = 0x00, |
| 80 METHOD_TYPE_PARAMETER = 0x01, |
| 81 |
| 82 // Targets for type uses that may be externally visible in classes and members |
| 83 // (ElementType.TYPE_USE): |
| 84 CLASS_EXTENDS = 0x10, |
| 85 CLASS_TYPE_PARAMETER_BOUND = 0x11, |
| 86 METHOD_TYPE_PARAMETER_BOUND = 0x12, |
| 87 FIELD = 0x13, |
| 88 METHOD_RETURN = 0x14, |
| 89 METHOD_RECEIVER = 0x15, |
| 90 METHOD_FORMAL_PARAMETER = 0x16, |
| 91 THROWS = 0x17, |
| 92 |
| 93 // TARGET_TYPE >= 0x40 is reserved for type uses that occur only within code |
| 94 // blocks. Ijar doesn't need to know about these. |
| 95 }; |
| 96 |
| 97 struct Constant; |
| 98 |
| 99 // TODO(adonovan) these globals are unfortunate |
| 100 static std::vector<Constant*> const_pool_in; // input constant pool |
| 101 static std::vector<Constant*> const_pool_out; // output constant_pool |
| 102 |
| 103 // Returns the Constant object, given an index into the input constant pool. |
| 104 // Note: constant(0) == NULL; this invariant is exploited by the |
| 105 // InnerClassesAttribute, inter alia. |
| 106 inline Constant *constant(int idx) { |
| 107 if (idx < 0 || (unsigned)idx >= const_pool_in.size()) { |
| 108 fprintf(stderr, "Illegal constant pool index: %d\n", idx); |
| 109 abort(); |
| 110 } |
| 111 return const_pool_in[idx]; |
| 112 } |
| 113 |
| 114 /********************************************************************** |
| 115 * * |
| 116 * Constants * |
| 117 * * |
| 118 **********************************************************************/ |
| 119 |
| 120 // See sec.4.4 of JVM spec. |
| 121 struct Constant { |
| 122 |
| 123 Constant(u1 tag) : |
| 124 slot_(0), |
| 125 tag_(tag) {} |
| 126 |
| 127 virtual ~Constant() {} |
| 128 |
| 129 // For UTF-8 string constants, returns the encoded string. |
| 130 // Otherwise, returns an undefined string value suitable for debugging. |
| 131 virtual std::string Display() = 0; |
| 132 |
| 133 virtual void Write(u1 *&p) = 0; |
| 134 |
| 135 // Called by slot() when a constant has been identified as required |
| 136 // in the output classfile's constant pool. This is a hook allowing |
| 137 // constants to register their dependency on other constants, by |
| 138 // calling slot() on them in turn. |
| 139 virtual void Keep() {} |
| 140 |
| 141 // Returns the index of this constant in the output class's constant |
| 142 // pool, assigning a slot if not already done. |
| 143 u2 slot() { |
| 144 if (slot_ == 0) { |
| 145 Keep(); |
| 146 slot_ = const_pool_out.size(); // BugBot's "narrowing" warning |
| 147 // is bogus. The number of |
| 148 // output constants can't exceed |
| 149 // the number of input constants. |
| 150 if (slot_ == 0) { |
| 151 fprintf(stderr, "Constant::slot() called before output phase.\n"); |
| 152 abort(); |
| 153 } |
| 154 const_pool_out.push_back(this); |
| 155 if (tag_ == CONSTANT_Long || tag_ == CONSTANT_Double) { |
| 156 const_pool_out.push_back(NULL); |
| 157 } |
| 158 } |
| 159 return slot_; |
| 160 } |
| 161 |
| 162 u2 slot_; // zero => "this constant is unreachable garbage" |
| 163 u1 tag_; |
| 164 }; |
| 165 |
| 166 // See sec.4.4.1 of JVM spec. |
| 167 struct Constant_Class : Constant |
| 168 { |
| 169 Constant_Class(u2 name_index) : |
| 170 Constant(CONSTANT_Class), |
| 171 name_index_(name_index) {} |
| 172 |
| 173 void Write(u1 *&p) { |
| 174 put_u1(p, tag_); |
| 175 put_u2be(p, constant(name_index_)->slot()); |
| 176 } |
| 177 |
| 178 std::string Display() { |
| 179 return constant(name_index_)->Display(); |
| 180 } |
| 181 |
| 182 void Keep() { constant(name_index_)->slot(); } |
| 183 |
| 184 u2 name_index_; |
| 185 }; |
| 186 |
| 187 // See sec.4.4.2 of JVM spec. |
| 188 struct Constant_FMIref : Constant |
| 189 { |
| 190 Constant_FMIref(u1 tag, |
| 191 u2 class_index, |
| 192 u2 name_type_index) : |
| 193 Constant(tag), |
| 194 class_index_(class_index), |
| 195 name_type_index_(name_type_index) {} |
| 196 |
| 197 void Write(u1 *&p) { |
| 198 put_u1(p, tag_); |
| 199 put_u2be(p, constant(class_index_)->slot()); |
| 200 put_u2be(p, constant(name_type_index_)->slot()); |
| 201 } |
| 202 |
| 203 std::string Display() { |
| 204 return constant(class_index_)->Display() + "::" + |
| 205 constant(name_type_index_)->Display(); |
| 206 } |
| 207 |
| 208 void Keep() { |
| 209 constant(class_index_)->slot(); |
| 210 constant(name_type_index_)->slot(); |
| 211 } |
| 212 |
| 213 u2 class_index_; |
| 214 u2 name_type_index_; |
| 215 }; |
| 216 |
| 217 // See sec.4.4.3 of JVM spec. |
| 218 struct Constant_String : Constant |
| 219 { |
| 220 Constant_String(u2 string_index) : |
| 221 Constant(CONSTANT_String), |
| 222 string_index_(string_index) {} |
| 223 |
| 224 void Write(u1 *&p) { |
| 225 put_u1(p, tag_); |
| 226 put_u2be(p, constant(string_index_)->slot()); |
| 227 } |
| 228 |
| 229 std::string Display() { |
| 230 return "\"" + constant(string_index_)->Display() + "\""; |
| 231 } |
| 232 |
| 233 void Keep() { constant(string_index_)->slot(); } |
| 234 |
| 235 u2 string_index_; |
| 236 }; |
| 237 |
| 238 // See sec.4.4.4 of JVM spec. |
| 239 struct Constant_IntegerOrFloat : Constant |
| 240 { |
| 241 Constant_IntegerOrFloat(u1 tag, u4 bytes) : |
| 242 Constant(tag), |
| 243 bytes_(bytes) {} |
| 244 |
| 245 void Write(u1 *&p) { |
| 246 put_u1(p, tag_); |
| 247 put_u4be(p, bytes_); |
| 248 } |
| 249 |
| 250 std::string Display() { return "int/float"; } |
| 251 |
| 252 u4 bytes_; |
| 253 }; |
| 254 |
| 255 // See sec.4.4.5 of JVM spec. |
| 256 struct Constant_LongOrDouble : Constant_IntegerOrFloat |
| 257 { |
| 258 Constant_LongOrDouble(u1 tag, u4 high_bytes, u4 low_bytes) : |
| 259 Constant_IntegerOrFloat(tag, high_bytes), |
| 260 low_bytes_(low_bytes) {} |
| 261 |
| 262 void Write(u1 *&p) { |
| 263 put_u1(p, tag_); |
| 264 put_u4be(p, bytes_); |
| 265 put_u4be(p, low_bytes_); |
| 266 } |
| 267 |
| 268 std::string Display() { return "long/double"; } |
| 269 |
| 270 u4 low_bytes_; |
| 271 }; |
| 272 |
| 273 // See sec.4.4.6 of JVM spec. |
| 274 struct Constant_NameAndType : Constant |
| 275 { |
| 276 Constant_NameAndType(u2 name_index, u2 descr_index) : |
| 277 Constant(CONSTANT_NameAndType), |
| 278 name_index_(name_index), |
| 279 descr_index_(descr_index) {} |
| 280 |
| 281 void Write(u1 *&p) { |
| 282 put_u1(p, tag_); |
| 283 put_u2be(p, constant(name_index_)->slot()); |
| 284 put_u2be(p, constant(descr_index_)->slot()); |
| 285 } |
| 286 |
| 287 std::string Display() { |
| 288 return constant(name_index_)->Display() + "::" + |
| 289 constant(descr_index_)->Display(); |
| 290 } |
| 291 |
| 292 void Keep() { |
| 293 constant(name_index_)->slot(); |
| 294 constant(descr_index_)->slot(); |
| 295 } |
| 296 |
| 297 u2 name_index_; |
| 298 u2 descr_index_; |
| 299 }; |
| 300 |
| 301 // See sec.4.4.7 of JVM spec. |
| 302 struct Constant_Utf8 : Constant |
| 303 { |
| 304 Constant_Utf8(u4 length, const u1 *utf8) : |
| 305 Constant(CONSTANT_Utf8), |
| 306 length_(length), |
| 307 utf8_(utf8) {} |
| 308 |
| 309 void Write(u1 *&p) { |
| 310 put_u1(p, tag_); |
| 311 put_u2be(p, length_); |
| 312 put_n(p, utf8_, length_); |
| 313 } |
| 314 |
| 315 std::string Display() { |
| 316 return std::string((const char*) utf8_, length_); |
| 317 } |
| 318 |
| 319 u4 length_; |
| 320 const u1 *utf8_; |
| 321 }; |
| 322 |
| 323 // See sec.4.4.8 of JVM spec. |
| 324 struct Constant_MethodHandle : Constant |
| 325 { |
| 326 Constant_MethodHandle(u1 reference_kind, u2 reference_index) : |
| 327 Constant(CONSTANT_MethodHandle), |
| 328 reference_kind_(reference_kind), |
| 329 reference_index_(reference_index) {} |
| 330 |
| 331 void Write(u1 *&p) { |
| 332 put_u1(p, tag_); |
| 333 put_u1(p, reference_kind_); |
| 334 put_u2be(p, reference_index_); |
| 335 } |
| 336 |
| 337 std::string Display() { |
| 338 return "Constant_MethodHandle::" + std::to_string(reference_kind_) + "::" |
| 339 + constant(reference_index_)->Display(); |
| 340 } |
| 341 |
| 342 u1 reference_kind_; |
| 343 u2 reference_index_; |
| 344 }; |
| 345 |
| 346 // See sec.4.4.9 of JVM spec. |
| 347 struct Constant_MethodType : Constant |
| 348 { |
| 349 Constant_MethodType(u2 descriptor_index) : |
| 350 Constant(CONSTANT_MethodType), |
| 351 descriptor_index_(descriptor_index) {} |
| 352 |
| 353 void Write(u1 *&p) { |
| 354 put_u1(p, tag_); |
| 355 put_u2be(p, descriptor_index_); |
| 356 } |
| 357 |
| 358 std::string Display() { |
| 359 return "Constant_MethodType::" + constant(descriptor_index_)->Display(); |
| 360 } |
| 361 |
| 362 u2 descriptor_index_; |
| 363 }; |
| 364 |
| 365 // See sec.4.4.10 of JVM spec. |
| 366 struct Constant_InvokeDynamic : Constant |
| 367 { |
| 368 Constant_InvokeDynamic(u2 bootstrap_method_attr_index, u2 name_and_type_index)
: |
| 369 Constant(CONSTANT_InvokeDynamic), |
| 370 bootstrap_method_attr_index_(bootstrap_method_attr_index), |
| 371 name_and_type_index_(name_and_type_index) {} |
| 372 |
| 373 void Write(u1 *&p) { |
| 374 put_u1(p, tag_); |
| 375 put_u2be(p, bootstrap_method_attr_index_); |
| 376 put_u2be(p, name_and_type_index_); |
| 377 } |
| 378 |
| 379 std::string Display() { |
| 380 return "Constant_InvokeDynamic::" |
| 381 + std::to_string(bootstrap_method_attr_index_) + "::" |
| 382 + constant(name_and_type_index_)->Display(); |
| 383 } |
| 384 |
| 385 u2 bootstrap_method_attr_index_; |
| 386 u2 name_and_type_index_; |
| 387 }; |
| 388 |
| 389 /********************************************************************** |
| 390 * * |
| 391 * Attributes * |
| 392 * * |
| 393 **********************************************************************/ |
| 394 |
| 395 // See sec.4.7 of JVM spec. |
| 396 struct Attribute { |
| 397 |
| 398 virtual ~Attribute() {} |
| 399 virtual void Write(u1 *&p) = 0; |
| 400 |
| 401 void WriteProlog(u1 *&p, u2 length) { |
| 402 put_u2be(p, attribute_name_->slot()); |
| 403 put_u4be(p, length); |
| 404 } |
| 405 |
| 406 Constant *attribute_name_; |
| 407 }; |
| 408 |
| 409 // See sec.4.7.5 of JVM spec. |
| 410 struct ExceptionsAttribute : Attribute { |
| 411 |
| 412 static ExceptionsAttribute* Read(const u1 *&p, Constant *attribute_name) { |
| 413 ExceptionsAttribute *attr = new ExceptionsAttribute; |
| 414 attr->attribute_name_ = attribute_name; |
| 415 u2 number_of_exceptions = get_u2be(p); |
| 416 for (int ii = 0; ii < number_of_exceptions; ++ii) { |
| 417 attr->exceptions_.push_back(constant(get_u2be(p))); |
| 418 } |
| 419 return attr; |
| 420 } |
| 421 |
| 422 void Write(u1 *&p) { |
| 423 WriteProlog(p, exceptions_.size() * 2 + 2); |
| 424 put_u2be(p, exceptions_.size()); |
| 425 for (size_t ii = 0; ii < exceptions_.size(); ++ii) { |
| 426 put_u2be(p, exceptions_[ii]->slot()); |
| 427 } |
| 428 } |
| 429 |
| 430 std::vector<Constant*> exceptions_; |
| 431 }; |
| 432 |
| 433 // See sec.4.7.6 of JVM spec. |
| 434 struct InnerClassesAttribute : Attribute { |
| 435 |
| 436 struct Entry { |
| 437 Constant *inner_class_info; |
| 438 Constant *outer_class_info; |
| 439 Constant *inner_name; |
| 440 u2 inner_class_access_flags; |
| 441 }; |
| 442 |
| 443 virtual ~InnerClassesAttribute() { |
| 444 for (size_t i = 0; i < entries_.size(); i++) { |
| 445 delete entries_[i]; |
| 446 } |
| 447 } |
| 448 |
| 449 static InnerClassesAttribute* Read(const u1 *&p, Constant *attribute_name) { |
| 450 InnerClassesAttribute *attr = new InnerClassesAttribute; |
| 451 attr->attribute_name_ = attribute_name; |
| 452 |
| 453 u2 number_of_classes = get_u2be(p); |
| 454 for (int ii = 0; ii < number_of_classes; ++ii) { |
| 455 Entry *entry = new Entry; |
| 456 entry->inner_class_info = constant(get_u2be(p)); |
| 457 entry->outer_class_info = constant(get_u2be(p)); |
| 458 entry->inner_name = constant(get_u2be(p)); |
| 459 entry->inner_class_access_flags = get_u2be(p); |
| 460 |
| 461 attr->entries_.push_back(entry); |
| 462 } |
| 463 return attr; |
| 464 } |
| 465 |
| 466 void Write(u1 *&p) { |
| 467 WriteProlog(p, 2 + entries_.size() * 8); |
| 468 put_u2be(p, entries_.size()); |
| 469 for (size_t ii = 0; ii < entries_.size(); ++ii) { |
| 470 Entry *entry = entries_[ii]; |
| 471 put_u2be(p, entry->inner_class_info == NULL |
| 472 ? 0 |
| 473 : entry->inner_class_info->slot()); |
| 474 put_u2be(p, entry->outer_class_info == NULL |
| 475 ? 0 |
| 476 : entry->outer_class_info->slot()); |
| 477 put_u2be(p, entry->inner_name == NULL |
| 478 ? 0 |
| 479 : entry->inner_name->slot()); |
| 480 put_u2be(p, entry->inner_class_access_flags); |
| 481 } |
| 482 } |
| 483 |
| 484 std::vector<Entry*> entries_; |
| 485 }; |
| 486 |
| 487 // See sec.4.7.7 of JVM spec. |
| 488 // We preserve EnclosingMethod attributes to be able to identify local and |
| 489 // anonymous classes. These classes will be stripped of most content, as they |
| 490 // represent implementation details that shoudn't leak into the ijars. Omitting |
| 491 // EnclosingMethod attributes can lead to type-checking failures in the presence |
| 492 // of generics (see b/9070939). |
| 493 struct EnclosingMethodAttribute : Attribute { |
| 494 |
| 495 static EnclosingMethodAttribute* Read(const u1 *&p, |
| 496 Constant *attribute_name) { |
| 497 EnclosingMethodAttribute *attr = new EnclosingMethodAttribute; |
| 498 attr->attribute_name_ = attribute_name; |
| 499 attr->class_ = constant(get_u2be(p)); |
| 500 attr->method_ = constant(get_u2be(p)); |
| 501 return attr; |
| 502 } |
| 503 |
| 504 void Write(u1 *&p) { |
| 505 WriteProlog(p, 4); |
| 506 put_u2be(p, class_->slot()); |
| 507 put_u2be(p, method_ == NULL ? 0 : method_->slot()); |
| 508 } |
| 509 |
| 510 Constant *class_; |
| 511 Constant *method_; |
| 512 }; |
| 513 |
| 514 // See sec.4.7.16.1 of JVM spec. |
| 515 // Used by AnnotationDefault and other attributes. |
| 516 struct ElementValue { |
| 517 virtual ~ElementValue() {} |
| 518 virtual void Write(u1 *&p) = 0; |
| 519 static ElementValue* Read(const u1 *&p); |
| 520 u1 tag_; |
| 521 u4 length_; |
| 522 }; |
| 523 |
| 524 struct BaseTypeElementValue : ElementValue { |
| 525 void Write(u1 *&p) { |
| 526 put_u1(p, tag_); |
| 527 put_u2be(p, const_value_->slot()); |
| 528 } |
| 529 static BaseTypeElementValue *Read(const u1 *&p) { |
| 530 BaseTypeElementValue *value = new BaseTypeElementValue; |
| 531 value->const_value_ = constant(get_u2be(p)); |
| 532 return value; |
| 533 } |
| 534 Constant *const_value_; |
| 535 }; |
| 536 |
| 537 struct EnumTypeElementValue : ElementValue { |
| 538 void Write(u1 *&p) { |
| 539 put_u1(p, tag_); |
| 540 put_u2be(p, type_name_->slot()); |
| 541 put_u2be(p, const_name_->slot()); |
| 542 } |
| 543 static EnumTypeElementValue *Read(const u1 *&p) { |
| 544 EnumTypeElementValue *value = new EnumTypeElementValue; |
| 545 value->type_name_ = constant(get_u2be(p)); |
| 546 value->const_name_ = constant(get_u2be(p)); |
| 547 return value; |
| 548 } |
| 549 Constant *type_name_; |
| 550 Constant *const_name_; |
| 551 }; |
| 552 |
| 553 struct ClassTypeElementValue : ElementValue { |
| 554 void Write(u1 *&p) { |
| 555 put_u1(p, tag_); |
| 556 put_u2be(p, class_info_->slot()); |
| 557 } |
| 558 static ClassTypeElementValue *Read(const u1 *&p) { |
| 559 ClassTypeElementValue *value = new ClassTypeElementValue; |
| 560 value->class_info_ = constant(get_u2be(p)); |
| 561 return value; |
| 562 } |
| 563 Constant *class_info_; |
| 564 }; |
| 565 |
| 566 struct ArrayTypeElementValue : ElementValue { |
| 567 virtual ~ArrayTypeElementValue() { |
| 568 for (size_t i = 0; i < values_.size(); i++) { |
| 569 delete values_[i]; |
| 570 } |
| 571 } |
| 572 |
| 573 void Write(u1 *&p) { |
| 574 put_u1(p, tag_); |
| 575 put_u2be(p, values_.size()); |
| 576 for (size_t ii = 0; ii < values_.size(); ++ii) { |
| 577 values_[ii]->Write(p); |
| 578 } |
| 579 } |
| 580 static ArrayTypeElementValue *Read(const u1 *&p) { |
| 581 ArrayTypeElementValue *value = new ArrayTypeElementValue; |
| 582 u2 num_values = get_u2be(p); |
| 583 for (int ii = 0; ii < num_values; ++ii) { |
| 584 value->values_.push_back(ElementValue::Read(p)); |
| 585 } |
| 586 return value; |
| 587 } |
| 588 std::vector<ElementValue*> values_; |
| 589 }; |
| 590 |
| 591 // See sec.4.7.16 of JVM spec. |
| 592 struct Annotation { |
| 593 virtual ~Annotation() { |
| 594 for (size_t i = 0; i < element_value_pairs_.size(); i++) { |
| 595 delete element_value_pairs_[i]->element_value_; |
| 596 delete element_value_pairs_[i]; |
| 597 } |
| 598 } |
| 599 |
| 600 void Write(u1 *&p) { |
| 601 put_u2be(p, type_->slot()); |
| 602 put_u2be(p, element_value_pairs_.size()); |
| 603 for (size_t ii = 0; ii < element_value_pairs_.size(); ++ii) { |
| 604 put_u2be(p, element_value_pairs_[ii]->element_name_->slot()); |
| 605 element_value_pairs_[ii]->element_value_->Write(p); |
| 606 } |
| 607 } |
| 608 static Annotation *Read(const u1 *&p) { |
| 609 Annotation *value = new Annotation; |
| 610 value->type_ = constant(get_u2be(p)); |
| 611 u2 num_element_value_pairs = get_u2be(p); |
| 612 for (int ii = 0; ii < num_element_value_pairs; ++ii) { |
| 613 ElementValuePair *pair = new ElementValuePair; |
| 614 pair->element_name_ = constant(get_u2be(p)); |
| 615 pair->element_value_ = ElementValue::Read(p); |
| 616 value->element_value_pairs_.push_back(pair); |
| 617 } |
| 618 return value; |
| 619 } |
| 620 Constant *type_; |
| 621 struct ElementValuePair { |
| 622 Constant *element_name_; |
| 623 ElementValue *element_value_; |
| 624 }; |
| 625 std::vector<ElementValuePair*> element_value_pairs_; |
| 626 }; |
| 627 |
| 628 // See sec 4.7.20 of Java 8 JVM Spec |
| 629 // |
| 630 // Each entry in the annotations table represents a single run-time visible |
| 631 // annotation on a type used in a declaration or expression. The type_annotation |
| 632 // structure has the following format: |
| 633 // |
| 634 // type_annotation { |
| 635 // u1 target_type; |
| 636 // union { |
| 637 // type_parameter_target; |
| 638 // supertype_target; |
| 639 // type_parameter_bound_target; |
| 640 // empty_target; |
| 641 // method_formal_parameter_target; |
| 642 // throws_target; |
| 643 // localvar_target; |
| 644 // catch_target; |
| 645 // offset_target; |
| 646 // type_argument_target; |
| 647 // } target_info; |
| 648 // type_path target_path; |
| 649 // u2 type_index; |
| 650 // u2 num_element_value_pairs; |
| 651 // { |
| 652 // u2 element_name_index; |
| 653 // element_value value; |
| 654 // } |
| 655 // element_value_pairs[num_element_value_pairs]; |
| 656 // } |
| 657 // |
| 658 struct TypeAnnotation { |
| 659 virtual ~TypeAnnotation() { |
| 660 delete target_info_; |
| 661 delete type_path_; |
| 662 delete annotation_; |
| 663 } |
| 664 |
| 665 void Write(u1 *&p) { |
| 666 put_u1(p, target_type_); |
| 667 target_info_->Write(p); |
| 668 type_path_->Write(p); |
| 669 annotation_->Write(p); |
| 670 } |
| 671 |
| 672 static TypeAnnotation *Read(const u1 *&p) { |
| 673 TypeAnnotation *value = new TypeAnnotation; |
| 674 value->target_type_ = get_u1(p); |
| 675 value->target_info_ = ReadTargetInfo(p, value->target_type_); |
| 676 value->type_path_ = TypePath::Read(p); |
| 677 value->annotation_ = Annotation::Read(p); |
| 678 return value; |
| 679 } |
| 680 |
| 681 struct TargetInfo { |
| 682 virtual ~TargetInfo() {} |
| 683 virtual void Write(u1 *&p) = 0; |
| 684 }; |
| 685 |
| 686 struct TypeParameterTargetInfo : TargetInfo { |
| 687 void Write(u1 *&p) { |
| 688 put_u1(p, type_parameter_index_); |
| 689 } |
| 690 static TypeParameterTargetInfo *Read(const u1 *&p) { |
| 691 TypeParameterTargetInfo *value = new TypeParameterTargetInfo; |
| 692 value->type_parameter_index_ = get_u1(p); |
| 693 return value; |
| 694 } |
| 695 u1 type_parameter_index_; |
| 696 }; |
| 697 |
| 698 struct ClassExtendsInfo : TargetInfo { |
| 699 void Write(u1 *&p) { |
| 700 put_u2be(p, supertype_index_); |
| 701 } |
| 702 static ClassExtendsInfo *Read(const u1 *&p) { |
| 703 ClassExtendsInfo *value = new ClassExtendsInfo; |
| 704 value->supertype_index_ = get_u2be(p); |
| 705 return value; |
| 706 } |
| 707 u2 supertype_index_; |
| 708 }; |
| 709 |
| 710 struct TypeParameterBoundInfo : TargetInfo { |
| 711 void Write(u1 *&p) { |
| 712 put_u1(p, type_parameter_index_); |
| 713 put_u1(p, bound_index_); |
| 714 } |
| 715 static TypeParameterBoundInfo *Read(const u1 *&p) { |
| 716 TypeParameterBoundInfo *value = new TypeParameterBoundInfo; |
| 717 value->type_parameter_index_ = get_u1(p); |
| 718 value->bound_index_ = get_u1(p); |
| 719 return value; |
| 720 } |
| 721 u1 type_parameter_index_; |
| 722 u1 bound_index_; |
| 723 }; |
| 724 |
| 725 struct EmptyInfo : TargetInfo { |
| 726 void Write(u1 *&p) {} |
| 727 static EmptyInfo *Read(const u1 *&p) { |
| 728 return new EmptyInfo; |
| 729 } |
| 730 }; |
| 731 |
| 732 struct MethodFormalParameterInfo : TargetInfo { |
| 733 void Write(u1 *&p) { |
| 734 put_u1(p, method_formal_parameter_index_); |
| 735 } |
| 736 static MethodFormalParameterInfo *Read(const u1 *&p) { |
| 737 MethodFormalParameterInfo *value = new MethodFormalParameterInfo; |
| 738 value->method_formal_parameter_index_ = get_u1(p); |
| 739 return value; |
| 740 } |
| 741 u1 method_formal_parameter_index_; |
| 742 }; |
| 743 |
| 744 struct ThrowsTypeInfo : TargetInfo { |
| 745 void Write(u1 *&p) { |
| 746 put_u2be(p, throws_type_index_); |
| 747 } |
| 748 static ThrowsTypeInfo *Read(const u1 *&p) { |
| 749 ThrowsTypeInfo *value = new ThrowsTypeInfo; |
| 750 value->throws_type_index_ = get_u2be(p); |
| 751 return value; |
| 752 } |
| 753 u2 throws_type_index_; |
| 754 }; |
| 755 |
| 756 static TargetInfo *ReadTargetInfo(const u1 *&p, u1 target_type) { |
| 757 switch (target_type) { |
| 758 case CLASS_TYPE_PARAMETER: |
| 759 case METHOD_TYPE_PARAMETER: |
| 760 return TypeParameterTargetInfo::Read(p); |
| 761 case CLASS_EXTENDS: |
| 762 return ClassExtendsInfo::Read(p); |
| 763 case CLASS_TYPE_PARAMETER_BOUND: |
| 764 case METHOD_TYPE_PARAMETER_BOUND: |
| 765 return TypeParameterBoundInfo::Read(p); |
| 766 case FIELD: |
| 767 case METHOD_RETURN: |
| 768 case METHOD_RECEIVER: |
| 769 return new EmptyInfo; |
| 770 case METHOD_FORMAL_PARAMETER: |
| 771 return MethodFormalParameterInfo::Read(p); |
| 772 case THROWS: |
| 773 return ThrowsTypeInfo::Read(p); |
| 774 default: |
| 775 fprintf(stderr, "Illegal type annotation target type: %d\n", |
| 776 target_type); |
| 777 abort(); |
| 778 } |
| 779 } |
| 780 |
| 781 struct TypePath { |
| 782 void Write(u1 *&p) { |
| 783 put_u1(p, path_.size()); |
| 784 for (TypePathEntry entry : path_) { |
| 785 put_u1(p, entry.type_path_kind_); |
| 786 put_u1(p, entry.type_argument_index_); |
| 787 } |
| 788 } |
| 789 static TypePath *Read(const u1 *&p) { |
| 790 TypePath *value = new TypePath; |
| 791 u1 path_length = get_u1(p); |
| 792 for (int ii = 0; ii < path_length; ++ii) { |
| 793 TypePathEntry entry; |
| 794 entry.type_path_kind_ = get_u1(p); |
| 795 entry.type_argument_index_ = get_u1(p); |
| 796 value->path_.push_back(entry); |
| 797 } |
| 798 return value; |
| 799 } |
| 800 |
| 801 struct TypePathEntry { |
| 802 u1 type_path_kind_; |
| 803 u1 type_argument_index_; |
| 804 }; |
| 805 std::vector<TypePathEntry> path_; |
| 806 }; |
| 807 |
| 808 u1 target_type_; |
| 809 TargetInfo *target_info_; |
| 810 TypePath *type_path_; |
| 811 Annotation *annotation_; |
| 812 }; |
| 813 |
| 814 struct AnnotationTypeElementValue : ElementValue { |
| 815 virtual ~AnnotationTypeElementValue() { |
| 816 delete annotation_; |
| 817 } |
| 818 |
| 819 void Write(u1 *&p) { |
| 820 put_u1(p, tag_); |
| 821 annotation_->Write(p); |
| 822 } |
| 823 static AnnotationTypeElementValue *Read(const u1 *&p) { |
| 824 AnnotationTypeElementValue *value = new AnnotationTypeElementValue; |
| 825 value->annotation_ = Annotation::Read(p); |
| 826 return value; |
| 827 } |
| 828 |
| 829 Annotation *annotation_; |
| 830 }; |
| 831 |
| 832 ElementValue* ElementValue::Read(const u1 *&p) { |
| 833 const u1* start = p; |
| 834 ElementValue *result; |
| 835 u1 tag = get_u1(p); |
| 836 if (tag != 0 && strchr("BCDFIJSZs", (char) tag) != NULL) { |
| 837 result = BaseTypeElementValue::Read(p); |
| 838 } else if ((char) tag == 'e') { |
| 839 result = EnumTypeElementValue::Read(p); |
| 840 } else if ((char) tag == 'c') { |
| 841 result = ClassTypeElementValue::Read(p); |
| 842 } else if ((char) tag == '[') { |
| 843 result = ArrayTypeElementValue::Read(p); |
| 844 } else if ((char) tag == '@') { |
| 845 result = AnnotationTypeElementValue::Read(p); |
| 846 } else { |
| 847 fprintf(stderr, "Illegal element_value::tag: %d\n", tag); |
| 848 abort(); |
| 849 } |
| 850 result->tag_ = tag; |
| 851 result->length_ = p - start; |
| 852 return result; |
| 853 } |
| 854 |
| 855 // See sec.4.7.20 of JVM spec. |
| 856 // We preserve AnnotationDefault attributes because they are required |
| 857 // in order to make use of an annotation in new code. |
| 858 struct AnnotationDefaultAttribute : Attribute { |
| 859 virtual ~AnnotationDefaultAttribute() { |
| 860 delete default_value_; |
| 861 } |
| 862 |
| 863 static AnnotationDefaultAttribute* Read(const u1 *&p, |
| 864 Constant *attribute_name) { |
| 865 AnnotationDefaultAttribute *attr = new AnnotationDefaultAttribute; |
| 866 attr->attribute_name_ = attribute_name; |
| 867 attr->default_value_ = ElementValue::Read(p); |
| 868 return attr; |
| 869 } |
| 870 |
| 871 void Write(u1 *&p) { |
| 872 WriteProlog(p, default_value_->length_); |
| 873 default_value_->Write(p); |
| 874 } |
| 875 |
| 876 ElementValue *default_value_; |
| 877 }; |
| 878 |
| 879 // See sec.4.7.2 of JVM spec. |
| 880 // We preserve ConstantValue attributes because they are required for |
| 881 // compile-time constant propagation. |
| 882 struct ConstantValueAttribute : Attribute { |
| 883 |
| 884 static ConstantValueAttribute* Read(const u1 *&p, Constant *attribute_name) { |
| 885 ConstantValueAttribute *attr = new ConstantValueAttribute; |
| 886 attr->attribute_name_ = attribute_name; |
| 887 attr->constantvalue_ = constant(get_u2be(p)); |
| 888 return attr; |
| 889 } |
| 890 |
| 891 void Write(u1 *&p) { |
| 892 WriteProlog(p, 2); |
| 893 put_u2be(p, constantvalue_->slot()); |
| 894 } |
| 895 |
| 896 Constant *constantvalue_; |
| 897 }; |
| 898 |
| 899 // See sec.4.7.9 of JVM spec. |
| 900 // We preserve Signature attributes because they are required by the |
| 901 // compiler for type-checking of generics. |
| 902 struct SignatureAttribute : Attribute { |
| 903 |
| 904 static SignatureAttribute* Read(const u1 *&p, Constant *attribute_name) { |
| 905 SignatureAttribute *attr = new SignatureAttribute; |
| 906 attr->attribute_name_ = attribute_name; |
| 907 attr->signature_ = constant(get_u2be(p)); |
| 908 return attr; |
| 909 } |
| 910 |
| 911 void Write(u1 *&p) { |
| 912 WriteProlog(p, 2); |
| 913 put_u2be(p, signature_->slot()); |
| 914 } |
| 915 |
| 916 Constant *signature_; |
| 917 }; |
| 918 |
| 919 // See sec.4.7.15 of JVM spec. |
| 920 // We preserve Deprecated attributes because they are required by the |
| 921 // compiler to generate warning messages. |
| 922 struct DeprecatedAttribute : Attribute { |
| 923 |
| 924 static DeprecatedAttribute* Read(const u1 *&p, Constant *attribute_name) { |
| 925 DeprecatedAttribute *attr = new DeprecatedAttribute; |
| 926 attr->attribute_name_ = attribute_name; |
| 927 return attr; |
| 928 } |
| 929 |
| 930 void Write(u1 *&p) { |
| 931 WriteProlog(p, 0); |
| 932 } |
| 933 }; |
| 934 |
| 935 // See sec.4.7.16-17 of JVM spec v3. Includes RuntimeVisible and |
| 936 // RuntimeInvisible. |
| 937 // |
| 938 // We preserve all annotations. |
| 939 struct AnnotationsAttribute : Attribute { |
| 940 virtual ~AnnotationsAttribute() { |
| 941 for (size_t i = 0; i < annotations_.size(); i++) { |
| 942 delete annotations_[i]; |
| 943 } |
| 944 } |
| 945 |
| 946 static AnnotationsAttribute* Read(const u1 *&p, Constant *attribute_name) { |
| 947 AnnotationsAttribute *attr = new AnnotationsAttribute; |
| 948 attr->attribute_name_ = attribute_name; |
| 949 u2 num_annotations = get_u2be(p); |
| 950 for (int ii = 0; ii < num_annotations; ++ii) { |
| 951 Annotation *annotation = Annotation::Read(p); |
| 952 attr->annotations_.push_back(annotation); |
| 953 } |
| 954 return attr; |
| 955 } |
| 956 |
| 957 void Write(u1 *&p) { |
| 958 WriteProlog(p, -1); |
| 959 u1 *payload_start = p - 4; |
| 960 put_u2be(p, annotations_.size()); |
| 961 for (size_t ii = 0; ii < annotations_.size(); ++ii) { |
| 962 annotations_[ii]->Write(p); |
| 963 } |
| 964 put_u4be(payload_start, p - 4 - payload_start); // backpatch length |
| 965 } |
| 966 |
| 967 std::vector<Annotation*> annotations_; |
| 968 }; |
| 969 |
| 970 // See sec.4.7.18-19 of JVM spec. Includes RuntimeVisible and |
| 971 // RuntimeInvisible. |
| 972 // |
| 973 // We preserve all annotations. |
| 974 struct ParameterAnnotationsAttribute : Attribute { |
| 975 |
| 976 static ParameterAnnotationsAttribute* Read(const u1 *&p, |
| 977 Constant *attribute_name) { |
| 978 ParameterAnnotationsAttribute *attr = new ParameterAnnotationsAttribute; |
| 979 attr->attribute_name_ = attribute_name; |
| 980 u1 num_parameters = get_u1(p); |
| 981 for (int ii = 0; ii < num_parameters; ++ii) { |
| 982 std::vector<Annotation*> annotations; |
| 983 u2 num_annotations = get_u2be(p); |
| 984 for (int ii = 0; ii < num_annotations; ++ii) { |
| 985 Annotation *annotation = Annotation::Read(p); |
| 986 annotations.push_back(annotation); |
| 987 } |
| 988 attr->parameter_annotations_.push_back(annotations); |
| 989 } |
| 990 return attr; |
| 991 } |
| 992 |
| 993 void Write(u1 *&p) { |
| 994 WriteProlog(p, -1); |
| 995 u1 *payload_start = p - 4; |
| 996 put_u1(p, parameter_annotations_.size()); |
| 997 for (size_t ii = 0; ii < parameter_annotations_.size(); ++ii) { |
| 998 std::vector<Annotation *> &annotations = parameter_annotations_[ii]; |
| 999 put_u2be(p, annotations.size()); |
| 1000 for (size_t jj = 0; jj < annotations.size(); ++jj) { |
| 1001 annotations[jj]->Write(p); |
| 1002 } |
| 1003 } |
| 1004 put_u4be(payload_start, p - 4 - payload_start); // backpatch length |
| 1005 } |
| 1006 |
| 1007 std::vector<std::vector<Annotation*> > parameter_annotations_; |
| 1008 }; |
| 1009 |
| 1010 // See sec.4.7.20 of Java 8 JVM spec. Includes RuntimeVisibleTypeAnnotations |
| 1011 // and RuntimeInvisibleTypeAnnotations. |
| 1012 struct TypeAnnotationsAttribute : Attribute { |
| 1013 static TypeAnnotationsAttribute* Read(const u1 *&p, Constant *attribute_name, |
| 1014 u4 attribute_length) { |
| 1015 auto attr = new TypeAnnotationsAttribute; |
| 1016 attr->attribute_name_ = attribute_name; |
| 1017 u2 num_annotations = get_u2be(p); |
| 1018 for (int ii = 0; ii < num_annotations; ++ii) { |
| 1019 TypeAnnotation *annotation = TypeAnnotation::Read(p); |
| 1020 attr->type_annotations_.push_back(annotation); |
| 1021 } |
| 1022 return attr; |
| 1023 } |
| 1024 |
| 1025 void Write(u1 *&p) { |
| 1026 WriteProlog(p, -1); |
| 1027 u1 *payload_start = p - 4; |
| 1028 put_u2be(p, type_annotations_.size()); |
| 1029 for (TypeAnnotation *annotation : type_annotations_) { |
| 1030 annotation->Write(p); |
| 1031 } |
| 1032 put_u4be(payload_start, p - 4 - payload_start); // backpatch length |
| 1033 } |
| 1034 |
| 1035 std::vector<TypeAnnotation*> type_annotations_; |
| 1036 }; |
| 1037 |
| 1038 struct GeneralAttribute : Attribute { |
| 1039 static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name, |
| 1040 u4 attribute_length) { |
| 1041 auto attr = new GeneralAttribute; |
| 1042 attr->attribute_name_ = attribute_name; |
| 1043 attr->attribute_length_ = attribute_length; |
| 1044 attr->attribute_content_ = p; |
| 1045 p += attribute_length; |
| 1046 return attr; |
| 1047 } |
| 1048 |
| 1049 void Write(u1 *&p) { |
| 1050 WriteProlog(p, attribute_length_); |
| 1051 put_n(p, attribute_content_, attribute_length_); |
| 1052 } |
| 1053 |
| 1054 u4 attribute_length_; |
| 1055 const u1 *attribute_content_; |
| 1056 }; |
| 1057 |
| 1058 /********************************************************************** |
| 1059 * * |
| 1060 * ClassFile * |
| 1061 * * |
| 1062 **********************************************************************/ |
| 1063 |
| 1064 struct HasAttrs { |
| 1065 std::vector<Attribute*> attributes; |
| 1066 |
| 1067 void WriteAttrs(u1 *&p); |
| 1068 void ReadAttrs(const u1 *&p); |
| 1069 |
| 1070 virtual ~HasAttrs() { |
| 1071 for (size_t i = 0; i < attributes.size(); i++) { |
| 1072 delete attributes[i]; |
| 1073 } |
| 1074 } |
| 1075 }; |
| 1076 |
| 1077 // A field or method. |
| 1078 // See sec.4.5 and 4.6 of JVM spec. |
| 1079 struct Member : HasAttrs { |
| 1080 u2 access_flags; |
| 1081 Constant *name; |
| 1082 Constant *descriptor; |
| 1083 |
| 1084 static Member* Read(const u1 *&p) { |
| 1085 Member *m = new Member; |
| 1086 m->access_flags = get_u2be(p); |
| 1087 m->name = constant(get_u2be(p)); |
| 1088 m->descriptor = constant(get_u2be(p)); |
| 1089 m->ReadAttrs(p); |
| 1090 return m; |
| 1091 } |
| 1092 |
| 1093 void Write(u1 *&p) { |
| 1094 put_u2be(p, access_flags); |
| 1095 put_u2be(p, name->slot()); |
| 1096 put_u2be(p, descriptor->slot()); |
| 1097 WriteAttrs(p); |
| 1098 } |
| 1099 }; |
| 1100 |
| 1101 // See sec.4.1 of JVM spec. |
| 1102 struct ClassFile : HasAttrs { |
| 1103 |
| 1104 size_t length; |
| 1105 |
| 1106 // Header: |
| 1107 u4 magic; |
| 1108 u2 major; |
| 1109 u2 minor; |
| 1110 |
| 1111 // Body: |
| 1112 u2 access_flags; |
| 1113 Constant *this_class; |
| 1114 Constant *super_class; |
| 1115 std::vector<Constant*> interfaces; |
| 1116 std::vector<Member*> fields; |
| 1117 std::vector<Member*> methods; |
| 1118 |
| 1119 virtual ~ClassFile() { |
| 1120 for (size_t i = 0; i < fields.size(); i++) { |
| 1121 delete fields[i]; |
| 1122 } |
| 1123 |
| 1124 for (size_t i = 0; i < methods.size(); i++) { |
| 1125 delete methods[i]; |
| 1126 } |
| 1127 |
| 1128 // Constants do not need to be deleted; they are owned by the constant pool. |
| 1129 } |
| 1130 |
| 1131 void WriteClass(u1 *&p); |
| 1132 |
| 1133 bool ReadConstantPool(const u1 *&p); |
| 1134 |
| 1135 void StripIfAnonymous(); |
| 1136 |
| 1137 void WriteHeader(u1 *&p) { |
| 1138 put_u4be(p, magic); |
| 1139 put_u2be(p, major); |
| 1140 put_u2be(p, minor); |
| 1141 |
| 1142 put_u2be(p, const_pool_out.size()); |
| 1143 for (u2 ii = 1; ii < const_pool_out.size(); ++ii) { |
| 1144 if (const_pool_out[ii] != NULL) { // NB: NULLs appear after long/double. |
| 1145 const_pool_out[ii]->Write(p); |
| 1146 } |
| 1147 } |
| 1148 } |
| 1149 |
| 1150 void WriteBody(u1 *&p) { |
| 1151 put_u2be(p, access_flags); |
| 1152 put_u2be(p, this_class->slot()); |
| 1153 put_u2be(p, super_class == NULL ? 0 : super_class->slot()); |
| 1154 put_u2be(p, interfaces.size()); |
| 1155 for (size_t ii = 0; ii < interfaces.size(); ++ii) { |
| 1156 put_u2be(p, interfaces[ii]->slot()); |
| 1157 } |
| 1158 put_u2be(p, fields.size()); |
| 1159 for (size_t ii = 0; ii < fields.size(); ++ii) { |
| 1160 fields[ii]->Write(p); |
| 1161 } |
| 1162 put_u2be(p, methods.size()); |
| 1163 for (size_t ii = 0; ii < methods.size(); ++ii) { |
| 1164 methods[ii]->Write(p); |
| 1165 } |
| 1166 WriteAttrs(p); |
| 1167 } |
| 1168 |
| 1169 }; |
| 1170 |
| 1171 void HasAttrs::ReadAttrs(const u1 *&p) { |
| 1172 u2 attributes_count = get_u2be(p); |
| 1173 for (int ii = 0; ii < attributes_count; ii++) { |
| 1174 Constant *attribute_name = constant(get_u2be(p)); |
| 1175 u4 attribute_length = get_u4be(p); |
| 1176 |
| 1177 std::string attr_name = attribute_name->Display(); |
| 1178 if (attr_name == "SourceFile" || |
| 1179 attr_name == "LineNumberTable" || |
| 1180 attr_name == "LocalVariableTable" || |
| 1181 attr_name == "LocalVariableTypeTable" || |
| 1182 attr_name == "Code" || |
| 1183 attr_name == "Synthetic" || |
| 1184 attr_name == "BootstrapMethods") { |
| 1185 p += attribute_length; // drop these attributes |
| 1186 } else if (attr_name == "Exceptions") { |
| 1187 attributes.push_back(ExceptionsAttribute::Read(p, attribute_name)); |
| 1188 } else if (attr_name == "Signature") { |
| 1189 attributes.push_back(SignatureAttribute::Read(p, attribute_name)); |
| 1190 } else if (attr_name == "Deprecated") { |
| 1191 attributes.push_back(DeprecatedAttribute::Read(p, attribute_name)); |
| 1192 } else if (attr_name == "EnclosingMethod") { |
| 1193 attributes.push_back(EnclosingMethodAttribute::Read(p, attribute_name)); |
| 1194 } else if (attr_name == "InnerClasses") { |
| 1195 // TODO(bazel-team): omit private inner classes |
| 1196 attributes.push_back(InnerClassesAttribute::Read(p, attribute_name)); |
| 1197 } else if (attr_name == "AnnotationDefault") { |
| 1198 attributes.push_back(AnnotationDefaultAttribute::Read(p, attribute_name)); |
| 1199 } else if (attr_name == "ConstantValue") { |
| 1200 attributes.push_back(ConstantValueAttribute::Read(p, attribute_name)); |
| 1201 } else if (attr_name == "RuntimeVisibleAnnotations" || |
| 1202 attr_name == "RuntimeInvisibleAnnotations") { |
| 1203 attributes.push_back(AnnotationsAttribute::Read(p, attribute_name)); |
| 1204 } else if (attr_name == "RuntimeVisibleParameterAnnotations" || |
| 1205 attr_name == "RuntimeInvisibleParameterAnnotations") { |
| 1206 attributes.push_back( |
| 1207 ParameterAnnotationsAttribute::Read(p, attribute_name)); |
| 1208 } else if (attr_name == "Scala" || |
| 1209 attr_name == "ScalaSig" || |
| 1210 attr_name == "ScalaInlineInfo") { |
| 1211 // These are opaque blobs, so can be handled with a general |
| 1212 // attribute handler |
| 1213 attributes.push_back(GeneralAttribute::Read(p, attribute_name, |
| 1214 attribute_length)); |
| 1215 } else if (attr_name == "RuntimeVisibleTypeAnnotations" || |
| 1216 attr_name == "RuntimeInvisibleTypeAnnotations") { |
| 1217 // JSR 308: annotations on types. JDK 7 has no use for these yet, but the |
| 1218 // Checkers Framework relies on them. |
| 1219 attributes.push_back(TypeAnnotationsAttribute::Read(p, attribute_name, |
| 1220 attribute_length)); |
| 1221 } else { |
| 1222 // Skip over unknown attributes with a warning. The JVM spec |
| 1223 // says this is ok, so long as we handle the mandatory attributes. |
| 1224 fprintf(stderr, "ijar: skipping unknown attribute: \"%s\".\n", |
| 1225 attr_name.c_str()); |
| 1226 p += attribute_length; |
| 1227 } |
| 1228 } |
| 1229 } |
| 1230 |
| 1231 void HasAttrs::WriteAttrs(u1 *&p) { |
| 1232 put_u2be(p, attributes.size()); |
| 1233 for (size_t ii = 0; ii < attributes.size(); ii++) { |
| 1234 attributes[ii]->Write(p); |
| 1235 } |
| 1236 } |
| 1237 |
| 1238 // See sec.4.4 of JVM spec. |
| 1239 bool ClassFile::ReadConstantPool(const u1 *&p) { |
| 1240 |
| 1241 const_pool_in.clear(); |
| 1242 const_pool_in.push_back(NULL); // dummy first item |
| 1243 |
| 1244 u2 cp_count = get_u2be(p); |
| 1245 for (int ii = 1; ii < cp_count; ++ii) { |
| 1246 u1 tag = get_u1(p); |
| 1247 |
| 1248 if (devtools_ijar::verbose) { |
| 1249 fprintf(stderr, "cp[%d/%d] = tag %d\n", ii, cp_count, tag); |
| 1250 } |
| 1251 |
| 1252 switch(tag) { |
| 1253 case CONSTANT_Class: { |
| 1254 u2 name_index = get_u2be(p); |
| 1255 const_pool_in.push_back(new Constant_Class(name_index)); |
| 1256 break; |
| 1257 } |
| 1258 case CONSTANT_FieldRef: |
| 1259 case CONSTANT_Methodref: |
| 1260 case CONSTANT_Interfacemethodref: { |
| 1261 u2 class_index = get_u2be(p); |
| 1262 u2 nti = get_u2be(p); |
| 1263 const_pool_in.push_back(new Constant_FMIref(tag, class_index, nti)); |
| 1264 break; |
| 1265 } |
| 1266 case CONSTANT_String: { |
| 1267 u2 string_index = get_u2be(p); |
| 1268 const_pool_in.push_back(new Constant_String(string_index)); |
| 1269 break; |
| 1270 } |
| 1271 case CONSTANT_NameAndType: { |
| 1272 u2 name_index = get_u2be(p); |
| 1273 u2 descriptor_index = get_u2be(p); |
| 1274 const_pool_in.push_back( |
| 1275 new Constant_NameAndType(name_index, descriptor_index)); |
| 1276 break; |
| 1277 } |
| 1278 case CONSTANT_Utf8: { |
| 1279 u2 length = get_u2be(p); |
| 1280 if (devtools_ijar::verbose) { |
| 1281 fprintf(stderr, "Utf8: \"%s\" (%d)\n", |
| 1282 std::string((const char*) p, length).c_str(), length); |
| 1283 } |
| 1284 |
| 1285 const_pool_in.push_back(new Constant_Utf8(length, p)); |
| 1286 p += length; |
| 1287 break; |
| 1288 } |
| 1289 case CONSTANT_Integer: |
| 1290 case CONSTANT_Float: { |
| 1291 u4 bytes = get_u4be(p); |
| 1292 const_pool_in.push_back(new Constant_IntegerOrFloat(tag, bytes)); |
| 1293 break; |
| 1294 } |
| 1295 case CONSTANT_Long: |
| 1296 case CONSTANT_Double: { |
| 1297 u4 high_bytes = get_u4be(p); |
| 1298 u4 low_bytes = get_u4be(p); |
| 1299 const_pool_in.push_back( |
| 1300 new Constant_LongOrDouble(tag, high_bytes, low_bytes)); |
| 1301 // Longs and doubles occupy two constant pool slots. |
| 1302 // ("In retrospect, making 8-byte constants take two "constant |
| 1303 // pool entries was a poor choice." --JVM Spec.) |
| 1304 const_pool_in.push_back(NULL); |
| 1305 ii++; |
| 1306 break; |
| 1307 } |
| 1308 case CONSTANT_MethodHandle: { |
| 1309 u1 reference_kind = get_u1(p); |
| 1310 u2 reference_index = get_u2be(p); |
| 1311 const_pool_in.push_back( |
| 1312 new Constant_MethodHandle(reference_kind, reference_index)); |
| 1313 break; |
| 1314 } |
| 1315 case CONSTANT_MethodType: { |
| 1316 u2 descriptor_index = get_u2be(p); |
| 1317 const_pool_in.push_back(new Constant_MethodType(descriptor_index)); |
| 1318 break; |
| 1319 } |
| 1320 case CONSTANT_InvokeDynamic: { |
| 1321 u2 bootstrap_method_attr = get_u2be(p); |
| 1322 u2 name_name_type_index = get_u2be(p); |
| 1323 const_pool_in.push_back(new Constant_InvokeDynamic( |
| 1324 bootstrap_method_attr, name_name_type_index)); |
| 1325 break; |
| 1326 } |
| 1327 default: { |
| 1328 fprintf(stderr, "Unknown constant: %02x. Passing class through.\n", |
| 1329 tag); |
| 1330 return false; |
| 1331 } |
| 1332 } |
| 1333 } |
| 1334 |
| 1335 return true; |
| 1336 } |
| 1337 |
| 1338 // Anonymous inner classes are stripped to opaque classes that only extend |
| 1339 // Object. None of their methods or fields are accessible anyway. |
| 1340 void ClassFile::StripIfAnonymous() { |
| 1341 int enclosing_index = -1; |
| 1342 int inner_classes_index = -1; |
| 1343 |
| 1344 for (size_t ii = 0; ii < attributes.size(); ++ii) { |
| 1345 if (attributes[ii]->attribute_name_->Display() == "EnclosingMethod") { |
| 1346 enclosing_index = ii; |
| 1347 } else if (attributes[ii]->attribute_name_->Display() == "InnerClasses") { |
| 1348 inner_classes_index = ii; |
| 1349 } |
| 1350 } |
| 1351 |
| 1352 // Presence of an EnclosingMethod attribute indicates a local or anonymous |
| 1353 // class, which can be stripped. |
| 1354 if (enclosing_index > -1) { |
| 1355 // Clear the signature to only extend java.lang.Object. |
| 1356 super_class = NULL; |
| 1357 interfaces.clear(); |
| 1358 |
| 1359 // Clear away all fields (implementation details). |
| 1360 for (size_t ii = 0; ii < fields.size(); ++ii) { |
| 1361 delete fields[ii]; |
| 1362 } |
| 1363 fields.clear(); |
| 1364 |
| 1365 // Clear away all methods (implementation details). |
| 1366 for (size_t ii = 0; ii < methods.size(); ++ii) { |
| 1367 delete methods[ii]; |
| 1368 } |
| 1369 methods.clear(); |
| 1370 |
| 1371 // Only preserve the InnerClasses attribute to comply with the spec. |
| 1372 Attribute *attr = NULL; |
| 1373 for (size_t ii = 0; ii < attributes.size(); ++ii) { |
| 1374 if (static_cast<int>(ii) != inner_classes_index) { |
| 1375 delete attributes[ii]; |
| 1376 } else { |
| 1377 attr = attributes[ii]; |
| 1378 } |
| 1379 } |
| 1380 attributes.clear(); |
| 1381 if (attr != NULL) { |
| 1382 attributes.push_back(attr); |
| 1383 } |
| 1384 } |
| 1385 } |
| 1386 |
| 1387 static ClassFile *ReadClass(const void *classdata, size_t length) { |
| 1388 const u1 *p = (u1*) classdata; |
| 1389 |
| 1390 ClassFile *clazz = new ClassFile; |
| 1391 |
| 1392 clazz->length = length; |
| 1393 |
| 1394 clazz->magic = get_u4be(p); |
| 1395 if (clazz->magic != 0xCAFEBABE) { |
| 1396 fprintf(stderr, "Bad magic %" PRIx32 "\n", clazz->magic); |
| 1397 abort(); |
| 1398 } |
| 1399 clazz->major = get_u2be(p); |
| 1400 clazz->minor = get_u2be(p); |
| 1401 |
| 1402 if (!clazz->ReadConstantPool(p)) { |
| 1403 delete clazz; |
| 1404 return NULL; |
| 1405 } |
| 1406 |
| 1407 clazz->access_flags = get_u2be(p); |
| 1408 clazz->this_class = constant(get_u2be(p)); |
| 1409 u2 super_class_id = get_u2be(p); |
| 1410 clazz->super_class = super_class_id == 0 ? NULL : constant(super_class_id); |
| 1411 |
| 1412 u2 interfaces_count = get_u2be(p); |
| 1413 for (int ii = 0; ii < interfaces_count; ++ii) { |
| 1414 clazz->interfaces.push_back(constant(get_u2be(p))); |
| 1415 } |
| 1416 |
| 1417 u2 fields_count = get_u2be(p); |
| 1418 for (int ii = 0; ii < fields_count; ++ii) { |
| 1419 Member *field = Member::Read(p); |
| 1420 |
| 1421 if (!(field->access_flags & ACC_PRIVATE)) { // drop private fields |
| 1422 clazz->fields.push_back(field); |
| 1423 } |
| 1424 } |
| 1425 |
| 1426 u2 methods_count = get_u2be(p); |
| 1427 for (int ii = 0; ii < methods_count; ++ii) { |
| 1428 Member *method = Member::Read(p); |
| 1429 |
| 1430 // drop class initializers |
| 1431 if (method->name->Display() == "<clinit>") continue; |
| 1432 |
| 1433 if (!(method->access_flags & ACC_PRIVATE)) { // drop private methods |
| 1434 clazz->methods.push_back(method); |
| 1435 } |
| 1436 } |
| 1437 |
| 1438 clazz->ReadAttrs(p); |
| 1439 clazz->StripIfAnonymous(); |
| 1440 |
| 1441 return clazz; |
| 1442 } |
| 1443 |
| 1444 void ClassFile::WriteClass(u1 *&p) { |
| 1445 // We have to write the body out before the header in order to reference |
| 1446 // the essential constants and populate the output constant pool: |
| 1447 u1 *body = new u1[length]; |
| 1448 u1 *q = body; |
| 1449 WriteBody(q); // advances q |
| 1450 u4 body_length = q - body; |
| 1451 |
| 1452 WriteHeader(p); // advances p |
| 1453 put_n(p, body, body_length); |
| 1454 delete[] body; |
| 1455 } |
| 1456 |
| 1457 |
| 1458 void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) { |
| 1459 ClassFile *clazz = ReadClass(classdata_in, in_length); |
| 1460 if (clazz == NULL) { |
| 1461 // Class is invalid. Simply copy it to the output and call it a day. |
| 1462 put_n(classdata_out, classdata_in, in_length); |
| 1463 } else { |
| 1464 |
| 1465 // Constant pool item zero is a dummy entry. Setting it marks the |
| 1466 // beginning of the output phase; calls to Constant::slot() will |
| 1467 // fail if called prior to this. |
| 1468 const_pool_out.push_back(NULL); |
| 1469 |
| 1470 // TODO(bazel-team): We should only keep classes in the InnerClass attribute
s |
| 1471 // if they're used in the output. The entries can then be cleaned out of the |
| 1472 // constant pool in the normal way. |
| 1473 |
| 1474 clazz->WriteClass(classdata_out); |
| 1475 |
| 1476 delete clazz; |
| 1477 } |
| 1478 |
| 1479 // Now clean up all the mess we left behind. |
| 1480 |
| 1481 for (size_t i = 0; i < const_pool_in.size(); i++) { |
| 1482 delete const_pool_in[i]; |
| 1483 } |
| 1484 |
| 1485 const_pool_in.clear(); |
| 1486 const_pool_out.clear(); |
| 1487 } |
| 1488 |
| 1489 } // namespace devtools_ijar |
OLD | NEW |