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