17cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines/* 27cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * Copyright 2012, The Android Open Source Project 37cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * 47cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * Licensed under the Apache License, Version 2.0 (the "License"); 57cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * you may not use this file except in compliance with the License. 67cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * You may obtain a copy of the License at 77cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * 87cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * http://www.apache.org/licenses/LICENSE-2.0 97cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * 107cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * Unless required by applicable law or agreed to in writing, software 117cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 127cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * See the License for the specific language governing permissions and 147cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * limitations under the License. 157cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines */ 167cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 177cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#ifndef LLVM_WRAP_BCHEADER_FIELD_H__ 187cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#define LLVM_WRAP_BCHEADER_FIELD_H__ 197cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 207cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#include <stdint.h> 217cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#include <stdio.h> 227cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#include <string.h> 237cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 247cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// Class representing a variable-size metadata field in the bitcode header. 257cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// Also contains the list of known Tag IDs. 267cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// Contains a pointer to the data but does not own the data, so it can be 277cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// copied with the trivial copy constructor/assignment operator. 287cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 297cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// The serialized format has 2 fixed subfields (ID and length) and the 307cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// variable-length data subfield 317cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hinesclass BCHeaderField { 327cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines public: 337cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines typedef enum { 347cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines kInvalid = 0, 357cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines kBitcodeHash = 1, 367cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines kAndroidCompilerVersion = 0x4001, 377cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines kAndroidOptimizationLevel = 0x4002 387cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } Tag; 397cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines typedef uint16_t FixedSubfield; 407cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 417cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines BCHeaderField(Tag ID, size_t len, uint8_t* data) : 427cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines ID_(ID), len_(len), data_(data) {} 437cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines size_t GetTotalSize() { 447cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines // Round up to 4 byte alignment 457cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines return (kTagLenSize + len_ + 3) & ~3; 467cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 477cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 487cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines bool Write(uint8_t* buf, size_t buf_len) { 497cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines size_t fields_len = kTagLenSize + len_; 507cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines size_t pad_len = (4 - (fields_len & 3)) & 3; 517cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines // Ensure buffer is large enough and that length can be represented 527cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines // in 16 bits 5326218cebf31dd9d0ec3c677fec91e1847a87a6d2Stephen Hines const size_t max_uint16_t = 65535; 547cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines if (buf_len < fields_len + pad_len || 5526218cebf31dd9d0ec3c677fec91e1847a87a6d2Stephen Hines len_ > max_uint16_t) return false; 567cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 577cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines WriteFixedSubfield(static_cast<FixedSubfield>(ID_), buf); 587cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines WriteFixedSubfield(static_cast<FixedSubfield>(len_), 597cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines buf + sizeof(FixedSubfield)); 607cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines memcpy(buf + kTagLenSize, data_, len_); 617cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines // Pad out to 4 byte alignment 627cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines if (pad_len) { 637cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines memset(buf + fields_len, 0, pad_len); 647cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 657cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines return true; 667cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 677cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 687cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines bool Read(const uint8_t* buf, size_t buf_len) { 697cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines if (buf_len < kTagLenSize) return false; 707cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines FixedSubfield field; 717cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines ReadFixedSubfield(&field, buf); 727cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines ID_ = static_cast<Tag>(field); 737cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines ReadFixedSubfield(&field, buf + sizeof(FixedSubfield)); 747cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines len_ = static_cast<size_t>(field); 757cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines if (buf_len < kTagLenSize + len_) return false; 767cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines memcpy(data_, buf + kTagLenSize, len_); 777cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines return true; 787cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 797cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 807cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines void Print() { 817cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines fprintf(stderr, "Field ID: %d, data length %d, total length %d\n", 827cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines ID_, static_cast<int>(len_), static_cast<int>(GetTotalSize())); 837cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines fprintf(stderr, "Data:"); 847cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines for (size_t i = 0; i < len_; i++) fprintf(stderr, "0x%x ", data_[i]); 857cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines fprintf(stderr, "\n"); 867cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 877cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 887cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines // Get the data size from a serialized field to allow allocation 897cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines static size_t GetDataSizeFromSerialized(const uint8_t* buf) { 907cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines FixedSubfield len; 917cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines ReadFixedSubfield(&len, buf + sizeof(FixedSubfield)); 927cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines return len; 937cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 947cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 957cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines Tag getID() const { 967cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines return ID_; 977cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 987cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 997cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines size_t getLen() const { 1007cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines return len_; 1017cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 1027cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 1037cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines private: 1047cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines // Combined size of the fixed subfields 1057cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines const static size_t kTagLenSize = 2 * sizeof(FixedSubfield); 1067cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) { 1077cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines buf[0] = value & 0xFF; 1087cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines buf[1] = (value >> 8) & 0xFF; 1097cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 1107cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines static void ReadFixedSubfield(FixedSubfield* value, const uint8_t* buf) { 1117cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines *value = buf[0] | buf[1] << 8; 1127cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines } 1137cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines Tag ID_; 1147cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines size_t len_; 1157cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines uint8_t *data_; 1167cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines}; 1177cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines 1187cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#endif // LLVM_WRAP_BCHEADER_FIELD_H__ 119