1/*
2 * Copyright (c) 2005, 2017, 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
31class JvmtiConstantPoolReconstituter : public StackObj {
32 private:
33  int                  _cpool_size;
34  SymbolHashMap*       _symmap;
35  SymbolHashMap*       _classmap;
36  constantPoolHandle   _cpool;
37  InstanceKlass*       _ik;
38  jvmtiError           _err;
39
40 protected:
41  InstanceKlass*  ik()           { return _ik; };
42  constantPoolHandle   cpool()   { return _cpool; };
43
44  u2 symbol_to_cpool_index(Symbol* sym) {
45    return _symmap->symbol_to_value(sym);
46  }
47
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
55  JvmtiConstantPoolReconstituter(InstanceKlass* ik){
56    set_error(JVMTI_ERROR_NONE);
57    _ik = ik;
58    _cpool = constantPoolHandle(Thread::current(), ik->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
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
81  void       set_error(jvmtiError err)    { _err = err; }
82  jvmtiError get_error()                  { return _err; }
83
84  int cpool_size()                        { return _cpool_size; }
85
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
96class 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
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(const methodHandle& method);
114  void write_code_attribute(const 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(const methodHandle& method);
121  void write_line_number_table_attribute(const methodHandle& method, u2 num_entries);
122  void write_local_variable_table_attribute(const methodHandle& method, u2 num_entries);
123  void write_local_variable_type_table_attribute(const methodHandle& method, u2 num_entries);
124  void write_stackmap_table_attribute(const 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
141  JvmtiClassFileReconstituter(InstanceKlass* ik) :
142                                      JvmtiConstantPoolReconstituter(ik) {
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
149  size_t class_file_size()    { return _buffer_ptr - _buffer; }
150
151  u1* class_file_bytes()      { return _buffer; }
152
153  static void copy_bytecodes(const methodHandle& method, unsigned char* bytecodes);
154};
155
156#endif // SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
157