1 // Copyright 2001,2007 Alan Donovan. All rights reserved.
2 //
3 // Author: Alan Donovan <adonovan@google.com>
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 // classfile.cc -- classfile parsing and stripping.
18 //
19
20 // TODO(adonovan) don't pass pointers by reference; this is not
21 // compatible with Google C++ style.
22
23 // See README.txt for details.
24 //
25 // For definition of JVM class file format, see:
26 // Java SE 8 Edition:
27 // http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4
28
29 #define __STDC_FORMAT_MACROS 1
30 #define __STDC_LIMIT_MACROS 1
31 #include <inttypes.h> // for PRIx32
32 #include <stddef.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include <set>
38 #include <string>
39 #include <vector>
40
41 #include "common.h"
42
43 namespace devtools_ijar {
44
45 // See Table 4.3 in JVM Spec.
46 enum CONSTANT {
47 CONSTANT_Class = 7,
48 CONSTANT_FieldRef = 9,
49 CONSTANT_Methodref = 10,
50 CONSTANT_Interfacemethodref = 11,
51 CONSTANT_String = 8,
52 CONSTANT_Integer = 3,
53 CONSTANT_Float = 4,
54 CONSTANT_Long = 5,
55 CONSTANT_Double = 6,
56 CONSTANT_NameAndType = 12,
57 CONSTANT_Utf8 = 1,
58 CONSTANT_MethodHandle = 15,
59 CONSTANT_MethodType = 16,
60 CONSTANT_InvokeDynamic = 18
61 };
62
63 // See Tables 4.1, 4.4, 4.5 in JVM Spec.
64 enum ACCESS {
65 ACC_PUBLIC = 0x0001,
66 ACC_PRIVATE = 0x0002,
67 ACC_PROTECTED = 0x0004,
68 ACC_STATIC = 0x0008,
69 ACC_FINAL = 0x0010,
70 ACC_SYNCHRONIZED = 0x0020,
71 ACC_VOLATILE = 0x0040,
72 ACC_TRANSIENT = 0x0080,
73 ACC_INTERFACE = 0x0200,
74 ACC_ABSTRACT = 0x0400
75 };
76
77 // See Table 4.7.20-A in Java 8 JVM Spec.
78 enum TARGET_TYPE {
79 // Targets for type parameter declarations (ElementType.TYPE_PARAMETER):
80 CLASS_TYPE_PARAMETER = 0x00,
81 METHOD_TYPE_PARAMETER = 0x01,
82
83 // Targets for type uses that may be externally visible in classes and members
84 // (ElementType.TYPE_USE):
85 CLASS_EXTENDS = 0x10,
86 CLASS_TYPE_PARAMETER_BOUND = 0x11,
87 METHOD_TYPE_PARAMETER_BOUND = 0x12,
88 FIELD = 0x13,
89 METHOD_RETURN = 0x14,
90 METHOD_RECEIVER = 0x15,
91 METHOD_FORMAL_PARAMETER = 0x16,
92 THROWS = 0x17,
93
94 // TARGET_TYPE >= 0x40 is reserved for type uses that occur only within code
95 // blocks. Ijar doesn't need to know about these.
96 };
97
98 struct Constant;
99
100 // TODO(adonovan) these globals are unfortunate
101 static std::vector<Constant*> const_pool_in; // input constant pool
102 static std::vector<Constant*> const_pool_out; // output constant_pool
103 static std::set<std::string> used_class_names;
104 static Constant * class_name;
105
106 // Returns the Constant object, given an index into the input constant pool.
107 // Note: constant(0) == NULL; this invariant is exploited by the
108 // InnerClassesAttribute, inter alia.
constant(int idx)109 inline Constant *constant(int idx) {
110 if (idx < 0 || (unsigned)idx >= const_pool_in.size()) {
111 fprintf(stderr, "Illegal constant pool index: %d\n", idx);
112 abort();
113 }
114 return const_pool_in[idx];
115 }
116
117 /**********************************************************************
118 * *
119 * Constants *
120 * *
121 **********************************************************************/
122
123 // See sec.4.4 of JVM spec.
124 struct Constant {
125
Constantdevtools_ijar::Constant126 Constant(u1 tag) :
127 slot_(0),
128 tag_(tag) {}
129
~Constantdevtools_ijar::Constant130 virtual ~Constant() {}
131
132 // For UTF-8 string constants, returns the encoded string.
133 // Otherwise, returns an undefined string value suitable for debugging.
134 virtual std::string Display() = 0;
135
136 virtual void Write(u1 *&p) = 0;
137
138 // Called by slot() when a constant has been identified as required
139 // in the output classfile's constant pool. This is a hook allowing
140 // constants to register their dependency on other constants, by
141 // calling slot() on them in turn.
Keepdevtools_ijar::Constant142 virtual void Keep() {}
143
Keptdevtools_ijar::Constant144 bool Kept() {
145 return slot_ != 0;
146 }
147
148 // Returns the index of this constant in the output class's constant
149 // pool, assigning a slot if not already done.
slotdevtools_ijar::Constant150 u2 slot() {
151 if (slot_ == 0) {
152 Keep();
153 slot_ = const_pool_out.size(); // BugBot's "narrowing" warning
154 // is bogus. The number of
155 // output constants can't exceed
156 // the number of input constants.
157 if (slot_ == 0) {
158 fprintf(stderr, "Constant::slot() called before output phase.\n");
159 abort();
160 }
161 const_pool_out.push_back(this);
162 if (tag_ == CONSTANT_Long || tag_ == CONSTANT_Double) {
163 const_pool_out.push_back(NULL);
164 }
165 }
166 return slot_;
167 }
168
169 u2 slot_; // zero => "this constant is unreachable garbage"
170 u1 tag_;
171 };
172
173 // Extracts class names from a signature and puts them into the global
174 // variable used_class_names.
175 //
176 // desc: the descriptor class names should be extracted from.
177 // p: the position where the extraction should tart.
178 void ExtractClassNames(const std::string& desc, size_t* p);
179
180 // See sec.4.4.1 of JVM spec.
181 struct Constant_Class : Constant
182 {
Constant_Classdevtools_ijar::Constant_Class183 Constant_Class(u2 name_index) :
184 Constant(CONSTANT_Class),
185 name_index_(name_index) {}
186
Writedevtools_ijar::Constant_Class187 void Write(u1 *&p) {
188 put_u1(p, tag_);
189 put_u2be(p, constant(name_index_)->slot());
190 }
191
Displaydevtools_ijar::Constant_Class192 std::string Display() {
193 return constant(name_index_)->Display();
194 }
195
Keepdevtools_ijar::Constant_Class196 void Keep() { constant(name_index_)->slot(); }
197
198 u2 name_index_;
199 };
200
201 // See sec.4.4.2 of JVM spec.
202 struct Constant_FMIref : Constant
203 {
Constant_FMIrefdevtools_ijar::Constant_FMIref204 Constant_FMIref(u1 tag,
205 u2 class_index,
206 u2 name_type_index) :
207 Constant(tag),
208 class_index_(class_index),
209 name_type_index_(name_type_index) {}
210
Writedevtools_ijar::Constant_FMIref211 void Write(u1 *&p) {
212 put_u1(p, tag_);
213 put_u2be(p, constant(class_index_)->slot());
214 put_u2be(p, constant(name_type_index_)->slot());
215 }
216
Displaydevtools_ijar::Constant_FMIref217 std::string Display() {
218 return constant(class_index_)->Display() + "::" +
219 constant(name_type_index_)->Display();
220 }
221
Keepdevtools_ijar::Constant_FMIref222 void Keep() {
223 constant(class_index_)->slot();
224 constant(name_type_index_)->slot();
225 }
226
227 u2 class_index_;
228 u2 name_type_index_;
229 };
230
231 // See sec.4.4.3 of JVM spec.
232 struct Constant_String : Constant
233 {
Constant_Stringdevtools_ijar::Constant_String234 Constant_String(u2 string_index) :
235 Constant(CONSTANT_String),
236 string_index_(string_index) {}
237
Writedevtools_ijar::Constant_String238 void Write(u1 *&p) {
239 put_u1(p, tag_);
240 put_u2be(p, constant(string_index_)->slot());
241 }
242
Displaydevtools_ijar::Constant_String243 std::string Display() {
244 return "\"" + constant(string_index_)->Display() + "\"";
245 }
246
Keepdevtools_ijar::Constant_String247 void Keep() { constant(string_index_)->slot(); }
248
249 u2 string_index_;
250 };
251
252 // See sec.4.4.4 of JVM spec.
253 struct Constant_IntegerOrFloat : Constant
254 {
Constant_IntegerOrFloatdevtools_ijar::Constant_IntegerOrFloat255 Constant_IntegerOrFloat(u1 tag, u4 bytes) :
256 Constant(tag),
257 bytes_(bytes) {}
258
Writedevtools_ijar::Constant_IntegerOrFloat259 void Write(u1 *&p) {
260 put_u1(p, tag_);
261 put_u4be(p, bytes_);
262 }
263
Displaydevtools_ijar::Constant_IntegerOrFloat264 std::string Display() { return "int/float"; }
265
266 u4 bytes_;
267 };
268
269 // See sec.4.4.5 of JVM spec.
270 struct Constant_LongOrDouble : Constant_IntegerOrFloat
271 {
Constant_LongOrDoubledevtools_ijar::Constant_LongOrDouble272 Constant_LongOrDouble(u1 tag, u4 high_bytes, u4 low_bytes) :
273 Constant_IntegerOrFloat(tag, high_bytes),
274 low_bytes_(low_bytes) {}
275
Writedevtools_ijar::Constant_LongOrDouble276 void Write(u1 *&p) {
277 put_u1(p, tag_);
278 put_u4be(p, bytes_);
279 put_u4be(p, low_bytes_);
280 }
281
Displaydevtools_ijar::Constant_LongOrDouble282 std::string Display() { return "long/double"; }
283
284 u4 low_bytes_;
285 };
286
287 // See sec.4.4.6 of JVM spec.
288 struct Constant_NameAndType : Constant
289 {
Constant_NameAndTypedevtools_ijar::Constant_NameAndType290 Constant_NameAndType(u2 name_index, u2 descr_index) :
291 Constant(CONSTANT_NameAndType),
292 name_index_(name_index),
293 descr_index_(descr_index) {}
294
Writedevtools_ijar::Constant_NameAndType295 void Write(u1 *&p) {
296 put_u1(p, tag_);
297 put_u2be(p, constant(name_index_)->slot());
298 put_u2be(p, constant(descr_index_)->slot());
299 }
300
Displaydevtools_ijar::Constant_NameAndType301 std::string Display() {
302 return constant(name_index_)->Display() + "::" +
303 constant(descr_index_)->Display();
304 }
305
Keepdevtools_ijar::Constant_NameAndType306 void Keep() {
307 constant(name_index_)->slot();
308 constant(descr_index_)->slot();
309 }
310
311 u2 name_index_;
312 u2 descr_index_;
313 };
314
315 // See sec.4.4.7 of JVM spec.
316 struct Constant_Utf8 : Constant
317 {
Constant_Utf8devtools_ijar::Constant_Utf8318 Constant_Utf8(u4 length, const u1 *utf8) :
319 Constant(CONSTANT_Utf8),
320 length_(length),
321 utf8_(utf8) {}
322
Writedevtools_ijar::Constant_Utf8323 void Write(u1 *&p) {
324 put_u1(p, tag_);
325 put_u2be(p, length_);
326 put_n(p, utf8_, length_);
327 }
328
Displaydevtools_ijar::Constant_Utf8329 std::string Display() {
330 return std::string((const char*) utf8_, length_);
331 }
332
333 u4 length_;
334 const u1 *utf8_;
335 };
336
337 // See sec.4.4.8 of JVM spec.
338 struct Constant_MethodHandle : Constant
339 {
Constant_MethodHandledevtools_ijar::Constant_MethodHandle340 Constant_MethodHandle(u1 reference_kind, u2 reference_index) :
341 Constant(CONSTANT_MethodHandle),
342 reference_kind_(reference_kind),
343 reference_index_(reference_index) {}
344
Writedevtools_ijar::Constant_MethodHandle345 void Write(u1 *&p) {
346 put_u1(p, tag_);
347 put_u1(p, reference_kind_);
348 put_u2be(p, reference_index_);
349 }
350
Displaydevtools_ijar::Constant_MethodHandle351 std::string Display() {
352 return "Constant_MethodHandle::" + std::to_string(reference_kind_) + "::"
353 + constant(reference_index_)->Display();
354 }
355
356 u1 reference_kind_;
357 u2 reference_index_;
358 };
359
360 // See sec.4.4.9 of JVM spec.
361 struct Constant_MethodType : Constant
362 {
Constant_MethodTypedevtools_ijar::Constant_MethodType363 Constant_MethodType(u2 descriptor_index) :
364 Constant(CONSTANT_MethodType),
365 descriptor_index_(descriptor_index) {}
366
Writedevtools_ijar::Constant_MethodType367 void Write(u1 *&p) {
368 put_u1(p, tag_);
369 put_u2be(p, descriptor_index_);
370 }
371
Displaydevtools_ijar::Constant_MethodType372 std::string Display() {
373 return "Constant_MethodType::" + constant(descriptor_index_)->Display();
374 }
375
376 u2 descriptor_index_;
377 };
378
379 // See sec.4.4.10 of JVM spec.
380 struct Constant_InvokeDynamic : Constant
381 {
Constant_InvokeDynamicdevtools_ijar::Constant_InvokeDynamic382 Constant_InvokeDynamic(u2 bootstrap_method_attr_index, u2 name_and_type_index) :
383 Constant(CONSTANT_InvokeDynamic),
384 bootstrap_method_attr_index_(bootstrap_method_attr_index),
385 name_and_type_index_(name_and_type_index) {}
386
Writedevtools_ijar::Constant_InvokeDynamic387 void Write(u1 *&p) {
388 put_u1(p, tag_);
389 put_u2be(p, bootstrap_method_attr_index_);
390 put_u2be(p, name_and_type_index_);
391 }
392
Displaydevtools_ijar::Constant_InvokeDynamic393 std::string Display() {
394 return "Constant_InvokeDynamic::"
395 + std::to_string(bootstrap_method_attr_index_) + "::"
396 + constant(name_and_type_index_)->Display();
397 }
398
399 u2 bootstrap_method_attr_index_;
400 u2 name_and_type_index_;
401 };
402
403 /**********************************************************************
404 * *
405 * Attributes *
406 * *
407 **********************************************************************/
408
409 // See sec.4.7 of JVM spec.
410 struct Attribute {
411
~Attributedevtools_ijar::Attribute412 virtual ~Attribute() {}
413 virtual void Write(u1 *&p) = 0;
ExtractClassNamesdevtools_ijar::Attribute414 virtual void ExtractClassNames() {}
415
WritePrologdevtools_ijar::Attribute416 void WriteProlog(u1 *&p, u2 length) {
417 put_u2be(p, attribute_name_->slot());
418 put_u4be(p, length);
419 }
420
421 Constant *attribute_name_;
422 };
423
424 // See sec.4.7.5 of JVM spec.
425 struct ExceptionsAttribute : Attribute {
426
Readdevtools_ijar::ExceptionsAttribute427 static ExceptionsAttribute* Read(const u1 *&p, Constant *attribute_name) {
428 ExceptionsAttribute *attr = new ExceptionsAttribute;
429 attr->attribute_name_ = attribute_name;
430 u2 number_of_exceptions = get_u2be(p);
431 for (int ii = 0; ii < number_of_exceptions; ++ii) {
432 attr->exceptions_.push_back(constant(get_u2be(p)));
433 }
434 return attr;
435 }
436
Writedevtools_ijar::ExceptionsAttribute437 void Write(u1 *&p) {
438 WriteProlog(p, exceptions_.size() * 2 + 2);
439 put_u2be(p, exceptions_.size());
440 for (size_t ii = 0; ii < exceptions_.size(); ++ii) {
441 put_u2be(p, exceptions_[ii]->slot());
442 }
443 }
444
445 std::vector<Constant*> exceptions_;
446 };
447
448 // See sec.4.7.6 of JVM spec.
449 struct InnerClassesAttribute : Attribute {
450
451 struct Entry {
452 Constant *inner_class_info;
453 Constant *outer_class_info;
454 Constant *inner_name;
455 u2 inner_class_access_flags;
456 };
457
~InnerClassesAttributedevtools_ijar::InnerClassesAttribute458 virtual ~InnerClassesAttribute() {
459 for (size_t i = 0; i < entries_.size(); i++) {
460 delete entries_[i];
461 }
462 }
463
Readdevtools_ijar::InnerClassesAttribute464 static InnerClassesAttribute* Read(const u1 *&p, Constant *attribute_name) {
465 InnerClassesAttribute *attr = new InnerClassesAttribute;
466 attr->attribute_name_ = attribute_name;
467
468 u2 number_of_classes = get_u2be(p);
469 for (int ii = 0; ii < number_of_classes; ++ii) {
470 Entry *entry = new Entry;
471 entry->inner_class_info = constant(get_u2be(p));
472 entry->outer_class_info = constant(get_u2be(p));
473 entry->inner_name = constant(get_u2be(p));
474 entry->inner_class_access_flags = get_u2be(p);
475
476 attr->entries_.push_back(entry);
477 }
478 return attr;
479 }
480
Writedevtools_ijar::InnerClassesAttribute481 void Write(u1 *&p) {
482 std::set<int> kept_entries;
483 // We keep an entry if the constant referring to the inner class is already
484 // kept. Then we mark its outer class and its class name as kept, too, then
485 // iterate until a fixed point is reached.
486 size_t entry_count;
487 int iteration = 0;
488
489 do {
490 entry_count = kept_entries.size();
491 for (size_t i_entry = 0; i_entry < entries_.size(); ++i_entry) {
492 Entry* entry = entries_[i_entry];
493 if (entry->inner_class_info->Kept() ||
494 used_class_names.find(entry->inner_class_info->Display())
495 != used_class_names.end() ||
496 entry->outer_class_info == class_name ||
497 entry->outer_class_info == NULL ||
498 entry->inner_name == NULL) {
499 kept_entries.insert(i_entry);
500
501 // These are zero for anonymous inner classes
502 if (entry->outer_class_info != NULL) {
503 entry->outer_class_info->slot();
504 }
505
506 if (entry->inner_name != NULL) {
507 entry->inner_name->slot();
508 }
509 }
510 }
511 iteration += 1;
512 } while (entry_count != kept_entries.size());
513
514 if (kept_entries.size() == 0) {
515 return;
516 }
517
518 WriteProlog(p, 2 + kept_entries.size() * 8);
519 put_u2be(p, kept_entries.size());
520
521 for (std::set<int>::iterator it = kept_entries.begin();
522 it != kept_entries.end();
523 ++it) {
524 Entry *entry = entries_[*it];
525 put_u2be(p, entry->inner_class_info == NULL
526 ? 0
527 : entry->inner_class_info->slot());
528 put_u2be(p, entry->outer_class_info == NULL
529 ? 0
530 : entry->outer_class_info->slot());
531 put_u2be(p, entry->inner_name == NULL
532 ? 0
533 : entry->inner_name->slot());
534 put_u2be(p, entry->inner_class_access_flags);
535 }
536 }
537
538 std::vector<Entry*> entries_;
539 };
540
541 // See sec.4.7.7 of JVM spec.
542 // We preserve EnclosingMethod attributes to be able to identify local and
543 // anonymous classes. These classes will be stripped of most content, as they
544 // represent implementation details that shoudn't leak into the ijars. Omitting
545 // EnclosingMethod attributes can lead to type-checking failures in the presence
546 // of generics (see b/9070939).
547 struct EnclosingMethodAttribute : Attribute {
548
Readdevtools_ijar::EnclosingMethodAttribute549 static EnclosingMethodAttribute* Read(const u1 *&p,
550 Constant *attribute_name) {
551 EnclosingMethodAttribute *attr = new EnclosingMethodAttribute;
552 attr->attribute_name_ = attribute_name;
553 attr->class_ = constant(get_u2be(p));
554 attr->method_ = constant(get_u2be(p));
555 return attr;
556 }
557
Writedevtools_ijar::EnclosingMethodAttribute558 void Write(u1 *&p) {
559 WriteProlog(p, 4);
560 put_u2be(p, class_->slot());
561 put_u2be(p, method_ == NULL ? 0 : method_->slot());
562 }
563
564 Constant *class_;
565 Constant *method_;
566 };
567
568 // See sec.4.7.16.1 of JVM spec.
569 // Used by AnnotationDefault and other attributes.
570 struct ElementValue {
~ElementValuedevtools_ijar::ElementValue571 virtual ~ElementValue() {}
572 virtual void Write(u1 *&p) = 0;
ExtractClassNamesdevtools_ijar::ElementValue573 virtual void ExtractClassNames() {}
574 static ElementValue* Read(const u1 *&p);
575 u1 tag_;
576 u4 length_;
577 };
578
579 struct BaseTypeElementValue : ElementValue {
Writedevtools_ijar::BaseTypeElementValue580 void Write(u1 *&p) {
581 put_u1(p, tag_);
582 put_u2be(p, const_value_->slot());
583 }
Readdevtools_ijar::BaseTypeElementValue584 static BaseTypeElementValue *Read(const u1 *&p) {
585 BaseTypeElementValue *value = new BaseTypeElementValue;
586 value->const_value_ = constant(get_u2be(p));
587 return value;
588 }
589 Constant *const_value_;
590 };
591
592 struct EnumTypeElementValue : ElementValue {
Writedevtools_ijar::EnumTypeElementValue593 void Write(u1 *&p) {
594 put_u1(p, tag_);
595 put_u2be(p, type_name_->slot());
596 put_u2be(p, const_name_->slot());
597 }
Readdevtools_ijar::EnumTypeElementValue598 static EnumTypeElementValue *Read(const u1 *&p) {
599 EnumTypeElementValue *value = new EnumTypeElementValue;
600 value->type_name_ = constant(get_u2be(p));
601 value->const_name_ = constant(get_u2be(p));
602 return value;
603 }
604 Constant *type_name_;
605 Constant *const_name_;
606 };
607
608 struct ClassTypeElementValue : ElementValue {
Writedevtools_ijar::ClassTypeElementValue609 void Write(u1 *&p) {
610 put_u1(p, tag_);
611 put_u2be(p, class_info_->slot());
612 }
613
ExtractClassNamesdevtools_ijar::ClassTypeElementValue614 virtual void ExtractClassNames() {
615 size_t idx = 0;
616 devtools_ijar::ExtractClassNames(class_info_->Display(), &idx);
617 }
618
Readdevtools_ijar::ClassTypeElementValue619 static ClassTypeElementValue *Read(const u1 *&p) {
620 ClassTypeElementValue *value = new ClassTypeElementValue;
621 value->class_info_ = constant(get_u2be(p));
622 return value;
623 }
624 Constant *class_info_;
625 };
626
627 struct ArrayTypeElementValue : ElementValue {
~ArrayTypeElementValuedevtools_ijar::ArrayTypeElementValue628 virtual ~ArrayTypeElementValue() {
629 for (size_t i = 0; i < values_.size(); i++) {
630 delete values_[i];
631 }
632 }
633
ExtractClassNamesdevtools_ijar::ArrayTypeElementValue634 virtual void ExtractClassNames() {
635 for (size_t i = 0; i < values_.size(); i++) {
636 values_[i]->ExtractClassNames();
637 }
638 }
639
Writedevtools_ijar::ArrayTypeElementValue640 void Write(u1 *&p) {
641 put_u1(p, tag_);
642 put_u2be(p, values_.size());
643 for (size_t ii = 0; ii < values_.size(); ++ii) {
644 values_[ii]->Write(p);
645 }
646 }
Readdevtools_ijar::ArrayTypeElementValue647 static ArrayTypeElementValue *Read(const u1 *&p) {
648 ArrayTypeElementValue *value = new ArrayTypeElementValue;
649 u2 num_values = get_u2be(p);
650 for (int ii = 0; ii < num_values; ++ii) {
651 value->values_.push_back(ElementValue::Read(p));
652 }
653 return value;
654 }
655 std::vector<ElementValue*> values_;
656 };
657
658 // See sec.4.7.16 of JVM spec.
659 struct Annotation {
~Annotationdevtools_ijar::Annotation660 virtual ~Annotation() {
661 for (size_t i = 0; i < element_value_pairs_.size(); i++) {
662 delete element_value_pairs_[i]->element_value_;
663 delete element_value_pairs_[i];
664 }
665 }
666
ExtractClassNamesdevtools_ijar::Annotation667 void ExtractClassNames() {
668 for (size_t i = 0; i < element_value_pairs_.size(); i++) {
669 element_value_pairs_[i]->element_value_->ExtractClassNames();
670 }
671 }
672
Writedevtools_ijar::Annotation673 void Write(u1 *&p) {
674 put_u2be(p, type_->slot());
675 put_u2be(p, element_value_pairs_.size());
676 for (size_t ii = 0; ii < element_value_pairs_.size(); ++ii) {
677 put_u2be(p, element_value_pairs_[ii]->element_name_->slot());
678 element_value_pairs_[ii]->element_value_->Write(p);
679 }
680 }
Readdevtools_ijar::Annotation681 static Annotation *Read(const u1 *&p) {
682 Annotation *value = new Annotation;
683 value->type_ = constant(get_u2be(p));
684 u2 num_element_value_pairs = get_u2be(p);
685 for (int ii = 0; ii < num_element_value_pairs; ++ii) {
686 ElementValuePair *pair = new ElementValuePair;
687 pair->element_name_ = constant(get_u2be(p));
688 pair->element_value_ = ElementValue::Read(p);
689 value->element_value_pairs_.push_back(pair);
690 }
691 return value;
692 }
693 Constant *type_;
694 struct ElementValuePair {
695 Constant *element_name_;
696 ElementValue *element_value_;
697 };
698 std::vector<ElementValuePair*> element_value_pairs_;
699 };
700
701 // See sec 4.7.20 of Java 8 JVM Spec
702 //
703 // Each entry in the annotations table represents a single run-time visible
704 // annotation on a type used in a declaration or expression. The type_annotation
705 // structure has the following format:
706 //
707 // type_annotation {
708 // u1 target_type;
709 // union {
710 // type_parameter_target;
711 // supertype_target;
712 // type_parameter_bound_target;
713 // empty_target;
714 // method_formal_parameter_target;
715 // throws_target;
716 // localvar_target;
717 // catch_target;
718 // offset_target;
719 // type_argument_target;
720 // } target_info;
721 // type_path target_path;
722 // u2 type_index;
723 // u2 num_element_value_pairs;
724 // {
725 // u2 element_name_index;
726 // element_value value;
727 // }
728 // element_value_pairs[num_element_value_pairs];
729 // }
730 //
731 struct TypeAnnotation {
~TypeAnnotationdevtools_ijar::TypeAnnotation732 virtual ~TypeAnnotation() {
733 delete target_info_;
734 delete type_path_;
735 delete annotation_;
736 }
737
ExtractClassNamesdevtools_ijar::TypeAnnotation738 void ExtractClassNames() {
739 annotation_->ExtractClassNames();
740 }
741
Writedevtools_ijar::TypeAnnotation742 void Write(u1 *&p) {
743 put_u1(p, target_type_);
744 target_info_->Write(p);
745 type_path_->Write(p);
746 annotation_->Write(p);
747 }
748
Readdevtools_ijar::TypeAnnotation749 static TypeAnnotation *Read(const u1 *&p) {
750 TypeAnnotation *value = new TypeAnnotation;
751 value->target_type_ = get_u1(p);
752 value->target_info_ = ReadTargetInfo(p, value->target_type_);
753 value->type_path_ = TypePath::Read(p);
754 value->annotation_ = Annotation::Read(p);
755 return value;
756 }
757
758 struct TargetInfo {
~TargetInfodevtools_ijar::TypeAnnotation::TargetInfo759 virtual ~TargetInfo() {}
760 virtual void Write(u1 *&p) = 0;
761 };
762
763 struct TypeParameterTargetInfo : TargetInfo {
Writedevtools_ijar::TypeAnnotation::TypeParameterTargetInfo764 void Write(u1 *&p) {
765 put_u1(p, type_parameter_index_);
766 }
Readdevtools_ijar::TypeAnnotation::TypeParameterTargetInfo767 static TypeParameterTargetInfo *Read(const u1 *&p) {
768 TypeParameterTargetInfo *value = new TypeParameterTargetInfo;
769 value->type_parameter_index_ = get_u1(p);
770 return value;
771 }
772 u1 type_parameter_index_;
773 };
774
775 struct ClassExtendsInfo : TargetInfo {
Writedevtools_ijar::TypeAnnotation::ClassExtendsInfo776 void Write(u1 *&p) {
777 put_u2be(p, supertype_index_);
778 }
Readdevtools_ijar::TypeAnnotation::ClassExtendsInfo779 static ClassExtendsInfo *Read(const u1 *&p) {
780 ClassExtendsInfo *value = new ClassExtendsInfo;
781 value->supertype_index_ = get_u2be(p);
782 return value;
783 }
784 u2 supertype_index_;
785 };
786
787 struct TypeParameterBoundInfo : TargetInfo {
Writedevtools_ijar::TypeAnnotation::TypeParameterBoundInfo788 void Write(u1 *&p) {
789 put_u1(p, type_parameter_index_);
790 put_u1(p, bound_index_);
791 }
Readdevtools_ijar::TypeAnnotation::TypeParameterBoundInfo792 static TypeParameterBoundInfo *Read(const u1 *&p) {
793 TypeParameterBoundInfo *value = new TypeParameterBoundInfo;
794 value->type_parameter_index_ = get_u1(p);
795 value->bound_index_ = get_u1(p);
796 return value;
797 }
798 u1 type_parameter_index_;
799 u1 bound_index_;
800 };
801
802 struct EmptyInfo : TargetInfo {
Writedevtools_ijar::TypeAnnotation::EmptyInfo803 void Write(u1 *&) {}
Readdevtools_ijar::TypeAnnotation::EmptyInfo804 static EmptyInfo *Read(const u1 *&) {
805 return new EmptyInfo;
806 }
807 };
808
809 struct MethodFormalParameterInfo : TargetInfo {
Writedevtools_ijar::TypeAnnotation::MethodFormalParameterInfo810 void Write(u1 *&p) {
811 put_u1(p, method_formal_parameter_index_);
812 }
Readdevtools_ijar::TypeAnnotation::MethodFormalParameterInfo813 static MethodFormalParameterInfo *Read(const u1 *&p) {
814 MethodFormalParameterInfo *value = new MethodFormalParameterInfo;
815 value->method_formal_parameter_index_ = get_u1(p);
816 return value;
817 }
818 u1 method_formal_parameter_index_;
819 };
820
821 struct ThrowsTypeInfo : TargetInfo {
Writedevtools_ijar::TypeAnnotation::ThrowsTypeInfo822 void Write(u1 *&p) {
823 put_u2be(p, throws_type_index_);
824 }
Readdevtools_ijar::TypeAnnotation::ThrowsTypeInfo825 static ThrowsTypeInfo *Read(const u1 *&p) {
826 ThrowsTypeInfo *value = new ThrowsTypeInfo;
827 value->throws_type_index_ = get_u2be(p);
828 return value;
829 }
830 u2 throws_type_index_;
831 };
832
ReadTargetInfodevtools_ijar::TypeAnnotation833 static TargetInfo *ReadTargetInfo(const u1 *&p, u1 target_type) {
834 switch (target_type) {
835 case CLASS_TYPE_PARAMETER:
836 case METHOD_TYPE_PARAMETER:
837 return TypeParameterTargetInfo::Read(p);
838 case CLASS_EXTENDS:
839 return ClassExtendsInfo::Read(p);
840 case CLASS_TYPE_PARAMETER_BOUND:
841 case METHOD_TYPE_PARAMETER_BOUND:
842 return TypeParameterBoundInfo::Read(p);
843 case FIELD:
844 case METHOD_RETURN:
845 case METHOD_RECEIVER:
846 return new EmptyInfo;
847 case METHOD_FORMAL_PARAMETER:
848 return MethodFormalParameterInfo::Read(p);
849 case THROWS:
850 return ThrowsTypeInfo::Read(p);
851 default:
852 fprintf(stderr, "Illegal type annotation target type: %d\n",
853 target_type);
854 abort();
855 }
856 }
857
858 struct TypePath {
Writedevtools_ijar::TypeAnnotation::TypePath859 void Write(u1 *&p) {
860 put_u1(p, path_.size());
861 for (TypePathEntry entry : path_) {
862 put_u1(p, entry.type_path_kind_);
863 put_u1(p, entry.type_argument_index_);
864 }
865 }
Readdevtools_ijar::TypeAnnotation::TypePath866 static TypePath *Read(const u1 *&p) {
867 TypePath *value = new TypePath;
868 u1 path_length = get_u1(p);
869 for (int ii = 0; ii < path_length; ++ii) {
870 TypePathEntry entry;
871 entry.type_path_kind_ = get_u1(p);
872 entry.type_argument_index_ = get_u1(p);
873 value->path_.push_back(entry);
874 }
875 return value;
876 }
877
878 struct TypePathEntry {
879 u1 type_path_kind_;
880 u1 type_argument_index_;
881 };
882 std::vector<TypePathEntry> path_;
883 };
884
885 u1 target_type_;
886 TargetInfo *target_info_;
887 TypePath *type_path_;
888 Annotation *annotation_;
889 };
890
891 struct AnnotationTypeElementValue : ElementValue {
~AnnotationTypeElementValuedevtools_ijar::AnnotationTypeElementValue892 virtual ~AnnotationTypeElementValue() {
893 delete annotation_;
894 }
895
Writedevtools_ijar::AnnotationTypeElementValue896 void Write(u1 *&p) {
897 put_u1(p, tag_);
898 annotation_->Write(p);
899 }
Readdevtools_ijar::AnnotationTypeElementValue900 static AnnotationTypeElementValue *Read(const u1 *&p) {
901 AnnotationTypeElementValue *value = new AnnotationTypeElementValue;
902 value->annotation_ = Annotation::Read(p);
903 return value;
904 }
905
906 Annotation *annotation_;
907 };
908
Read(const u1 * & p)909 ElementValue* ElementValue::Read(const u1 *&p) {
910 const u1* start = p;
911 ElementValue *result;
912 u1 tag = get_u1(p);
913 if (tag != 0 && strchr("BCDFIJSZs", (char) tag) != NULL) {
914 result = BaseTypeElementValue::Read(p);
915 } else if ((char) tag == 'e') {
916 result = EnumTypeElementValue::Read(p);
917 } else if ((char) tag == 'c') {
918 result = ClassTypeElementValue::Read(p);
919 } else if ((char) tag == '[') {
920 result = ArrayTypeElementValue::Read(p);
921 } else if ((char) tag == '@') {
922 result = AnnotationTypeElementValue::Read(p);
923 } else {
924 fprintf(stderr, "Illegal element_value::tag: %d\n", tag);
925 abort();
926 }
927 result->tag_ = tag;
928 result->length_ = p - start;
929 return result;
930 }
931
932 // See sec.4.7.20 of JVM spec.
933 // We preserve AnnotationDefault attributes because they are required
934 // in order to make use of an annotation in new code.
935 struct AnnotationDefaultAttribute : Attribute {
~AnnotationDefaultAttributedevtools_ijar::AnnotationDefaultAttribute936 virtual ~AnnotationDefaultAttribute() {
937 delete default_value_;
938 }
939
Readdevtools_ijar::AnnotationDefaultAttribute940 static AnnotationDefaultAttribute* Read(const u1 *&p,
941 Constant *attribute_name) {
942 AnnotationDefaultAttribute *attr = new AnnotationDefaultAttribute;
943 attr->attribute_name_ = attribute_name;
944 attr->default_value_ = ElementValue::Read(p);
945 return attr;
946 }
947
Writedevtools_ijar::AnnotationDefaultAttribute948 void Write(u1 *&p) {
949 WriteProlog(p, default_value_->length_);
950 default_value_->Write(p);
951 }
952
ExtractClassNamesdevtools_ijar::AnnotationDefaultAttribute953 virtual void ExtractClassNames() {
954 default_value_->ExtractClassNames();
955 }
956
957 ElementValue *default_value_;
958 };
959
960 // See sec.4.7.2 of JVM spec.
961 // We preserve ConstantValue attributes because they are required for
962 // compile-time constant propagation.
963 struct ConstantValueAttribute : Attribute {
964
Readdevtools_ijar::ConstantValueAttribute965 static ConstantValueAttribute* Read(const u1 *&p, Constant *attribute_name) {
966 ConstantValueAttribute *attr = new ConstantValueAttribute;
967 attr->attribute_name_ = attribute_name;
968 attr->constantvalue_ = constant(get_u2be(p));
969 return attr;
970 }
971
Writedevtools_ijar::ConstantValueAttribute972 void Write(u1 *&p) {
973 WriteProlog(p, 2);
974 put_u2be(p, constantvalue_->slot());
975 }
976
977 Constant *constantvalue_;
978 };
979
980 // See sec.4.7.9 of JVM spec.
981 // We preserve Signature attributes because they are required by the
982 // compiler for type-checking of generics.
983 struct SignatureAttribute : Attribute {
984
Readdevtools_ijar::SignatureAttribute985 static SignatureAttribute* Read(const u1 *&p, Constant *attribute_name) {
986 SignatureAttribute *attr = new SignatureAttribute;
987 attr->attribute_name_ = attribute_name;
988 attr->signature_ = constant(get_u2be(p));
989 return attr;
990 }
991
Writedevtools_ijar::SignatureAttribute992 void Write(u1 *&p) {
993 WriteProlog(p, 2);
994 put_u2be(p, signature_->slot());
995 }
996
ExtractClassNamesdevtools_ijar::SignatureAttribute997 virtual void ExtractClassNames() {
998 size_t signature_idx = 0;
999 devtools_ijar::ExtractClassNames(signature_->Display(), &signature_idx);
1000 }
1001
1002 Constant *signature_;
1003 };
1004
1005 // See sec.4.7.15 of JVM spec.
1006 // We preserve Deprecated attributes because they are required by the
1007 // compiler to generate warning messages.
1008 struct DeprecatedAttribute : Attribute {
1009
Readdevtools_ijar::DeprecatedAttribute1010 static DeprecatedAttribute* Read(const u1 *&, Constant *attribute_name) {
1011 DeprecatedAttribute *attr = new DeprecatedAttribute;
1012 attr->attribute_name_ = attribute_name;
1013 return attr;
1014 }
1015
Writedevtools_ijar::DeprecatedAttribute1016 void Write(u1 *&p) {
1017 WriteProlog(p, 0);
1018 }
1019 };
1020
1021 // See sec.4.7.16-17 of JVM spec v3. Includes RuntimeVisible and
1022 // RuntimeInvisible.
1023 //
1024 // We preserve all annotations.
1025 struct AnnotationsAttribute : Attribute {
~AnnotationsAttributedevtools_ijar::AnnotationsAttribute1026 virtual ~AnnotationsAttribute() {
1027 for (size_t i = 0; i < annotations_.size(); i++) {
1028 delete annotations_[i];
1029 }
1030 }
1031
Readdevtools_ijar::AnnotationsAttribute1032 static AnnotationsAttribute* Read(const u1 *&p, Constant *attribute_name) {
1033 AnnotationsAttribute *attr = new AnnotationsAttribute;
1034 attr->attribute_name_ = attribute_name;
1035 u2 num_annotations = get_u2be(p);
1036 for (int ii = 0; ii < num_annotations; ++ii) {
1037 Annotation *annotation = Annotation::Read(p);
1038 attr->annotations_.push_back(annotation);
1039 }
1040 return attr;
1041 }
1042
ExtractClassNamesdevtools_ijar::AnnotationsAttribute1043 virtual void ExtractClassNames() {
1044 for (size_t i = 0; i < annotations_.size(); i++) {
1045 annotations_[i]->ExtractClassNames();
1046 }
1047 }
1048
Writedevtools_ijar::AnnotationsAttribute1049 void Write(u1 *&p) {
1050 WriteProlog(p, -1);
1051 u1 *payload_start = p - 4;
1052 put_u2be(p, annotations_.size());
1053 for (size_t ii = 0; ii < annotations_.size(); ++ii) {
1054 annotations_[ii]->Write(p);
1055 }
1056 put_u4be(payload_start, p - 4 - payload_start); // backpatch length
1057 }
1058
1059 std::vector<Annotation*> annotations_;
1060 };
1061
1062 // See sec.4.7.18-19 of JVM spec. Includes RuntimeVisible and
1063 // RuntimeInvisible.
1064 //
1065 // We preserve all annotations.
1066 struct ParameterAnnotationsAttribute : Attribute {
1067
Readdevtools_ijar::ParameterAnnotationsAttribute1068 static ParameterAnnotationsAttribute* Read(const u1 *&p,
1069 Constant *attribute_name) {
1070 ParameterAnnotationsAttribute *attr = new ParameterAnnotationsAttribute;
1071 attr->attribute_name_ = attribute_name;
1072 u1 num_parameters = get_u1(p);
1073 for (int ii = 0; ii < num_parameters; ++ii) {
1074 std::vector<Annotation*> annotations;
1075 u2 num_annotations = get_u2be(p);
1076 for (int ii = 0; ii < num_annotations; ++ii) {
1077 Annotation *annotation = Annotation::Read(p);
1078 annotations.push_back(annotation);
1079 }
1080 attr->parameter_annotations_.push_back(annotations);
1081 }
1082 return attr;
1083 }
1084
ExtractClassNamesdevtools_ijar::ParameterAnnotationsAttribute1085 virtual void ExtractClassNames() {
1086 for (size_t i = 0; i < parameter_annotations_.size(); i++) {
1087 const std::vector<Annotation*>& annotations = parameter_annotations_[i];
1088 for (size_t j = 0; j < annotations.size(); j++) {
1089 annotations[j]->ExtractClassNames();
1090 }
1091 }
1092 }
1093
Writedevtools_ijar::ParameterAnnotationsAttribute1094 void Write(u1 *&p) {
1095 WriteProlog(p, -1);
1096 u1 *payload_start = p - 4;
1097 put_u1(p, parameter_annotations_.size());
1098 for (size_t ii = 0; ii < parameter_annotations_.size(); ++ii) {
1099 std::vector<Annotation *> &annotations = parameter_annotations_[ii];
1100 put_u2be(p, annotations.size());
1101 for (size_t jj = 0; jj < annotations.size(); ++jj) {
1102 annotations[jj]->Write(p);
1103 }
1104 }
1105 put_u4be(payload_start, p - 4 - payload_start); // backpatch length
1106 }
1107
1108 std::vector<std::vector<Annotation*> > parameter_annotations_;
1109 };
1110
1111 // See sec.4.7.20 of Java 8 JVM spec. Includes RuntimeVisibleTypeAnnotations
1112 // and RuntimeInvisibleTypeAnnotations.
1113 struct TypeAnnotationsAttribute : Attribute {
Readdevtools_ijar::TypeAnnotationsAttribute1114 static TypeAnnotationsAttribute* Read(const u1 *&p, Constant *attribute_name,
1115 u4) {
1116 auto attr = new TypeAnnotationsAttribute;
1117 attr->attribute_name_ = attribute_name;
1118 u2 num_annotations = get_u2be(p);
1119 for (int ii = 0; ii < num_annotations; ++ii) {
1120 TypeAnnotation *annotation = TypeAnnotation::Read(p);
1121 attr->type_annotations_.push_back(annotation);
1122 }
1123 return attr;
1124 }
1125
ExtractClassNamesdevtools_ijar::TypeAnnotationsAttribute1126 virtual void ExtractClassNames() {
1127 for (size_t i = 0; i < type_annotations_.size(); i++) {
1128 type_annotations_[i]->ExtractClassNames();
1129 }
1130 }
1131
Writedevtools_ijar::TypeAnnotationsAttribute1132 void Write(u1 *&p) {
1133 WriteProlog(p, -1);
1134 u1 *payload_start = p - 4;
1135 put_u2be(p, type_annotations_.size());
1136 for (TypeAnnotation *annotation : type_annotations_) {
1137 annotation->Write(p);
1138 }
1139 put_u4be(payload_start, p - 4 - payload_start); // backpatch length
1140 }
1141
1142 std::vector<TypeAnnotation*> type_annotations_;
1143 };
1144
1145 struct GeneralAttribute : Attribute {
Readdevtools_ijar::GeneralAttribute1146 static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name,
1147 u4 attribute_length) {
1148 auto attr = new GeneralAttribute;
1149 attr->attribute_name_ = attribute_name;
1150 attr->attribute_length_ = attribute_length;
1151 attr->attribute_content_ = p;
1152 p += attribute_length;
1153 return attr;
1154 }
1155
Writedevtools_ijar::GeneralAttribute1156 void Write(u1 *&p) {
1157 WriteProlog(p, attribute_length_);
1158 put_n(p, attribute_content_, attribute_length_);
1159 }
1160
1161 u4 attribute_length_;
1162 const u1 *attribute_content_;
1163 };
1164
1165 /**********************************************************************
1166 * *
1167 * ClassFile *
1168 * *
1169 **********************************************************************/
1170
1171 struct HasAttrs {
1172 std::vector<Attribute*> attributes;
1173
1174 void WriteAttrs(u1 *&p);
1175 void ReadAttrs(const u1 *&p);
1176
~HasAttrsdevtools_ijar::HasAttrs1177 virtual ~HasAttrs() {
1178 for (size_t i = 0; i < attributes.size(); i++) {
1179 delete attributes[i];
1180 }
1181 }
1182
ExtractClassNamesdevtools_ijar::HasAttrs1183 void ExtractClassNames() {
1184 for (size_t i = 0; i < attributes.size(); i++) {
1185 attributes[i]->ExtractClassNames();
1186 }
1187 }
1188 };
1189
1190 // A field or method.
1191 // See sec.4.5 and 4.6 of JVM spec.
1192 struct Member : HasAttrs {
1193 u2 access_flags;
1194 Constant *name;
1195 Constant *descriptor;
1196
Readdevtools_ijar::Member1197 static Member* Read(const u1 *&p) {
1198 Member *m = new Member;
1199 m->access_flags = get_u2be(p);
1200 m->name = constant(get_u2be(p));
1201 m->descriptor = constant(get_u2be(p));
1202 m->ReadAttrs(p);
1203 return m;
1204 }
1205
Writedevtools_ijar::Member1206 void Write(u1 *&p) {
1207 put_u2be(p, access_flags);
1208 put_u2be(p, name->slot());
1209 put_u2be(p, descriptor->slot());
1210 WriteAttrs(p);
1211 }
1212 };
1213
1214 // See sec.4.1 of JVM spec.
1215 struct ClassFile : HasAttrs {
1216
1217 size_t length;
1218
1219 // Header:
1220 u4 magic;
1221 u2 major;
1222 u2 minor;
1223
1224 // Body:
1225 u2 access_flags;
1226 Constant *this_class;
1227 Constant *super_class;
1228 std::vector<Constant*> interfaces;
1229 std::vector<Member*> fields;
1230 std::vector<Member*> methods;
1231
~ClassFiledevtools_ijar::ClassFile1232 virtual ~ClassFile() {
1233 for (size_t i = 0; i < fields.size(); i++) {
1234 delete fields[i];
1235 }
1236
1237 for (size_t i = 0; i < methods.size(); i++) {
1238 delete methods[i];
1239 }
1240
1241 // Constants do not need to be deleted; they are owned by the constant pool.
1242 }
1243
1244 void WriteClass(u1 *&p);
1245
1246 bool ReadConstantPool(const u1 *&p);
1247
1248 void StripIfAnonymous();
1249
WriteHeaderdevtools_ijar::ClassFile1250 void WriteHeader(u1 *&p) {
1251 put_u4be(p, magic);
1252 put_u2be(p, major);
1253 put_u2be(p, minor);
1254
1255 put_u2be(p, const_pool_out.size());
1256 for (u2 ii = 1; ii < const_pool_out.size(); ++ii) {
1257 if (const_pool_out[ii] != NULL) { // NB: NULLs appear after long/double.
1258 const_pool_out[ii]->Write(p);
1259 }
1260 }
1261 }
1262
WriteBodydevtools_ijar::ClassFile1263 void WriteBody(u1 *&p) {
1264 put_u2be(p, access_flags);
1265 put_u2be(p, this_class->slot());
1266 put_u2be(p, super_class == NULL ? 0 : super_class->slot());
1267 put_u2be(p, interfaces.size());
1268 for (size_t ii = 0; ii < interfaces.size(); ++ii) {
1269 put_u2be(p, interfaces[ii]->slot());
1270 }
1271 put_u2be(p, fields.size());
1272 for (size_t ii = 0; ii < fields.size(); ++ii) {
1273 fields[ii]->Write(p);
1274 }
1275 put_u2be(p, methods.size());
1276 for (size_t ii = 0; ii < methods.size(); ++ii) {
1277 methods[ii]->Write(p);
1278 }
1279
1280 Attribute* inner_classes = NULL;
1281
1282 // Make the inner classes attribute the last, so that it can know which
1283 // constants were needed
1284 for (size_t ii = 0; ii < attributes.size(); ii++) {
1285 if (attributes[ii]->attribute_name_->Display() == "InnerClasses") {
1286 inner_classes = attributes[ii];
1287 attributes.erase(attributes.begin() + ii);
1288 break;
1289 }
1290 }
1291
1292 if (inner_classes != NULL) {
1293 attributes.push_back(inner_classes);
1294 }
1295
1296 WriteAttrs(p);
1297 }
1298
1299 };
1300
ReadAttrs(const u1 * & p)1301 void HasAttrs::ReadAttrs(const u1 *&p) {
1302 u2 attributes_count = get_u2be(p);
1303 for (int ii = 0; ii < attributes_count; ii++) {
1304 Constant *attribute_name = constant(get_u2be(p));
1305 u4 attribute_length = get_u4be(p);
1306
1307 std::string attr_name = attribute_name->Display();
1308 if (attr_name == "SourceFile" ||
1309 attr_name == "LineNumberTable" ||
1310 attr_name == "LocalVariableTable" ||
1311 attr_name == "LocalVariableTypeTable" ||
1312 attr_name == "Code" ||
1313 attr_name == "Synthetic" ||
1314 attr_name == "BootstrapMethods") {
1315 p += attribute_length; // drop these attributes
1316 } else if (attr_name == "Exceptions") {
1317 attributes.push_back(ExceptionsAttribute::Read(p, attribute_name));
1318 } else if (attr_name == "Signature") {
1319 attributes.push_back(SignatureAttribute::Read(p, attribute_name));
1320 } else if (attr_name == "Deprecated") {
1321 attributes.push_back(DeprecatedAttribute::Read(p, attribute_name));
1322 } else if (attr_name == "EnclosingMethod") {
1323 attributes.push_back(EnclosingMethodAttribute::Read(p, attribute_name));
1324 } else if (attr_name == "InnerClasses") {
1325 // TODO(bazel-team): omit private inner classes
1326 attributes.push_back(InnerClassesAttribute::Read(p, attribute_name));
1327 } else if (attr_name == "AnnotationDefault") {
1328 attributes.push_back(AnnotationDefaultAttribute::Read(p, attribute_name));
1329 } else if (attr_name == "ConstantValue") {
1330 attributes.push_back(ConstantValueAttribute::Read(p, attribute_name));
1331 } else if (attr_name == "RuntimeVisibleAnnotations" ||
1332 attr_name == "RuntimeInvisibleAnnotations") {
1333 attributes.push_back(AnnotationsAttribute::Read(p, attribute_name));
1334 } else if (attr_name == "RuntimeVisibleParameterAnnotations" ||
1335 attr_name == "RuntimeInvisibleParameterAnnotations") {
1336 attributes.push_back(
1337 ParameterAnnotationsAttribute::Read(p, attribute_name));
1338 } else if (attr_name == "Scala" ||
1339 attr_name == "ScalaSig" ||
1340 attr_name == "ScalaInlineInfo") {
1341 // These are opaque blobs, so can be handled with a general
1342 // attribute handler
1343 attributes.push_back(GeneralAttribute::Read(p, attribute_name,
1344 attribute_length));
1345 } else if (attr_name == "RuntimeVisibleTypeAnnotations" ||
1346 attr_name == "RuntimeInvisibleTypeAnnotations") {
1347 // JSR 308: annotations on types. JDK 7 has no use for these yet, but the
1348 // Checkers Framework relies on them.
1349 attributes.push_back(TypeAnnotationsAttribute::Read(p, attribute_name,
1350 attribute_length));
1351 } else {
1352 // Skip over unknown attributes with a warning. The JVM spec
1353 // says this is ok, so long as we handle the mandatory attributes.
1354 fprintf(stderr, "ijar: skipping unknown attribute: \"%s\".\n",
1355 attr_name.c_str());
1356 p += attribute_length;
1357 }
1358 }
1359 }
1360
WriteAttrs(u1 * & p)1361 void HasAttrs::WriteAttrs(u1 *&p) {
1362 u1* p_size = p;
1363
1364 put_u2be(p, 0);
1365 int n_written_attrs = 0;
1366 for (size_t ii = 0; ii < attributes.size(); ii++) {
1367 u1* before = p;
1368 attributes[ii]->Write(p);
1369 if (p != before) {
1370 n_written_attrs++;
1371 }
1372 }
1373
1374 put_u2be(p_size, n_written_attrs);
1375 }
1376
1377 // See sec.4.4 of JVM spec.
ReadConstantPool(const u1 * & p)1378 bool ClassFile::ReadConstantPool(const u1 *&p) {
1379
1380 const_pool_in.clear();
1381 const_pool_in.push_back(NULL); // dummy first item
1382
1383 u2 cp_count = get_u2be(p);
1384 for (int ii = 1; ii < cp_count; ++ii) {
1385 u1 tag = get_u1(p);
1386
1387 if (devtools_ijar::verbose) {
1388 fprintf(stderr, "cp[%d/%d] = tag %d\n", ii, cp_count, tag);
1389 }
1390
1391 switch(tag) {
1392 case CONSTANT_Class: {
1393 u2 name_index = get_u2be(p);
1394 const_pool_in.push_back(new Constant_Class(name_index));
1395 break;
1396 }
1397 case CONSTANT_FieldRef:
1398 case CONSTANT_Methodref:
1399 case CONSTANT_Interfacemethodref: {
1400 u2 class_index = get_u2be(p);
1401 u2 nti = get_u2be(p);
1402 const_pool_in.push_back(new Constant_FMIref(tag, class_index, nti));
1403 break;
1404 }
1405 case CONSTANT_String: {
1406 u2 string_index = get_u2be(p);
1407 const_pool_in.push_back(new Constant_String(string_index));
1408 break;
1409 }
1410 case CONSTANT_NameAndType: {
1411 u2 name_index = get_u2be(p);
1412 u2 descriptor_index = get_u2be(p);
1413 const_pool_in.push_back(
1414 new Constant_NameAndType(name_index, descriptor_index));
1415 break;
1416 }
1417 case CONSTANT_Utf8: {
1418 u2 length = get_u2be(p);
1419 if (devtools_ijar::verbose) {
1420 fprintf(stderr, "Utf8: \"%s\" (%d)\n",
1421 std::string((const char*) p, length).c_str(), length);
1422 }
1423
1424 const_pool_in.push_back(new Constant_Utf8(length, p));
1425 p += length;
1426 break;
1427 }
1428 case CONSTANT_Integer:
1429 case CONSTANT_Float: {
1430 u4 bytes = get_u4be(p);
1431 const_pool_in.push_back(new Constant_IntegerOrFloat(tag, bytes));
1432 break;
1433 }
1434 case CONSTANT_Long:
1435 case CONSTANT_Double: {
1436 u4 high_bytes = get_u4be(p);
1437 u4 low_bytes = get_u4be(p);
1438 const_pool_in.push_back(
1439 new Constant_LongOrDouble(tag, high_bytes, low_bytes));
1440 // Longs and doubles occupy two constant pool slots.
1441 // ("In retrospect, making 8-byte constants take two "constant
1442 // pool entries was a poor choice." --JVM Spec.)
1443 const_pool_in.push_back(NULL);
1444 ii++;
1445 break;
1446 }
1447 case CONSTANT_MethodHandle: {
1448 u1 reference_kind = get_u1(p);
1449 u2 reference_index = get_u2be(p);
1450 const_pool_in.push_back(
1451 new Constant_MethodHandle(reference_kind, reference_index));
1452 break;
1453 }
1454 case CONSTANT_MethodType: {
1455 u2 descriptor_index = get_u2be(p);
1456 const_pool_in.push_back(new Constant_MethodType(descriptor_index));
1457 break;
1458 }
1459 case CONSTANT_InvokeDynamic: {
1460 u2 bootstrap_method_attr = get_u2be(p);
1461 u2 name_name_type_index = get_u2be(p);
1462 const_pool_in.push_back(new Constant_InvokeDynamic(
1463 bootstrap_method_attr, name_name_type_index));
1464 break;
1465 }
1466 default: {
1467 fprintf(stderr, "Unknown constant: %02x. Passing class through.\n",
1468 tag);
1469 return false;
1470 }
1471 }
1472 }
1473
1474 return true;
1475 }
1476
1477 // Anonymous inner classes are stripped to opaque classes that only extend
1478 // Object. None of their methods or fields are accessible anyway.
StripIfAnonymous()1479 void ClassFile::StripIfAnonymous() {
1480 int enclosing_index = -1;
1481 int inner_classes_index = -1;
1482
1483 for (size_t ii = 0; ii < attributes.size(); ++ii) {
1484 if (attributes[ii]->attribute_name_->Display() == "EnclosingMethod") {
1485 enclosing_index = ii;
1486 } else if (attributes[ii]->attribute_name_->Display() == "InnerClasses") {
1487 inner_classes_index = ii;
1488 }
1489 }
1490
1491 // Presence of an EnclosingMethod attribute indicates a local or anonymous
1492 // class, which can be stripped.
1493 if (enclosing_index > -1) {
1494 // Clear the signature to only extend java.lang.Object.
1495 super_class = NULL;
1496 interfaces.clear();
1497
1498 // Clear away all fields (implementation details).
1499 for (size_t ii = 0; ii < fields.size(); ++ii) {
1500 delete fields[ii];
1501 }
1502 fields.clear();
1503
1504 // Clear away all methods (implementation details).
1505 for (size_t ii = 0; ii < methods.size(); ++ii) {
1506 delete methods[ii];
1507 }
1508 methods.clear();
1509
1510 // Only preserve the InnerClasses attribute to comply with the spec.
1511 Attribute *attr = NULL;
1512 for (size_t ii = 0; ii < attributes.size(); ++ii) {
1513 if (static_cast<int>(ii) != inner_classes_index) {
1514 delete attributes[ii];
1515 } else {
1516 attr = attributes[ii];
1517 }
1518 }
1519 attributes.clear();
1520 if (attr != NULL) {
1521 attributes.push_back(attr);
1522 }
1523 }
1524 }
1525
ReadClass(const void * classdata,size_t length)1526 static ClassFile *ReadClass(const void *classdata, size_t length) {
1527 const u1 *p = (u1*) classdata;
1528
1529 ClassFile *clazz = new ClassFile;
1530
1531 clazz->length = length;
1532
1533 clazz->magic = get_u4be(p);
1534 if (clazz->magic != 0xCAFEBABE) {
1535 fprintf(stderr, "Bad magic %" PRIx32 "\n", clazz->magic);
1536 abort();
1537 }
1538 clazz->major = get_u2be(p);
1539 clazz->minor = get_u2be(p);
1540
1541 if (!clazz->ReadConstantPool(p)) {
1542 delete clazz;
1543 return NULL;
1544 }
1545
1546 clazz->access_flags = get_u2be(p);
1547 clazz->this_class = constant(get_u2be(p));
1548 class_name = clazz->this_class;
1549
1550 u2 super_class_id = get_u2be(p);
1551 clazz->super_class = super_class_id == 0 ? NULL : constant(super_class_id);
1552
1553 u2 interfaces_count = get_u2be(p);
1554 for (int ii = 0; ii < interfaces_count; ++ii) {
1555 clazz->interfaces.push_back(constant(get_u2be(p)));
1556 }
1557
1558 u2 fields_count = get_u2be(p);
1559 for (int ii = 0; ii < fields_count; ++ii) {
1560 Member *field = Member::Read(p);
1561
1562 if (!(field->access_flags & ACC_PRIVATE)) { // drop private fields
1563 clazz->fields.push_back(field);
1564 }
1565 }
1566
1567 u2 methods_count = get_u2be(p);
1568 for (int ii = 0; ii < methods_count; ++ii) {
1569 Member *method = Member::Read(p);
1570
1571 // drop class initializers
1572 if (method->name->Display() == "<clinit>") continue;
1573
1574 if (!(method->access_flags & ACC_PRIVATE)) { // drop private methods
1575 clazz->methods.push_back(method);
1576 }
1577 }
1578
1579 clazz->ReadAttrs(p);
1580 clazz->StripIfAnonymous();
1581
1582 return clazz;
1583 }
1584
1585 // In theory, '/' is also reserved, but it's okay if we just parse package
1586 // identifiers as part of the class name. Note that signatures are UTF-8, but
1587 // this works just as well as in plain ASCII.
1588 static const char *SIGNATURE_NON_IDENTIFIER_CHARS = ".;[<>:";
1589
Expect(const std::string & desc,size_t * p,char expected)1590 void Expect(const std::string& desc, size_t* p, char expected) {
1591 if (desc[*p] != expected) {
1592 fprintf(stderr, "Expected '%c' in '%s' at %zd in signature\n",
1593 expected, desc.substr(*p).c_str(), *p);
1594 exit(1);
1595 }
1596
1597 *p += 1;
1598 }
1599
1600 // These functions form a crude recursive descent parser for descriptors and
1601 // signatures in class files (see JVM spec 4.3).
1602 //
1603 // This parser is a bit more liberal than the spec, but this should be fine,
1604 // because it accepts all valid class files and croaks only on invalid ones.
1605 void ParseFromClassTypeSignature(const std::string& desc, size_t* p);
1606 void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p);
1607 void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p);
1608 void ParseIdentifier(const std::string& desc, size_t* p);
1609 void ParseTypeArgumentsOpt(const std::string& desc, size_t* p);
1610 void ParseMethodDescriptor(const std::string& desc, size_t* p);
1611
ParseClassTypeSignature(const std::string & desc,size_t * p)1612 void ParseClassTypeSignature(const std::string& desc, size_t* p) {
1613 Expect(desc, p, 'L');
1614 ParseSimpleClassTypeSignature(desc, p);
1615 ParseClassTypeSignatureSuffix(desc, p);
1616 Expect(desc, p, ';');
1617 }
1618
ParseSimpleClassTypeSignature(const std::string & desc,size_t * p)1619 void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p) {
1620 ParseIdentifier(desc, p);
1621 ParseTypeArgumentsOpt(desc, p);
1622 }
1623
ParseClassTypeSignatureSuffix(const std::string & desc,size_t * p)1624 void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p) {
1625 while (desc[*p] == '.') {
1626 *p += 1;
1627 ParseSimpleClassTypeSignature(desc, p);
1628 }
1629 }
1630
ParseIdentifier(const std::string & desc,size_t * p)1631 void ParseIdentifier(const std::string& desc, size_t* p) {
1632 size_t next = desc.find_first_of(SIGNATURE_NON_IDENTIFIER_CHARS, *p);
1633 std::string id = desc.substr(*p, next - *p);
1634 used_class_names.insert(id);
1635 *p = next;
1636 }
1637
ParseTypeArgumentsOpt(const std::string & desc,size_t * p)1638 void ParseTypeArgumentsOpt(const std::string& desc, size_t* p) {
1639 if (desc[*p] != '<') {
1640 return;
1641 }
1642
1643 *p += 1;
1644 while (desc[*p] != '>') {
1645 switch (desc[*p]) {
1646 case '*':
1647 *p += 1;
1648 break;
1649
1650 case '+':
1651 case '-':
1652 *p += 1;
1653 ExtractClassNames(desc, p);
1654 break;
1655
1656 default:
1657 ExtractClassNames(desc, p);
1658 break;
1659 }
1660 }
1661
1662 *p += 1;
1663 }
1664
ParseMethodDescriptor(const std::string & desc,size_t * p)1665 void ParseMethodDescriptor(const std::string& desc, size_t* p) {
1666 Expect(desc, p, '(');
1667 while (desc[*p] != ')') {
1668 ExtractClassNames(desc, p);
1669 }
1670
1671 Expect(desc, p, ')');
1672 ExtractClassNames(desc, p);
1673 }
1674
ParseFormalTypeParameters(const std::string & desc,size_t * p)1675 void ParseFormalTypeParameters(const std::string& desc, size_t* p) {
1676 Expect(desc, p, '<');
1677 while (desc[*p] != '>') {
1678 ParseIdentifier(desc, p);
1679 Expect(desc, p, ':');
1680 if (desc[*p] != ':' && desc[*p] != '>') {
1681 ExtractClassNames(desc, p);
1682 }
1683
1684 while (desc[*p] == ':') {
1685 Expect(desc, p, ':');
1686 ExtractClassNames(desc, p);
1687 }
1688 }
1689
1690 Expect(desc, p, '>');
1691 }
1692
ExtractClassNames(const std::string & desc,size_t * p)1693 void ExtractClassNames(const std::string& desc, size_t* p) {
1694 switch (desc[*p]) {
1695 case '<':
1696 ParseFormalTypeParameters(desc, p);
1697 ExtractClassNames(desc, p);
1698 break;
1699
1700 case 'L':
1701 ParseClassTypeSignature(desc, p);
1702 break;
1703
1704 case '[':
1705 *p += 1;
1706 ExtractClassNames(desc, p);
1707 break;
1708
1709 case 'T':
1710 *p += 1;
1711 ParseIdentifier(desc, p);
1712 Expect(desc, p, ';');
1713 break;
1714
1715 case '(':
1716 ParseMethodDescriptor(desc, p);
1717 break;
1718
1719 case 'B':
1720 case 'C':
1721 case 'D':
1722 case 'F':
1723 case 'I':
1724 case 'J':
1725 case 'S':
1726 case 'Z':
1727 case 'V':
1728 *p += 1;
1729 break;
1730
1731 default:
1732 fprintf(stderr, "Invalid signature %s\n", desc.substr(*p).c_str());
1733 }
1734 }
1735
WriteClass(u1 * & p)1736 void ClassFile::WriteClass(u1 *&p) {
1737 used_class_names.clear();
1738 std::vector<Member *> members;
1739 members.insert(members.end(), fields.begin(), fields.end());
1740 members.insert(members.end(), methods.begin(), methods.end());
1741 ExtractClassNames();
1742 for (size_t i = 0; i < members.size(); i++) {
1743 Member *member = members[i];
1744 size_t idx = 0;
1745 devtools_ijar::ExtractClassNames(member->descriptor->Display(), &idx);
1746 member->ExtractClassNames();
1747 }
1748
1749 // We have to write the body out before the header in order to reference
1750 // the essential constants and populate the output constant pool:
1751 u1 *body = new u1[length];
1752 u1 *q = body;
1753 WriteBody(q); // advances q
1754 u4 body_length = q - body;
1755
1756 WriteHeader(p); // advances p
1757 put_n(p, body, body_length);
1758 delete[] body;
1759 }
1760
1761
StripClass(u1 * & classdata_out,const u1 * classdata_in,size_t in_length)1762 void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) {
1763 ClassFile *clazz = ReadClass(classdata_in, in_length);
1764 if (clazz == NULL) {
1765 // Class is invalid. Simply copy it to the output and call it a day.
1766 put_n(classdata_out, classdata_in, in_length);
1767 } else {
1768
1769 // Constant pool item zero is a dummy entry. Setting it marks the
1770 // beginning of the output phase; calls to Constant::slot() will
1771 // fail if called prior to this.
1772 const_pool_out.push_back(NULL);
1773 clazz->WriteClass(classdata_out);
1774
1775 delete clazz;
1776 }
1777
1778 // Now clean up all the mess we left behind.
1779
1780 for (size_t i = 0; i < const_pool_in.size(); i++) {
1781 delete const_pool_in[i];
1782 }
1783
1784 const_pool_in.clear();
1785 const_pool_out.clear();
1786 }
1787
1788 } // namespace devtools_ijar
1789