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