summaryrefslogtreecommitdiffstats
path: root/compiler/oat_writer.h
blob: 1f97bf853c63765d36155da33327b5a23fe40113 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_SRC_OAT_WRITER_H_
#define ART_SRC_OAT_WRITER_H_

#include <stdint.h>

#include <cstddef>

#include "driver/compiler_driver.h"
#include "mem_map.h"
#include "oat.h"
#include "mirror/class.h"
#include "safe_map.h"
#include "UniquePtr.h"

namespace art {

class OutputStream;

// OatHeader         variable length with count of D OatDexFiles
//
// OatDexFile[0]     one variable sized OatDexFile with offsets to Dex and OatClasses
// OatDexFile[1]
// ...
// OatDexFile[D]
//
// Dex[0]            one variable sized DexFile for each OatDexFile.
// Dex[1]            these are literal copies of the input .dex files.
// ...
// Dex[D]
//
// OatClass[0]       one variable sized OatClass for each of C DexFile::ClassDefs
// OatClass[1]       contains OatClass entries with class status, offsets to code, etc.
// ...
// OatClass[C]
//
// padding           if necessary so that the following code will be page aligned
//
// CompiledMethod    one variable sized blob with the contents of each CompiledMethod
// CompiledMethod
// CompiledMethod
// CompiledMethod
// CompiledMethod
// CompiledMethod
// ...
// CompiledMethod
//
class OatWriter {
 public:
  // Write an oat file. Returns true on success, false on failure.
  static bool Create(OutputStream& out,
                     const std::vector<const DexFile*>& dex_files,
                     uint32_t image_file_location_oat_checksum,
                     uint32_t image_file_location_oat_begin,
                     const std::string& image_file_location,
                     const CompilerDriver& compiler)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

 private:
  OatWriter(const std::vector<const DexFile*>& dex_files,
            uint32_t image_file_location_oat_checksum,
            uint32_t image_file_location_oat_begin,
            const std::string& image_file_location,
            const CompilerDriver* compiler) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  ~OatWriter();

