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 BCHeaderField(Tag ID,size_t len,uint8_t * data)41 BCHeaderField(Tag ID, size_t len, uint8_t* data) : 42 ID_(ID), len_(len), data_(data) {} GetTotalSize()43 size_t GetTotalSize() { 44 // Round up to 4 byte alignment 45 return (kTagLenSize + len_ + 3) & ~3; 46 } 47 Write(uint8_t * buf,size_t buf_len)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 Read(const uint8_t * buf,size_t buf_len)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 Print()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 GetDataSizeFromSerialized(const uint8_t * buf)89 static size_t GetDataSizeFromSerialized(const uint8_t* buf) { 90 FixedSubfield len; 91 ReadFixedSubfield(&len, buf + sizeof(FixedSubfield)); 92 return len; 93 } 94 getID()95 Tag getID() const { 96 return ID_; 97 } 98 getLen()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); WriteFixedSubfield(FixedSubfield value,uint8_t * buf)106 static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) { 107 buf[0] = value & 0xFF; 108 buf[1] = (value >> 8) & 0xFF; 109 } ReadFixedSubfield(FixedSubfield * value,const uint8_t * buf)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