blob: 752121e8df58092cd53f77e2c04c63c61242e3ff [file] [log] [blame]
Logan1f028c02010-11-27 01:02:48 +08001/*
2 * Copyright 2010, 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#define LOG_TAG "bcc"
18#include <cutils/log.h>
19
Logan1f028c02010-11-27 01:02:48 +080020#if defined(__arm__)
21# define DEFAULT_ARM_CODEGEN
22# define PROVIDE_ARM_CODEGEN
23#elif defined(__i386__)
24# define DEFAULT_X86_CODEGEN
25# define PROVIDE_X86_CODEGEN
26#elif defined(__x86_64__)
27# define DEFAULT_X64_CODEGEN
28# define PROVIDE_X64_CODEGEN
29#endif
30
31#if defined(FORCE_ARM_CODEGEN)
32# define DEFAULT_ARM_CODEGEN
33# undef DEFAULT_X86_CODEGEN
34# undef DEFAULT_X64_CODEGEN
35# define PROVIDE_ARM_CODEGEN
36# undef PROVIDE_X86_CODEGEN
37# undef PROVIDE_X64_CODEGEN
38#elif defined(FORCE_X86_CODEGEN)
39# undef DEFAULT_ARM_CODEGEN
40# define DEFAULT_X86_CODEGEN
41# undef DEFAULT_X64_CODEGEN
42# undef PROVIDE_ARM_CODEGEN
43# define PROVIDE_X86_CODEGEN
44# undef PROVIDE_X64_CODEGEN
45#elif defined(FORCE_X64_CODEGEN)
46# undef DEFAULT_ARM_CODEGEN
47# undef DEFAULT_X86_CODEGEN
48# define DEFAULT_X64_CODEGEN
49# undef PROVIDE_ARM_CODEGEN
50# undef PROVIDE_X86_CODEGEN
51# define PROVIDE_X64_CODEGEN
52#endif
53
54#if defined(DEFAULT_ARM_CODEGEN)
Logandf23afa2010-11-27 11:04:54 +080055# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Logan1f028c02010-11-27 01:02:48 +080056#elif defined(DEFAULT_X86_CODEGEN)
Logandf23afa2010-11-27 11:04:54 +080057# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Logan1f028c02010-11-27 01:02:48 +080058#elif defined(DEFAULT_X64_CODEGEN)
Logandf23afa2010-11-27 11:04:54 +080059# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Logan1f028c02010-11-27 01:02:48 +080060#endif
61
62#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
63# define ARM_USE_VFP
64#endif
65
Loganc4395232010-11-27 18:54:17 +080066#include "Compiler.h"
Logan1f028c02010-11-27 01:02:48 +080067
Logandf23afa2010-11-27 11:04:54 +080068#include "llvm/ADT/StringRef.h"
Logan1f028c02010-11-27 01:02:48 +080069
Logandf23afa2010-11-27 11:04:54 +080070#include "llvm/Analysis/Passes.h"
Logan1f028c02010-11-27 01:02:48 +080071
Logan1f028c02010-11-27 01:02:48 +080072#include "llvm/Bitcode/ReaderWriter.h"
73
Logan1f028c02010-11-27 01:02:48 +080074#include "llvm/CodeGen/Passes.h"
Logan1f028c02010-11-27 01:02:48 +080075#include "llvm/CodeGen/RegAllocRegistry.h"
76#include "llvm/CodeGen/SchedulerRegistry.h"
Logan1f028c02010-11-27 01:02:48 +080077
Logandf23afa2010-11-27 11:04:54 +080078#include "llvm/Transforms/IPO.h"
79#include "llvm/Transforms/Scalar.h"
80
81#include "llvm/Target/SubtargetFeature.h"
82#include "llvm/Target/TargetData.h"
83#include "llvm/Target/TargetMachine.h"
84#include "llvm/Target/TargetOptions.h"
85#include "llvm/Target/TargetRegistry.h"
86#include "llvm/Target/TargetSelect.h"
87
88#include "llvm/Support/ErrorHandling.h"
89#include "llvm/Support/MemoryBuffer.h"
90
91#include "llvm/GlobalValue.h"
92#include "llvm/Linker.h"
93#include "llvm/LLVMContext.h"
94#include "llvm/Metadata.h"
95#include "llvm/Module.h"
96#include "llvm/PassManager.h"
97#include "llvm/Value.h"
98
99#include <errno.h>
100#include <sys/file.h>
101#include <sys/mman.h>
102#include <sys/stat.h>
103#include <sys/types.h>
104#include <unistd.h>
105
106#include <string>
107#include <vector>
Logan1f028c02010-11-27 01:02:48 +0800108
Logandf23afa2010-11-27 11:04:54 +0800109namespace {
Logan1f028c02010-11-27 01:02:48 +0800110
111#define TEMP_FAILURE_RETRY1(exp) ({ \
112 typeof (exp) _rc; \
113 do { \
114 _rc = (exp); \
115 } while (_rc == -1 && errno == EINTR); \
116 _rc; })
117
118
Logandf23afa2010-11-27 11:04:54 +0800119int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg) {
Logan1f028c02010-11-27 01:02:48 +0800120 while (count != 0) {
121 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
122 if (actual < 0) {
123 int err = errno;
124 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
125 return err;
126 } else if (actual != (ssize_t) count) {
127 LOGD("%s: partial write (will retry): (%d of %zd)\n",
128 logMsg, (int) actual, count);
129 buf = (const void*) (((const uint8_t*) buf) + actual);
130 }
131 count -= actual;
132 }
133
134 return 0;
135}
136
Logan9d94f162010-12-07 12:39:25 +0800137inline uint32_t statModifyTime(char const *filepath) {
138 struct stat st;
139
140 if (stat(filepath, &st) < 0) {
141 LOGE("Unable to stat \'%s\', with reason: %s\n", filepath, strerror(errno));
142 return 0;
143 }
144
145 return static_cast<uint32_t>(st.st_mtime);
146}
147
148static char const libRSPath[] = "/system/lib/libRS.so";
149
150static char const libBccPath[] = "/system/lib/libbcc.so";
151
Logandf23afa2010-11-27 11:04:54 +0800152} // namespace anonymous
153
Logan1f028c02010-11-27 01:02:48 +0800154
155namespace bcc {
156
157//////////////////////////////////////////////////////////////////////////////
158// BCC Compiler Static Variables
159//////////////////////////////////////////////////////////////////////////////
160
161bool Compiler::GlobalInitialized = false;
162
163bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
164
165// Code generation optimization level for the compiler
166llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
167
168std::string Compiler::Triple;
169
170std::string Compiler::CPU;
171
172std::vector<std::string> Compiler::Features;
173
174// The named of metadata node that pragma resides (should be synced with
175// slang.cpp)
176const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
177
178// The named of metadata node that export variable name resides (should be
179// synced with slang_rs_metadata.h)
180const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
181
182// The named of metadata node that export function name resides (should be
183// synced with slang_rs_metadata.h)
184const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
185
186
187//////////////////////////////////////////////////////////////////////////////
188// Compiler
189//////////////////////////////////////////////////////////////////////////////
190
191void Compiler::GlobalInitialization() {
192 if (GlobalInitialized)
193 return;
194
195 // if (!llvm::llvm_is_multithreaded())
196 // llvm::llvm_start_multithreaded();
197
198 // Set Triple, CPU and Features here
199 Triple = TARGET_TRIPLE_STRING;
200
201 // TODO(sliao): NEON for JIT
202 // Features.push_back("+neon");
203 // Features.push_back("+vmlx");
204 // Features.push_back("+neonfp");
205 Features.push_back("+vfp3");
206 Features.push_back("+d16");
207
208#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
209 LLVMInitializeARMTargetInfo();
210 LLVMInitializeARMTarget();
211#if defined(USE_DISASSEMBLER)
212 LLVMInitializeARMDisassembler();
213 LLVMInitializeARMAsmPrinter();
214#endif
215#endif
216
217#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
218 LLVMInitializeX86TargetInfo();
219 LLVMInitializeX86Target();
220#if defined(USE_DISASSEMBLER)
221 LLVMInitializeX86Disassembler();
222 LLVMInitializeX86AsmPrinter();
223#endif
224#endif
225
226#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
227 LLVMInitializeX86TargetInfo();
228 LLVMInitializeX86Target();
229#if defined(USE_DISASSEMBLER)
230 LLVMInitializeX86Disassembler();
231 LLVMInitializeX86AsmPrinter();
232#endif
233#endif
234
235 // -O0: llvm::CodeGenOpt::None
236 // -O1: llvm::CodeGenOpt::Less
237 // -O2: llvm::CodeGenOpt::Default
238 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liao72f67a62010-12-14 13:36:15 -0800239 CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
Logan1f028c02010-11-27 01:02:48 +0800240
241 // Below are the global settings to LLVM
242
243 // Disable frame pointer elimination optimization
244 llvm::NoFramePointerElim = false;
245
246 // Use hardfloat ABI
247 //
248 // TODO(all): Need to detect the CPU capability and decide whether to use
249 // softfp. To use softfp, change following 2 lines to
250 //
251 // llvm::FloatABIType = llvm::FloatABI::Soft;
252 // llvm::UseSoftFloat = true;
253 //
254 llvm::FloatABIType = llvm::FloatABI::Soft;
255 llvm::UseSoftFloat = false;
256
257 // BCC needs all unknown symbols resolved at JIT/compilation time.
258 // So we don't need any dynamic relocation model.
259 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
260
261#if defined(DEFAULT_X64_CODEGEN)
262 // Data address in X86_64 architecture may reside in a far-away place
263 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
264#else
265 // This is set for the linker (specify how large of the virtual addresses
266 // we can access for all unknown symbols.)
267 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
268#endif
269
270 // Register the scheduler
271 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
272
273 // Register allocation policy:
274 // createFastRegisterAllocator: fast but bad quality
275 // createLinearScanRegisterAllocator: not so fast but good quality
276 llvm::RegisterRegAlloc::setDefault
277 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
278 llvm::createFastRegisterAllocator :
279 llvm::createLinearScanRegisterAllocator);
280
281 GlobalInitialized = true;
282}
283
284
285void Compiler::LLVMErrorHandler(void *UserData, const std::string &Message) {
286 std::string *Error = static_cast<std::string*>(UserData);
287 Error->assign(Message);
288 LOGE("%s", Message.c_str());
289 exit(1);
290}
291
292
293CodeMemoryManager *Compiler::createCodeMemoryManager() {
294 mCodeMemMgr.reset(new CodeMemoryManager());
295 return mCodeMemMgr.get();
296}
297
298
299CodeEmitter *Compiler::createCodeEmitter() {
300 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
301 return mCodeEmitter.get();
302}
303
304
305Compiler::Compiler()
306 : mUseCache(false),
307 mCacheNew(false),
308 mCacheFd(-1),
309 mCacheMapAddr(NULL),
310 mCacheHdr(NULL),
311 mCacheSize(0),
312 mCacheDiff(0),
313 mCodeDataAddr(NULL),
314 mpSymbolLookupFn(NULL),
315 mpSymbolLookupContext(NULL),
316 mContext(NULL),
317 mModule(NULL),
318 mHasLinked(false) /* Turn off linker */ {
319 llvm::remove_fatal_error_handler();
320 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
321 mContext = new llvm::LLVMContext();
322 return;
323}
324
325
326int Compiler::readBC(const char *bitcode,
327 size_t bitcodeSize,
Shih-wei Liaoe6a18512010-12-09 12:38:10 -0800328 const BCCchar *resName,
329 const BCCchar *cacheDir) {
Logan1f028c02010-11-27 01:02:48 +0800330 GlobalInitialization();
331
332 if (resName) {
333 // Turn on mUseCache mode iff
334 // 1. Has resName
335 // and, assuming USE_RELOCATE is false:
336 // 2. Later running code doesn't violate the following condition:
337 // mCodeDataAddr (set in loadCacheFile()) ==
338 // mCacheHdr->cachedCodeDataAddr
339 //
340 // BTW, this condition is achievable only when in the earlier
341 // cache-generating run,
342 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
343 // which means the mmap'ed is in the reserved area,
344 //
345 // Note: Upon violation, mUseCache will be set back to false.
346 mUseCache = true;
347
Shih-wei Liaoe6a18512010-12-09 12:38:10 -0800348 mCacheFd = openCacheFile(resName, cacheDir, true /* createIfMissing */);
Logan1f028c02010-11-27 01:02:48 +0800349 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
Logan139dc3c2010-12-03 01:32:05 +0800350 return -mCacheFd - 1;
Logan1f028c02010-11-27 01:02:48 +0800351 }
352 }
353
354 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
355
356 if (bitcode == NULL || bitcodeSize <= 0)
357 return 0;
358
359 // Package input to object MemoryBuffer
360 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
361 llvm::StringRef(bitcode, bitcodeSize)));
362
363 if (MEM.get() == NULL) {
364 setError("Error reading input program bitcode into memory");
365 return hasError();
366 }
367
368 // Read the input Bitcode as a Module
369 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
370 MEM.reset();
371 return hasError();
372}
373
374
375int Compiler::linkBC(const char *bitcode, size_t bitcodeSize) {
376 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
377
378 if (bitcode == NULL || bitcodeSize <= 0)
379 return 0;
380
381 if (mModule == NULL) {
382 setError("No module presents for linking");
383 return hasError();
384 }
385
386 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
387 llvm::StringRef(bitcode, bitcodeSize)));
388
389 if (MEM.get() == NULL) {
390 setError("Error reading input library bitcode into memory");
391 return hasError();
392 }
393
394 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
395 *mContext,
396 &mError));
397 if (Lib.get() == NULL)
398 return hasError();
399
400 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
401 return hasError();
402
403 // Everything for linking should be settled down here with no error occurs
404 mHasLinked = true;
405 return hasError();
406}
407
408
409// interface for bccLoadBinary()
410int Compiler::loadCacheFile() {
411 // Check File Descriptor
412 if (mCacheFd < 0) {
413 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
414 goto giveup;
415 }
416
417 // Check File Size
418 struct stat statCacheFd;
419 if (fstat(mCacheFd, &statCacheFd) < 0) {
420 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
421 goto giveup;
422 }
423
424 mCacheSize = statCacheFd.st_size;
425
426 if (mCacheSize < sizeof(oBCCHeader) ||
427 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
428 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
429 goto giveup;
430 }
431
432 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
433 LOGE("Unable to seek to 0: %s\n", strerror(errno));
434 goto giveup;
435 }
436
437 // Part 1. Deal with the non-codedata section first
438 {
439 // Read cached file and perform quick integrity check
440
441 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
442 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
443 (unsigned int)mCacheSize,
444 (unsigned long long int)heuristicCodeOffset);
445
446 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
447 if (!mCacheMapAddr) {
448 flock(mCacheFd, LOCK_UN);
449 LOGE("allocation failed.\n");
450 goto bail;
451 }
452
453 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
454 heuristicCodeOffset));
455 if (nread != (size_t)heuristicCodeOffset) {
456 LOGE("read(mCacheFd) failed\n");
457 goto bail;
458 }
459
460 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
461 // Sanity check
462 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
463 LOGE("assertion failed: heuristic code offset is not correct.\n");
464 goto bail;
465 }
466 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
467 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
468 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
469 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
470 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
471
472 // Verify the Cache File
473 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
474 LOGE("bad magic word\n");
475 goto bail;
476 }
477
478 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
479 LOGE("bad oBCC version 0x%08x\n",
480 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
481 goto bail;
482 }
483
484 if (mCacheSize < mCacheHdr->relocOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800485 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
Logan1f028c02010-11-27 01:02:48 +0800486 LOGE("relocate table overflow\n");
487 goto bail;
488 }
489
490 if (mCacheSize < mCacheHdr->exportVarsOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800491 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
Logan1f028c02010-11-27 01:02:48 +0800492 LOGE("export variables table overflow\n");
493 goto bail;
494 }
495
496 if (mCacheSize < mCacheHdr->exportFuncsOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800497 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
Logan1f028c02010-11-27 01:02:48 +0800498 LOGE("export functions table overflow\n");
499 goto bail;
500 }
501
502 if (mCacheSize < mCacheHdr->exportPragmasOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800503 mCacheHdr->exportPragmasSize) {
Logan1f028c02010-11-27 01:02:48 +0800504 LOGE("export pragmas table overflow\n");
505 goto bail;
506 }
507
508 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
509 LOGE("code cache overflow\n");
510 goto bail;
511 }
512
513 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
514 LOGE("data (global variable) cache overflow\n");
515 goto bail;
516 }
517
518 long pagesize = sysconf(_SC_PAGESIZE);
519 if (mCacheHdr->codeOffset % pagesize != 0) {
520 LOGE("code offset must aligned to pagesize\n");
521 goto bail;
522 }
523 }
524
525 // Part 2. Deal with the codedata section
526 {
527 long pagesize = sysconf(_SC_PAGESIZE);
528
529 if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
530 void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
531
532 // Try to mmap at cached address directly.
533 mCodeDataAddr = (char *) mmap(addr,
534 BCC_MMAP_IMG_SIZE,
535 PROT_READ | PROT_EXEC | PROT_WRITE,
536 MAP_PRIVATE | MAP_FIXED,
537 mCacheFd,
538 mCacheHdr->codeOffset);
539
540 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
541 // Cheers! Mapped at the cached address successfully.
542
543 // Update the BccMmapImgAddrTaken table (if required)
544 if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
545 size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
Shih-wei Liao19ee3112010-12-15 03:50:21 -0800546 size_t scriptId = offset / BCC_MMAP_IMG_SIZE;
Logan1f028c02010-11-27 01:02:48 +0800547
548 if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
Shih-wei Liao19ee3112010-12-15 03:50:21 -0800549 scriptId < BCC_MMAP_IMG_COUNT) {
550 if (Compiler::BccMmapImgAddrTaken[scriptId] == true) {
551 mCodeDataAddr = (char *) MAP_FAILED;
552 } else {
553 Compiler::BccMmapImgAddrTaken[scriptId] = true;
554 }
Logan1f028c02010-11-27 01:02:48 +0800555 }
556 }
557
558#if 1
559 // Check the checksum of code and data
560 {
561 uint32_t sum = mCacheHdr->checksum;
562 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
563
564 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
565 sum ^= *ptr++;
566 }
567
568 if (sum != 0) {
569 LOGE("Checksum check failed\n");
570 goto bail;
571 }
572
Shih-wei Liao9ea54b52010-12-01 17:57:07 -0800573 LOGI("Passed checksum even parity verification.\n");
Logan1f028c02010-11-27 01:02:48 +0800574 }
575#endif
576
577 flock(mCacheFd, LOCK_UN);
578 return 0; // loadCacheFile succeed!
579 }
580 }
581 }
582
583#if !USE_RELOCATE
584 // Note: Since this build does not support relocation, we have no
585 // choose but give up to load the cached file, and recompile the
586 // code.
587
588 flock(mCacheFd, LOCK_UN);
589 goto bail;
590#else
591
592 // Note: Currently, relocation code is not working. Give up now.
593 flock(mCacheFd, LOCK_UN);
594 goto bail;
595
596 // TODO(logan): Following code is not working. Don't use them.
597 // And rewrite them asap.
598#if 0
599 {
600 // Try to allocate at arbitary address. And perform relocation.
601 mCacheMapAddr = (char *) mmap(0,
602 mCacheSize,
603 PROT_READ | PROT_EXEC | PROT_WRITE,
604 MAP_PRIVATE,
605 mCacheFd,
606 0);
607
608 if (mCacheMapAddr == MAP_FAILED) {
609 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
610 flock(mCacheFd, LOCK_UN);
611 goto giveup;
612 }
613
614 flock(mCacheFd, LOCK_UN);
615 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
616
617 // Relocate
618 mCacheDiff = mCodeDataAddr -
619 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
620
621 if (mCacheDiff) { // To relocate
622 if (mCacheHdr->rootAddr) {
623 mCacheHdr->rootAddr += mCacheDiff;
624 }
625
626 if (mCacheHdr->initAddr) {
627 mCacheHdr->initAddr += mCacheDiff;
628 }
629
630 oBCCRelocEntry *cachedRelocTable =
631 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
632 mCacheHdr->relocOffset);
633
634 std::vector<llvm::MachineRelocation> relocations;
635
636 // Read in the relocs
637 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
638 oBCCRelocEntry *entry = &cachedRelocTable[i];
639
640 llvm::MachineRelocation reloc =
641 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
642 (unsigned)entry->relocType, 0, 0);
643
644 reloc.setResultPointer(
645 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
646
647 relocations.push_back(reloc);
648 }
649
650 // Rewrite machine code using llvm::TargetJITInfo relocate
651 {
652 llvm::TargetMachine *TM = NULL;
653 const llvm::Target *Target;
654 std::string FeaturesStr;
655
656 // Create TargetMachine
657 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
658 if (hasError())
659 goto bail;
660
661 if (!CPU.empty() || !Features.empty()) {
662 llvm::SubtargetFeatures F;
663 F.setCPU(CPU);
664 for (std::vector<std::string>::const_iterator I = Features.begin(),
665 E = Features.end(); I != E; I++)
666 F.AddFeature(*I);
667 FeaturesStr = F.getString();
668 }
669
670 TM = Target->createTargetMachine(Triple, FeaturesStr);
671 if (TM == NULL) {
672 setError("Failed to create target machine implementation for the"
673 " specified triple '" + Triple + "'");
674 goto bail;
675 }
676
677 TM->getJITInfo()->relocate(mCodeDataAddr,
678 &relocations[0], relocations.size(),
679 (unsigned char *)mCodeDataAddr+MaxCodeSize);
680
681 if (mCodeEmitter.get()) {
682 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
683 reinterpret_cast<uint8_t*>(mCodeDataAddr),
684 2 * 1024 /*MaxCodeSize*/,
685 false);
686 }
687
688 delete TM;
689 }
690 } // End of if (mCacheDiff)
691
692 return 0; // Success!
693 }
694#endif
695#endif
696
697bail:
698 if (mCacheMapAddr) {
699 free(mCacheMapAddr);
700 }
701
702 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
703 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
704 LOGE("munmap failed: %s\n", strerror(errno));
705 }
706 }
707
708 mCacheMapAddr = NULL;
709 mCacheHdr = NULL;
710 mCodeDataAddr = NULL;
711
712giveup:
713 return 1;
714}
715
716// interace for bccCompileBC()
717int Compiler::compile() {
718 llvm::TargetData *TD = NULL;
719
720 llvm::TargetMachine *TM = NULL;
721 const llvm::Target *Target;
722 std::string FeaturesStr;
723
724 llvm::FunctionPassManager *CodeGenPasses = NULL;
725
726 const llvm::NamedMDNode *PragmaMetadata;
727 const llvm::NamedMDNode *ExportVarMetadata;
728 const llvm::NamedMDNode *ExportFuncMetadata;
729
730 if (mModule == NULL) // No module was loaded
731 return 0;
732
733 // Create TargetMachine
734 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
735 if (hasError())
736 goto on_bcc_compile_error;
737
738 if (!CPU.empty() || !Features.empty()) {
739 llvm::SubtargetFeatures F;
740 F.setCPU(CPU);
Logana4994f52010-11-27 14:06:02 +0800741
742 for (std::vector<std::string>::const_iterator
743 I = Features.begin(), E = Features.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +0800744 F.AddFeature(*I);
Logana4994f52010-11-27 14:06:02 +0800745 }
746
Logan1f028c02010-11-27 01:02:48 +0800747 FeaturesStr = F.getString();
748 }
749
750 TM = Target->createTargetMachine(Triple, FeaturesStr);
751 if (TM == NULL) {
752 setError("Failed to create target machine implementation for the"
753 " specified triple '" + Triple + "'");
754 goto on_bcc_compile_error;
755 }
756
757 // Create memory manager for creation of code emitter later.
758 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
759 setError("Failed to startup memory management for further compilation");
760 goto on_bcc_compile_error;
761 }
762 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
763
764 // Create code emitter
765 if (!mCodeEmitter.get()) {
766 if (!createCodeEmitter()) {
767 setError("Failed to create machine code emitter to complete"
768 " the compilation");
769 goto on_bcc_compile_error;
770 }
771 } else {
772 // Reuse the code emitter
773 mCodeEmitter->reset();
774 }
775
776 mCodeEmitter->setTargetMachine(*TM);
777 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
778 mpSymbolLookupContext);
779
780 // Get target data from Module
781 TD = new llvm::TargetData(mModule);
782
783 // Load named metadata
784 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
785 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
786 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
787
788 // Create LTO passes and run them on the mModule
789 if (mHasLinked) {
790 llvm::TimePassesIsEnabled = true; // TODO(all)
791 llvm::PassManager LTOPasses;
792 LTOPasses.add(new llvm::TargetData(*TD));
793
794 std::vector<const char*> ExportSymbols;
795
796 // A workaround for getting export variable and function name. Will refine
797 // it soon.
798 if (ExportVarMetadata) {
799 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
800 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
801 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
802 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
803 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
804 llvm::StringRef ExportVarName =
805 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
806 ExportSymbols.push_back(ExportVarName.data());
807 }
808 }
809 }
810 }
811
812 if (ExportFuncMetadata) {
813 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
814 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
815 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
816 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
817 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
818 llvm::StringRef ExportFuncName =
819 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
820 ExportSymbols.push_back(ExportFuncName.data());
821 }
822 }
823 }
824 }
825 // root() and init() are born to be exported
826 ExportSymbols.push_back("root");
827 ExportSymbols.push_back("init");
828
829 // We now create passes list performing LTO. These are copied from
830 // (including comments) llvm::createStandardLTOPasses().
831
832 // Internalize all other symbols not listed in ExportSymbols
833 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
834
835 // Propagate constants at call sites into the functions they call. This
836 // opens opportunities for globalopt (and inlining) by substituting
837 // function pointers passed as arguments to direct uses of functions.
838 LTOPasses.add(llvm::createIPSCCPPass());
839
840 // Now that we internalized some globals, see if we can hack on them!
841 LTOPasses.add(llvm::createGlobalOptimizerPass());
842
843 // Linking modules together can lead to duplicated global constants, only
844 // keep one copy of each constant...
845 LTOPasses.add(llvm::createConstantMergePass());
846
847 // Remove unused arguments from functions...
848 LTOPasses.add(llvm::createDeadArgEliminationPass());
849
850 // Reduce the code after globalopt and ipsccp. Both can open up
851 // significant simplification opportunities, and both can propagate
852 // functions through function pointers. When this happens, we often have
853 // to resolve varargs calls, etc, so let instcombine do this.
854 LTOPasses.add(llvm::createInstructionCombiningPass());
855
856 // Inline small functions
857 LTOPasses.add(llvm::createFunctionInliningPass());
858
859 // Remove dead EH info.
860 LTOPasses.add(llvm::createPruneEHPass());
861
862 // Internalize the globals again after inlining
863 LTOPasses.add(llvm::createGlobalOptimizerPass());
864
865 // Remove dead functions.
866 LTOPasses.add(llvm::createGlobalDCEPass());
867
868 // If we didn't decide to inline a function, check to see if we can
869 // transform it to pass arguments by value instead of by reference.
870 LTOPasses.add(llvm::createArgumentPromotionPass());
871
872 // The IPO passes may leave cruft around. Clean up after them.
873 LTOPasses.add(llvm::createInstructionCombiningPass());
874 LTOPasses.add(llvm::createJumpThreadingPass());
875
876 // Break up allocas
877 LTOPasses.add(llvm::createScalarReplAggregatesPass());
878
879 // Run a few AA driven optimizations here and now, to cleanup the code.
880 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
881 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
882
883 // Hoist loop invariants.
884 LTOPasses.add(llvm::createLICMPass());
885
886 // Remove redundancies.
887 LTOPasses.add(llvm::createGVNPass());
888
889 // Remove dead memcpys.
890 LTOPasses.add(llvm::createMemCpyOptPass());
891
892 // Nuke dead stores.
893 LTOPasses.add(llvm::createDeadStoreEliminationPass());
894
895 // Cleanup and simplify the code after the scalar optimizations.
896 LTOPasses.add(llvm::createInstructionCombiningPass());
897
898 LTOPasses.add(llvm::createJumpThreadingPass());
899
900 // Delete basic blocks, which optimization passes may have killed.
901 LTOPasses.add(llvm::createCFGSimplificationPass());
902
903 // Now that we have optimized the program, discard unreachable functions.
904 LTOPasses.add(llvm::createGlobalDCEPass());
905
906 LTOPasses.run(*mModule);
907 }
908
909 // Create code-gen pass to run the code emitter
910 CodeGenPasses = new llvm::FunctionPassManager(mModule);
911 CodeGenPasses->add(TD); // Will take the ownership of TD
912
913 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
914 *mCodeEmitter,
915 CodeGenOptLevel)) {
916 setError("The machine code emission is not supported by BCC on target '"
917 + Triple + "'");
918 goto on_bcc_compile_error;
919 }
920
921 // Run the pass (the code emitter) on every non-declaration function in the
922 // module
923 CodeGenPasses->doInitialization();
924 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
925 I != E; I++) {
926 if (!I->isDeclaration()) {
927 CodeGenPasses->run(*I);
928 }
929 }
930
931 CodeGenPasses->doFinalization();
932
933 // Copy the global address mapping from code emitter and remapping
934 if (ExportVarMetadata) {
935 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
936 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
937 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
938 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
939 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
940 llvm::StringRef ExportVarName =
941 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
942
943 CodeEmitter::global_addresses_const_iterator I, E;
944 for (I = mCodeEmitter->global_address_begin(),
945 E = mCodeEmitter->global_address_end();
946 I != E; I++) {
947 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
948 continue;
949 if (ExportVarName == I->first->getName()) {
950 mExportVars.push_back(I->second);
951 break;
952 }
953 }
954 if (I != mCodeEmitter->global_address_end())
955 continue; // found
956 }
957 }
958 // if reaching here, we know the global variable record in metadata is
959 // not found. So we make an empty slot
960 mExportVars.push_back(NULL);
961 }
962 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
963 "Number of slots doesn't match the number of export variables!");
964 }
965
966 if (ExportFuncMetadata) {
967 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
968 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
969 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
970 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
971 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
972 llvm::StringRef ExportFuncName =
973 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
974 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
975 }
976 }
977 }
978 }
979
980 // Tell code emitter now can release the memory using during the JIT since
981 // we have done the code emission
982 mCodeEmitter->releaseUnnecessary();
983
984 // Finally, read pragma information from the metadata node of the @Module if
985 // any.
986 if (PragmaMetadata)
987 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
988 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
989 if (Pragma != NULL &&
990 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
991 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
992 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
993
994 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
995 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
996 llvm::StringRef PragmaName =
997 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
998 llvm::StringRef PragmaValue =
999 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
1000
1001 mPragmas.push_back(
1002 std::make_pair(std::string(PragmaName.data(),
1003 PragmaName.size()),
1004 std::string(PragmaValue.data(),
1005 PragmaValue.size())));
1006 }
1007 }
1008 }
1009
1010on_bcc_compile_error:
1011 // LOGE("on_bcc_compiler_error");
1012 if (CodeGenPasses) {
1013 delete CodeGenPasses;
1014 } else if (TD) {
1015 delete TD;
1016 }
1017 if (TM)
1018 delete TM;
1019
1020 if (mError.empty()) {
1021 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
1022 genCacheFile();
1023 flock(mCacheFd, LOCK_UN);
1024 }
1025
1026 return false;
1027 }
1028
1029 // LOGE(getErrorMessage());
1030 return true;
1031}
1032
1033
1034// interface for bccGetScriptLabel()
1035void *Compiler::lookup(const char *name) {
1036 void *addr = NULL;
1037 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1038 if (!strcmp(name, "root")) {
1039 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
1040 } else if (!strcmp(name, "init")) {
1041 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
1042 }
1043 return addr;
1044 }
1045
1046 if (mCodeEmitter.get())
1047 // Find function pointer
1048 addr = mCodeEmitter->lookup(name);
1049 return addr;
1050}
1051
1052
1053// Interface for bccGetExportVars()
1054void Compiler::getExportVars(BCCsizei *actualVarCount,
1055 BCCsizei maxVarCount,
1056 BCCvoid **vars) {
1057 int varCount;
1058
1059 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1060 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
1061 if (actualVarCount)
1062 *actualVarCount = varCount;
1063 if (varCount > maxVarCount)
1064 varCount = maxVarCount;
1065 if (vars) {
1066 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
1067 mCacheHdr->exportVarsOffset);
1068
1069 for (int i = 0; i < varCount; i++) {
Logan7cc1baf2010-11-28 23:46:11 +08001070 *vars = (BCCvoid *)((char *)(*cachedVars) + mCacheDiff);
1071 vars++;
Logan1f028c02010-11-27 01:02:48 +08001072 cachedVars++;
1073 }
1074 }
1075 return;
1076 }
1077
1078 varCount = mExportVars.size();
1079 if (actualVarCount)
1080 *actualVarCount = varCount;
1081 if (varCount > maxVarCount)
1082 varCount = maxVarCount;
1083 if (vars) {
Logana4994f52010-11-27 14:06:02 +08001084 for (ExportVarList::const_iterator
1085 I = mExportVars.begin(), E = mExportVars.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +08001086 *vars++ = *I;
1087 }
1088 }
Logan1f028c02010-11-27 01:02:48 +08001089}
1090
1091
1092// Interface for bccGetExportFuncs()
1093void Compiler::getExportFuncs(BCCsizei *actualFuncCount,
1094 BCCsizei maxFuncCount,
1095 BCCvoid **funcs) {
1096 int funcCount;
1097
1098 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1099 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
1100 if (actualFuncCount)
1101 *actualFuncCount = funcCount;
1102 if (funcCount > maxFuncCount)
1103 funcCount = maxFuncCount;
1104 if (funcs) {
1105 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
1106 mCacheHdr->exportFuncsOffset);
1107
1108 for (int i = 0; i < funcCount; i++) {
Logan7cc1baf2010-11-28 23:46:11 +08001109 *funcs = (BCCvoid *)((char *)(*cachedFuncs) + mCacheDiff);
1110 funcs++;
Logan1f028c02010-11-27 01:02:48 +08001111 cachedFuncs++;
1112 }
1113 }
1114 return;
1115 }
1116
1117 funcCount = mExportFuncs.size();
1118 if (actualFuncCount)
1119 *actualFuncCount = funcCount;
1120 if (funcCount > maxFuncCount)
1121 funcCount = maxFuncCount;
1122 if (funcs) {
Logan7cc1baf2010-11-28 23:46:11 +08001123 for (ExportFuncList::const_iterator
1124 I = mExportFuncs.begin(), E = mExportFuncs.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +08001125 *funcs++ = *I;
1126 }
1127 }
Logan1f028c02010-11-27 01:02:48 +08001128}
1129
1130
1131// Interface for bccGetPragmas()
1132void Compiler::getPragmas(BCCsizei *actualStringCount,
1133 BCCsizei maxStringCount,
1134 BCCchar **strings) {
1135 int stringCount;
Logan7cc1baf2010-11-28 23:46:11 +08001136
Logan1f028c02010-11-27 01:02:48 +08001137 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Logan7cc1baf2010-11-28 23:46:11 +08001138 stringCount = static_cast<int>(mCacheHdr->exportPragmasCount) * 2;
1139
Logan1f028c02010-11-27 01:02:48 +08001140 if (actualStringCount)
Logan7cc1baf2010-11-28 23:46:11 +08001141 *actualStringCount = stringCount;
1142
1143 if (stringCount > maxStringCount)
1144 stringCount = maxStringCount;
1145
1146 if (strings) {
1147 char *pragmaTab = mCacheMapAddr + mCacheHdr->exportPragmasOffset;
1148
1149 oBCCPragmaEntry *cachedPragmaEntries = (oBCCPragmaEntry *)pragmaTab;
1150
1151 for (int i = 0; stringCount >= 2; stringCount -= 2, i++) {
1152 *strings++ = pragmaTab + cachedPragmaEntries[i].pragmaNameOffset;
1153 *strings++ = pragmaTab + cachedPragmaEntries[i].pragmaValueOffset;
1154 }
1155 }
1156
Logan1f028c02010-11-27 01:02:48 +08001157 return;
1158 }
1159
1160 stringCount = mPragmas.size() * 2;
1161
1162 if (actualStringCount)
1163 *actualStringCount = stringCount;
1164 if (stringCount > maxStringCount)
1165 stringCount = maxStringCount;
1166 if (strings) {
Logan7cc1baf2010-11-28 23:46:11 +08001167 size_t i = 0;
Logan1f028c02010-11-27 01:02:48 +08001168 for (PragmaList::const_iterator it = mPragmas.begin();
Logan7cc1baf2010-11-28 23:46:11 +08001169 stringCount >= 2; stringCount -= 2, it++, ++i) {
Logan1f028c02010-11-27 01:02:48 +08001170 *strings++ = const_cast<BCCchar*>(it->first.c_str());
1171 *strings++ = const_cast<BCCchar*>(it->second.c_str());
1172 }
1173 }
1174
1175 return;
1176}
1177
1178
1179// Interface for bccGetFunctions()
1180void Compiler::getFunctions(BCCsizei *actualFunctionCount,
1181 BCCsizei maxFunctionCount,
1182 BCCchar **functions) {
1183 if (mCodeEmitter.get())
1184 mCodeEmitter->getFunctionNames(actualFunctionCount,
1185 maxFunctionCount,
1186 functions);
1187 else
1188 *actualFunctionCount = 0;
1189
1190 return;
1191}
1192
1193
1194// Interface for bccGetFunctionBinary()
1195void Compiler::getFunctionBinary(BCCchar *function,
1196 BCCvoid **base,
1197 BCCsizei *length) {
1198 if (mCodeEmitter.get()) {
1199 mCodeEmitter->getFunctionBinary(function, base, length);
1200 } else {
1201 *base = NULL;
1202 *length = 0;
1203 }
1204 return;
1205}
1206
1207
1208Compiler::~Compiler() {
1209 if (!mCodeMemMgr.get()) {
1210 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
1211 // managed by CodeMemoryManager.
1212
1213 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
1214 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
1215 LOGE("munmap failed while releasing mCodeDataAddr\n");
1216 }
1217 }
1218
1219 if (mCacheMapAddr) {
1220 free(mCacheMapAddr);
1221 }
1222
1223 mCodeDataAddr = 0;
1224 mCacheMapAddr = 0;
1225 }
1226
1227 delete mModule;
Logan1f028c02010-11-27 01:02:48 +08001228 delete mContext;
Logana4994f52010-11-27 14:06:02 +08001229
1230 // llvm::llvm_shutdown();
Logan1f028c02010-11-27 01:02:48 +08001231}
1232
1233
1234// Design of caching EXE:
1235// ======================
1236// 1. Each process will have virtual address available starting at 0x7e00000.
1237// E.g., Books and Youtube all have its own 0x7e00000. Next, we should
1238// minimize the chance of needing to do relocation INSIDE an app too.
1239//
1240// 2. Each process will have ONE class static variable called BccCodeAddr.
1241// I.e., even though the Compiler class will have multiple Compiler objects,
1242// e.g, one object for carousel.rs and the other for pageturn.rs,
1243// both Compiler objects will share 1 static variable called BccCodeAddr.
1244//
1245// Key observation: Every app (process) initiates, say 3, scripts (which
1246// correspond to 3 Compiler objects) in the same order, usually.
1247//
1248// So, we should mmap to, e.g., 0x7e00000, 0x7e40000, 0x7e80000 for the 3
1249// scripts, respectively. Each time, BccCodeAddr should be updated after
1250// JITTing a script. BTW, in ~Compiler(), BccCodeAddr should NOT be
1251// decremented back by CodeDataSize. I.e., for 3 scripts: A, B, C,
1252// even if it's A -> B -> ~B -> C -> ~C -> B -> C ... no relocation will
1253// ever be needed.)
1254//
1255// If we are lucky, then we don't need relocation ever, since next time the
1256// application gets run, the 3 scripts are likely created in the SAME order.
1257//
1258//
1259// End-to-end algorithm on when to caching and when to JIT:
1260// ========================================================
1261// Prologue:
1262// ---------
1263// Assertion: bccReadBC() is always called and is before bccCompileBC(),
1264// bccLoadBinary(), ...
1265//
1266// Key variable definitions: Normally,
1267// Compiler::BccCodeAddr: non-zero if (USE_CACHE)
1268// | (Stricter, because currently relocation doesn't work. So mUseCache only
1269// | when BccCodeAddr is nonzero.)
1270// V
1271// mUseCache: In addition to (USE_CACHE), resName is non-zero
1272// Note: mUseCache will be set to false later on whenever we find that caching
1273// won't work. E.g., when mCodeDataAddr != mCacheHdr->cachedCodeDataAddr.
1274// This is because currently relocation doesn't work.
1275// | (Stricter, initially)
1276// V
1277// mCacheFd: In addition, >= 0 if openCacheFile() returns >= 0
1278// | (Stricter)
1279// V
1280// mCacheNew: In addition, mCacheFd's size is 0, so need to call genCacheFile()
1281// at the end of compile()
1282//
1283//
1284// Main algorithm:
1285// ---------------
1286// #if !USE_RELOCATE
1287// Case 1. ReadBC() doesn't detect a cache file:
1288// compile(), which calls genCacheFile() at the end.
1289// Note: mCacheNew will guard the invocation of genCacheFile()
1290// Case 2. ReadBC() find a cache file
1291// loadCacheFile(). But if loadCacheFile() failed, should go to Case 1.
1292// #endif
1293
1294// Note: loadCacheFile() and genCacheFile() go hand in hand
1295void Compiler::genCacheFile() {
1296 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
1297 LOGE("Unable to seek to 0: %s\n", strerror(errno));
1298 return;
1299 }
1300
1301 bool codeOffsetNeedPadding = false;
1302
1303 uint32_t offset = sizeof(oBCCHeader);
1304
1305 // BCC Cache File Header
1306 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
1307
1308 if (!hdr) {
1309 LOGE("Unable to allocate oBCCHeader.\n");
1310 return;
1311 }
1312
1313 // Magic Words
1314 memcpy(hdr->magic, OBCC_MAGIC, 4);
1315 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
1316
1317 // Timestamp
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001318 // TODO(sliao): Should be .bc's ModifyTime. Now just use it to store
1319 // threadable
1320 hdr->sourceWhen = (uint32_t) mCodeEmitter->mpSymbolLookupFn(
1321 mpSymbolLookupContext,
1322 "__isThreadable");
1323
1324 hdr->rslibWhen = 0; // TODO(sliao)
Logan9d94f162010-12-07 12:39:25 +08001325 hdr->libRSWhen = statModifyTime(libRSPath);
1326 hdr->libbccWhen = statModifyTime(libBccPath);
Logan1f028c02010-11-27 01:02:48 +08001327
1328 // Current Memory Address (Saved for Recalculation)
1329 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
1330 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
1331 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
1332
1333 // Relocation Table Offset and Entry Count
1334 hdr->relocOffset = sizeof(oBCCHeader);
1335 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
1336
Logan7cc1baf2010-11-28 23:46:11 +08001337 offset += hdr->relocCount * sizeof(oBCCRelocEntry);
Logan1f028c02010-11-27 01:02:48 +08001338
1339 // Export Variable Table Offset and Entry Count
1340 hdr->exportVarsOffset = offset;
1341 hdr->exportVarsCount = mExportVars.size();
1342
1343 offset += hdr->exportVarsCount * sizeof(uint32_t);
1344
1345 // Export Function Table Offset and Entry Count
1346 hdr->exportFuncsOffset = offset;
1347 hdr->exportFuncsCount = mExportFuncs.size();
1348
1349 offset += hdr->exportFuncsCount * sizeof(uint32_t);
1350
1351 // Export Pragmas Table Offset and Entry Count
1352 hdr->exportPragmasOffset = offset;
Logan7cc1baf2010-11-28 23:46:11 +08001353 hdr->exportPragmasCount = mPragmas.size();
1354 hdr->exportPragmasSize = hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
Logan1f028c02010-11-27 01:02:48 +08001355
Logan7cc1baf2010-11-28 23:46:11 +08001356 offset += hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
1357
1358 for (PragmaList::const_iterator
1359 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1360 offset += I->first.size() + 1;
1361 offset += I->second.size() + 1;
1362 hdr->exportPragmasSize += I->first.size() + I->second.size() + 2;
1363 }
Logan1f028c02010-11-27 01:02:48 +08001364
1365 // Code Offset and Size
1366
1367 { // Always pad to the page boundary for now
1368 long pagesize = sysconf(_SC_PAGESIZE);
1369
1370 if (offset % pagesize > 0) {
1371 codeOffsetNeedPadding = true;
1372 offset += pagesize - (offset % pagesize);
1373 }
1374 }
1375
1376 hdr->codeOffset = offset;
1377 hdr->codeSize = MaxCodeSize;
1378
1379 offset += hdr->codeSize;
1380
1381 // Data (Global Variable) Offset and Size
1382 hdr->dataOffset = offset;
1383 hdr->dataSize = MaxGlobalVarSize;
1384
1385 offset += hdr->dataSize;
1386
1387 // Checksum
1388#if 1
1389 {
1390 // Note: This is an simple checksum implementation that are using xor
1391 // to calculate even parity (for code and data only).
1392
1393 uint32_t sum = 0;
1394 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
1395
1396 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
1397 sum ^= *ptr++;
1398 }
1399
1400 hdr->checksum = sum;
1401 }
1402#else
1403 hdr->checksum = 0; // Set Field checksum. TODO(all)
1404#endif
1405
1406 // Write Header
1407 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
1408 sizeof(oBCCHeader), "Write oBCC header");
1409
1410 // Write Relocation Entry Table
1411 {
1412 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
1413
1414 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
1415
1416 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
1417 allocSize, "Write Relocation Entries");
1418 }
1419
1420 // Write Export Variables Table
1421 {
1422 uint32_t *record, *ptr;
1423
1424 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
1425 ptr = record;
1426
1427 if (!record) {
1428 goto bail;
1429 }
1430
1431 for (ExportVarList::const_iterator I = mExportVars.begin(),
1432 E = mExportVars.end(); I != E; I++) {
1433 *ptr++ = reinterpret_cast<uint32_t>(*I);
1434 }
1435
1436 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1437 hdr->exportVarsCount * sizeof(uint32_t),
1438 "Write ExportVars");
1439
1440 free(record);
1441 }
1442
1443 // Write Export Functions Table
1444 {
1445 uint32_t *record, *ptr;
1446
1447 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
1448 ptr = record;
1449
1450 if (!record) {
1451 goto bail;
1452 }
1453
1454 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
1455 E = mExportFuncs.end(); I != E; I++) {
1456 *ptr++ = reinterpret_cast<uint32_t>(*I);
1457 }
1458
1459 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1460 hdr->exportFuncsCount * sizeof(uint32_t),
1461 "Write ExportFuncs");
1462
1463 free(record);
1464 }
1465
1466
Logan7cc1baf2010-11-28 23:46:11 +08001467 // Write Export Pragmas Table
1468 {
1469 uint32_t pragmaEntryOffset =
1470 hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
Logan1f028c02010-11-27 01:02:48 +08001471
Logan7cc1baf2010-11-28 23:46:11 +08001472 for (PragmaList::const_iterator
1473 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1474 oBCCPragmaEntry entry;
1475
1476 entry.pragmaNameOffset = pragmaEntryOffset;
1477 entry.pragmaNameSize = I->first.size();
1478 pragmaEntryOffset += entry.pragmaNameSize + 1;
1479
1480 entry.pragmaValueOffset = pragmaEntryOffset;
1481 entry.pragmaValueSize = I->second.size();
1482 pragmaEntryOffset += entry.pragmaValueSize + 1;
1483
1484 sysWriteFully(mCacheFd, (char *)&entry, sizeof(oBCCPragmaEntry),
1485 "Write export pragma entry");
1486 }
1487
1488 for (PragmaList::const_iterator
1489 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1490 sysWriteFully(mCacheFd, I->first.c_str(), I->first.size() + 1,
1491 "Write export pragma name string");
1492 sysWriteFully(mCacheFd, I->second.c_str(), I->second.size() + 1,
1493 "Write export pragma value string");
1494 }
1495 }
Logan1f028c02010-11-27 01:02:48 +08001496
1497 if (codeOffsetNeedPadding) {
1498 // requires additional padding
1499 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
1500 }
1501
1502 // Write Generated Code and Global Variable
1503 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
1504 "Write code and global variable");
1505
1506 goto close_return;
1507
1508bail:
1509 if (ftruncate(mCacheFd, 0) != 0) {
1510 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
1511 }
1512
1513close_return:
1514 free(hdr);
1515 close(mCacheFd);
1516 mCacheFd = -1;
1517}
1518
1519
1520// OpenCacheFile() returns fd of the cache file.
1521// Input:
1522// BCCchar *resName: Used to genCacheFileName()
1523// bool createIfMissing: If false, turn off caching
1524// Output:
1525// returns fd: If -1: Failed
1526// mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
1527// cache file's file descriptor
1528// Note: openCacheFile() will check the cache file's validity,
1529// such as Magic number, sourceWhen... dependencies.
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001530int Compiler::openCacheFile(const BCCchar *resName,
1531 const BCCchar *cacheDir,
1532 bool createIfMissing) {
Logan1f028c02010-11-27 01:02:48 +08001533 int fd, cc;
1534 struct stat fdStat, fileStat;
1535 bool readOnly = false;
1536
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001537 char *cacheFileName = genCacheFileName(cacheDir, resName, ".oBCC");
Logan1f028c02010-11-27 01:02:48 +08001538
1539 mCacheNew = false;
1540
1541retry:
1542 /*
1543 * Try to open the cache file. If we've been asked to,
1544 * create it if it doesn't exist.
1545 */
1546 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
1547 if (fd < 0) {
1548 fd = open(cacheFileName, O_RDONLY, 0);
1549 if (fd < 0) {
1550 if (createIfMissing) {
1551 LOGW("Can't open bcc-cache '%s': %s\n",
1552 cacheFileName, strerror(errno));
1553 mUseCache = false;
1554 }
1555 return fd;
1556 }
1557 readOnly = true;
1558 }
1559
1560 /*
1561 * Grab an exclusive lock on the cache file. If somebody else is
1562 * working on it, we'll block here until they complete.
1563 */
1564 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
1565 cacheFileName, fd);
1566
1567 cc = flock(fd, LOCK_EX | LOCK_NB);
1568 if (cc != 0) {
1569 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
1570 cc = flock(fd, LOCK_EX);
1571 }
1572
1573 if (cc != 0) {
1574 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
1575 close(fd);
1576 return -1;
1577 }
1578 LOGV("bcc: locked cache file\n");
1579
1580 /*
1581 * Check to see if the fd we opened and locked matches the file in
1582 * the filesystem. If they don't, then somebody else unlinked ours
1583 * and created a new file, and we need to use that one instead. (If
1584 * we caught them between the unlink and the create, we'll get an
1585 * ENOENT from the file stat.)
1586 */
1587 cc = fstat(fd, &fdStat);
1588 if (cc != 0) {
1589 LOGE("Can't stat open file '%s'\n", cacheFileName);
1590 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1591 goto close_fail;
1592 }
1593 cc = stat(cacheFileName, &fileStat);
1594 if (cc != 0 ||
1595 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
1596 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
1597 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1598 flock(fd, LOCK_UN);
1599 close(fd);
1600 usleep(250 * 1000); // if something is hosed, don't peg machine
1601 goto retry;
1602 }
1603
1604 /*
1605 * We have the correct file open and locked. If the file size is zero,
1606 * then it was just created by us, and we want to fill in some fields
1607 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
1608 * verify that the fields in the header match our expectations, and
1609 * reset the file if they don't.
1610 */
1611 if (fdStat.st_size == 0) {
1612 if (readOnly) { // The device is readOnly --> close_fail
1613 LOGW("bcc: file has zero length and isn't writable\n");
1614 goto close_fail;
1615 }
1616 /*cc = createEmptyHeader(fd);
1617 if (cc != 0)
1618 goto close_fail;
1619 */
1620 mCacheNew = true;
1621 LOGV("bcc: successfully initialized new cache file\n");
1622 } else {
1623 // Calculate sourceWhen
1624 // XXX
1625 uint32_t sourceWhen = 0;
1626 uint32_t rslibWhen = 0;
Logan9d94f162010-12-07 12:39:25 +08001627 uint32_t libRSWhen = statModifyTime(libRSPath);
1628 uint32_t libbccWhen = statModifyTime(libBccPath);
Logan1f028c02010-11-27 01:02:48 +08001629 if (!checkHeaderAndDependencies(fd,
1630 sourceWhen,
1631 rslibWhen,
1632 libRSWhen,
1633 libbccWhen)) {
1634 // If checkHeaderAndDependencies returns 0: FAILED
1635 // Will truncate the file and retry to createIfMissing the file
1636
1637 if (readOnly) { // Shouldn't be readonly.
1638 /*
1639 * We could unlink and rewrite the file if we own it or
1640 * the "sticky" bit isn't set on the directory. However,
1641 * we're not able to truncate it, which spoils things. So,
1642 * give up now.
1643 */
1644 if (createIfMissing) {
1645 LOGW("Cached file %s is stale and not writable\n",
1646 cacheFileName);
1647 }
1648 goto close_fail;
1649 }
1650
1651 /*
1652 * If we truncate the existing file before unlinking it, any
1653 * process that has it mapped will fail when it tries to touch
1654 * the pages? Probably OK because we use MAP_PRIVATE.
1655 */
1656 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
1657 cacheFileName);
1658 if (ftruncate(fd, 0) != 0) {
1659 LOGW("Warning: unable to truncate cache file '%s': %s\n",
1660 cacheFileName, strerror(errno));
1661 /* keep going */
1662 }
1663 if (unlink(cacheFileName) != 0) {
1664 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
1665 cacheFileName, errno, strerror(errno));
1666 /* keep going; permission failure should probably be fatal */
1667 }
1668 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1669 flock(fd, LOCK_UN);
1670 close(fd);
1671 goto retry;
1672 } else {
1673 // Got cacheFile! Good to go.
1674 LOGV("Good cache file\n");
1675 }
1676 }
1677
1678 assert(fd >= 0);
1679 return fd;
1680
1681close_fail:
1682 flock(fd, LOCK_UN);
1683 close(fd);
1684 return -1;
1685} // End of openCacheFile()
1686
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001687// Input: cacheDir
1688// Input: resName
1689// Input: extName
1690//
1691// Note: cacheFile = resName + extName
1692//
1693// Output: Returns cachePath == cacheDir + cacheFile
1694char *Compiler::genCacheFileName(const char *cacheDir,
1695 const char *resName,
1696 const char *extName) {
1697 char cachePath[512];
1698 char cacheFile[sizeof(cachePath)];
1699 const size_t kBufLen = sizeof(cachePath) - 1;
Logan1f028c02010-11-27 01:02:48 +08001700
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001701 cacheFile[0] = '\0';
1702 // Note: resName today is usually something like
1703 // "/com.android.fountain:raw/fountain"
1704 if (resName[0] != '/') {
1705 // Get the absolute path of the raw/***.bc file.
1706
1707 // Generate the absolute path. This doesn't do everything it
1708 // should, e.g. if resName is "./out/whatever" it doesn't crunch
1709 // the leading "./" out because this if-block is not triggered,
1710 // but it'll make do.
1711 //
1712 if (getcwd(cacheFile, kBufLen) == NULL) {
Logan1f028c02010-11-27 01:02:48 +08001713 LOGE("Can't get CWD while opening raw/***.bc file\n");
1714 return NULL;
1715 }
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001716 // Append "/" at the end of cacheFile so far.
1717 strncat(cacheFile, "/", kBufLen);
1718 }
1719
1720 // cacheFile = resName + extName
1721 //
1722 strncat(cacheFile, resName, kBufLen);
1723 if (extName != NULL) {
Logan1f028c02010-11-27 01:02:48 +08001724 // TODO(srhines): strncat() is a bit dangerous
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001725 strncat(cacheFile, extName, kBufLen);
Logan1f028c02010-11-27 01:02:48 +08001726 }
1727
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001728 // Turn the path into a flat filename by replacing
1729 // any slashes after the first one with '@' characters.
1730 char *cp = cacheFile + 1;
Logan1f028c02010-11-27 01:02:48 +08001731 while (*cp != '\0') {
1732 if (*cp == '/') {
1733 *cp = '@';
1734 }
1735 cp++;
1736 }
1737
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001738 // Tack on the file name for the actual cache file path.
1739 strncpy(cachePath, cacheDir, kBufLen);
1740 strncat(cachePath, cacheFile, kBufLen);
Logan1f028c02010-11-27 01:02:48 +08001741
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001742 LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
1743 return strdup(cachePath);
Logan1f028c02010-11-27 01:02:48 +08001744}
1745
1746/*
1747 * Read the oBCC header, verify it, then read the dependent section
1748 * and verify that data as well.
1749 *
1750 * On successful return, the file will be seeked immediately past the
1751 * oBCC header.
1752 */
1753bool Compiler::checkHeaderAndDependencies(int fd,
1754 uint32_t sourceWhen,
1755 uint32_t rslibWhen,
1756 uint32_t libRSWhen,
1757 uint32_t libbccWhen) {
1758 ssize_t actual;
1759 oBCCHeader optHdr;
1760 uint32_t val;
1761 uint8_t const *magic, *magicVer;
1762
1763 /*
1764 * Start at the start. The "bcc" header, when present, will always be
1765 * the first thing in the file.
1766 */
1767 if (lseek(fd, 0, SEEK_SET) != 0) {
1768 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
1769 goto bail;
1770 }
1771
1772 /*
1773 * Read and do trivial verification on the bcc header. The header is
1774 * always in host byte order.
1775 */
1776 actual = read(fd, &optHdr, sizeof(optHdr));
1777 if (actual < 0) {
1778 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
1779 goto bail;
1780 } else if (actual != sizeof(optHdr)) {
1781 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
1782 (int) actual, sizeof(optHdr));
1783 goto bail;
1784 }
1785
1786 magic = optHdr.magic;
1787 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
1788 /* not an oBCC file, or previous attempt was interrupted */
1789 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
1790 magic[0], magic[1], magic[2], magic[3]);
1791 goto bail;
1792 }
1793
1794 magicVer = optHdr.magicVersion;
Logancd045f92010-12-06 19:04:53 +08001795 if (memcmp(magicVer, OBCC_MAGIC_VERS, 4) != 0) {
Logan1f028c02010-11-27 01:02:48 +08001796 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
1797 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
1798 goto bail;
1799 }
1800
1801 /*
1802 * Do the header flags match up with what we want?
1803 *
1804 * This is useful because it allows us to automatically regenerate
1805 * a file when settings change (e.g. verification is now mandatory),
1806 * but can cause difficulties if the thing we depend upon
1807 * were handled differently than the current options specify.
1808 *
1809 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
1810 * by limiting the match mask.
1811 *
1812 * The only thing we really can't handle is incorrect byte-ordering.
1813 */
1814
1815 val = optHdr.sourceWhen;
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001816 // TODO(sliao): Shouldn't overload sourceWhen in the future.
1817 if (!val) {
1818 mpSymbolLookupFn(mpSymbolLookupContext, "__clearThreadable");
Logan1f028c02010-11-27 01:02:48 +08001819 }
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001820 // if (val && (val != sourceWhen)) {
1821 // LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
1822 // val, sourceWhen);
1823 // goto bail;
1824 // }
1825
Logan1f028c02010-11-27 01:02:48 +08001826 val = optHdr.rslibWhen;
1827 if (val && (val != rslibWhen)) {
1828 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
1829 val, rslibWhen);
1830 goto bail;
1831 }
1832 val = optHdr.libRSWhen;
1833 if (val && (val != libRSWhen)) {
1834 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
1835 val, libRSWhen);
1836 goto bail;
1837 }
1838 val = optHdr.libbccWhen;
1839 if (val && (val != libbccWhen)) {
1840 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
1841 val, libbccWhen);
1842 goto bail;
1843 }
1844
1845 return true;
1846
1847bail:
1848 return false;
1849}
1850
1851} // namespace bcc