1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Define utility class to wrap/unwrap bitcode files. Does wrapping/unwrapping
18// in such a way that the wrappered bitcode file is still a bitcode file.
19
20#ifndef LLVM_WRAP_BITCODE_WRAPPERER_H__
21#define LLVM_WRAP_BITCODE_WRAPPERER_H__
22
23#include <stdint.h>
24#include <stddef.h>
25#include <vector>
26
27#include "bcinfo/Wrap/support_macros.h"
28#include "bcinfo/Wrap/BCHeaderField.h"
29#include "bcinfo/Wrap/wrapper_input.h"
30#include "bcinfo/Wrap/wrapper_output.h"
31
32// The bitcode wrapper header is the following 7 fixed 4-byte fields:
33//      1) 0B17C0DE - The magic number expected by llvm for wrapped bitcodes
34//      2) Version # 0 - The current version of wrapped bitcode files
35//      3) (raw) bitcode offset
36//      4) (raw) bitcode size
37//      5) Android header version
38//      6) Android target API
39//      7) PNaCl Bitcode version
40//      plus 0 or more variable-length fields (consisting of ID, length, data)
41
42// Initial buffer size. It is expanded if needed to hold large variable-size
43// fields.
44static const size_t kBitcodeWrappererBufferSize = 1024;
45
46// Support class for outputting a wrapped bitcode file from a raw bitcode
47// file (and optionally additional header fields), or for outputting a raw
48// bitcode file from a wrapped one.
49class BitcodeWrapperer {
50 public:
51  // Create a bitcode wrapperer using the following
52  // input and output files.
53  BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile);
54
55  // Returns true if the input file begins with a bitcode
56  // wrapper magic number. As a side effect, _wrapper_ fields are set.
57  bool IsInputBitcodeWrapper();
58
59  // Returns true if the input file begins with a bitcode
60  // file magic number.
61  bool IsInputBitcodeFile();
62
63  // Add a variable-length field to the header. The caller is responsible
64  // for freeing the data pointed to by the BCHeaderField.
65  void AddHeaderField(BCHeaderField* field);
66
67  // Generate a wrapped bitcode file from the input bitcode file
68  // and the current header data. Return true on success.
69  bool GenerateWrappedBitcodeFile();
70
71  // Unwrap the wrapped bitcode file, to the corresponding
72  // outfile. Return true on success.
73  bool GenerateRawBitcodeFile();
74
75  // Print current wrapper header fields to stderr for debugging.
76  void PrintWrapperHeader();
77
78  uint32_t getAndroidHeaderVersion() {
79    return android_header_version_;
80  }
81
82  uint32_t getAndroidTargetAPI() {
83    return android_target_api_;
84  }
85
86  uint32_t getAndroidCompilerVersion() {
87    return android_compiler_version_;
88  }
89
90  uint32_t getAndroidOptimizationLevel() {
91    return android_optimization_level_;
92  }
93
94  ~BitcodeWrapperer();
95
96 private:
97  DISALLOW_CLASS_COPY_AND_ASSIGN(BitcodeWrapperer);
98
99  // Refills the buffer with more bytes. Does this in a way
100  // such that it is maximally filled.
101  void FillBuffer();
102
103  // Returns the number of bytes in infile.
104  off_t GetInFileSize() {
105    if (infile_ != NULL) {
106      return infile_->Size();
107    } else {
108      return 0;
109    }
110  }
111
112  // Returns the offset of bitcode (i.e. the size of the wrapper header)
113  // if the output file were to be written now.
114  size_t BitcodeOffset();
115
116  // Returns true if we can read a word. If necessary, fills the buffer
117  // with enough characters so that there are at least a 32-bit value
118  // in the buffer. Returns false if there isn't a 32-bit value
119  // to read from the input file.
120  bool CanReadWord();
121
122  // Read a (32-bit) word from the input. Return true
123  // if able to read the word.
124  bool ReadWord(uint32_t& word);
125
126  // Write a (32-bit) word to the output. Return true if successful
127  bool WriteWord(uint32_t word);
128
129  // Write all variable-sized header fields to the output. Return true
130  // if successful.
131  bool WriteVariableFields();
132
133  // Parse the bitcode wrapper header in the infile, if any. Return true
134  // if successful.
135  bool ParseWrapperHeader();
136
137  // Returns the i-th character in front of the cursor in the buffer.
138  uint8_t BufferLookahead(int i) { return buffer_[cursor_ + i]; }
139
140  // Returns how many unread bytes are in the buffer.
141  size_t GetBufferUnreadBytes() { return buffer_size_ - cursor_; }
142
143
144  // Backs up the read cursor to the beginning of the input buffer.
145  void ResetCursor() {
146    cursor_ = 0;
147  }
148
149  // Generates the header sequence for the wrapped bitcode being
150  // generated.
151  bool WriteBitcodeWrapperHeader();
152
153  // Copies size bytes of infile to outfile, using the buffer.
154  bool BufferCopyInToOut(uint32_t size);
155
156  // Discards the old infile and replaces it with the given file.
157  void ReplaceInFile(WrapperInput* new_infile);
158
159  // Discards the old outfile and replaces it with the given file.
160  void ReplaceOutFile(WrapperOutput* new_outfile);
161
162  // Moves to the given position in the input file. Returns false
163  // if unsuccessful.
164  bool Seek(uint32_t pos);
165
166  // Clear the buffer of all contents.
167  void ClearBuffer();
168
169  // The input file being processed. Can be either
170  // a bitcode file, a wrappered bitcode file, or a secondary
171  // file to be wrapped.
172  WrapperInput* infile_;
173
174  // The output file being generated. Can be either
175  // a bitcode file, a wrappered bitcode file, or a secondary
176  // unwrapped file.
177  WrapperOutput* outfile_;
178
179  // A buffer of bytes read from the input file.
180  std::vector<uint8_t> buffer_;
181
182  // The number of bytes that were read from the input file
183  // into the buffer.
184  size_t buffer_size_;
185
186  // The index to the current read point within the buffer.
187  size_t cursor_;
188
189  // True when eof of input is reached.
190  bool infile_at_eof_;
191
192  // The 32-bit value defining the offset of the raw bitcode in the input file.
193  uint32_t infile_bc_offset_;
194
195  // The 32-bit value defining the generated offset of the wrapped bitcode.
196  // This value changes as new fields are added with AddHeaderField
197  uint32_t wrapper_bc_offset_;
198
199  // The 32-bit value defining the size of the raw wrapped bitcode.
200  uint32_t wrapper_bc_size_;
201
202  // Android header version and target API
203  uint32_t android_header_version_;
204  uint32_t android_target_api_;
205  uint32_t android_compiler_version_;
206  uint32_t android_optimization_level_;
207
208  // PNaCl bitcode version
209  uint32_t pnacl_bc_version_;
210
211  // Vector of variable header fields
212  std::vector<BCHeaderField> header_fields_;
213  // If any bufferdata from header fields is owned, it is stored here and
214  // freed on destruction.
215  std::vector<uint8_t*> variable_field_data_;
216
217  // True if there was an error condition (e.g. the file is not bitcode)
218  bool error_;
219};
220
221#endif  // LLVM_WRAP_BITCODE_WRAPPERER_H__
222