blob: 0a49497173a1f82a183291b198fe129f7fcea430 [file] [log] [blame]
Stephen Hines7cd4c492012-03-13 19:57:37 -07001/*
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#include "bcinfo/Wrap/bitcode_wrapperer.h"
18
19#define LOG_TAG "bcinfo"
20#include <cutils/log.h>
21
22#include <stdio.h>
23#include <sys/stat.h>
24
25using std::vector;
26
27// The number of bytes in a 32 bit integer.
28static const uint32_t kWordSize = 4;
29
30// Number of LLVM-defined fixed fields in the header.
31static const uint32_t kLLVMFields = 4;
32
33// Total number of fixed fields in the header.
34static const uint32_t kFixedFields = 7;
35
36// The magic number that must exist for bitcode wrappers.
37static const uint32_t kWrapperMagicNumber = 0x0B17C0DE;
38
39// The version number associated with a wrapper file.
40// Note: llvm currently only allows the value 0. When this changes,
41// we should consider making this a command line option.
42static const uint32_t kLLVMVersionNumber = 0;
43
44// Fields defined by Android bitcode header.
45static const uint32_t kAndroidHeaderVersion = 0;
46static const uint32_t kAndroidTargetAPI = 0;
47static const uint32_t kAndroidDefaultCompilerVersion = 0;
48static const uint32_t kAndroidDefaultOptimizationLevel = 3;
49
50// PNaCl bitcode version number.
51static const uint32_t kPnaclBitcodeVersion = 0;
52
53// Max size for variable fields. Currently only used for writing them
54// out to files (the parsing works for arbitrary sizes).
55static const size_t kMaxVariableFieldSize = 256;
56
57BitcodeWrapperer::BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile)
58 : infile_(infile),
59 outfile_(outfile),
60 buffer_size_(0),
61 cursor_(0),
62 infile_at_eof_(false),
63 infile_bc_offset_(0),
64 wrapper_bc_offset_(0),
65 wrapper_bc_size_(0),
66 android_header_version_(kAndroidHeaderVersion),
67 android_target_api_(kAndroidTargetAPI),
68 android_compiler_version_(kAndroidDefaultCompilerVersion),
69 android_optimization_level_(kAndroidDefaultOptimizationLevel),
70 pnacl_bc_version_(0),
71 error_(false) {
72 buffer_.resize(kBitcodeWrappererBufferSize);
73 if (IsInputBitcodeWrapper()) {
74 ParseWrapperHeader();
75 } else if (IsInputBitcodeFile()) {
76 wrapper_bc_offset_ = kWordSize * kFixedFields;
77 wrapper_bc_size_ = GetInFileSize();
78 } else {
79 ALOGE("Error: input file is not a bitcode file.\n");
80 error_ = true;
81 }
82}
83
84BitcodeWrapperer::~BitcodeWrapperer() {
85 for(size_t i = 0; i < variable_field_data_.size(); i++) {
86 delete [] variable_field_data_[i];
87 }
88}
89
90
91void BitcodeWrapperer::ClearBuffer() {
92 buffer_size_ = 0;
93 cursor_ = 0;
94 infile_at_eof_ = false;
95}
96
97bool BitcodeWrapperer::Seek(uint32_t pos) {
Chris Wailes900c6c12014-08-13 15:40:00 -070098 if (infile_ != nullptr && infile_->Seek(pos)) {
Stephen Hines7cd4c492012-03-13 19:57:37 -070099 ClearBuffer();
100 return true;
101 }
102 return false;
103}
104
105bool BitcodeWrapperer::CanReadWord() {
106 if (GetBufferUnreadBytes() < kWordSize) {
107 FillBuffer();
108 return GetBufferUnreadBytes() >= kWordSize;
109 } else {
110 return true;
111 }
112}
113
114void BitcodeWrapperer::FillBuffer() {
115 if (cursor_ > 0) {
116 // Before filling, move any remaining bytes to the
117 // front of the buffer. This allows us to assume
118 // that after the call to FillBuffer, readable
119 // text is contiguous.
120 if (cursor_ < buffer_size_) {
121 size_t i = 0;
122 while (cursor_ < buffer_size_) {
123 buffer_[i++] = buffer_[cursor_++];
124 }
125 cursor_ = 0;
126 buffer_size_ = i;
127 }
128 } else {
129 // Assume the buffer contents have been used,
130 // and we want to completely refill it.
131 buffer_size_ = 0;
132 }
133
Stephen Hines1ad35fb2012-03-26 10:20:46 -0700134 // If we don't have an input, we can't refill the buffer at all.
Chris Wailes900c6c12014-08-13 15:40:00 -0700135 if (infile_ == nullptr) {
Stephen Hines1ad35fb2012-03-26 10:20:46 -0700136 return;
137 }
138
Stephen Hines7cd4c492012-03-13 19:57:37 -0700139 // Now fill in remaining space.
140 size_t needed = buffer_.size() - buffer_size_;
141
142 while (buffer_.size() > buffer_size_) {
143 int actually_read = infile_->Read(&buffer_[buffer_size_], needed);
144 if (infile_->AtEof()) {
145 infile_at_eof_ = true;
146 }
147 if (actually_read) {
148 buffer_size_ += actually_read;
149 needed -= actually_read;
150 } else if (infile_at_eof_) {
151 break;
152 }
153 }
154}
155
156bool BitcodeWrapperer::ReadWord(uint32_t& word) {
157 if (!CanReadWord()) return false;
158 word = (((uint32_t) BufferLookahead(0)) << 0)
159 | (((uint32_t) BufferLookahead(1)) << 8)
160 | (((uint32_t) BufferLookahead(2)) << 16)
161 | (((uint32_t) BufferLookahead(3)) << 24);
162 cursor_ += kWordSize;
163 return true;
164}
165
166bool BitcodeWrapperer::WriteWord(uint32_t value) {
167 uint8_t buffer[kWordSize];
168 buffer[3] = (value >> 24) & 0xFF;
169 buffer[2] = (value >> 16) & 0xFF;
170 buffer[1] = (value >> 8) & 0xFF;
171 buffer[0] = (value >> 0) & 0xFF;
172 return outfile_->Write(buffer, kWordSize);
173}
174
175bool BitcodeWrapperer::WriteVariableFields() {
176 // This buffer may have to be bigger if we start using the fields
177 // for larger things.
178 uint8_t buffer[kMaxVariableFieldSize];
179 for (vector<BCHeaderField>::iterator it = header_fields_.begin();
180 it != header_fields_.end(); ++it) {
181 if (!it->Write(buffer, kMaxVariableFieldSize) ||
182 !outfile_->Write(buffer, it->GetTotalSize())) {
183 return false;
184 }
185 }
186 return true;
187}
188
189bool BitcodeWrapperer::ParseWrapperHeader() {
190 // Make sure LLVM-defined fields have been parsed
191 if (!IsInputBitcodeWrapper()) return false;
192 // Check the android/pnacl fields
193 if (!ReadWord(android_header_version_) ||
194 !ReadWord(android_target_api_) || !ReadWord(pnacl_bc_version_)) {
195 ALOGW("Error: file not long enough to contain header\n");
196 return false;
197 }
198 if (pnacl_bc_version_ != kPnaclBitcodeVersion) {
199 ALOGW("Error: bad PNaCl Bitcode version\n");
200 return false;
201 }
202 int field_data_total = wrapper_bc_offset_ - kWordSize * kFixedFields;
203 if (field_data_total > 0) {
204 // Read in the variable fields. We need to allocate space for the data.
205 int field_data_read = 0;
206
207 while (field_data_read < field_data_total) {
208 FillBuffer();
209 size_t buffer_needed = BCHeaderField::GetDataSizeFromSerialized(
210 &buffer_[cursor_]);
211 if (buffer_needed > buffer_.size()) {
212 buffer_.resize(buffer_needed +
213 sizeof(BCHeaderField::FixedSubfield) * 2);
214 FillBuffer();
215 }
216 variable_field_data_.push_back(new uint8_t[buffer_needed]);
217
218 BCHeaderField field(BCHeaderField::kInvalid, 0,
219 variable_field_data_.back());
220 field.Read(&buffer_[cursor_], buffer_size_);
221 header_fields_.push_back(field);
222 size_t field_size = field.GetTotalSize();
223 cursor_ += field_size;
224 field_data_read += field_size;
225 if (field_data_read > field_data_total) {
226 // We read too much data, the header is corrupted
227 ALOGE("Error: raw bitcode offset inconsistent with "
228 "variable field data\n");
229 return false;
230 }
231
232 struct IntFieldHelper {
233 BCHeaderField::FixedSubfield tag;
234 uint16_t len;
235 uint32_t val;
236 };
237 IntFieldHelper tempIntField;
238
239 switch (field.getID()) {
240 case BCHeaderField::kAndroidCompilerVersion:
241 if (field.Write((uint8_t*)&tempIntField,
242 sizeof(tempIntField))) {
243 android_compiler_version_ = tempIntField.val;
244 }
245 break;
246 case BCHeaderField::kAndroidOptimizationLevel:
247 if (field.Write((uint8_t*)&tempIntField,
248 sizeof(tempIntField))) {
249 android_optimization_level_ = tempIntField.val;
250 }
251 break;
252 default:
253 // Ignore other field types for now
254 break;
255 }
256 }
257 Seek(0);
258 }
259 return true;
260}
261
262bool BitcodeWrapperer::IsInputBitcodeWrapper() {
263 ResetCursor();
264 // First make sure that there are enough words (LLVM header)
265 // to peek at.
266 if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) {
267 FillBuffer();
268 if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) return false;
269 }
270
271 // Now make sure the magic number is right.
272 uint32_t first_word;
273 if ((!ReadWord(first_word)) ||
274 (kWrapperMagicNumber != first_word)) return false;
275
276 // Make sure the version is right.
277 uint32_t second_word;
278 if ((!ReadWord(second_word)) ||
279 (kLLVMVersionNumber != second_word)) return false;
280
281 // Make sure that the offset and size (for llvm) is defined.
282 uint32_t bc_offset;
283 uint32_t bc_size;
284 if (ReadWord(bc_offset) &&
285 ReadWord(bc_size)) {
286 // Before returning, save the extracted values.
287 wrapper_bc_offset_ = bc_offset;
288 infile_bc_offset_ = bc_offset;
289 wrapper_bc_size_ = bc_size;
290 return true;
291 }
292 // If reached, unable to read wrapped header.
293 return false;
294}
295
296bool BitcodeWrapperer::IsInputBitcodeFile() {
297 ResetCursor();
298 // First make sure that there are four bytes to peek at.
299 if (GetBufferUnreadBytes() < kWordSize) {
300 FillBuffer();
301 if (GetBufferUnreadBytes() < kWordSize) return false;
302 }
303 // If reached, Check if first 4 bytes match bitcode
304 // file magic number.
305 return (BufferLookahead(0) == 'B') &&
306 (BufferLookahead(1) == 'C') &&
307 (BufferLookahead(2) == 0xc0) &&
308 (BufferLookahead(3) == 0xde);
309}
310
311bool BitcodeWrapperer::BufferCopyInToOut(uint32_t size) {
312 while (size > 0) {
313 // Be sure buffer is non-empty before writing.
314 if (0 == buffer_size_) {
315 FillBuffer();
316 if (0 == buffer_size_) {
317 return false;
318 }
319 }
320 // copy the buffer to the output file.
321 size_t block = (buffer_size_ < size) ? buffer_size_ : size;
322 if (!outfile_->Write(&buffer_[cursor_], block)) return false;
323 size -= block;
324 buffer_size_ = 0;
325 }
326 // Be sure that there isn't more bytes on the input stream.
327 FillBuffer();
328 return buffer_size_ == 0;
329}
330
331void BitcodeWrapperer::AddHeaderField(BCHeaderField* field) {
332 header_fields_.push_back(*field);
333 wrapper_bc_offset_ += field->GetTotalSize();
334}
335
336bool BitcodeWrapperer::WriteBitcodeWrapperHeader() {
337 return
338 // Note: This writes out the 4 word header required by llvm wrapped
339 // bitcode.
340 WriteWord(kWrapperMagicNumber) &&
341 WriteWord(kLLVMVersionNumber) &&
342 WriteWord(wrapper_bc_offset_) &&
343 WriteWord(wrapper_bc_size_) &&
344 // 2 fixed fields defined by Android
345 WriteWord(android_header_version_) &&
346 WriteWord(android_target_api_) &&
347 // PNaClBitcode version
348 WriteWord(kPnaclBitcodeVersion) &&
349 // Common variable-length fields
350 WriteVariableFields();
351}
352
353void BitcodeWrapperer::PrintWrapperHeader() {
354 if (error_) {
355 fprintf(stderr, "Error condition exists: the following"
356 "data may not be reliable\n");
357 }
358 fprintf(stderr, "Wrapper magic:\t\t%x\n", kWrapperMagicNumber);
359 fprintf(stderr, "LLVM Bitcode version:\t%d\n", kLLVMVersionNumber);
360 fprintf(stderr, "Raw bitcode offset:\t%d\n", wrapper_bc_offset_);
361 fprintf(stderr, "Raw bitcode size:\t%d\n", wrapper_bc_size_);
362 fprintf(stderr, "Android header version:\t%d\n", android_header_version_);
363 fprintf(stderr, "Android target API:\t%d\n", android_target_api_);
364 fprintf(stderr, "PNaCl bitcode version:\t%d\n", kPnaclBitcodeVersion);
365 for (size_t i = 0; i < header_fields_.size(); i++) header_fields_[i].Print();
366}
367
368bool BitcodeWrapperer::GenerateWrappedBitcodeFile() {
369 if (!error_ &&
370 WriteBitcodeWrapperHeader() &&
371 Seek(infile_bc_offset_) &&
372 BufferCopyInToOut(wrapper_bc_size_)) {
373 off_t dangling = wrapper_bc_size_ & 3;
374 if (dangling) {
375 return outfile_->Write((const uint8_t*) "\0\0\0\0", 4 - dangling);
376 }
377 return true;
378 }
379 return false;
380}
381
382bool BitcodeWrapperer::GenerateRawBitcodeFile() {
383 return !error_ && Seek(infile_bc_offset_) &&
384 BufferCopyInToOut(wrapper_bc_size_);
385}