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
26using std::vector;
27
28// The number of bytes in a 32 bit integer.
29static const uint32_t kWordSize = 4;
30
31// Number of LLVM-defined fixed fields in the header.
32static const uint32_t kLLVMFields = 4;
33
34// Total number of fixed fields in the header.
35static const uint32_t kFixedFields = 7;
36
37// The magic number that must exist for bitcode wrappers.
38static 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.
43static const uint32_t kLLVMVersionNumber = 0;
44
45// Fields defined by Android bitcode header.
46static const uint32_t kAndroidHeaderVersion = 0;
47static const uint32_t kAndroidTargetAPI = 0;
48static const uint32_t kAndroidDefaultCompilerVersion = 0;
49static const uint32_t kAndroidDefaultOptimizationLevel = 3;
50
51// PNaCl bitcode version number.
52static 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).
56static const size_t kMaxVariableFieldSize = 256;
57
58BitcodeWrapperer::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
85BitcodeWrapperer::~BitcodeWrapperer() {
86  for(size_t i = 0; i < variable_field_data_.size(); i++) {
87    delete [] variable_field_data_[i];
88  }
89}
90
91
92void BitcodeWrapperer::ClearBuffer() {
93  buffer_size_ = 0;
94  cursor_ = 0;
95  infile_at_eof_ = false;
96}
97
98bool BitcodeWrapperer::Seek(uint32_t pos) {
99  if (infile_ != nullptr && infile_->Seek(pos)) {
100    ClearBuffer();
101    return true;
102  }
103  return false;
104}
105
106bool BitcodeWrapperer::CanReadWord() {
107  if (GetBufferUnreadBytes() < kWordSize) {
108    FillBuffer();
109    return GetBufferUnreadBytes() >= kWordSize;
110  } else {
111    return true;
112  }
113}
114
115void 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
157bool 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
167bool 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
176bool 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
190bool 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
263bool 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
297bool 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
312bool 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
332void BitcodeWrapperer::AddHeaderField(BCHeaderField* field) {
333  header_fields_.push_back(*field);
334  wrapper_bc_offset_ += field->GetTotalSize();
335}
336
337bool 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
354void 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
369bool 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
383bool BitcodeWrapperer::GenerateRawBitcodeFile() {
384  return !error_ && Seek(infile_bc_offset_) &&
385      BufferCopyInToOut(wrapper_bc_size_);
386}
387