• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
44 static 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.
49 class 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 
getAndroidHeaderVersion()78   uint32_t getAndroidHeaderVersion() {
79     return android_header_version_;
80   }
81 
getAndroidTargetAPI()82   uint32_t getAndroidTargetAPI() {
83     return android_target_api_;
84   }
85 
getAndroidCompilerVersion()86   uint32_t getAndroidCompilerVersion() {
87     return android_compiler_version_;
88   }
89 
getAndroidOptimizationLevel()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.
GetInFileSize()104   off_t GetInFileSize() {
105     if (infile_ != nullptr) {
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.
BufferLookahead(int i)138   uint8_t BufferLookahead(int i) { return buffer_[cursor_ + i]; }
139 
140   // Returns how many unread bytes are in the buffer.
GetBufferUnreadBytes()141   size_t GetBufferUnreadBytes() { return buffer_size_ - cursor_; }
142 
143 
144   // Backs up the read cursor to the beginning of the input buffer.
ResetCursor()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