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 #ifndef LLVM_WRAP_BCHEADER_FIELD_H__
     18 #define LLVM_WRAP_BCHEADER_FIELD_H__
     19 
     20 #include <stdint.h>
     21 #include <stdio.h>
     22 #include <string.h>
     23 
     24 // Class representing a variable-size metadata field in the bitcode header.
     25 // Also contains the list of known Tag IDs.
     26 // Contains a pointer to the data but does not own the data, so it can be
     27 // copied with the trivial copy constructor/assignment operator.
     28 
     29 // The serialized format has 2 fixed subfields (ID and length) and the
     30 // variable-length data subfield
     31 class BCHeaderField {
     32  public:
     33   typedef enum {
     34     kInvalid = 0,
     35     kBitcodeHash = 1,
     36     kAndroidCompilerVersion = 0x4001,
     37     kAndroidOptimizationLevel = 0x4002
     38   } Tag;
     39   typedef uint16_t FixedSubfield;
     40 
     41   BCHeaderField(Tag ID, size_t len, uint8_t* data) :
     42       ID_(ID), len_(len), data_(data) {}
     43   size_t GetTotalSize() {
     44     // Round up to 4 byte alignment
     45     return (kTagLenSize + len_ + 3) & ~3;
     46   }
     47 
     48   bool Write(uint8_t* buf, size_t buf_len) {
     49     size_t fields_len = kTagLenSize + len_;
     50     size_t pad_len = (4 - (fields_len & 3)) & 3;
     51     // Ensure buffer is large enough and that length can be represented
     52     // in 16 bits
     53     const size_t max_uint16_t = 65535;
     54     if (buf_len < fields_len + pad_len ||
     55         len_ > max_uint16_t) return false;
     56 
     57     WriteFixedSubfield(static_cast<FixedSubfield>(ID_), buf);
     58     WriteFixedSubfield(static_cast<FixedSubfield>(len_),
     59                        buf + sizeof(FixedSubfield));
     60     memcpy(buf + kTagLenSize, data_, len_);
     61     // Pad out to 4 byte alignment
     62     if (pad_len) {
     63       memset(buf + fields_len, 0, pad_len);
     64     }
     65     return true;
     66   }
     67 
     68   bool Read(const uint8_t* buf, size_t buf_len) {
     69     if (buf_len < kTagLenSize) return false;
     70     FixedSubfield field;
     71     ReadFixedSubfield(&field, buf);
     72     ID_ = static_cast<Tag>(field);
     73     ReadFixedSubfield(&field, buf + sizeof(FixedSubfield));
     74     len_ = static_cast<size_t>(field);
     75     if (buf_len < kTagLenSize + len_) return false;
     76     memcpy(data_, buf + kTagLenSize, len_);
     77     return true;
     78   }
     79 
     80   void Print() {
     81     fprintf(stderr, "Field ID: %d, data length %d, total length %d\n",
     82             ID_, static_cast<int>(len_), static_cast<int>(GetTotalSize()));
     83     fprintf(stderr, "Data:");
     84     for (size_t i = 0; i < len_; i++) fprintf(stderr, "0x%x ", data_[i]);
     85     fprintf(stderr, "\n");
     86   }
     87 
     88   // Get the data size from a serialized field to allow allocation
     89   static size_t GetDataSizeFromSerialized(const uint8_t* buf) {
     90     FixedSubfield len;
     91     ReadFixedSubfield(&len, buf + sizeof(FixedSubfield));
     92     return len;
     93   }
     94 
     95   Tag getID() const {
     96     return ID_;
     97   }
     98 
     99   size_t getLen() const {
    100     return len_;
    101   }
    102 
    103  private:
    104  // Combined size of the fixed subfields
    105  const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
    106   static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) {
    107     buf[0] = value & 0xFF;
    108     buf[1] = (value >> 8) & 0xFF;
    109   }
    110   static void ReadFixedSubfield(FixedSubfield* value, const uint8_t* buf) {
    111     *value = buf[0] | buf[1] << 8;
    112   }
    113   Tag ID_;
    114   size_t len_;
    115   uint8_t *data_;
    116 };
    117 
    118 #endif  // LLVM_WRAP_BCHEADER_FIELD_H__
    119