1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
/* Copyright 2012 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can
* be found in the LICENSE file.
*/
// 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 "llvm/Support/support_macros.h"
#include "llvm/Wrap/BCHeaderField.h"
#include "llvm/Wrap/wrapper_input.h"
#include "llvm/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();
~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_;
// 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__
|