1 /*
2  * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #ifndef SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
26 #define SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
27 
28 #include "jvmtifiles/jvmtiEnv.hpp"
29 
30 
31 class JvmtiConstantPoolReconstituter : public StackObj {
32  private:
33   int                  _cpool_size;
34   SymbolHashMap*       _symmap;
35   SymbolHashMap*       _classmap;
36   constantPoolHandle   _cpool;
37   instanceKlassHandle  _ikh;
38   jvmtiError           _err;
39 
40  protected:
ikh()41   instanceKlassHandle  ikh()     { return _ikh; };
cpool()42   constantPoolHandle   cpool()   { return _cpool; };
43 
symbol_to_cpool_index(Symbol * sym)44   u2 symbol_to_cpool_index(Symbol* sym) {
45     return _symmap->symbol_to_value(sym);
46   }
47 
class_symbol_to_cpool_index(Symbol * sym)48   u2 class_symbol_to_cpool_index(Symbol* sym) {
49     return _classmap->symbol_to_value(sym);
50   }
51 
52  public:
53   // Calls to this constructor must be proceeded by a ResourceMark
54   // and a HandleMark
JvmtiConstantPoolReconstituter(instanceKlassHandle ikh)55   JvmtiConstantPoolReconstituter(instanceKlassHandle ikh){
56     set_error(JVMTI_ERROR_NONE);
57     _ikh = ikh;
58     _cpool = constantPoolHandle(Thread::current(), ikh->constants());
59     _symmap = new SymbolHashMap();
60     _classmap = new SymbolHashMap();
61     _cpool_size = _cpool->hash_entries_to(_symmap, _classmap);
62     if (_cpool_size == 0) {
63       set_error(JVMTI_ERROR_OUT_OF_MEMORY);
64     } else if (_cpool_size < 0) {
65       set_error(JVMTI_ERROR_INTERNAL);
66     }
67   }
68 
~JvmtiConstantPoolReconstituter()69   ~JvmtiConstantPoolReconstituter() {
70     if (_symmap != NULL) {
71       delete _symmap;
72       _symmap = NULL;
73     }
74     if (_classmap != NULL) {
75       delete _classmap;
76       _classmap = NULL;
77     }
78   }
79 
80 
set_error(jvmtiError err)81   void       set_error(jvmtiError err)    { _err = err; }
get_error()82   jvmtiError get_error()                  { return _err; }
83 
cpool_size()84   int cpool_size()                        { return _cpool_size; }
85 
copy_cpool_bytes(unsigned char * cpool_bytes)86   void copy_cpool_bytes(unsigned char *cpool_bytes) {
87     if (cpool_bytes == NULL) {
88       assert(cpool_bytes != NULL, "cpool_bytes pointer must not be NULL");
89       return;
90     }
91     cpool()->copy_cpool_bytes(cpool_size(), _symmap, cpool_bytes);
92   }
93 };
94 
95 
96 class JvmtiClassFileReconstituter : public JvmtiConstantPoolReconstituter {
97  private:
98   size_t               _buffer_size;
99   u1*                  _buffer;
100   u1*                  _buffer_ptr;
101   Thread*              _thread;
102 
103   enum {
104     // initial size should be power of two
105     initial_buffer_size = 1024
106   };
107 
thread()108   inline Thread* thread() { return _thread; }
109 
110   void write_class_file_format();
111   void write_field_infos();
112   void write_method_infos();
113   void write_method_info(methodHandle method);
114   void write_code_attribute(methodHandle method);
115   void write_exceptions_attribute(ConstMethod* const_method);
116   void write_synthetic_attribute();
117   void write_class_attributes();
118   void write_source_file_attribute();
119   void write_source_debug_extension_attribute();
120   u2 line_number_table_entries(methodHandle method);
121   void write_line_number_table_attribute(methodHandle method, u2 num_entries);
122   void write_local_variable_table_attribute(methodHandle method, u2 num_entries);
123   void write_local_variable_type_table_attribute(methodHandle method, u2 num_entries);
124   void write_stackmap_table_attribute(methodHandle method, int stackmap_table_len);
125   u2 inner_classes_attribute_length();
126   void write_inner_classes_attribute(int length);
127   void write_signature_attribute(u2 generic_signaure_index);
128   void write_attribute_name_index(const char* name);
129   void write_annotations_attribute(const char* attr_name, AnnotationArray* annos);
130   void write_bootstrapmethod_attribute();
131 
132   address writeable_address(size_t size);
133   void write_u1(u1 x);
134   void write_u2(u2 x);
135   void write_u4(u4 x);
136   void write_u8(u8 x);
137 
138  public:
139   // Calls to this constructor must be proceeded by a ResourceMark
140   // and a HandleMark
JvmtiClassFileReconstituter(instanceKlassHandle ikh)141   JvmtiClassFileReconstituter(instanceKlassHandle ikh) :
142                                       JvmtiConstantPoolReconstituter(ikh) {
143     _buffer_size = initial_buffer_size;
144     _buffer = _buffer_ptr = NEW_RESOURCE_ARRAY(u1, _buffer_size);
145     _thread = Thread::current();
146     write_class_file_format();
147   };
148 
class_file_size()149   size_t class_file_size()    { return _buffer_ptr - _buffer; }
150 
class_file_bytes()151   u1* class_file_bytes()      { return _buffer; }
152 
153   static void copy_bytecodes(methodHandle method, unsigned char* bytecodes);
154 };
155 
156 #endif // SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
157