OLD | NEW |
1 // Copyright 2001,2007 Alan Donovan. All rights reserved. | 1 // Copyright 2015 The Bazel Authors. All rights reserved. |
2 // | 2 // |
3 // Author: Alan Donovan <adonovan@google.com> | |
4 // | |
5 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
6 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
7 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
8 // | 6 // |
9 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
10 // | 8 // |
11 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
12 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
(...skipping 12 matching lines...) Expand all Loading... |
27 // http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4 | 25 // http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4 |
28 | 26 |
29 #define __STDC_FORMAT_MACROS 1 | 27 #define __STDC_FORMAT_MACROS 1 |
30 #define __STDC_LIMIT_MACROS 1 | 28 #define __STDC_LIMIT_MACROS 1 |
31 #include <inttypes.h> // for PRIx32 | 29 #include <inttypes.h> // for PRIx32 |
32 #include <stddef.h> | 30 #include <stddef.h> |
33 #include <stdio.h> | 31 #include <stdio.h> |
34 #include <stdlib.h> | 32 #include <stdlib.h> |
35 #include <string.h> | 33 #include <string.h> |
36 | 34 |
| 35 #include <set> |
| 36 #include <sstream> |
37 #include <string> | 37 #include <string> |
38 #include <vector> | 38 #include <vector> |
39 | 39 |
40 #include "third_party/ijar/common.h" | 40 #include "third_party/ijar/common.h" |
41 | 41 |
| 42 namespace { |
| 43 // Converts a value to string. |
| 44 // Workaround for mingw where std::to_string is not implemented. |
| 45 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52015. |
| 46 template <typename T> |
| 47 std::string ToString(const T& value) { |
| 48 std::ostringstream oss; |
| 49 oss << value; |
| 50 return oss.str(); |
| 51 } |
| 52 } // namespace |
| 53 |
42 namespace devtools_ijar { | 54 namespace devtools_ijar { |
43 | 55 |
44 // See Table 4.3 in JVM Spec. | 56 // See Table 4.3 in JVM Spec. |
45 enum CONSTANT { | 57 enum CONSTANT { |
46 CONSTANT_Class = 7, | 58 CONSTANT_Class = 7, |
47 CONSTANT_FieldRef = 9, | 59 CONSTANT_FieldRef = 9, |
48 CONSTANT_Methodref = 10, | 60 CONSTANT_Methodref = 10, |
49 CONSTANT_Interfacemethodref = 11, | 61 CONSTANT_Interfacemethodref = 11, |
50 CONSTANT_String = 8, | 62 CONSTANT_String = 8, |
51 CONSTANT_Integer = 3, | 63 CONSTANT_Integer = 3, |
52 CONSTANT_Float = 4, | 64 CONSTANT_Float = 4, |
53 CONSTANT_Long = 5, | 65 CONSTANT_Long = 5, |
54 CONSTANT_Double = 6, | 66 CONSTANT_Double = 6, |
55 CONSTANT_NameAndType = 12, | 67 CONSTANT_NameAndType = 12, |
56 CONSTANT_Utf8 = 1, | 68 CONSTANT_Utf8 = 1, |
57 CONSTANT_MethodHandle = 15, | 69 CONSTANT_MethodHandle = 15, |
58 CONSTANT_MethodType = 16, | 70 CONSTANT_MethodType = 16, |
59 CONSTANT_InvokeDynamic = 18 | 71 CONSTANT_InvokeDynamic = 18 |
60 }; | 72 }; |
61 | 73 |
62 // See Tables 4.1, 4.4, 4.5 in JVM Spec. | 74 // See Tables 4.1, 4.4, 4.5 in JVM Spec. |
63 enum ACCESS { | 75 enum ACCESS { |
64 ACC_PUBLIC = 0x0001, | 76 ACC_PUBLIC = 0x0001, |
65 ACC_PRIVATE = 0x0002, | 77 ACC_PRIVATE = 0x0002, |
66 ACC_PROTECTED = 0x0004, | 78 ACC_PROTECTED = 0x0004, |
67 ACC_STATIC = 0x0008, | 79 ACC_STATIC = 0x0008, |
68 ACC_FINAL = 0x0010, | 80 ACC_FINAL = 0x0010, |
69 ACC_SYNCHRONIZED = 0x0020, | 81 ACC_SYNCHRONIZED = 0x0020, |
70 ACC_VOLATILE = 0x0040, | 82 ACC_BRIDGE = 0x0040, |
71 ACC_TRANSIENT = 0x0080, | 83 ACC_VOLATILE = 0x0040, |
72 ACC_INTERFACE = 0x0200, | 84 ACC_TRANSIENT = 0x0080, |
73 ACC_ABSTRACT = 0x0400 | 85 ACC_INTERFACE = 0x0200, |
| 86 ACC_ABSTRACT = 0x0400, |
| 87 ACC_SYNTHETIC = 0x1000 |
74 }; | 88 }; |
75 | 89 |
76 // See Table 4.7.20-A in Java 8 JVM Spec. | 90 // See Table 4.7.20-A in Java 8 JVM Spec. |
77 enum TARGET_TYPE { | 91 enum TARGET_TYPE { |
78 // Targets for type parameter declarations (ElementType.TYPE_PARAMETER): | 92 // Targets for type parameter declarations (ElementType.TYPE_PARAMETER): |
79 CLASS_TYPE_PARAMETER = 0x00, | 93 CLASS_TYPE_PARAMETER = 0x00, |
80 METHOD_TYPE_PARAMETER = 0x01, | 94 METHOD_TYPE_PARAMETER = 0x01, |
81 | 95 |
82 // Targets for type uses that may be externally visible in classes and members | 96 // Targets for type uses that may be externally visible in classes and members |
83 // (ElementType.TYPE_USE): | 97 // (ElementType.TYPE_USE): |
84 CLASS_EXTENDS = 0x10, | 98 CLASS_EXTENDS = 0x10, |
85 CLASS_TYPE_PARAMETER_BOUND = 0x11, | 99 CLASS_TYPE_PARAMETER_BOUND = 0x11, |
86 METHOD_TYPE_PARAMETER_BOUND = 0x12, | 100 METHOD_TYPE_PARAMETER_BOUND = 0x12, |
87 FIELD = 0x13, | 101 FIELD = 0x13, |
88 METHOD_RETURN = 0x14, | 102 METHOD_RETURN = 0x14, |
89 METHOD_RECEIVER = 0x15, | 103 METHOD_RECEIVER = 0x15, |
90 METHOD_FORMAL_PARAMETER = 0x16, | 104 METHOD_FORMAL_PARAMETER = 0x16, |
91 THROWS = 0x17, | 105 THROWS = 0x17, |
92 | 106 |
93 // TARGET_TYPE >= 0x40 is reserved for type uses that occur only within code | 107 // TARGET_TYPE >= 0x40 is reserved for type uses that occur only within code |
94 // blocks. Ijar doesn't need to know about these. | 108 // blocks. Ijar doesn't need to know about these. |
95 }; | 109 }; |
96 | 110 |
97 struct Constant; | 111 struct Constant; |
98 | 112 |
99 // TODO(adonovan) these globals are unfortunate | 113 // TODO(adonovan) these globals are unfortunate |
100 static std::vector<Constant*> const_pool_in; // input constant pool | 114 static std::vector<Constant*> const_pool_in; // input constant pool |
101 static std::vector<Constant*> const_pool_out; // output constant_pool | 115 static std::vector<Constant*> const_pool_out; // output constant_pool |
| 116 static std::set<std::string> used_class_names; |
| 117 static Constant * class_name; |
102 | 118 |
103 // Returns the Constant object, given an index into the input constant pool. | 119 // Returns the Constant object, given an index into the input constant pool. |
104 // Note: constant(0) == NULL; this invariant is exploited by the | 120 // Note: constant(0) == NULL; this invariant is exploited by the |
105 // InnerClassesAttribute, inter alia. | 121 // InnerClassesAttribute, inter alia. |
106 inline Constant *constant(int idx) { | 122 inline Constant *constant(int idx) { |
107 if (idx < 0 || (unsigned)idx >= const_pool_in.size()) { | 123 if (idx < 0 || (unsigned)idx >= const_pool_in.size()) { |
108 fprintf(stderr, "Illegal constant pool index: %d\n", idx); | 124 fprintf(stderr, "Illegal constant pool index: %d\n", idx); |
109 abort(); | 125 abort(); |
110 } | 126 } |
111 return const_pool_in[idx]; | 127 return const_pool_in[idx]; |
(...skipping 19 matching lines...) Expand all Loading... |
131 virtual std::string Display() = 0; | 147 virtual std::string Display() = 0; |
132 | 148 |
133 virtual void Write(u1 *&p) = 0; | 149 virtual void Write(u1 *&p) = 0; |
134 | 150 |
135 // Called by slot() when a constant has been identified as required | 151 // Called by slot() when a constant has been identified as required |
136 // in the output classfile's constant pool. This is a hook allowing | 152 // in the output classfile's constant pool. This is a hook allowing |
137 // constants to register their dependency on other constants, by | 153 // constants to register their dependency on other constants, by |
138 // calling slot() on them in turn. | 154 // calling slot() on them in turn. |
139 virtual void Keep() {} | 155 virtual void Keep() {} |
140 | 156 |
| 157 bool Kept() { |
| 158 return slot_ != 0; |
| 159 } |
| 160 |
141 // Returns the index of this constant in the output class's constant | 161 // Returns the index of this constant in the output class's constant |
142 // pool, assigning a slot if not already done. | 162 // pool, assigning a slot if not already done. |
143 u2 slot() { | 163 u2 slot() { |
144 if (slot_ == 0) { | 164 if (slot_ == 0) { |
145 Keep(); | 165 Keep(); |
146 slot_ = const_pool_out.size(); // BugBot's "narrowing" warning | 166 slot_ = const_pool_out.size(); // BugBot's "narrowing" warning |
147 // is bogus. The number of | 167 // is bogus. The number of |
148 // output constants can't exceed | 168 // output constants can't exceed |
149 // the number of input constants. | 169 // the number of input constants. |
150 if (slot_ == 0) { | 170 if (slot_ == 0) { |
151 fprintf(stderr, "Constant::slot() called before output phase.\n"); | 171 fprintf(stderr, "Constant::slot() called before output phase.\n"); |
152 abort(); | 172 abort(); |
153 } | 173 } |
154 const_pool_out.push_back(this); | 174 const_pool_out.push_back(this); |
155 if (tag_ == CONSTANT_Long || tag_ == CONSTANT_Double) { | 175 if (tag_ == CONSTANT_Long || tag_ == CONSTANT_Double) { |
156 const_pool_out.push_back(NULL); | 176 const_pool_out.push_back(NULL); |
157 } | 177 } |
158 } | 178 } |
159 return slot_; | 179 return slot_; |
160 } | 180 } |
161 | 181 |
162 u2 slot_; // zero => "this constant is unreachable garbage" | 182 u2 slot_; // zero => "this constant is unreachable garbage" |
163 u1 tag_; | 183 u1 tag_; |
164 }; | 184 }; |
165 | 185 |
| 186 // Extracts class names from a signature and puts them into the global |
| 187 // variable used_class_names. |
| 188 // |
| 189 // desc: the descriptor class names should be extracted from. |
| 190 // p: the position where the extraction should tart. |
| 191 void ExtractClassNames(const std::string& desc, size_t* p); |
| 192 |
166 // See sec.4.4.1 of JVM spec. | 193 // See sec.4.4.1 of JVM spec. |
167 struct Constant_Class : Constant | 194 struct Constant_Class : Constant |
168 { | 195 { |
169 Constant_Class(u2 name_index) : | 196 Constant_Class(u2 name_index) : |
170 Constant(CONSTANT_Class), | 197 Constant(CONSTANT_Class), |
171 name_index_(name_index) {} | 198 name_index_(name_index) {} |
172 | 199 |
173 void Write(u1 *&p) { | 200 void Write(u1 *&p) { |
174 put_u1(p, tag_); | 201 put_u1(p, tag_); |
175 put_u2be(p, constant(name_index_)->slot()); | 202 put_u2be(p, constant(name_index_)->slot()); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 reference_kind_(reference_kind), | 355 reference_kind_(reference_kind), |
329 reference_index_(reference_index) {} | 356 reference_index_(reference_index) {} |
330 | 357 |
331 void Write(u1 *&p) { | 358 void Write(u1 *&p) { |
332 put_u1(p, tag_); | 359 put_u1(p, tag_); |
333 put_u1(p, reference_kind_); | 360 put_u1(p, reference_kind_); |
334 put_u2be(p, reference_index_); | 361 put_u2be(p, reference_index_); |
335 } | 362 } |
336 | 363 |
337 std::string Display() { | 364 std::string Display() { |
338 return "Constant_MethodHandle::" + std::to_string(reference_kind_) + "::" | 365 return "Constant_MethodHandle::" + ToString(reference_kind_) + "::" |
339 + constant(reference_index_)->Display(); | 366 + constant(reference_index_)->Display(); |
340 } | 367 } |
341 | 368 |
342 u1 reference_kind_; | 369 u1 reference_kind_; |
343 u2 reference_index_; | 370 u2 reference_index_; |
344 }; | 371 }; |
345 | 372 |
346 // See sec.4.4.9 of JVM spec. | 373 // See sec.4.4.9 of JVM spec. |
347 struct Constant_MethodType : Constant | 374 struct Constant_MethodType : Constant |
348 { | 375 { |
(...skipping 22 matching lines...) Expand all Loading... |
371 name_and_type_index_(name_and_type_index) {} | 398 name_and_type_index_(name_and_type_index) {} |
372 | 399 |
373 void Write(u1 *&p) { | 400 void Write(u1 *&p) { |
374 put_u1(p, tag_); | 401 put_u1(p, tag_); |
375 put_u2be(p, bootstrap_method_attr_index_); | 402 put_u2be(p, bootstrap_method_attr_index_); |
376 put_u2be(p, name_and_type_index_); | 403 put_u2be(p, name_and_type_index_); |
377 } | 404 } |
378 | 405 |
379 std::string Display() { | 406 std::string Display() { |
380 return "Constant_InvokeDynamic::" | 407 return "Constant_InvokeDynamic::" |
381 + std::to_string(bootstrap_method_attr_index_) + "::" | 408 + ToString(bootstrap_method_attr_index_) + "::" |
382 + constant(name_and_type_index_)->Display(); | 409 + constant(name_and_type_index_)->Display(); |
383 } | 410 } |
384 | 411 |
385 u2 bootstrap_method_attr_index_; | 412 u2 bootstrap_method_attr_index_; |
386 u2 name_and_type_index_; | 413 u2 name_and_type_index_; |
387 }; | 414 }; |
388 | 415 |
389 /********************************************************************** | 416 /********************************************************************** |
390 * * | 417 * * |
391 * Attributes * | 418 * Attributes * |
392 * * | 419 * * |
393 **********************************************************************/ | 420 **********************************************************************/ |
394 | 421 |
395 // See sec.4.7 of JVM spec. | 422 // See sec.4.7 of JVM spec. |
396 struct Attribute { | 423 struct Attribute { |
397 | 424 |
398 virtual ~Attribute() {} | 425 virtual ~Attribute() {} |
399 virtual void Write(u1 *&p) = 0; | 426 virtual void Write(u1 *&p) = 0; |
| 427 virtual void ExtractClassNames() {} |
400 | 428 |
401 void WriteProlog(u1 *&p, u2 length) { | 429 void WriteProlog(u1 *&p, u2 length) { |
402 put_u2be(p, attribute_name_->slot()); | 430 put_u2be(p, attribute_name_->slot()); |
403 put_u4be(p, length); | 431 put_u4be(p, length); |
404 } | 432 } |
405 | 433 |
406 Constant *attribute_name_; | 434 Constant *attribute_name_; |
407 }; | 435 }; |
408 | 436 |
409 // See sec.4.7.5 of JVM spec. | 437 // See sec.4.7.5 of JVM spec. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 entry->outer_class_info = constant(get_u2be(p)); | 485 entry->outer_class_info = constant(get_u2be(p)); |
458 entry->inner_name = constant(get_u2be(p)); | 486 entry->inner_name = constant(get_u2be(p)); |
459 entry->inner_class_access_flags = get_u2be(p); | 487 entry->inner_class_access_flags = get_u2be(p); |
460 | 488 |
461 attr->entries_.push_back(entry); | 489 attr->entries_.push_back(entry); |
462 } | 490 } |
463 return attr; | 491 return attr; |
464 } | 492 } |
465 | 493 |
466 void Write(u1 *&p) { | 494 void Write(u1 *&p) { |
467 WriteProlog(p, 2 + entries_.size() * 8); | 495 std::set<int> kept_entries; |
468 put_u2be(p, entries_.size()); | 496 // We keep an entry if the constant referring to the inner class is already |
469 for (size_t ii = 0; ii < entries_.size(); ++ii) { | 497 // kept. Then we mark its outer class and its class name as kept, too, then |
470 Entry *entry = entries_[ii]; | 498 // iterate until a fixed point is reached. |
| 499 int entry_count; |
| 500 int iteration = 0; |
| 501 |
| 502 do { |
| 503 entry_count = kept_entries.size(); |
| 504 for (int i_entry = 0; i_entry < static_cast<int>(entries_.size()); |
| 505 ++i_entry) { |
| 506 Entry* entry = entries_[i_entry]; |
| 507 if (entry->inner_class_info->Kept() || |
| 508 used_class_names.find(entry->inner_class_info->Display()) != |
| 509 used_class_names.end() || |
| 510 entry->outer_class_info == class_name) { |
| 511 if (entry->inner_name == NULL) { |
| 512 // JVMS 4.7.6: inner_name_index is zero iff the class is anonymous |
| 513 continue; |
| 514 } |
| 515 |
| 516 kept_entries.insert(i_entry); |
| 517 |
| 518 // JVMS 4.7.6: outer_class_info_index is zero for top-level classes |
| 519 if (entry->outer_class_info != NULL) { |
| 520 entry->outer_class_info->slot(); |
| 521 } |
| 522 |
| 523 entry->inner_name->slot(); |
| 524 } |
| 525 } |
| 526 iteration += 1; |
| 527 } while (entry_count != static_cast<int>(kept_entries.size())); |
| 528 |
| 529 if (kept_entries.size() == 0) { |
| 530 return; |
| 531 } |
| 532 |
| 533 WriteProlog(p, 2 + kept_entries.size() * 8); |
| 534 put_u2be(p, kept_entries.size()); |
| 535 |
| 536 for (std::set<int>::iterator it = kept_entries.begin(); |
| 537 it != kept_entries.end(); |
| 538 ++it) { |
| 539 Entry *entry = entries_[*it]; |
471 put_u2be(p, entry->inner_class_info == NULL | 540 put_u2be(p, entry->inner_class_info == NULL |
472 ? 0 | 541 ? 0 |
473 : entry->inner_class_info->slot()); | 542 : entry->inner_class_info->slot()); |
474 put_u2be(p, entry->outer_class_info == NULL | 543 put_u2be(p, entry->outer_class_info == NULL |
475 ? 0 | 544 ? 0 |
476 : entry->outer_class_info->slot()); | 545 : entry->outer_class_info->slot()); |
477 put_u2be(p, entry->inner_name == NULL | 546 put_u2be(p, entry->inner_name == NULL |
478 ? 0 | 547 ? 0 |
479 : entry->inner_name->slot()); | 548 : entry->inner_name->slot()); |
480 put_u2be(p, entry->inner_class_access_flags); | 549 put_u2be(p, entry->inner_class_access_flags); |
(...skipping 28 matching lines...) Expand all Loading... |
509 | 578 |
510 Constant *class_; | 579 Constant *class_; |
511 Constant *method_; | 580 Constant *method_; |
512 }; | 581 }; |
513 | 582 |
514 // See sec.4.7.16.1 of JVM spec. | 583 // See sec.4.7.16.1 of JVM spec. |
515 // Used by AnnotationDefault and other attributes. | 584 // Used by AnnotationDefault and other attributes. |
516 struct ElementValue { | 585 struct ElementValue { |
517 virtual ~ElementValue() {} | 586 virtual ~ElementValue() {} |
518 virtual void Write(u1 *&p) = 0; | 587 virtual void Write(u1 *&p) = 0; |
| 588 virtual void ExtractClassNames() {} |
519 static ElementValue* Read(const u1 *&p); | 589 static ElementValue* Read(const u1 *&p); |
520 u1 tag_; | 590 u1 tag_; |
521 u4 length_; | 591 u4 length_; |
522 }; | 592 }; |
523 | 593 |
524 struct BaseTypeElementValue : ElementValue { | 594 struct BaseTypeElementValue : ElementValue { |
525 void Write(u1 *&p) { | 595 void Write(u1 *&p) { |
526 put_u1(p, tag_); | 596 put_u1(p, tag_); |
527 put_u2be(p, const_value_->slot()); | 597 put_u2be(p, const_value_->slot()); |
528 } | 598 } |
(...skipping 19 matching lines...) Expand all Loading... |
548 } | 618 } |
549 Constant *type_name_; | 619 Constant *type_name_; |
550 Constant *const_name_; | 620 Constant *const_name_; |
551 }; | 621 }; |
552 | 622 |
553 struct ClassTypeElementValue : ElementValue { | 623 struct ClassTypeElementValue : ElementValue { |
554 void Write(u1 *&p) { | 624 void Write(u1 *&p) { |
555 put_u1(p, tag_); | 625 put_u1(p, tag_); |
556 put_u2be(p, class_info_->slot()); | 626 put_u2be(p, class_info_->slot()); |
557 } | 627 } |
| 628 |
| 629 virtual void ExtractClassNames() { |
| 630 size_t idx = 0; |
| 631 devtools_ijar::ExtractClassNames(class_info_->Display(), &idx); |
| 632 } |
| 633 |
558 static ClassTypeElementValue *Read(const u1 *&p) { | 634 static ClassTypeElementValue *Read(const u1 *&p) { |
559 ClassTypeElementValue *value = new ClassTypeElementValue; | 635 ClassTypeElementValue *value = new ClassTypeElementValue; |
560 value->class_info_ = constant(get_u2be(p)); | 636 value->class_info_ = constant(get_u2be(p)); |
561 return value; | 637 return value; |
562 } | 638 } |
563 Constant *class_info_; | 639 Constant *class_info_; |
564 }; | 640 }; |
565 | 641 |
566 struct ArrayTypeElementValue : ElementValue { | 642 struct ArrayTypeElementValue : ElementValue { |
567 virtual ~ArrayTypeElementValue() { | 643 virtual ~ArrayTypeElementValue() { |
568 for (size_t i = 0; i < values_.size(); i++) { | 644 for (const auto *value : values_) { |
569 delete values_[i]; | 645 delete value; |
| 646 } |
| 647 } |
| 648 |
| 649 virtual void ExtractClassNames() { |
| 650 for (auto *value : values_) { |
| 651 value->ExtractClassNames(); |
570 } | 652 } |
571 } | 653 } |
572 | 654 |
573 void Write(u1 *&p) { | 655 void Write(u1 *&p) { |
574 put_u1(p, tag_); | 656 put_u1(p, tag_); |
575 put_u2be(p, values_.size()); | 657 put_u2be(p, values_.size()); |
576 for (size_t ii = 0; ii < values_.size(); ++ii) { | 658 for (auto *value : values_) { |
577 values_[ii]->Write(p); | 659 value->Write(p); |
578 } | 660 } |
579 } | 661 } |
580 static ArrayTypeElementValue *Read(const u1 *&p) { | 662 static ArrayTypeElementValue *Read(const u1 *&p) { |
581 ArrayTypeElementValue *value = new ArrayTypeElementValue; | 663 ArrayTypeElementValue *value = new ArrayTypeElementValue; |
582 u2 num_values = get_u2be(p); | 664 u2 num_values = get_u2be(p); |
583 for (int ii = 0; ii < num_values; ++ii) { | 665 for (int ii = 0; ii < num_values; ++ii) { |
584 value->values_.push_back(ElementValue::Read(p)); | 666 value->values_.push_back(ElementValue::Read(p)); |
585 } | 667 } |
586 return value; | 668 return value; |
587 } | 669 } |
588 std::vector<ElementValue*> values_; | 670 std::vector<ElementValue*> values_; |
589 }; | 671 }; |
590 | 672 |
591 // See sec.4.7.16 of JVM spec. | 673 // See sec.4.7.16 of JVM spec. |
592 struct Annotation { | 674 struct Annotation { |
593 virtual ~Annotation() { | 675 virtual ~Annotation() { |
594 for (size_t i = 0; i < element_value_pairs_.size(); i++) { | 676 for (size_t i = 0; i < element_value_pairs_.size(); i++) { |
595 delete element_value_pairs_[i]->element_value_; | 677 delete element_value_pairs_[i]->element_value_; |
596 delete element_value_pairs_[i]; | 678 delete element_value_pairs_[i]; |
597 } | 679 } |
598 } | 680 } |
599 | 681 |
| 682 void ExtractClassNames() { |
| 683 for (size_t i = 0; i < element_value_pairs_.size(); i++) { |
| 684 element_value_pairs_[i]->element_value_->ExtractClassNames(); |
| 685 } |
| 686 } |
| 687 |
600 void Write(u1 *&p) { | 688 void Write(u1 *&p) { |
601 put_u2be(p, type_->slot()); | 689 put_u2be(p, type_->slot()); |
602 put_u2be(p, element_value_pairs_.size()); | 690 put_u2be(p, element_value_pairs_.size()); |
603 for (size_t ii = 0; ii < element_value_pairs_.size(); ++ii) { | 691 for (size_t ii = 0; ii < element_value_pairs_.size(); ++ii) { |
604 put_u2be(p, element_value_pairs_[ii]->element_name_->slot()); | 692 put_u2be(p, element_value_pairs_[ii]->element_name_->slot()); |
605 element_value_pairs_[ii]->element_value_->Write(p); | 693 element_value_pairs_[ii]->element_value_->Write(p); |
606 } | 694 } |
607 } | 695 } |
608 static Annotation *Read(const u1 *&p) { | 696 static Annotation *Read(const u1 *&p) { |
609 Annotation *value = new Annotation; | 697 Annotation *value = new Annotation; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 // element_value_pairs[num_element_value_pairs]; | 743 // element_value_pairs[num_element_value_pairs]; |
656 // } | 744 // } |
657 // | 745 // |
658 struct TypeAnnotation { | 746 struct TypeAnnotation { |
659 virtual ~TypeAnnotation() { | 747 virtual ~TypeAnnotation() { |
660 delete target_info_; | 748 delete target_info_; |
661 delete type_path_; | 749 delete type_path_; |
662 delete annotation_; | 750 delete annotation_; |
663 } | 751 } |
664 | 752 |
| 753 void ExtractClassNames() { |
| 754 annotation_->ExtractClassNames(); |
| 755 } |
| 756 |
665 void Write(u1 *&p) { | 757 void Write(u1 *&p) { |
666 put_u1(p, target_type_); | 758 put_u1(p, target_type_); |
667 target_info_->Write(p); | 759 target_info_->Write(p); |
668 type_path_->Write(p); | 760 type_path_->Write(p); |
669 annotation_->Write(p); | 761 annotation_->Write(p); |
670 } | 762 } |
671 | 763 |
672 static TypeAnnotation *Read(const u1 *&p) { | 764 static TypeAnnotation *Read(const u1 *&p) { |
673 TypeAnnotation *value = new TypeAnnotation; | 765 TypeAnnotation *value = new TypeAnnotation; |
674 value->target_type_ = get_u1(p); | 766 value->target_type_ = get_u1(p); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 attr->attribute_name_ = attribute_name; | 958 attr->attribute_name_ = attribute_name; |
867 attr->default_value_ = ElementValue::Read(p); | 959 attr->default_value_ = ElementValue::Read(p); |
868 return attr; | 960 return attr; |
869 } | 961 } |
870 | 962 |
871 void Write(u1 *&p) { | 963 void Write(u1 *&p) { |
872 WriteProlog(p, default_value_->length_); | 964 WriteProlog(p, default_value_->length_); |
873 default_value_->Write(p); | 965 default_value_->Write(p); |
874 } | 966 } |
875 | 967 |
| 968 virtual void ExtractClassNames() { |
| 969 default_value_->ExtractClassNames(); |
| 970 } |
| 971 |
876 ElementValue *default_value_; | 972 ElementValue *default_value_; |
877 }; | 973 }; |
878 | 974 |
879 // See sec.4.7.2 of JVM spec. | 975 // See sec.4.7.2 of JVM spec. |
880 // We preserve ConstantValue attributes because they are required for | 976 // We preserve ConstantValue attributes because they are required for |
881 // compile-time constant propagation. | 977 // compile-time constant propagation. |
882 struct ConstantValueAttribute : Attribute { | 978 struct ConstantValueAttribute : Attribute { |
883 | 979 |
884 static ConstantValueAttribute* Read(const u1 *&p, Constant *attribute_name) { | 980 static ConstantValueAttribute* Read(const u1 *&p, Constant *attribute_name) { |
885 ConstantValueAttribute *attr = new ConstantValueAttribute; | 981 ConstantValueAttribute *attr = new ConstantValueAttribute; |
(...skipping 20 matching lines...) Expand all Loading... |
906 attr->attribute_name_ = attribute_name; | 1002 attr->attribute_name_ = attribute_name; |
907 attr->signature_ = constant(get_u2be(p)); | 1003 attr->signature_ = constant(get_u2be(p)); |
908 return attr; | 1004 return attr; |
909 } | 1005 } |
910 | 1006 |
911 void Write(u1 *&p) { | 1007 void Write(u1 *&p) { |
912 WriteProlog(p, 2); | 1008 WriteProlog(p, 2); |
913 put_u2be(p, signature_->slot()); | 1009 put_u2be(p, signature_->slot()); |
914 } | 1010 } |
915 | 1011 |
| 1012 virtual void ExtractClassNames() { |
| 1013 size_t signature_idx = 0; |
| 1014 devtools_ijar::ExtractClassNames(signature_->Display(), &signature_idx); |
| 1015 } |
| 1016 |
916 Constant *signature_; | 1017 Constant *signature_; |
917 }; | 1018 }; |
918 | 1019 |
919 // See sec.4.7.15 of JVM spec. | 1020 // See sec.4.7.15 of JVM spec. |
920 // We preserve Deprecated attributes because they are required by the | 1021 // We preserve Deprecated attributes because they are required by the |
921 // compiler to generate warning messages. | 1022 // compiler to generate warning messages. |
922 struct DeprecatedAttribute : Attribute { | 1023 struct DeprecatedAttribute : Attribute { |
923 | 1024 |
924 static DeprecatedAttribute* Read(const u1 *&p, Constant *attribute_name) { | 1025 static DeprecatedAttribute* Read(const u1 *&p, Constant *attribute_name) { |
925 DeprecatedAttribute *attr = new DeprecatedAttribute; | 1026 DeprecatedAttribute *attr = new DeprecatedAttribute; |
(...skipping 21 matching lines...) Expand all Loading... |
947 AnnotationsAttribute *attr = new AnnotationsAttribute; | 1048 AnnotationsAttribute *attr = new AnnotationsAttribute; |
948 attr->attribute_name_ = attribute_name; | 1049 attr->attribute_name_ = attribute_name; |
949 u2 num_annotations = get_u2be(p); | 1050 u2 num_annotations = get_u2be(p); |
950 for (int ii = 0; ii < num_annotations; ++ii) { | 1051 for (int ii = 0; ii < num_annotations; ++ii) { |
951 Annotation *annotation = Annotation::Read(p); | 1052 Annotation *annotation = Annotation::Read(p); |
952 attr->annotations_.push_back(annotation); | 1053 attr->annotations_.push_back(annotation); |
953 } | 1054 } |
954 return attr; | 1055 return attr; |
955 } | 1056 } |
956 | 1057 |
| 1058 virtual void ExtractClassNames() { |
| 1059 for (auto *annotation : annotations_) { |
| 1060 annotation->ExtractClassNames(); |
| 1061 } |
| 1062 } |
| 1063 |
957 void Write(u1 *&p) { | 1064 void Write(u1 *&p) { |
958 WriteProlog(p, -1); | 1065 WriteProlog(p, -1); |
959 u1 *payload_start = p - 4; | 1066 u1 *payload_start = p - 4; |
960 put_u2be(p, annotations_.size()); | 1067 put_u2be(p, annotations_.size()); |
961 for (size_t ii = 0; ii < annotations_.size(); ++ii) { | 1068 for (auto *annotation : annotations_) { |
962 annotations_[ii]->Write(p); | 1069 annotation->Write(p); |
963 } | 1070 } |
964 put_u4be(payload_start, p - 4 - payload_start); // backpatch length | 1071 put_u4be(payload_start, p - 4 - payload_start); // backpatch length |
965 } | 1072 } |
966 | 1073 |
967 std::vector<Annotation*> annotations_; | 1074 std::vector<Annotation*> annotations_; |
968 }; | 1075 }; |
969 | 1076 |
970 // See sec.4.7.18-19 of JVM spec. Includes RuntimeVisible and | 1077 // See sec.4.7.18-19 of JVM spec. Includes RuntimeVisible and |
971 // RuntimeInvisible. | 1078 // RuntimeInvisible. |
972 // | 1079 // |
(...skipping 10 matching lines...) Expand all Loading... |
983 u2 num_annotations = get_u2be(p); | 1090 u2 num_annotations = get_u2be(p); |
984 for (int ii = 0; ii < num_annotations; ++ii) { | 1091 for (int ii = 0; ii < num_annotations; ++ii) { |
985 Annotation *annotation = Annotation::Read(p); | 1092 Annotation *annotation = Annotation::Read(p); |
986 annotations.push_back(annotation); | 1093 annotations.push_back(annotation); |
987 } | 1094 } |
988 attr->parameter_annotations_.push_back(annotations); | 1095 attr->parameter_annotations_.push_back(annotations); |
989 } | 1096 } |
990 return attr; | 1097 return attr; |
991 } | 1098 } |
992 | 1099 |
| 1100 virtual void ExtractClassNames() { |
| 1101 for (size_t i = 0; i < parameter_annotations_.size(); i++) { |
| 1102 const std::vector<Annotation*>& annotations = parameter_annotations_[i]; |
| 1103 for (size_t j = 0; j < annotations.size(); j++) { |
| 1104 annotations[j]->ExtractClassNames(); |
| 1105 } |
| 1106 } |
| 1107 } |
| 1108 |
993 void Write(u1 *&p) { | 1109 void Write(u1 *&p) { |
994 WriteProlog(p, -1); | 1110 WriteProlog(p, -1); |
995 u1 *payload_start = p - 4; | 1111 u1 *payload_start = p - 4; |
996 put_u1(p, parameter_annotations_.size()); | 1112 put_u1(p, parameter_annotations_.size()); |
997 for (size_t ii = 0; ii < parameter_annotations_.size(); ++ii) { | 1113 for (size_t ii = 0; ii < parameter_annotations_.size(); ++ii) { |
998 std::vector<Annotation *> &annotations = parameter_annotations_[ii]; | 1114 std::vector<Annotation *> &annotations = parameter_annotations_[ii]; |
999 put_u2be(p, annotations.size()); | 1115 put_u2be(p, annotations.size()); |
1000 for (size_t jj = 0; jj < annotations.size(); ++jj) { | 1116 for (size_t jj = 0; jj < annotations.size(); ++jj) { |
1001 annotations[jj]->Write(p); | 1117 annotations[jj]->Write(p); |
1002 } | 1118 } |
(...skipping 12 matching lines...) Expand all Loading... |
1015 auto attr = new TypeAnnotationsAttribute; | 1131 auto attr = new TypeAnnotationsAttribute; |
1016 attr->attribute_name_ = attribute_name; | 1132 attr->attribute_name_ = attribute_name; |
1017 u2 num_annotations = get_u2be(p); | 1133 u2 num_annotations = get_u2be(p); |
1018 for (int ii = 0; ii < num_annotations; ++ii) { | 1134 for (int ii = 0; ii < num_annotations; ++ii) { |
1019 TypeAnnotation *annotation = TypeAnnotation::Read(p); | 1135 TypeAnnotation *annotation = TypeAnnotation::Read(p); |
1020 attr->type_annotations_.push_back(annotation); | 1136 attr->type_annotations_.push_back(annotation); |
1021 } | 1137 } |
1022 return attr; | 1138 return attr; |
1023 } | 1139 } |
1024 | 1140 |
| 1141 virtual void ExtractClassNames() { |
| 1142 for (auto *type_annotation : type_annotations_) { |
| 1143 type_annotation->ExtractClassNames(); |
| 1144 } |
| 1145 } |
| 1146 |
1025 void Write(u1 *&p) { | 1147 void Write(u1 *&p) { |
1026 WriteProlog(p, -1); | 1148 WriteProlog(p, -1); |
1027 u1 *payload_start = p - 4; | 1149 u1 *payload_start = p - 4; |
1028 put_u2be(p, type_annotations_.size()); | 1150 put_u2be(p, type_annotations_.size()); |
1029 for (TypeAnnotation *annotation : type_annotations_) { | 1151 for (TypeAnnotation *annotation : type_annotations_) { |
1030 annotation->Write(p); | 1152 annotation->Write(p); |
1031 } | 1153 } |
1032 put_u4be(payload_start, p - 4 - payload_start); // backpatch length | 1154 put_u4be(payload_start, p - 4 - payload_start); // backpatch length |
1033 } | 1155 } |
1034 | 1156 |
1035 std::vector<TypeAnnotation*> type_annotations_; | 1157 std::vector<TypeAnnotation*> type_annotations_; |
1036 }; | 1158 }; |
1037 | 1159 |
| 1160 // See JVMS §4.7.24 |
| 1161 struct MethodParametersAttribute : Attribute { |
| 1162 static MethodParametersAttribute *Read(const u1 *&p, Constant *attribute_name, |
| 1163 u4 attribute_length) { |
| 1164 auto attr = new MethodParametersAttribute; |
| 1165 attr->attribute_name_ = attribute_name; |
| 1166 u1 parameters_count = get_u1(p); |
| 1167 for (int ii = 0; ii < parameters_count; ++ii) { |
| 1168 MethodParameter* parameter = new MethodParameter; |
| 1169 parameter->name_ = constant(get_u2be(p)); |
| 1170 parameter->access_flags_ = get_u2be(p); |
| 1171 attr->parameters_.push_back(parameter); |
| 1172 } |
| 1173 return attr; |
| 1174 } |
| 1175 |
| 1176 void Write(u1 *&p) { |
| 1177 WriteProlog(p, -1); |
| 1178 u1 *payload_start = p - 4; |
| 1179 put_u1(p, parameters_.size()); |
| 1180 for (MethodParameter* parameter : parameters_) { |
| 1181 put_u2be(p, parameter->name_->slot()); |
| 1182 put_u2be(p, parameter->access_flags_); |
| 1183 } |
| 1184 put_u4be(payload_start, p - 4 - payload_start); // backpatch length |
| 1185 } |
| 1186 |
| 1187 struct MethodParameter { |
| 1188 Constant *name_; |
| 1189 u2 access_flags_; |
| 1190 }; |
| 1191 |
| 1192 std::vector<MethodParameter*> parameters_; |
| 1193 }; |
| 1194 |
1038 struct GeneralAttribute : Attribute { | 1195 struct GeneralAttribute : Attribute { |
1039 static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name, | 1196 static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name, |
1040 u4 attribute_length) { | 1197 u4 attribute_length) { |
1041 auto attr = new GeneralAttribute; | 1198 auto attr = new GeneralAttribute; |
1042 attr->attribute_name_ = attribute_name; | 1199 attr->attribute_name_ = attribute_name; |
1043 attr->attribute_length_ = attribute_length; | 1200 attr->attribute_length_ = attribute_length; |
1044 attr->attribute_content_ = p; | 1201 attr->attribute_content_ = p; |
1045 p += attribute_length; | 1202 p += attribute_length; |
1046 return attr; | 1203 return attr; |
1047 } | 1204 } |
(...skipping 13 matching lines...) Expand all Loading... |
1061 * * | 1218 * * |
1062 **********************************************************************/ | 1219 **********************************************************************/ |
1063 | 1220 |
1064 struct HasAttrs { | 1221 struct HasAttrs { |
1065 std::vector<Attribute*> attributes; | 1222 std::vector<Attribute*> attributes; |
1066 | 1223 |
1067 void WriteAttrs(u1 *&p); | 1224 void WriteAttrs(u1 *&p); |
1068 void ReadAttrs(const u1 *&p); | 1225 void ReadAttrs(const u1 *&p); |
1069 | 1226 |
1070 virtual ~HasAttrs() { | 1227 virtual ~HasAttrs() { |
1071 for (size_t i = 0; i < attributes.size(); i++) { | 1228 for (const auto *attribute : attributes) { |
1072 delete attributes[i]; | 1229 delete attribute; |
| 1230 } |
| 1231 } |
| 1232 |
| 1233 void ExtractClassNames() { |
| 1234 for (auto *attribute : attributes) { |
| 1235 attribute->ExtractClassNames(); |
1073 } | 1236 } |
1074 } | 1237 } |
1075 }; | 1238 }; |
1076 | 1239 |
1077 // A field or method. | 1240 // A field or method. |
1078 // See sec.4.5 and 4.6 of JVM spec. | 1241 // See sec.4.5 and 4.6 of JVM spec. |
1079 struct Member : HasAttrs { | 1242 struct Member : HasAttrs { |
1080 u2 access_flags; | 1243 u2 access_flags; |
1081 Constant *name; | 1244 Constant *name; |
1082 Constant *descriptor; | 1245 Constant *descriptor; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 delete methods[i]; | 1288 delete methods[i]; |
1126 } | 1289 } |
1127 | 1290 |
1128 // Constants do not need to be deleted; they are owned by the constant pool. | 1291 // Constants do not need to be deleted; they are owned by the constant pool. |
1129 } | 1292 } |
1130 | 1293 |
1131 void WriteClass(u1 *&p); | 1294 void WriteClass(u1 *&p); |
1132 | 1295 |
1133 bool ReadConstantPool(const u1 *&p); | 1296 bool ReadConstantPool(const u1 *&p); |
1134 | 1297 |
1135 void StripIfAnonymous(); | 1298 bool IsLocalOrAnonymous(); |
1136 | 1299 |
1137 void WriteHeader(u1 *&p) { | 1300 void WriteHeader(u1 *&p) { |
1138 put_u4be(p, magic); | 1301 put_u4be(p, magic); |
1139 put_u2be(p, major); | 1302 put_u2be(p, major); |
1140 put_u2be(p, minor); | 1303 put_u2be(p, minor); |
1141 | 1304 |
1142 put_u2be(p, const_pool_out.size()); | 1305 put_u2be(p, const_pool_out.size()); |
1143 for (u2 ii = 1; ii < const_pool_out.size(); ++ii) { | 1306 for (u2 ii = 1; ii < const_pool_out.size(); ++ii) { |
1144 if (const_pool_out[ii] != NULL) { // NB: NULLs appear after long/double. | 1307 if (const_pool_out[ii] != NULL) { // NB: NULLs appear after long/double. |
1145 const_pool_out[ii]->Write(p); | 1308 const_pool_out[ii]->Write(p); |
(...skipping 10 matching lines...) Expand all Loading... |
1156 put_u2be(p, interfaces[ii]->slot()); | 1319 put_u2be(p, interfaces[ii]->slot()); |
1157 } | 1320 } |
1158 put_u2be(p, fields.size()); | 1321 put_u2be(p, fields.size()); |
1159 for (size_t ii = 0; ii < fields.size(); ++ii) { | 1322 for (size_t ii = 0; ii < fields.size(); ++ii) { |
1160 fields[ii]->Write(p); | 1323 fields[ii]->Write(p); |
1161 } | 1324 } |
1162 put_u2be(p, methods.size()); | 1325 put_u2be(p, methods.size()); |
1163 for (size_t ii = 0; ii < methods.size(); ++ii) { | 1326 for (size_t ii = 0; ii < methods.size(); ++ii) { |
1164 methods[ii]->Write(p); | 1327 methods[ii]->Write(p); |
1165 } | 1328 } |
| 1329 |
| 1330 Attribute* inner_classes = NULL; |
| 1331 |
| 1332 // Make the inner classes attribute the last, so that it can know which |
| 1333 // constants were needed |
| 1334 for (size_t ii = 0; ii < attributes.size(); ii++) { |
| 1335 if (attributes[ii]->attribute_name_->Display() == "InnerClasses") { |
| 1336 inner_classes = attributes[ii]; |
| 1337 attributes.erase(attributes.begin() + ii); |
| 1338 break; |
| 1339 } |
| 1340 } |
| 1341 |
| 1342 if (inner_classes != NULL) { |
| 1343 attributes.push_back(inner_classes); |
| 1344 } |
| 1345 |
1166 WriteAttrs(p); | 1346 WriteAttrs(p); |
1167 } | 1347 } |
1168 | 1348 |
1169 }; | 1349 }; |
1170 | 1350 |
1171 void HasAttrs::ReadAttrs(const u1 *&p) { | 1351 void HasAttrs::ReadAttrs(const u1 *&p) { |
1172 u2 attributes_count = get_u2be(p); | 1352 u2 attributes_count = get_u2be(p); |
1173 for (int ii = 0; ii < attributes_count; ii++) { | 1353 for (int ii = 0; ii < attributes_count; ii++) { |
1174 Constant *attribute_name = constant(get_u2be(p)); | 1354 Constant *attribute_name = constant(get_u2be(p)); |
1175 u4 attribute_length = get_u4be(p); | 1355 u4 attribute_length = get_u4be(p); |
1176 | 1356 |
1177 std::string attr_name = attribute_name->Display(); | 1357 std::string attr_name = attribute_name->Display(); |
1178 if (attr_name == "SourceFile" || | 1358 if (attr_name == "SourceFile" || |
| 1359 attr_name == "StackMapTable" || |
1179 attr_name == "LineNumberTable" || | 1360 attr_name == "LineNumberTable" || |
1180 attr_name == "LocalVariableTable" || | 1361 attr_name == "LocalVariableTable" || |
1181 attr_name == "LocalVariableTypeTable" || | 1362 attr_name == "LocalVariableTypeTable" || |
1182 attr_name == "Code" || | 1363 attr_name == "Code" || |
1183 attr_name == "Synthetic" || | 1364 attr_name == "Synthetic" || |
1184 attr_name == "BootstrapMethods") { | 1365 attr_name == "BootstrapMethods" || |
| 1366 attr_name == "SourceDebugExtension") { |
1185 p += attribute_length; // drop these attributes | 1367 p += attribute_length; // drop these attributes |
1186 } else if (attr_name == "Exceptions") { | 1368 } else if (attr_name == "Exceptions") { |
1187 attributes.push_back(ExceptionsAttribute::Read(p, attribute_name)); | 1369 attributes.push_back(ExceptionsAttribute::Read(p, attribute_name)); |
1188 } else if (attr_name == "Signature") { | 1370 } else if (attr_name == "Signature") { |
1189 attributes.push_back(SignatureAttribute::Read(p, attribute_name)); | 1371 attributes.push_back(SignatureAttribute::Read(p, attribute_name)); |
1190 } else if (attr_name == "Deprecated") { | 1372 } else if (attr_name == "Deprecated") { |
1191 attributes.push_back(DeprecatedAttribute::Read(p, attribute_name)); | 1373 attributes.push_back(DeprecatedAttribute::Read(p, attribute_name)); |
1192 } else if (attr_name == "EnclosingMethod") { | 1374 } else if (attr_name == "EnclosingMethod") { |
1193 attributes.push_back(EnclosingMethodAttribute::Read(p, attribute_name)); | 1375 attributes.push_back(EnclosingMethodAttribute::Read(p, attribute_name)); |
1194 } else if (attr_name == "InnerClasses") { | 1376 } else if (attr_name == "InnerClasses") { |
(...skipping 12 matching lines...) Expand all Loading... |
1207 ParameterAnnotationsAttribute::Read(p, attribute_name)); | 1389 ParameterAnnotationsAttribute::Read(p, attribute_name)); |
1208 } else if (attr_name == "Scala" || | 1390 } else if (attr_name == "Scala" || |
1209 attr_name == "ScalaSig" || | 1391 attr_name == "ScalaSig" || |
1210 attr_name == "ScalaInlineInfo") { | 1392 attr_name == "ScalaInlineInfo") { |
1211 // These are opaque blobs, so can be handled with a general | 1393 // These are opaque blobs, so can be handled with a general |
1212 // attribute handler | 1394 // attribute handler |
1213 attributes.push_back(GeneralAttribute::Read(p, attribute_name, | 1395 attributes.push_back(GeneralAttribute::Read(p, attribute_name, |
1214 attribute_length)); | 1396 attribute_length)); |
1215 } else if (attr_name == "RuntimeVisibleTypeAnnotations" || | 1397 } else if (attr_name == "RuntimeVisibleTypeAnnotations" || |
1216 attr_name == "RuntimeInvisibleTypeAnnotations") { | 1398 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, | 1399 attributes.push_back(TypeAnnotationsAttribute::Read(p, attribute_name, |
1220 attribute_length)); | 1400 attribute_length)); |
| 1401 } else if (attr_name == "MethodParameters") { |
| 1402 attributes.push_back( |
| 1403 MethodParametersAttribute::Read(p, attribute_name, attribute_length)); |
1221 } else { | 1404 } else { |
1222 // Skip over unknown attributes with a warning. The JVM spec | 1405 // Skip over unknown attributes with a warning. The JVM spec |
1223 // says this is ok, so long as we handle the mandatory attributes. | 1406 // says this is ok, so long as we handle the mandatory attributes. |
1224 fprintf(stderr, "ijar: skipping unknown attribute: \"%s\".\n", | 1407 fprintf(stderr, "ijar: skipping unknown attribute: \"%s\".\n", |
1225 attr_name.c_str()); | 1408 attr_name.c_str()); |
1226 p += attribute_length; | 1409 p += attribute_length; |
1227 } | 1410 } |
1228 } | 1411 } |
1229 } | 1412 } |
1230 | 1413 |
1231 void HasAttrs::WriteAttrs(u1 *&p) { | 1414 void HasAttrs::WriteAttrs(u1 *&p) { |
1232 put_u2be(p, attributes.size()); | 1415 u1* p_size = p; |
| 1416 |
| 1417 put_u2be(p, 0); |
| 1418 int n_written_attrs = 0; |
1233 for (size_t ii = 0; ii < attributes.size(); ii++) { | 1419 for (size_t ii = 0; ii < attributes.size(); ii++) { |
| 1420 u1* before = p; |
1234 attributes[ii]->Write(p); | 1421 attributes[ii]->Write(p); |
| 1422 if (p != before) { |
| 1423 n_written_attrs++; |
| 1424 } |
1235 } | 1425 } |
| 1426 |
| 1427 put_u2be(p_size, n_written_attrs); |
1236 } | 1428 } |
1237 | 1429 |
1238 // See sec.4.4 of JVM spec. | 1430 // See sec.4.4 of JVM spec. |
1239 bool ClassFile::ReadConstantPool(const u1 *&p) { | 1431 bool ClassFile::ReadConstantPool(const u1 *&p) { |
1240 | 1432 |
1241 const_pool_in.clear(); | 1433 const_pool_in.clear(); |
1242 const_pool_in.push_back(NULL); // dummy first item | 1434 const_pool_in.push_back(NULL); // dummy first item |
1243 | 1435 |
1244 u2 cp_count = get_u2be(p); | 1436 u2 cp_count = get_u2be(p); |
1245 for (int ii = 1; ii < cp_count; ++ii) { | 1437 for (int ii = 1; ii < cp_count; ++ii) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 fprintf(stderr, "Unknown constant: %02x. Passing class through.\n", | 1520 fprintf(stderr, "Unknown constant: %02x. Passing class through.\n", |
1329 tag); | 1521 tag); |
1330 return false; | 1522 return false; |
1331 } | 1523 } |
1332 } | 1524 } |
1333 } | 1525 } |
1334 | 1526 |
1335 return true; | 1527 return true; |
1336 } | 1528 } |
1337 | 1529 |
1338 // Anonymous inner classes are stripped to opaque classes that only extend | 1530 bool ClassFile::IsLocalOrAnonymous() { |
1339 // Object. None of their methods or fields are accessible anyway. | 1531 for (const Attribute *attribute : attributes) { |
1340 void ClassFile::StripIfAnonymous() { | 1532 if (attribute->attribute_name_->Display() == "EnclosingMethod") { |
1341 int enclosing_index = -1; | 1533 // JVMS 4.7.6: a class must has EnclosingMethod attribute iff it |
1342 int inner_classes_index = -1; | 1534 // represents a local class or an anonymous class |
1343 | 1535 return true; |
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 } | 1536 } |
1350 } | 1537 } |
1351 | 1538 return false; |
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 } | 1539 } |
1386 | 1540 |
1387 static ClassFile *ReadClass(const void *classdata, size_t length) { | 1541 static ClassFile *ReadClass(const void *classdata, size_t length) { |
1388 const u1 *p = (u1*) classdata; | 1542 const u1 *p = (u1*) classdata; |
1389 | 1543 |
1390 ClassFile *clazz = new ClassFile; | 1544 ClassFile *clazz = new ClassFile; |
1391 | 1545 |
1392 clazz->length = length; | 1546 clazz->length = length; |
1393 | 1547 |
1394 clazz->magic = get_u4be(p); | 1548 clazz->magic = get_u4be(p); |
1395 if (clazz->magic != 0xCAFEBABE) { | 1549 if (clazz->magic != 0xCAFEBABE) { |
1396 fprintf(stderr, "Bad magic %" PRIx32 "\n", clazz->magic); | 1550 fprintf(stderr, "Bad magic %" PRIx32 "\n", clazz->magic); |
1397 abort(); | 1551 abort(); |
1398 } | 1552 } |
1399 clazz->major = get_u2be(p); | 1553 clazz->major = get_u2be(p); |
1400 clazz->minor = get_u2be(p); | 1554 clazz->minor = get_u2be(p); |
1401 | 1555 |
1402 if (!clazz->ReadConstantPool(p)) { | 1556 if (!clazz->ReadConstantPool(p)) { |
1403 delete clazz; | 1557 delete clazz; |
1404 return NULL; | 1558 return NULL; |
1405 } | 1559 } |
1406 | 1560 |
1407 clazz->access_flags = get_u2be(p); | 1561 clazz->access_flags = get_u2be(p); |
1408 clazz->this_class = constant(get_u2be(p)); | 1562 clazz->this_class = constant(get_u2be(p)); |
| 1563 class_name = clazz->this_class; |
| 1564 |
1409 u2 super_class_id = get_u2be(p); | 1565 u2 super_class_id = get_u2be(p); |
1410 clazz->super_class = super_class_id == 0 ? NULL : constant(super_class_id); | 1566 clazz->super_class = super_class_id == 0 ? NULL : constant(super_class_id); |
1411 | 1567 |
1412 u2 interfaces_count = get_u2be(p); | 1568 u2 interfaces_count = get_u2be(p); |
1413 for (int ii = 0; ii < interfaces_count; ++ii) { | 1569 for (int ii = 0; ii < interfaces_count; ++ii) { |
1414 clazz->interfaces.push_back(constant(get_u2be(p))); | 1570 clazz->interfaces.push_back(constant(get_u2be(p))); |
1415 } | 1571 } |
1416 | 1572 |
1417 u2 fields_count = get_u2be(p); | 1573 u2 fields_count = get_u2be(p); |
1418 for (int ii = 0; ii < fields_count; ++ii) { | 1574 for (int ii = 0; ii < fields_count; ++ii) { |
1419 Member *field = Member::Read(p); | 1575 Member *field = Member::Read(p); |
1420 | 1576 |
1421 if (!(field->access_flags & ACC_PRIVATE)) { // drop private fields | 1577 if ((field->access_flags & ACC_PRIVATE) == ACC_PRIVATE) { |
1422 clazz->fields.push_back(field); | 1578 // drop private fields |
| 1579 continue; |
1423 } | 1580 } |
| 1581 clazz->fields.push_back(field); |
1424 } | 1582 } |
1425 | 1583 |
1426 u2 methods_count = get_u2be(p); | 1584 u2 methods_count = get_u2be(p); |
1427 for (int ii = 0; ii < methods_count; ++ii) { | 1585 for (int ii = 0; ii < methods_count; ++ii) { |
1428 Member *method = Member::Read(p); | 1586 Member *method = Member::Read(p); |
1429 | 1587 |
1430 // drop class initializers | 1588 // drop class initializers |
1431 if (method->name->Display() == "<clinit>") continue; | 1589 if (method->name->Display() == "<clinit>") continue; |
1432 | 1590 |
1433 if (!(method->access_flags & ACC_PRIVATE)) { // drop private methods | 1591 if ((method->access_flags & ACC_PRIVATE) == ACC_PRIVATE) { |
1434 clazz->methods.push_back(method); | 1592 // drop private methods |
| 1593 continue; |
1435 } | 1594 } |
| 1595 if ((method->access_flags & (ACC_SYNTHETIC | ACC_BRIDGE)) == |
| 1596 ACC_SYNTHETIC) { |
| 1597 // drop non-bridge synthetic methods, e.g. package-private synthetic |
| 1598 // constructors used to instantiate private nested classes within their |
| 1599 // declaring compilation unit |
| 1600 continue; |
| 1601 } |
| 1602 clazz->methods.push_back(method); |
1436 } | 1603 } |
1437 | 1604 |
1438 clazz->ReadAttrs(p); | 1605 clazz->ReadAttrs(p); |
1439 clazz->StripIfAnonymous(); | |
1440 | 1606 |
1441 return clazz; | 1607 return clazz; |
1442 } | 1608 } |
1443 | 1609 |
| 1610 // In theory, '/' is also reserved, but it's okay if we just parse package |
| 1611 // identifiers as part of the class name. Note that signatures are UTF-8, but |
| 1612 // this works just as well as in plain ASCII. |
| 1613 static const char *SIGNATURE_NON_IDENTIFIER_CHARS = ".;[<>:"; |
| 1614 |
| 1615 void Expect(const std::string& desc, size_t* p, char expected) { |
| 1616 if (desc[*p] != expected) { |
| 1617 fprintf(stderr, "Expected '%c' in '%s' at %zd in signature\n", |
| 1618 expected, desc.substr(*p).c_str(), *p); |
| 1619 exit(1); |
| 1620 } |
| 1621 |
| 1622 *p += 1; |
| 1623 } |
| 1624 |
| 1625 // These functions form a crude recursive descent parser for descriptors and |
| 1626 // signatures in class files (see JVM spec 4.3). |
| 1627 // |
| 1628 // This parser is a bit more liberal than the spec, but this should be fine, |
| 1629 // because it accepts all valid class files and croaks only on invalid ones. |
| 1630 void ParseFromClassTypeSignature(const std::string& desc, size_t* p); |
| 1631 void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p); |
| 1632 void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p); |
| 1633 void ParseIdentifier(const std::string& desc, size_t* p); |
| 1634 void ParseTypeArgumentsOpt(const std::string& desc, size_t* p); |
| 1635 void ParseMethodDescriptor(const std::string& desc, size_t* p); |
| 1636 |
| 1637 void ParseClassTypeSignature(const std::string& desc, size_t* p) { |
| 1638 Expect(desc, p, 'L'); |
| 1639 ParseSimpleClassTypeSignature(desc, p); |
| 1640 ParseClassTypeSignatureSuffix(desc, p); |
| 1641 Expect(desc, p, ';'); |
| 1642 } |
| 1643 |
| 1644 void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p) { |
| 1645 ParseIdentifier(desc, p); |
| 1646 ParseTypeArgumentsOpt(desc, p); |
| 1647 } |
| 1648 |
| 1649 void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p) { |
| 1650 while (desc[*p] == '.') { |
| 1651 *p += 1; |
| 1652 ParseSimpleClassTypeSignature(desc, p); |
| 1653 } |
| 1654 } |
| 1655 |
| 1656 void ParseIdentifier(const std::string& desc, size_t* p) { |
| 1657 size_t next = desc.find_first_of(SIGNATURE_NON_IDENTIFIER_CHARS, *p); |
| 1658 std::string id = desc.substr(*p, next - *p); |
| 1659 used_class_names.insert(id); |
| 1660 *p = next; |
| 1661 } |
| 1662 |
| 1663 void ParseTypeArgumentsOpt(const std::string& desc, size_t* p) { |
| 1664 if (desc[*p] != '<') { |
| 1665 return; |
| 1666 } |
| 1667 |
| 1668 *p += 1; |
| 1669 while (desc[*p] != '>') { |
| 1670 switch (desc[*p]) { |
| 1671 case '*': |
| 1672 *p += 1; |
| 1673 break; |
| 1674 |
| 1675 case '+': |
| 1676 case '-': |
| 1677 *p += 1; |
| 1678 ExtractClassNames(desc, p); |
| 1679 break; |
| 1680 |
| 1681 default: |
| 1682 ExtractClassNames(desc, p); |
| 1683 break; |
| 1684 } |
| 1685 } |
| 1686 |
| 1687 *p += 1; |
| 1688 } |
| 1689 |
| 1690 void ParseMethodDescriptor(const std::string& desc, size_t* p) { |
| 1691 Expect(desc, p, '('); |
| 1692 while (desc[*p] != ')') { |
| 1693 ExtractClassNames(desc, p); |
| 1694 } |
| 1695 |
| 1696 Expect(desc, p, ')'); |
| 1697 ExtractClassNames(desc, p); |
| 1698 } |
| 1699 |
| 1700 void ParseFormalTypeParameters(const std::string& desc, size_t* p) { |
| 1701 Expect(desc, p, '<'); |
| 1702 while (desc[*p] != '>') { |
| 1703 ParseIdentifier(desc, p); |
| 1704 Expect(desc, p, ':'); |
| 1705 if (desc[*p] != ':' && desc[*p] != '>') { |
| 1706 ExtractClassNames(desc, p); |
| 1707 } |
| 1708 |
| 1709 while (desc[*p] == ':') { |
| 1710 Expect(desc, p, ':'); |
| 1711 ExtractClassNames(desc, p); |
| 1712 } |
| 1713 } |
| 1714 |
| 1715 Expect(desc, p, '>'); |
| 1716 } |
| 1717 |
| 1718 void ExtractClassNames(const std::string& desc, size_t* p) { |
| 1719 switch (desc[*p]) { |
| 1720 case '<': |
| 1721 ParseFormalTypeParameters(desc, p); |
| 1722 ExtractClassNames(desc, p); |
| 1723 break; |
| 1724 |
| 1725 case 'L': |
| 1726 ParseClassTypeSignature(desc, p); |
| 1727 break; |
| 1728 |
| 1729 case '[': |
| 1730 *p += 1; |
| 1731 ExtractClassNames(desc, p); |
| 1732 break; |
| 1733 |
| 1734 case 'T': |
| 1735 *p += 1; |
| 1736 ParseIdentifier(desc, p); |
| 1737 Expect(desc, p, ';'); |
| 1738 break; |
| 1739 |
| 1740 case '(': |
| 1741 ParseMethodDescriptor(desc, p); |
| 1742 break; |
| 1743 |
| 1744 case 'B': |
| 1745 case 'C': |
| 1746 case 'D': |
| 1747 case 'F': |
| 1748 case 'I': |
| 1749 case 'J': |
| 1750 case 'S': |
| 1751 case 'Z': |
| 1752 case 'V': |
| 1753 *p += 1; |
| 1754 break; |
| 1755 |
| 1756 default: |
| 1757 fprintf(stderr, "Invalid signature %s\n", desc.substr(*p).c_str()); |
| 1758 } |
| 1759 } |
| 1760 |
1444 void ClassFile::WriteClass(u1 *&p) { | 1761 void ClassFile::WriteClass(u1 *&p) { |
| 1762 used_class_names.clear(); |
| 1763 std::vector<Member *> members; |
| 1764 members.insert(members.end(), fields.begin(), fields.end()); |
| 1765 members.insert(members.end(), methods.begin(), methods.end()); |
| 1766 ExtractClassNames(); |
| 1767 for (auto *member : members) { |
| 1768 size_t idx = 0; |
| 1769 devtools_ijar::ExtractClassNames(member->descriptor->Display(), &idx); |
| 1770 member->ExtractClassNames(); |
| 1771 } |
| 1772 |
1445 // We have to write the body out before the header in order to reference | 1773 // We have to write the body out before the header in order to reference |
1446 // the essential constants and populate the output constant pool: | 1774 // the essential constants and populate the output constant pool: |
1447 u1 *body = new u1[length]; | 1775 u1 *body = new u1[length]; |
1448 u1 *q = body; | 1776 u1 *q = body; |
1449 WriteBody(q); // advances q | 1777 WriteBody(q); // advances q |
1450 u4 body_length = q - body; | 1778 u4 body_length = q - body; |
1451 | 1779 |
1452 WriteHeader(p); // advances p | 1780 WriteHeader(p); // advances p |
1453 put_n(p, body, body_length); | 1781 put_n(p, body, body_length); |
1454 delete[] body; | 1782 delete[] body; |
1455 } | 1783 } |
1456 | 1784 |
1457 | 1785 bool StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) { |
1458 void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) { | |
1459 ClassFile *clazz = ReadClass(classdata_in, in_length); | 1786 ClassFile *clazz = ReadClass(classdata_in, in_length); |
| 1787 bool keep = true; |
1460 if (clazz == NULL) { | 1788 if (clazz == NULL) { |
1461 // Class is invalid. Simply copy it to the output and call it a day. | 1789 // Class is invalid. Simply copy it to the output and call it a day. |
1462 put_n(classdata_out, classdata_in, in_length); | 1790 put_n(classdata_out, classdata_in, in_length); |
| 1791 } else if (clazz->IsLocalOrAnonymous()) { |
| 1792 keep = false; |
1463 } else { | 1793 } else { |
1464 | 1794 |
1465 // Constant pool item zero is a dummy entry. Setting it marks the | 1795 // Constant pool item zero is a dummy entry. Setting it marks the |
1466 // beginning of the output phase; calls to Constant::slot() will | 1796 // beginning of the output phase; calls to Constant::slot() will |
1467 // fail if called prior to this. | 1797 // fail if called prior to this. |
1468 const_pool_out.push_back(NULL); | 1798 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); | 1799 clazz->WriteClass(classdata_out); |
1475 | 1800 |
1476 delete clazz; | 1801 delete clazz; |
1477 } | 1802 } |
1478 | 1803 |
1479 // Now clean up all the mess we left behind. | 1804 // Now clean up all the mess we left behind. |
1480 | 1805 |
1481 for (size_t i = 0; i < const_pool_in.size(); i++) { | 1806 for (size_t i = 0; i < const_pool_in.size(); i++) { |
1482 delete const_pool_in[i]; | 1807 delete const_pool_in[i]; |
1483 } | 1808 } |
1484 | 1809 |
1485 const_pool_in.clear(); | 1810 const_pool_in.clear(); |
1486 const_pool_out.clear(); | 1811 const_pool_out.clear(); |
| 1812 return keep; |
1487 } | 1813 } |
1488 | 1814 |
1489 } // namespace devtools_ijar | 1815 } // namespace devtools_ijar |
OLD | NEW |