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

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

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

Powered by Google App Engine
This is Rietveld 408576698