  size_t InitOatHeader();
  size_t InitOatDexFiles(size_t offset);
  size_t InitDexFiles(size_t offset);
  size_t InitOatClasses(size_t offset);
  size_t InitOatCode(size_t offset)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  size_t InitOatCodeDexFiles(size_t offset)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  size_t InitOatCodeDexFile(size_t offset,
                            size_t& oat_class_index,
                            const DexFile& dex_file)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  size_t InitOatCodeClassDef(size_t offset,
                             size_t oat_class_index, size_t class_def_index,
                             const DexFile& dex_file,
                             const DexFile::ClassDef& class_def)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  size_t InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t class_def_index,
                           size_t class_def_method_index, bool is_native, InvokeType type,
                           uint32_t method_idx, const DexFile*)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  bool Write(OutputStream& out);
  bool WriteTables(OutputStream& out);
  size_t WriteCode(OutputStream& out);
  size_t WriteCodeDexFiles(OutputStream& out, size_t offset);
  size_t WriteCodeDexFile(OutputStream& out, size_t offset, size_t& oat_class_index,
                          const DexFile& dex_file);
  size_t WriteCodeClassDef(OutputStream& out, size_t offset, size_t oat_class_index,
                           const DexFile& dex_file, const DexFile::ClassDef& class_def);
  size_t WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_class_index,
                         size_t class_def_method_index, bool is_static, uint32_t method_idx,
                         const DexFile& dex_file);

  void ReportWriteFailure(const char* what, uint32_t method_idx, const DexFile& dex_file,
                          OutputStream& out) const;

  class OatDexFile {
   public:
    explicit OatDexFile(size_t offset, const DexFile& dex_file);
    size_t SizeOf() const;
    void UpdateChecksum(OatHeader& oat_header) const;
    bool Write(OatWriter* oat_writer, OutputStream& out) const;

    // Offset of start of OatDexFile from beginning of OatHeader. It is
    // used to validate file position when writing.
    size_t offset_;

    // data to write
    uint32_t dex_file_location_size_;
    const uint8_t* dex_file_location_data_;
    uint32_t dex_file_location_checksum_;
    uint32_t dex_file_offset_;
    std::vector<uint32_t> methods_offsets_;

   private:
    DISALLOW_COPY_AND_ASSIGN(OatDexFile);
  };

  class OatClass {
   public:
    explicit OatClass(size_t offset, mirror::Class::Status status, uint32_t methods_count);
    size_t GetOatMethodOffsetsOffsetFromOatHeader(size_t class_def_method_index_) const;
    size_t GetOatMethodOffsetsOffsetFromOatClass(size_t class_def_method_index_) const;
    size_t SizeOf() const;
    void UpdateChecksum(OatHeader& oat_header) const;
    bool Write(OatWriter* oat_writer, OutputStream& out) const;

    // Offset of start of OatClass from beginning of OatHeader. It is
    // used to validate file position when writing. For Portable, it
    // is also used to calculate the position of the OatMethodOffsets
    // so that code pointers within the OatMethodOffsets can be
    // patched to point to code in the Portable .o ELF objects.
    size_t offset_;

    // data to write
    mirror::Class::Status status_;
    std::vector<OatMethodOffsets> method_offsets_;

   private:
    DISALLOW_COPY_AND_ASSIGN(OatClass);
  };

  const CompilerDriver* const compiler_driver_;

  // note OatFile does not take ownership of the DexFiles
  const std::vector<const DexFile*>* dex_files_;

  // dependencies on the image.
  uint32_t image_file_location_oat_checksum_;
  uint32_t image_file_location_oat_begin_;
  std::string image_file_location_;

  // data to write
  OatHeader* oat_header_;
  std::vector<OatDexFile*> oat_dex_files_;
  std::vector<OatClass*> oat_classes_;
  UniquePtr<const std::vector<uint8_t> > interpreter_to_interpreter_entry_;
  UniquePtr<const std::vector<uint8_t> > interpreter_to_quick_entry_;
  UniquePtr<const std::vector<uint8_t> > portable_resolution_trampoline_;
  UniquePtr<const std::vector<uint8_t> > quick_resolution_trampoline_;

  // output stats
  uint32_t size_dex_file_alignment_;
  uint32_t size_executable_offset_alignment_;
  uint32_t size_oat_header_;
  uint32_t size_oat_header_image_file_location_;
  uint32_t size_dex_file_;
  uint32_t size_interpreter_to_interpreter_entry_;
  uint32_t size_interpreter_to_quick_entry_;
  uint32_t size_portable_resolution_trampoline_;
  uint32_t size_quick_resolution_trampoline_;
  uint32_t size_stubs_alignment_;
  uint32_t size_code_size_;
  uint32_t size_code_;
  uint32_t size_code_alignment_;
  uint32_t size_mapping_table_;
  uint32_t size_vmap_table_;
  uint32_t size_gc_map_;
  uint32_t size_oat_dex_file_location_size_;
  uint32_t size_oat_dex_file_location_data_;
  uint32_t size_oat_dex_file_location_checksum_;
  uint32_t size_oat_dex_file_offset_;
  uint32_t size_oat_dex_file_methods_offsets_;
  uint32_t size_oat_class_status_;
  uint32_t size_oat_class_method_offsets_;

  template <class T> struct MapCompare {
   public:
    bool operator() (const T* const &a, const T* const &b) const {
      return *a < *b;
    }
  };

  // code mappings for deduplication
  SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > code_offsets_;
  SafeMap<const std::vector<uint16_t>*, uint32_t, MapCompare<std::vector<uint16_t> > > vmap_table_offsets_;
  SafeMap<const std::vector<uint32_t>*, uint32_t, MapCompare<std::vector<uint32_t> > > mapping_table_offsets_;
  SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > gc_map_offsets_;

  DISALLOW_COPY_AND_ASSIGN(OatWriter);
};

}  // namespace art

#endif  // ART_SRC_OAT_WRITER_H_