| /* |
| * Copyright 2012, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Define utility class to wrap/unwrap bitcode files. Does wrapping/unwrapping |
| // in such a way that the wrappered bitcode file is still a bitcode file. |
| |
| #ifndef LLVM_WRAP_BITCODE_WRAPPERER_H__ |
| #define LLVM_WRAP_BITCODE_WRAPPERER_H__ |
| |
| #include <stdint.h> |
| #include <stddef.h> |
| #include <vector> |
| |
| #include "bcinfo/Wrap/support_macros.h" |
| #include "bcinfo/Wrap/BCHeaderField.h" |
| #include "bcinfo/Wrap/wrapper_input.h" |
| #include "bcinfo/Wrap/wrapper_output.h" |
| |
| // The bitcode wrapper header is the following 7 fixed 4-byte fields: |
| // 1) 0B17C0DE - The magic number expected by llvm for wrapped bitcodes |
| // 2) Version # 0 - The current version of wrapped bitcode files |
| // 3) (raw) bitcode offset |
| // 4) (raw) bitcode size |
| // 5) Android header version |
| // 6) Android target API |
| // 7) PNaCl Bitcode version |
| // plus 0 or more variable-length fields (consisting of ID, length, data) |
| |
| // Initial buffer size. It is expanded if needed to hold large variable-size |
| // fields. |
| static const size_t kBitcodeWrappererBufferSize = 1024; |
| |
| // Support class for outputting a wrapped bitcode file from a raw bitcode |
| // file (and optionally additional header fields), or for outputting a raw |
| // bitcode file from a wrapped one. |
| class BitcodeWrapperer { |
| public: |
| // Create a bitcode wrapperer using the following |
| // input and output files. |
| BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile); |
| |
| // Returns true if the input file begins with a bitcode |
| // wrapper magic number. As a side effect, _wrapper_ fields are set. |
| bool IsInputBitcodeWrapper(); |
| |
| // Returns true if the input file begins with a bitcode |
| // file magic number. |
| bool IsInputBitcodeFile(); |
| |
| // Add a variable-length field to the header. The caller is responsible |
| // for freeing the data pointed to by the BCHeaderField. |
| void AddHeaderField(BCHeaderField* field); |
| |
| // Generate a wrapped bitcode file from the input bitcode file |
| // and the current header data. Return true on success. |
| bool GenerateWrappedBitcodeFile(); |
| |
| // Unwrap the wrapped bitcode file, to the corresponding |
| // outfile. Return true on success. |
| bool GenerateRawBitcodeFile(); |
| |
| // Print current wrapper header fields to stderr for debugging. |
| void PrintWrapperHeader(); |
| |
| uint32_t getAndroidHeaderVersion() { |
| return android_header_version_; |
| } |
| |
| uint32_t getAndroidTargetAPI() { |
| return android_target_api_; |
| } |
| |
| uint32_t getAndroidCompilerVersion() { |
| return android_compiler_version_; |
| } |
| |
| uint32_t getAndroidOptimizationLevel() { |
| return android_optimization_level_; |
| } |
| |
| ~BitcodeWrapperer(); |
| |
| private: |
| DISALLOW_CLASS_COPY_AND_ASSIGN(BitcodeWrapperer); |
| |
| // Refills the buffer with more bytes. Does this in a way |
| // such that it is maximally filled. |
| void FillBuffer(); |
| |
| // Returns the number of bytes in infile. |
| off_t GetInFileSize() { |
| if (infile_ != NULL) { |
| return infile_->Size(); |
| } else { |
| return 0; |
| } |
| } |
| |
| // Returns the offset of bitcode (i.e. the size of the wrapper header) |
| // if the output file were to be written now. |
| size_t BitcodeOffset(); |
| |
| // Returns true if we can read a word. If necessary, fills the buffer |
| // with enough characters so that there are at least a 32-bit value |
| // in the buffer. Returns false if there isn't a 32-bit value |
| // to read from the input file. |
| bool CanReadWord(); |
| |
| // Read a (32-bit) word from the input. Return true |
| // if able to read the word. |
| bool ReadWord(uint32_t& word); |
| |
| // Write a (32-bit) word to the output. Return true if successful |
| bool WriteWord(uint32_t word); |
| |
| // Write all variable-sized header fields to the output. Return true |
| // if successful. |
| bool WriteVariableFields(); |
| |
| // Parse the bitcode wrapper header in the infile, if any. Return true |
| // if successful. |
| bool ParseWrapperHeader(); |
| |
| // Returns the i-th character in front of the cursor in the buffer. |
| uint8_t BufferLookahead(int i) { return buffer_[cursor_ + i]; } |
| |
| // Returns how many unread bytes are in the buffer. |
| size_t GetBufferUnreadBytes() { return buffer_size_ - cursor_; } |
| |
| |
| // Backs up the read cursor to the beginning of the input buffer. |
| void ResetCursor() { |
| cursor_ = 0; |
| } |
| |
| // Generates the header sequence for the wrapped bitcode being |
| // generated. |
| bool WriteBitcodeWrapperHeader(); |
| |
| // Copies size bytes of infile to outfile, using the buffer. |
| bool BufferCopyInToOut(uint32_t size); |
| |
| // Discards the old infile and replaces it with the given file. |
| void ReplaceInFile(WrapperInput* new_infile); |
| |
| // Discards the old outfile and replaces it with the given file. |
| void ReplaceOutFile(WrapperOutput* new_outfile); |
| |
| // Moves to the given position in the input file. Returns false |
| // if unsuccessful. |
| bool Seek(uint32_t pos); |
| |
| // Clear the buffer of all contents. |
| void ClearBuffer(); |
| |
| // The input file being processed. Can be either |
| // a bitcode file, a wrappered bitcode file, or a secondary |
| // file to be wrapped. |
| WrapperInput* infile_; |
| |
| // The output file being generated. Can be either |
| // a bitcode file, a wrappered bitcode file, or a secondary |
| // unwrapped file. |
| WrapperOutput* outfile_; |
| |
| // A buffer of bytes read from the input file. |
| std::vector<uint8_t> buffer_; |
| |
| // The number of bytes that were read from the input file |
| // into the buffer. |
| size_t buffer_size_; |
| |
| // The index to the current read point within the buffer. |
| size_t cursor_; |
| |
| // True when eof of input is reached. |
| bool infile_at_eof_; |
| |
| // The 32-bit value defining the offset of the raw bitcode in the input file. |
| uint32_t infile_bc_offset_; |
| |
| // The 32-bit value defining the generated offset of the wrapped bitcode. |
| // This value changes as new fields are added with AddHeaderField |
| uint32_t wrapper_bc_offset_; |
| |
| // The 32-bit value defining the size of the raw wrapped bitcode. |
| uint32_t wrapper_bc_size_; |
| |
| // Android header version and target API |
| uint32_t android_header_version_; |
| uint32_t android_target_api_; |
| uint32_t android_compiler_version_; |
| uint32_t android_optimization_level_; |
| |
| // PNaCl bitcode version |
| uint32_t pnacl_bc_version_; |
| |
| // Vector of variable header fields |
| std::vector<BCHeaderField> header_fields_; |
| // If any bufferdata from header fields is owned, it is stored here and |
| // freed on destruction. |
| std::vector<uint8_t*> variable_field_data_; |
| |
| // True if there was an error condition (e.g. the file is not bitcode) |
| bool error_; |
| }; |
| |
| #endif // LLVM_WRAP_BITCODE_WRAPPERER_H__ |