Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(604)

Side by Side Diff: third_party/ijar/classfile.cc

Issue 1901473003: 🐞 Update version of third_party/ijar (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/ijar/README.chromium ('k') | third_party/ijar/common.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/ijar/README.chromium ('k') | third_party/ijar/common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698