• 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 #include "bcinfo/Wrap/bitcode_wrapperer.h"
18 
19 #define LOG_TAG "bcinfo"
20 
21 #include <stdio.h>
22 #include <sys/stat.h>
23 
24 #include <log/log.h>
25 
26 using std::vector;
27 
28 // The number of bytes in a 32 bit integer.
29 static const uint32_t kWordSize = 4;
30 
31 // Number of LLVM-defined fixed fields in the header.
32 static const uint32_t kLLVMFields = 4;
33 
34 // Total number of fixed fields in the header.
35 static const uint32_t kFixedFields = 7;
36 
37 // The magic number that must exist for bitcode wrappers.
38 static const uint32_t kWrapperMagicNumber = 0x0B17C0DE;
39 
40 // The version number associated with a wrapper file.
41 // Note: llvm currently only allows the value 0. When this changes,
42 // we should consider making this a command line option.
43 static const uint32_t kLLVMVersionNumber = 0;
44 
45 // Fields defined by Android bitcode header.
46 static const uint32_t kAndroidHeaderVersion = 0;
47 static const uint32_t kAndroidTargetAPI = 0;
48 static const uint32_t kAndroidDefaultCompilerVersion = 0;
49 static const uint32_t kAndroidDefaultOptimizationLevel = 3;
50 
51 // PNaCl bitcode version number.
52 static const uint32_t kPnaclBitcodeVersion = 0;
53 
54 // Max size for variable fields. Currently only used for writing them
55 // out to files (the parsing works for arbitrary sizes).
56 static const size_t kMaxVariableFieldSize = 256;
57 
BitcodeWrapperer(WrapperInput * infile,WrapperOutput * outfile)58 BitcodeWrapperer::BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile)
59     : infile_(infile),
60       outfile_(outfile),
61       buffer_size_(0),
62       cursor_(0),
63       infile_at_eof_(false),
64       infile_bc_offset_(0),
65       wrapper_bc_offset_(0),
66       wrapper_bc_size_(0),
67       android_header_version_(kAndroidHeaderVersion),
68       android_target_api_(kAndroidTargetAPI),
69       android_compiler_version_(kAndroidDefaultCompilerVersion),
70       android_optimization_level_(kAndroidDefaultOptimizationLevel),
71       pnacl_bc_version_(0),
72       error_(false) {
73   buffer_.resize(kBitcodeWrappererBufferSize);
74   if (IsInputBitcodeWrapper()) {
75     ParseWrapperHeader();
76   } else if (IsInputBitcodeFile()) {
77     wrapper_bc_offset_ = kWordSize * kFixedFields;
78     wrapper_bc_size_ = GetInFileSize();
79   } else {
80     ALOGE("Error: input file is not a bitcode file.\n");
81     error_ = true;
82   }
83 }
84 
~BitcodeWrapperer()85 BitcodeWrapperer::~BitcodeWrapperer() {
86   for(size_t i = 0; i < variable_field_data_.size(); i++) {
87     delete [] variable_field_data_[i];
88   }
89 }
90 
91 
ClearBuffer()92 void BitcodeWrapperer::ClearBuffer() {
93   buffer_size_ = 0;
94   cursor_ = 0;
95   infile_at_eof_ = false;
96 }
97 
Seek(uint32_t pos)98 bool BitcodeWrapperer::Seek(uint32_t pos) {
99   if (infile_ != nullptr && infile_->Seek(pos)) {
100     ClearBuffer();
101     return true;
102   }
103   return false;
104 }
105 
CanReadWord()106 bool BitcodeWrapperer::CanReadWord() {
107   if (GetBufferUnreadBytes() < kWordSize) {
108     FillBuffer();
109     return GetBufferUnreadBytes() >= kWordSize;
110   } else {
111     return true;
112   }
113 }
114 
FillBuffer()115 void BitcodeWrapperer::FillBuffer() {
116   if (cursor_ > 0) {
117     // Before filling, move any remaining bytes to the
118     // front of the buffer. This allows us to assume
119     // that after the call to FillBuffer, readable
120     // text is contiguous.
121     if (cursor_ < buffer_size_) {
122       size_t i = 0;
123       while (cursor_ < buffer_size_) {
124         buffer_[i++] = buffer_[cursor_++];
125       }
126       cursor_ = 0;
127       buffer_size_ = i;
128     }
129   } else {
130     // Assume the buffer contents have been used,
131     // and we want to completely refill it.
132     buffer_size_ = 0;
133   }
134 
135   // If we don't have an input, we can't refill the buffer at all.
136   if (infile_ == nullptr) {
137     return;
138   }
139 
140   // Now fill in remaining space.
141   size_t needed = buffer_.size() - buffer_size_;
142 
143   while (buffer_.size() > buffer_size_) {
144     int actually_read = infile_->Read(&buffer_[buffer_size_], needed);
145     if (infile_->AtEof()) {
146       infile_at_eof_ = true;
147     }
148     if (actually_read) {
149       buffer_size_ += actually_read;
150       needed -= actually_read;
151     } else if (infile_at_eof_) {
152       break;
153     }
154   }
155 }
156 
ReadWord(uint32_t & word)157 bool BitcodeWrapperer::ReadWord(uint32_t& word) {
158   if (!CanReadWord()) return false;
159   word = (((uint32_t) BufferLookahead(0)) << 0)
160       | (((uint32_t) BufferLookahead(1)) << 8)
161       | (((uint32_t) BufferLookahead(2)) << 16)
162       | (((uint32_t) BufferLookahead(3)) << 24);
163   cursor_ += kWordSize;
164   return true;
165 }
166 
WriteWord(uint32_t value)167 bool BitcodeWrapperer::WriteWord(uint32_t value) {
168   uint8_t buffer[kWordSize];
169   buffer[3] = (value >> 24) & 0xFF;
170   buffer[2] = (value >> 16) & 0xFF;
171   buffer[1] = (value >> 8)  & 0xFF;
172   buffer[0] = (value >> 0)  & 0xFF;
173   return outfile_->Write(buffer, kWordSize);
174 }
175 
WriteVariableFields()176 bool BitcodeWrapperer::WriteVariableFields() {
177   // This buffer may have to be bigger if we start using the fields
178   // for larger things.
179   uint8_t buffer[kMaxVariableFieldSize];
180   for (vector<BCHeaderField>::iterator it = header_fields_.begin();
181        it != header_fields_.end(); ++it) {
182     if (!it->Write(buffer, kMaxVariableFieldSize) ||
183         !outfile_->Write(buffer, it->GetTotalSize())) {
184       return false;
185     }
186   }
187   return true;
188 }
189 
ParseWrapperHeader()190 bool BitcodeWrapperer::ParseWrapperHeader() {
191   // Make sure LLVM-defined fields have been parsed
192   if (!IsInputBitcodeWrapper()) return false;
193   // Check the android/pnacl fields
194   if (!ReadWord(android_header_version_) ||
195       !ReadWord(android_target_api_) || !ReadWord(pnacl_bc_version_)) {
196     ALOGW("Error: file not long enough to contain header\n");
197     return false;
198   }
199   if (pnacl_bc_version_ != kPnaclBitcodeVersion) {
200     ALOGW("Error: bad PNaCl Bitcode version\n");
201     return false;
202   }
203   int field_data_total = wrapper_bc_offset_ - kWordSize * kFixedFields;
204   if (field_data_total > 0) {
205     // Read in the variable fields. We need to allocate space for the data.
206     int field_data_read = 0;
207 
208     while (field_data_read < field_data_total) {
209       FillBuffer();
210       size_t buffer_needed = BCHeaderField::GetDataSizeFromSerialized(
211           &buffer_[cursor_]);
212       if (buffer_needed > buffer_.size()) {
213         buffer_.resize(buffer_needed +
214                        sizeof(BCHeaderField::FixedSubfield) * 2);
215         FillBuffer();
216       }
217       variable_field_data_.push_back(new uint8_t[buffer_needed]);
218 
219       BCHeaderField field(BCHeaderField::kInvalid, 0,
220                           variable_field_data_.back());
221       field.Read(&buffer_[cursor_], buffer_size_);
222       header_fields_.push_back(field);
223       size_t field_size = field.GetTotalSize();
224       cursor_ += field_size;
225       field_data_read += field_size;
226       if (field_data_read > field_data_total) {
227         // We read too much data, the header is corrupted
228         ALOGE("Error: raw bitcode offset inconsistent with "
229               "variable field data\n");
230         return false;
231       }
232 
233       struct IntFieldHelper {
234         BCHeaderField::FixedSubfield tag;
235         uint16_t len;
236         uint32_t val;
237       };
238       IntFieldHelper tempIntField;
239 
240       switch (field.getID()) {
241         case BCHeaderField::kAndroidCompilerVersion:
242           if (field.Write((uint8_t*)&tempIntField,
243                           sizeof(tempIntField))) {
244             android_compiler_version_ = tempIntField.val;
245           }
246           break;
247         case BCHeaderField::kAndroidOptimizationLevel:
248           if (field.Write((uint8_t*)&tempIntField,
249                           sizeof(tempIntField))) {
250             android_optimization_level_ = tempIntField.val;
251           }
252           break;
253         default:
254           // Ignore other field types for now
255           break;
256       }
257     }
258     Seek(0);
259   }
260   return true;
261 }
262 
IsInputBitcodeWrapper()263 bool BitcodeWrapperer::IsInputBitcodeWrapper() {
264   ResetCursor();
265   // First make sure that there are enough words (LLVM header)
266   // to peek at.
267   if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) {
268     FillBuffer();
269     if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) return false;
270   }
271 
272   // Now make sure the magic number is right.
273   uint32_t first_word;
274   if ((!ReadWord(first_word)) ||
275       (kWrapperMagicNumber != first_word)) return false;
276 
277   // Make sure the version is right.
278   uint32_t second_word;
279   if ((!ReadWord(second_word)) ||
280       (kLLVMVersionNumber != second_word)) return false;
281 
282   // Make sure that the offset and size (for llvm) is defined.
283   uint32_t bc_offset;
284   uint32_t bc_size;
285   if (ReadWord(bc_offset) &&
286       ReadWord(bc_size)) {
287     // Before returning, save the extracted values.
288     wrapper_bc_offset_ = bc_offset;
289     infile_bc_offset_ = bc_offset;
290     wrapper_bc_size_ = bc_size;
291     return true;
292   }
293   // If reached, unable to read wrapped header.
294   return false;
295 }
296 
IsInputBitcodeFile()297 bool BitcodeWrapperer::IsInputBitcodeFile() {
298   ResetCursor();
299   // First make sure that there are four bytes to peek at.
300   if (GetBufferUnreadBytes() < kWordSize) {
301     FillBuffer();
302     if (GetBufferUnreadBytes() < kWordSize) return false;
303   }
304   // If reached, Check if first 4 bytes match bitcode
305   // file magic number.
306   return (BufferLookahead(0) == 'B') &&
307       (BufferLookahead(1) == 'C') &&
308       (BufferLookahead(2) == 0xc0) &&
309       (BufferLookahead(3) == 0xde);
310 }
311 
BufferCopyInToOut(uint32_t size)312 bool BitcodeWrapperer::BufferCopyInToOut(uint32_t size) {
313   while (size > 0) {
314     // Be sure buffer is non-empty before writing.
315     if (0 == buffer_size_) {
316       FillBuffer();
317       if (0 == buffer_size_) {
318         return false;
319       }
320     }
321     // copy the buffer to the output file.
322     size_t block = (buffer_size_ < size) ? buffer_size_ : size;
323     if (!outfile_->Write(&buffer_[cursor_], block)) return false;
324     size -= block;
325     buffer_size_ = 0;
326   }
327   // Be sure that there isn't more bytes on the input stream.
328   FillBuffer();
329   return buffer_size_ == 0;
330 }
331 
AddHeaderField(BCHeaderField * field)332 void BitcodeWrapperer::AddHeaderField(BCHeaderField* field) {
333   header_fields_.push_back(*field);
334   wrapper_bc_offset_ += field->GetTotalSize();
335 }
336 
WriteBitcodeWrapperHeader()337 bool BitcodeWrapperer::WriteBitcodeWrapperHeader() {
338   return
339       // Note: This writes out the 4 word header required by llvm wrapped
340       // bitcode.
341       WriteWord(kWrapperMagicNumber) &&
342       WriteWord(kLLVMVersionNumber) &&
343       WriteWord(wrapper_bc_offset_) &&
344       WriteWord(wrapper_bc_size_) &&
345       // 2 fixed fields defined by Android
346       WriteWord(android_header_version_) &&
347       WriteWord(android_target_api_) &&
348       // PNaClBitcode version
349       WriteWord(kPnaclBitcodeVersion) &&
350       // Common variable-length fields
351       WriteVariableFields();
352 }
353 
PrintWrapperHeader()354 void BitcodeWrapperer::PrintWrapperHeader() {
355   if (error_) {
356     fprintf(stderr, "Error condition exists: the following"
357             "data may not be reliable\n");
358   }
359   fprintf(stderr, "Wrapper magic:\t\t%x\n", kWrapperMagicNumber);
360   fprintf(stderr, "LLVM Bitcode version:\t%d\n", kLLVMVersionNumber);
361   fprintf(stderr, "Raw bitcode offset:\t%d\n", wrapper_bc_offset_);
362   fprintf(stderr, "Raw bitcode size:\t%d\n", wrapper_bc_size_);
363   fprintf(stderr, "Android header version:\t%d\n", android_header_version_);
364   fprintf(stderr, "Android target API:\t%d\n", android_target_api_);
365   fprintf(stderr, "PNaCl bitcode version:\t%d\n", kPnaclBitcodeVersion);
366   for (size_t i = 0; i < header_fields_.size(); i++) header_fields_[i].Print();
367 }
368 
GenerateWrappedBitcodeFile()369 bool BitcodeWrapperer::GenerateWrappedBitcodeFile() {
370   if (!error_ &&
371       WriteBitcodeWrapperHeader() &&
372       Seek(infile_bc_offset_) &&
373       BufferCopyInToOut(wrapper_bc_size_)) {
374     off_t dangling = wrapper_bc_size_ & 3;
375     if (dangling) {
376       return outfile_->Write((const uint8_t*) "\0\0\0\0", 4 - dangling);
377     }
378     return true;
379   }
380   return false;
381 }
382 
GenerateRawBitcodeFile()383 bool BitcodeWrapperer::GenerateRawBitcodeFile() {
384   return !error_ && Seek(infile_bc_offset_) &&
385       BufferCopyInToOut(wrapper_bc_size_);
386 }
387