blob: 6ab1dd3a9fefc6677b1683220903721dd8d17c2e [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;
546
547 if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
548 (offset / BCC_MMAP_IMG_SIZE) < BCC_MMAP_IMG_COUNT) {
549 Compiler::BccMmapImgAddrTaken[offset / BCC_MMAP_IMG_SIZE] = true;
550 }
551 }
552
553#if 1
554 // Check the checksum of code and data
555 {
556 uint32_t sum = mCacheHdr->checksum;
557 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
558
559 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
560 sum ^= *ptr++;
561 }
562
563 if (sum != 0) {
564 LOGE("Checksum check failed\n");
565 goto bail;
566 }
567
Shih-wei Liao9ea54b52010-12-01 17:57:07 -0800568 LOGI("Passed checksum even parity verification.\n");
Logan1f028c02010-11-27 01:02:48 +0800569 }
570#endif
571
572 flock(mCacheFd, LOCK_UN);
573 return 0; // loadCacheFile succeed!
574 }
575 }
576 }
577
578#if !USE_RELOCATE
579 // Note: Since this build does not support relocation, we have no
580 // choose but give up to load the cached file, and recompile the
581 // code.
582
583 flock(mCacheFd, LOCK_UN);
584 goto bail;
585#else
586
587 // Note: Currently, relocation code is not working. Give up now.
588 flock(mCacheFd, LOCK_UN);
589 goto bail;
590
591 // TODO(logan): Following code is not working. Don't use them.
592 // And rewrite them asap.
593#if 0
594 {
595 // Try to allocate at arbitary address. And perform relocation.
596 mCacheMapAddr = (char *) mmap(0,
597 mCacheSize,
598 PROT_READ | PROT_EXEC | PROT_WRITE,
599 MAP_PRIVATE,
600 mCacheFd,
601 0);
602
603 if (mCacheMapAddr == MAP_FAILED) {
604 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
605 flock(mCacheFd, LOCK_UN);
606 goto giveup;
607 }
608
609 flock(mCacheFd, LOCK_UN);
610 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
611
612 // Relocate
613 mCacheDiff = mCodeDataAddr -
614 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
615
616 if (mCacheDiff) { // To relocate
617 if (mCacheHdr->rootAddr) {
618 mCacheHdr->rootAddr += mCacheDiff;
619 }
620
621 if (mCacheHdr->initAddr) {
622 mCacheHdr->initAddr += mCacheDiff;
623 }
624
625 oBCCRelocEntry *cachedRelocTable =
626 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
627 mCacheHdr->relocOffset);
628
629 std::vector<llvm::MachineRelocation> relocations;
630
631 // Read in the relocs
632 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
633 oBCCRelocEntry *entry = &cachedRelocTable[i];
634
635 llvm::MachineRelocation reloc =
636 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
637 (unsigned)entry->relocType, 0, 0);
638
639 reloc.setResultPointer(
640 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
641
642 relocations.push_back(reloc);
643 }
644
645 // Rewrite machine code using llvm::TargetJITInfo relocate
646 {
647 llvm::TargetMachine *TM = NULL;
648 const llvm::Target *Target;
649 std::string FeaturesStr;
650
651 // Create TargetMachine
652 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
653 if (hasError())
654 goto bail;
655
656 if (!CPU.empty() || !Features.empty()) {
657 llvm::SubtargetFeatures F;
658 F.setCPU(CPU);
659 for (std::vector<std::string>::const_iterator I = Features.begin(),
660 E = Features.end(); I != E; I++)
661 F.AddFeature(*I);
662 FeaturesStr = F.getString();
663 }
664
665 TM = Target->createTargetMachine(Triple, FeaturesStr);
666 if (TM == NULL) {
667 setError("Failed to create target machine implementation for the"
668 " specified triple '" + Triple + "'");
669 goto bail;
670 }
671
672 TM->getJITInfo()->relocate(mCodeDataAddr,
673 &relocations[0], relocations.size(),
674 (unsigned char *)mCodeDataAddr+MaxCodeSize);
675
676 if (mCodeEmitter.get()) {
677 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
678 reinterpret_cast<uint8_t*>(mCodeDataAddr),
679 2 * 1024 /*MaxCodeSize*/,
680 false);
681 }
682
683 delete TM;
684 }
685 } // End of if (mCacheDiff)
686
687 return 0; // Success!
688 }
689#endif
690#endif
691
692bail:
693 if (mCacheMapAddr) {
694 free(mCacheMapAddr);
695 }
696
697 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
698 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
699 LOGE("munmap failed: %s\n", strerror(errno));
700 }
701 }
702
703 mCacheMapAddr = NULL;
704 mCacheHdr = NULL;
705 mCodeDataAddr = NULL;
706
707giveup:
708 return 1;
709}
710
711// interace for bccCompileBC()
712int Compiler::compile() {
713 llvm::TargetData *TD = NULL;
714
715 llvm::TargetMachine *TM = NULL;
716 const llvm::Target *Target;
717 std::string FeaturesStr;
718
719 llvm::FunctionPassManager *CodeGenPasses = NULL;
720
721 const llvm::NamedMDNode *PragmaMetadata;
722 const llvm::NamedMDNode *ExportVarMetadata;
723 const llvm::NamedMDNode *ExportFuncMetadata;
724
725 if (mModule == NULL) // No module was loaded
726 return 0;
727
728 // Create TargetMachine
729 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
730 if (hasError())
731 goto on_bcc_compile_error;
732
733 if (!CPU.empty() || !Features.empty()) {
734 llvm::SubtargetFeatures F;
735 F.setCPU(CPU);
Logana4994f52010-11-27 14:06:02 +0800736
737 for (std::vector<std::string>::const_iterator
738 I = Features.begin(), E = Features.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +0800739 F.AddFeature(*I);
Logana4994f52010-11-27 14:06:02 +0800740 }
741
Logan1f028c02010-11-27 01:02:48 +0800742 FeaturesStr = F.getString();
743 }
744
745 TM = Target->createTargetMachine(Triple, FeaturesStr);
746 if (TM == NULL) {
747 setError("Failed to create target machine implementation for the"
748 " specified triple '" + Triple + "'");
749 goto on_bcc_compile_error;
750 }
751
752 // Create memory manager for creation of code emitter later.
753 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
754 setError("Failed to startup memory management for further compilation");
755 goto on_bcc_compile_error;
756 }
757 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
758
759 // Create code emitter
760 if (!mCodeEmitter.get()) {
761 if (!createCodeEmitter()) {
762 setError("Failed to create machine code emitter to complete"
763 " the compilation");
764 goto on_bcc_compile_error;
765 }
766 } else {
767 // Reuse the code emitter
768 mCodeEmitter->reset();
769 }
770
771 mCodeEmitter->setTargetMachine(*TM);
772 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
773 mpSymbolLookupContext);
774
775 // Get target data from Module
776 TD = new llvm::TargetData(mModule);
777
778 // Load named metadata
779 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
780 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
781 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
782
783 // Create LTO passes and run them on the mModule
784 if (mHasLinked) {
785 llvm::TimePassesIsEnabled = true; // TODO(all)
786 llvm::PassManager LTOPasses;
787 LTOPasses.add(new llvm::TargetData(*TD));
788
789 std::vector<const char*> ExportSymbols;
790
791 // A workaround for getting export variable and function name. Will refine
792 // it soon.
793 if (ExportVarMetadata) {
794 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
795 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
796 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
797 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
798 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
799 llvm::StringRef ExportVarName =
800 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
801 ExportSymbols.push_back(ExportVarName.data());
802 }
803 }
804 }
805 }
806
807 if (ExportFuncMetadata) {
808 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
809 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
810 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
811 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
812 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
813 llvm::StringRef ExportFuncName =
814 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
815 ExportSymbols.push_back(ExportFuncName.data());
816 }
817 }
818 }
819 }
820 // root() and init() are born to be exported
821 ExportSymbols.push_back("root");
822 ExportSymbols.push_back("init");
823
824 // We now create passes list performing LTO. These are copied from
825 // (including comments) llvm::createStandardLTOPasses().
826
827 // Internalize all other symbols not listed in ExportSymbols
828 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
829
830 // Propagate constants at call sites into the functions they call. This
831 // opens opportunities for globalopt (and inlining) by substituting
832 // function pointers passed as arguments to direct uses of functions.
833 LTOPasses.add(llvm::createIPSCCPPass());
834
835 // Now that we internalized some globals, see if we can hack on them!
836 LTOPasses.add(llvm::createGlobalOptimizerPass());
837
838 // Linking modules together can lead to duplicated global constants, only
839 // keep one copy of each constant...
840 LTOPasses.add(llvm::createConstantMergePass());
841
842 // Remove unused arguments from functions...
843 LTOPasses.add(llvm::createDeadArgEliminationPass());
844
845 // Reduce the code after globalopt and ipsccp. Both can open up
846 // significant simplification opportunities, and both can propagate
847 // functions through function pointers. When this happens, we often have
848 // to resolve varargs calls, etc, so let instcombine do this.
849 LTOPasses.add(llvm::createInstructionCombiningPass());
850
851 // Inline small functions
852 LTOPasses.add(llvm::createFunctionInliningPass());
853
854 // Remove dead EH info.
855 LTOPasses.add(llvm::createPruneEHPass());
856
857 // Internalize the globals again after inlining
858 LTOPasses.add(llvm::createGlobalOptimizerPass());
859
860 // Remove dead functions.
861 LTOPasses.add(llvm::createGlobalDCEPass());
862
863 // If we didn't decide to inline a function, check to see if we can
864 // transform it to pass arguments by value instead of by reference.
865 LTOPasses.add(llvm::createArgumentPromotionPass());
866
867 // The IPO passes may leave cruft around. Clean up after them.
868 LTOPasses.add(llvm::createInstructionCombiningPass());
869 LTOPasses.add(llvm::createJumpThreadingPass());
870
871 // Break up allocas
872 LTOPasses.add(llvm::createScalarReplAggregatesPass());
873
874 // Run a few AA driven optimizations here and now, to cleanup the code.
875 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
876 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
877
878 // Hoist loop invariants.
879 LTOPasses.add(llvm::createLICMPass());
880
881 // Remove redundancies.
882 LTOPasses.add(llvm::createGVNPass());
883
884 // Remove dead memcpys.
885 LTOPasses.add(llvm::createMemCpyOptPass());
886
887 // Nuke dead stores.
888 LTOPasses.add(llvm::createDeadStoreEliminationPass());
889
890 // Cleanup and simplify the code after the scalar optimizations.
891 LTOPasses.add(llvm::createInstructionCombiningPass());
892
893 LTOPasses.add(llvm::createJumpThreadingPass());
894
895 // Delete basic blocks, which optimization passes may have killed.
896 LTOPasses.add(llvm::createCFGSimplificationPass());
897
898 // Now that we have optimized the program, discard unreachable functions.
899 LTOPasses.add(llvm::createGlobalDCEPass());
900
901 LTOPasses.run(*mModule);
902 }
903
904 // Create code-gen pass to run the code emitter
905 CodeGenPasses = new llvm::FunctionPassManager(mModule);
906 CodeGenPasses->add(TD); // Will take the ownership of TD
907
908 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
909 *mCodeEmitter,
910 CodeGenOptLevel)) {
911 setError("The machine code emission is not supported by BCC on target '"
912 + Triple + "'");
913 goto on_bcc_compile_error;
914 }
915
916 // Run the pass (the code emitter) on every non-declaration function in the
917 // module
918 CodeGenPasses->doInitialization();
919 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
920 I != E; I++) {
921 if (!I->isDeclaration()) {
922 CodeGenPasses->run(*I);
923 }
924 }
925
926 CodeGenPasses->doFinalization();
927
928 // Copy the global address mapping from code emitter and remapping
929 if (ExportVarMetadata) {
930 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
931 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
932 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
933 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
934 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
935 llvm::StringRef ExportVarName =
936 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
937
938 CodeEmitter::global_addresses_const_iterator I, E;
939 for (I = mCodeEmitter->global_address_begin(),
940 E = mCodeEmitter->global_address_end();
941 I != E; I++) {
942 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
943 continue;
944 if (ExportVarName == I->first->getName()) {
945 mExportVars.push_back(I->second);
946 break;
947 }
948 }
949 if (I != mCodeEmitter->global_address_end())
950 continue; // found
951 }
952 }
953 // if reaching here, we know the global variable record in metadata is
954 // not found. So we make an empty slot
955 mExportVars.push_back(NULL);
956 }
957 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
958 "Number of slots doesn't match the number of export variables!");
959 }
960
961 if (ExportFuncMetadata) {
962 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
963 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
964 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
965 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
966 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
967 llvm::StringRef ExportFuncName =
968 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
969 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
970 }
971 }
972 }
973 }
974
975 // Tell code emitter now can release the memory using during the JIT since
976 // we have done the code emission
977 mCodeEmitter->releaseUnnecessary();
978
979 // Finally, read pragma information from the metadata node of the @Module if
980 // any.
981 if (PragmaMetadata)
982 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
983 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
984 if (Pragma != NULL &&
985 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
986 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
987 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
988
989 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
990 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
991 llvm::StringRef PragmaName =
992 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
993 llvm::StringRef PragmaValue =
994 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
995
996 mPragmas.push_back(
997 std::make_pair(std::string(PragmaName.data(),
998 PragmaName.size()),
999 std::string(PragmaValue.data(),
1000 PragmaValue.size())));
1001 }
1002 }
1003 }
1004
1005on_bcc_compile_error:
1006 // LOGE("on_bcc_compiler_error");
1007 if (CodeGenPasses) {
1008 delete CodeGenPasses;
1009 } else if (TD) {
1010 delete TD;
1011 }
1012 if (TM)
1013 delete TM;
1014
1015 if (mError.empty()) {
1016 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
1017 genCacheFile();
1018 flock(mCacheFd, LOCK_UN);
1019 }
1020
1021 return false;
1022 }
1023
1024 // LOGE(getErrorMessage());
1025 return true;
1026}
1027
1028
1029// interface for bccGetScriptLabel()
1030void *Compiler::lookup(const char *name) {
1031 void *addr = NULL;
1032 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1033 if (!strcmp(name, "root")) {
1034 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
1035 } else if (!strcmp(name, "init")) {
1036 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
1037 }
1038 return addr;
1039 }
1040
1041 if (mCodeEmitter.get())
1042 // Find function pointer
1043 addr = mCodeEmitter->lookup(name);
1044 return addr;
1045}
1046
1047
1048// Interface for bccGetExportVars()
1049void Compiler::getExportVars(BCCsizei *actualVarCount,
1050 BCCsizei maxVarCount,
1051 BCCvoid **vars) {
1052 int varCount;
1053
1054 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1055 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
1056 if (actualVarCount)
1057 *actualVarCount = varCount;
1058 if (varCount > maxVarCount)
1059 varCount = maxVarCount;
1060 if (vars) {
1061 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
1062 mCacheHdr->exportVarsOffset);
1063
1064 for (int i = 0; i < varCount; i++) {
Logan7cc1baf2010-11-28 23:46:11 +08001065 *vars = (BCCvoid *)((char *)(*cachedVars) + mCacheDiff);
1066 vars++;
Logan1f028c02010-11-27 01:02:48 +08001067 cachedVars++;
1068 }
1069 }
1070 return;
1071 }
1072
1073 varCount = mExportVars.size();
1074 if (actualVarCount)
1075 *actualVarCount = varCount;
1076 if (varCount > maxVarCount)
1077 varCount = maxVarCount;
1078 if (vars) {
Logana4994f52010-11-27 14:06:02 +08001079 for (ExportVarList::const_iterator
1080 I = mExportVars.begin(), E = mExportVars.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +08001081 *vars++ = *I;
1082 }
1083 }
Logan1f028c02010-11-27 01:02:48 +08001084}
1085
1086
1087// Interface for bccGetExportFuncs()
1088void Compiler::getExportFuncs(BCCsizei *actualFuncCount,
1089 BCCsizei maxFuncCount,
1090 BCCvoid **funcs) {
1091 int funcCount;
1092
1093 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1094 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
1095 if (actualFuncCount)
1096 *actualFuncCount = funcCount;
1097 if (funcCount > maxFuncCount)
1098 funcCount = maxFuncCount;
1099 if (funcs) {
1100 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
1101 mCacheHdr->exportFuncsOffset);
1102
1103 for (int i = 0; i < funcCount; i++) {
Logan7cc1baf2010-11-28 23:46:11 +08001104 *funcs = (BCCvoid *)((char *)(*cachedFuncs) + mCacheDiff);
1105 funcs++;
Logan1f028c02010-11-27 01:02:48 +08001106 cachedFuncs++;
1107 }
1108 }
1109 return;
1110 }
1111
1112 funcCount = mExportFuncs.size();
1113 if (actualFuncCount)
1114 *actualFuncCount = funcCount;
1115 if (funcCount > maxFuncCount)
1116 funcCount = maxFuncCount;
1117 if (funcs) {
Logan7cc1baf2010-11-28 23:46:11 +08001118 for (ExportFuncList::const_iterator
1119 I = mExportFuncs.begin(), E = mExportFuncs.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +08001120 *funcs++ = *I;
1121 }
1122 }
Logan1f028c02010-11-27 01:02:48 +08001123}
1124
1125
1126// Interface for bccGetPragmas()
1127void Compiler::getPragmas(BCCsizei *actualStringCount,
1128 BCCsizei maxStringCount,
1129 BCCchar **strings) {
1130 int stringCount;
Logan7cc1baf2010-11-28 23:46:11 +08001131
Logan1f028c02010-11-27 01:02:48 +08001132 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Logan7cc1baf2010-11-28 23:46:11 +08001133 stringCount = static_cast<int>(mCacheHdr->exportPragmasCount) * 2;
1134
Logan1f028c02010-11-27 01:02:48 +08001135 if (actualStringCount)
Logan7cc1baf2010-11-28 23:46:11 +08001136 *actualStringCount = stringCount;
1137
1138 if (stringCount > maxStringCount)
1139 stringCount = maxStringCount;
1140
1141 if (strings) {
1142 char *pragmaTab = mCacheMapAddr + mCacheHdr->exportPragmasOffset;
1143
1144 oBCCPragmaEntry *cachedPragmaEntries = (oBCCPragmaEntry *)pragmaTab;
1145
1146 for (int i = 0; stringCount >= 2; stringCount -= 2, i++) {
1147 *strings++ = pragmaTab + cachedPragmaEntries[i].pragmaNameOffset;
1148 *strings++ = pragmaTab + cachedPragmaEntries[i].pragmaValueOffset;
1149 }
1150 }
1151
Logan1f028c02010-11-27 01:02:48 +08001152 return;
1153 }
1154
1155 stringCount = mPragmas.size() * 2;
1156
1157 if (actualStringCount)
1158 *actualStringCount = stringCount;
1159 if (stringCount > maxStringCount)
1160 stringCount = maxStringCount;
1161 if (strings) {
Logan7cc1baf2010-11-28 23:46:11 +08001162 size_t i = 0;
Logan1f028c02010-11-27 01:02:48 +08001163 for (PragmaList::const_iterator it = mPragmas.begin();
Logan7cc1baf2010-11-28 23:46:11 +08001164 stringCount >= 2; stringCount -= 2, it++, ++i) {
Logan1f028c02010-11-27 01:02:48 +08001165 *strings++ = const_cast<BCCchar*>(it->first.c_str());
1166 *strings++ = const_cast<BCCchar*>(it->second.c_str());
1167 }
1168 }
1169
1170 return;
1171}
1172
1173
1174// Interface for bccGetFunctions()
1175void Compiler::getFunctions(BCCsizei *actualFunctionCount,
1176 BCCsizei maxFunctionCount,
1177 BCCchar **functions) {
1178 if (mCodeEmitter.get())
1179 mCodeEmitter->getFunctionNames(actualFunctionCount,
1180 maxFunctionCount,
1181 functions);
1182 else
1183 *actualFunctionCount = 0;
1184
1185 return;
1186}
1187
1188
1189// Interface for bccGetFunctionBinary()
1190void Compiler::getFunctionBinary(BCCchar *function,
1191 BCCvoid **base,
1192 BCCsizei *length) {
1193 if (mCodeEmitter.get()) {
1194 mCodeEmitter->getFunctionBinary(function, base, length);
1195 } else {
1196 *base = NULL;
1197 *length = 0;
1198 }
1199 return;
1200}
1201
1202
1203Compiler::~Compiler() {
1204 if (!mCodeMemMgr.get()) {
1205 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
1206 // managed by CodeMemoryManager.
1207
1208 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
1209 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
1210 LOGE("munmap failed while releasing mCodeDataAddr\n");
1211 }
1212 }
1213
1214 if (mCacheMapAddr) {
1215 free(mCacheMapAddr);
1216 }
1217
1218 mCodeDataAddr = 0;
1219 mCacheMapAddr = 0;
1220 }
1221
1222 delete mModule;
Logan1f028c02010-11-27 01:02:48 +08001223 delete mContext;
Logana4994f52010-11-27 14:06:02 +08001224
1225 // llvm::llvm_shutdown();
Logan1f028c02010-11-27 01:02:48 +08001226}
1227
1228
1229// Design of caching EXE:
1230// ======================
1231// 1. Each process will have virtual address available starting at 0x7e00000.
1232// E.g., Books and Youtube all have its own 0x7e00000. Next, we should
1233// minimize the chance of needing to do relocation INSIDE an app too.
1234//
1235// 2. Each process will have ONE class static variable called BccCodeAddr.
1236// I.e., even though the Compiler class will have multiple Compiler objects,
1237// e.g, one object for carousel.rs and the other for pageturn.rs,
1238// both Compiler objects will share 1 static variable called BccCodeAddr.
1239//
1240// Key observation: Every app (process) initiates, say 3, scripts (which
1241// correspond to 3 Compiler objects) in the same order, usually.
1242//
1243// So, we should mmap to, e.g., 0x7e00000, 0x7e40000, 0x7e80000 for the 3
1244// scripts, respectively. Each time, BccCodeAddr should be updated after
1245// JITTing a script. BTW, in ~Compiler(), BccCodeAddr should NOT be
1246// decremented back by CodeDataSize. I.e., for 3 scripts: A, B, C,
1247// even if it's A -> B -> ~B -> C -> ~C -> B -> C ... no relocation will
1248// ever be needed.)
1249//
1250// If we are lucky, then we don't need relocation ever, since next time the
1251// application gets run, the 3 scripts are likely created in the SAME order.
1252//
1253//
1254// End-to-end algorithm on when to caching and when to JIT:
1255// ========================================================
1256// Prologue:
1257// ---------
1258// Assertion: bccReadBC() is always called and is before bccCompileBC(),
1259// bccLoadBinary(), ...
1260//
1261// Key variable definitions: Normally,
1262// Compiler::BccCodeAddr: non-zero if (USE_CACHE)
1263// | (Stricter, because currently relocation doesn't work. So mUseCache only
1264// | when BccCodeAddr is nonzero.)
1265// V
1266// mUseCache: In addition to (USE_CACHE), resName is non-zero
1267// Note: mUseCache will be set to false later on whenever we find that caching
1268// won't work. E.g., when mCodeDataAddr != mCacheHdr->cachedCodeDataAddr.
1269// This is because currently relocation doesn't work.
1270// | (Stricter, initially)
1271// V
1272// mCacheFd: In addition, >= 0 if openCacheFile() returns >= 0
1273// | (Stricter)
1274// V
1275// mCacheNew: In addition, mCacheFd's size is 0, so need to call genCacheFile()
1276// at the end of compile()
1277//
1278//
1279// Main algorithm:
1280// ---------------
1281// #if !USE_RELOCATE
1282// Case 1. ReadBC() doesn't detect a cache file:
1283// compile(), which calls genCacheFile() at the end.
1284// Note: mCacheNew will guard the invocation of genCacheFile()
1285// Case 2. ReadBC() find a cache file
1286// loadCacheFile(). But if loadCacheFile() failed, should go to Case 1.
1287// #endif
1288
1289// Note: loadCacheFile() and genCacheFile() go hand in hand
1290void Compiler::genCacheFile() {
1291 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
1292 LOGE("Unable to seek to 0: %s\n", strerror(errno));
1293 return;
1294 }
1295
1296 bool codeOffsetNeedPadding = false;
1297
1298 uint32_t offset = sizeof(oBCCHeader);
1299
1300 // BCC Cache File Header
1301 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
1302
1303 if (!hdr) {
1304 LOGE("Unable to allocate oBCCHeader.\n");
1305 return;
1306 }
1307
1308 // Magic Words
1309 memcpy(hdr->magic, OBCC_MAGIC, 4);
1310 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
1311
1312 // Timestamp
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001313 // TODO(sliao): Should be .bc's ModifyTime. Now just use it to store
1314 // threadable
1315 hdr->sourceWhen = (uint32_t) mCodeEmitter->mpSymbolLookupFn(
1316 mpSymbolLookupContext,
1317 "__isThreadable");
1318
1319 hdr->rslibWhen = 0; // TODO(sliao)
Logan9d94f162010-12-07 12:39:25 +08001320 hdr->libRSWhen = statModifyTime(libRSPath);
1321 hdr->libbccWhen = statModifyTime(libBccPath);
Logan1f028c02010-11-27 01:02:48 +08001322
1323 // Current Memory Address (Saved for Recalculation)
1324 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
1325 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
1326 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
1327
1328 // Relocation Table Offset and Entry Count
1329 hdr->relocOffset = sizeof(oBCCHeader);
1330 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
1331
Logan7cc1baf2010-11-28 23:46:11 +08001332 offset += hdr->relocCount * sizeof(oBCCRelocEntry);
Logan1f028c02010-11-27 01:02:48 +08001333
1334 // Export Variable Table Offset and Entry Count
1335 hdr->exportVarsOffset = offset;
1336 hdr->exportVarsCount = mExportVars.size();
1337
1338 offset += hdr->exportVarsCount * sizeof(uint32_t);
1339
1340 // Export Function Table Offset and Entry Count
1341 hdr->exportFuncsOffset = offset;
1342 hdr->exportFuncsCount = mExportFuncs.size();
1343
1344 offset += hdr->exportFuncsCount * sizeof(uint32_t);
1345
1346 // Export Pragmas Table Offset and Entry Count
1347 hdr->exportPragmasOffset = offset;
Logan7cc1baf2010-11-28 23:46:11 +08001348 hdr->exportPragmasCount = mPragmas.size();
1349 hdr->exportPragmasSize = hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
Logan1f028c02010-11-27 01:02:48 +08001350
Logan7cc1baf2010-11-28 23:46:11 +08001351 offset += hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
1352
1353 for (PragmaList::const_iterator
1354 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1355 offset += I->first.size() + 1;
1356 offset += I->second.size() + 1;
1357 hdr->exportPragmasSize += I->first.size() + I->second.size() + 2;
1358 }
Logan1f028c02010-11-27 01:02:48 +08001359
1360 // Code Offset and Size
1361
1362 { // Always pad to the page boundary for now
1363 long pagesize = sysconf(_SC_PAGESIZE);
1364
1365 if (offset % pagesize > 0) {
1366 codeOffsetNeedPadding = true;
1367 offset += pagesize - (offset % pagesize);
1368 }
1369 }
1370
1371 hdr->codeOffset = offset;
1372 hdr->codeSize = MaxCodeSize;
1373
1374 offset += hdr->codeSize;
1375
1376 // Data (Global Variable) Offset and Size
1377 hdr->dataOffset = offset;
1378 hdr->dataSize = MaxGlobalVarSize;
1379
1380 offset += hdr->dataSize;
1381
1382 // Checksum
1383#if 1
1384 {
1385 // Note: This is an simple checksum implementation that are using xor
1386 // to calculate even parity (for code and data only).
1387
1388 uint32_t sum = 0;
1389 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
1390
1391 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
1392 sum ^= *ptr++;
1393 }
1394
1395 hdr->checksum = sum;
1396 }
1397#else
1398 hdr->checksum = 0; // Set Field checksum. TODO(all)
1399#endif
1400
1401 // Write Header
1402 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
1403 sizeof(oBCCHeader), "Write oBCC header");
1404
1405 // Write Relocation Entry Table
1406 {
1407 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
1408
1409 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
1410
1411 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
1412 allocSize, "Write Relocation Entries");
1413 }
1414
1415 // Write Export Variables Table
1416 {
1417 uint32_t *record, *ptr;
1418
1419 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
1420 ptr = record;
1421
1422 if (!record) {
1423 goto bail;
1424 }
1425
1426 for (ExportVarList::const_iterator I = mExportVars.begin(),
1427 E = mExportVars.end(); I != E; I++) {
1428 *ptr++ = reinterpret_cast<uint32_t>(*I);
1429 }
1430
1431 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1432 hdr->exportVarsCount * sizeof(uint32_t),
1433 "Write ExportVars");
1434
1435 free(record);
1436 }
1437
1438 // Write Export Functions Table
1439 {
1440 uint32_t *record, *ptr;
1441
1442 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
1443 ptr = record;
1444
1445 if (!record) {
1446 goto bail;
1447 }
1448
1449 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
1450 E = mExportFuncs.end(); I != E; I++) {
1451 *ptr++ = reinterpret_cast<uint32_t>(*I);
1452 }
1453
1454 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1455 hdr->exportFuncsCount * sizeof(uint32_t),
1456 "Write ExportFuncs");
1457
1458 free(record);
1459 }
1460
1461
Logan7cc1baf2010-11-28 23:46:11 +08001462 // Write Export Pragmas Table
1463 {
1464 uint32_t pragmaEntryOffset =
1465 hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
Logan1f028c02010-11-27 01:02:48 +08001466
Logan7cc1baf2010-11-28 23:46:11 +08001467 for (PragmaList::const_iterator
1468 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1469 oBCCPragmaEntry entry;
1470
1471 entry.pragmaNameOffset = pragmaEntryOffset;
1472 entry.pragmaNameSize = I->first.size();
1473 pragmaEntryOffset += entry.pragmaNameSize + 1;
1474
1475 entry.pragmaValueOffset = pragmaEntryOffset;
1476 entry.pragmaValueSize = I->second.size();
1477 pragmaEntryOffset += entry.pragmaValueSize + 1;
1478
1479 sysWriteFully(mCacheFd, (char *)&entry, sizeof(oBCCPragmaEntry),
1480 "Write export pragma entry");
1481 }
1482
1483 for (PragmaList::const_iterator
1484 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1485 sysWriteFully(mCacheFd, I->first.c_str(), I->first.size() + 1,
1486 "Write export pragma name string");
1487 sysWriteFully(mCacheFd, I->second.c_str(), I->second.size() + 1,
1488 "Write export pragma value string");
1489 }
1490 }
Logan1f028c02010-11-27 01:02:48 +08001491
1492 if (codeOffsetNeedPadding) {
1493 // requires additional padding
1494 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
1495 }
1496
1497 // Write Generated Code and Global Variable
1498 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
1499 "Write code and global variable");
1500
1501 goto close_return;
1502
1503bail:
1504 if (ftruncate(mCacheFd, 0) != 0) {
1505 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
1506 }
1507
1508close_return:
1509 free(hdr);
1510 close(mCacheFd);
1511 mCacheFd = -1;
1512}
1513
1514
1515// OpenCacheFile() returns fd of the cache file.
1516// Input:
1517// BCCchar *resName: Used to genCacheFileName()
1518// bool createIfMissing: If false, turn off caching
1519// Output:
1520// returns fd: If -1: Failed
1521// mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
1522// cache file's file descriptor
1523// Note: openCacheFile() will check the cache file's validity,
1524// such as Magic number, sourceWhen... dependencies.
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001525int Compiler::openCacheFile(const BCCchar *resName,
1526 const BCCchar *cacheDir,
1527 bool createIfMissing) {
Logan1f028c02010-11-27 01:02:48 +08001528 int fd, cc;
1529 struct stat fdStat, fileStat;
1530 bool readOnly = false;
1531
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001532 char *cacheFileName = genCacheFileName(cacheDir, resName, ".oBCC");
Logan1f028c02010-11-27 01:02:48 +08001533
1534 mCacheNew = false;
1535
1536retry:
1537 /*
1538 * Try to open the cache file. If we've been asked to,
1539 * create it if it doesn't exist.
1540 */
1541 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
1542 if (fd < 0) {
1543 fd = open(cacheFileName, O_RDONLY, 0);
1544 if (fd < 0) {
1545 if (createIfMissing) {
1546 LOGW("Can't open bcc-cache '%s': %s\n",
1547 cacheFileName, strerror(errno));
1548 mUseCache = false;
1549 }
1550 return fd;
1551 }
1552 readOnly = true;
1553 }
1554
1555 /*
1556 * Grab an exclusive lock on the cache file. If somebody else is
1557 * working on it, we'll block here until they complete.
1558 */
1559 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
1560 cacheFileName, fd);
1561
1562 cc = flock(fd, LOCK_EX | LOCK_NB);
1563 if (cc != 0) {
1564 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
1565 cc = flock(fd, LOCK_EX);
1566 }
1567
1568 if (cc != 0) {
1569 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
1570 close(fd);
1571 return -1;
1572 }
1573 LOGV("bcc: locked cache file\n");
1574
1575 /*
1576 * Check to see if the fd we opened and locked matches the file in
1577 * the filesystem. If they don't, then somebody else unlinked ours
1578 * and created a new file, and we need to use that one instead. (If
1579 * we caught them between the unlink and the create, we'll get an
1580 * ENOENT from the file stat.)
1581 */
1582 cc = fstat(fd, &fdStat);
1583 if (cc != 0) {
1584 LOGE("Can't stat open file '%s'\n", cacheFileName);
1585 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1586 goto close_fail;
1587 }
1588 cc = stat(cacheFileName, &fileStat);
1589 if (cc != 0 ||
1590 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
1591 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
1592 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1593 flock(fd, LOCK_UN);
1594 close(fd);
1595 usleep(250 * 1000); // if something is hosed, don't peg machine
1596 goto retry;
1597 }
1598
1599 /*
1600 * We have the correct file open and locked. If the file size is zero,
1601 * then it was just created by us, and we want to fill in some fields
1602 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
1603 * verify that the fields in the header match our expectations, and
1604 * reset the file if they don't.
1605 */
1606 if (fdStat.st_size == 0) {
1607 if (readOnly) { // The device is readOnly --> close_fail
1608 LOGW("bcc: file has zero length and isn't writable\n");
1609 goto close_fail;
1610 }
1611 /*cc = createEmptyHeader(fd);
1612 if (cc != 0)
1613 goto close_fail;
1614 */
1615 mCacheNew = true;
1616 LOGV("bcc: successfully initialized new cache file\n");
1617 } else {
1618 // Calculate sourceWhen
1619 // XXX
1620 uint32_t sourceWhen = 0;
1621 uint32_t rslibWhen = 0;
Logan9d94f162010-12-07 12:39:25 +08001622 uint32_t libRSWhen = statModifyTime(libRSPath);
1623 uint32_t libbccWhen = statModifyTime(libBccPath);
Logan1f028c02010-11-27 01:02:48 +08001624 if (!checkHeaderAndDependencies(fd,
1625 sourceWhen,
1626 rslibWhen,
1627 libRSWhen,
1628 libbccWhen)) {
1629 // If checkHeaderAndDependencies returns 0: FAILED
1630 // Will truncate the file and retry to createIfMissing the file
1631
1632 if (readOnly) { // Shouldn't be readonly.
1633 /*
1634 * We could unlink and rewrite the file if we own it or
1635 * the "sticky" bit isn't set on the directory. However,
1636 * we're not able to truncate it, which spoils things. So,
1637 * give up now.
1638 */
1639 if (createIfMissing) {
1640 LOGW("Cached file %s is stale and not writable\n",
1641 cacheFileName);
1642 }
1643 goto close_fail;
1644 }
1645
1646 /*
1647 * If we truncate the existing file before unlinking it, any
1648 * process that has it mapped will fail when it tries to touch
1649 * the pages? Probably OK because we use MAP_PRIVATE.
1650 */
1651 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
1652 cacheFileName);
1653 if (ftruncate(fd, 0) != 0) {
1654 LOGW("Warning: unable to truncate cache file '%s': %s\n",
1655 cacheFileName, strerror(errno));
1656 /* keep going */
1657 }
1658 if (unlink(cacheFileName) != 0) {
1659 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
1660 cacheFileName, errno, strerror(errno));
1661 /* keep going; permission failure should probably be fatal */
1662 }
1663 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1664 flock(fd, LOCK_UN);
1665 close(fd);
1666 goto retry;
1667 } else {
1668 // Got cacheFile! Good to go.
1669 LOGV("Good cache file\n");
1670 }
1671 }
1672
1673 assert(fd >= 0);
1674 return fd;
1675
1676close_fail:
1677 flock(fd, LOCK_UN);
1678 close(fd);
1679 return -1;
1680} // End of openCacheFile()
1681
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001682// Input: cacheDir
1683// Input: resName
1684// Input: extName
1685//
1686// Note: cacheFile = resName + extName
1687//
1688// Output: Returns cachePath == cacheDir + cacheFile
1689char *Compiler::genCacheFileName(const char *cacheDir,
1690 const char *resName,
1691 const char *extName) {
1692 char cachePath[512];
1693 char cacheFile[sizeof(cachePath)];
1694 const size_t kBufLen = sizeof(cachePath) - 1;
Logan1f028c02010-11-27 01:02:48 +08001695
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001696 cacheFile[0] = '\0';
1697 // Note: resName today is usually something like
1698 // "/com.android.fountain:raw/fountain"
1699 if (resName[0] != '/') {
1700 // Get the absolute path of the raw/***.bc file.
1701
1702 // Generate the absolute path. This doesn't do everything it
1703 // should, e.g. if resName is "./out/whatever" it doesn't crunch
1704 // the leading "./" out because this if-block is not triggered,
1705 // but it'll make do.
1706 //
1707 if (getcwd(cacheFile, kBufLen) == NULL) {
Logan1f028c02010-11-27 01:02:48 +08001708 LOGE("Can't get CWD while opening raw/***.bc file\n");
1709 return NULL;
1710 }
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001711 // Append "/" at the end of cacheFile so far.
1712 strncat(cacheFile, "/", kBufLen);
1713 }
1714
1715 // cacheFile = resName + extName
1716 //
1717 strncat(cacheFile, resName, kBufLen);
1718 if (extName != NULL) {
Logan1f028c02010-11-27 01:02:48 +08001719 // TODO(srhines): strncat() is a bit dangerous
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001720 strncat(cacheFile, extName, kBufLen);
Logan1f028c02010-11-27 01:02:48 +08001721 }
1722
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001723 // Turn the path into a flat filename by replacing
1724 // any slashes after the first one with '@' characters.
1725 char *cp = cacheFile + 1;
Logan1f028c02010-11-27 01:02:48 +08001726 while (*cp != '\0') {
1727 if (*cp == '/') {
1728 *cp = '@';
1729 }
1730 cp++;
1731 }
1732
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001733 // Tack on the file name for the actual cache file path.
1734 strncpy(cachePath, cacheDir, kBufLen);
1735 strncat(cachePath, cacheFile, kBufLen);
Logan1f028c02010-11-27 01:02:48 +08001736
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001737 LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
1738 return strdup(cachePath);
Logan1f028c02010-11-27 01:02:48 +08001739}
1740
1741/*
1742 * Read the oBCC header, verify it, then read the dependent section
1743 * and verify that data as well.
1744 *
1745 * On successful return, the file will be seeked immediately past the
1746 * oBCC header.
1747 */
1748bool Compiler::checkHeaderAndDependencies(int fd,
1749 uint32_t sourceWhen,
1750 uint32_t rslibWhen,
1751 uint32_t libRSWhen,
1752 uint32_t libbccWhen) {
1753 ssize_t actual;
1754 oBCCHeader optHdr;
1755 uint32_t val;
1756 uint8_t const *magic, *magicVer;
1757
1758 /*
1759 * Start at the start. The "bcc" header, when present, will always be
1760 * the first thing in the file.
1761 */
1762 if (lseek(fd, 0, SEEK_SET) != 0) {
1763 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
1764 goto bail;
1765 }
1766
1767 /*
1768 * Read and do trivial verification on the bcc header. The header is
1769 * always in host byte order.
1770 */
1771 actual = read(fd, &optHdr, sizeof(optHdr));
1772 if (actual < 0) {
1773 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
1774 goto bail;
1775 } else if (actual != sizeof(optHdr)) {
1776 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
1777 (int) actual, sizeof(optHdr));
1778 goto bail;
1779 }
1780
1781 magic = optHdr.magic;
1782 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
1783 /* not an oBCC file, or previous attempt was interrupted */
1784 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
1785 magic[0], magic[1], magic[2], magic[3]);
1786 goto bail;
1787 }
1788
1789 magicVer = optHdr.magicVersion;
Logancd045f92010-12-06 19:04:53 +08001790 if (memcmp(magicVer, OBCC_MAGIC_VERS, 4) != 0) {
Logan1f028c02010-11-27 01:02:48 +08001791 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
1792 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
1793 goto bail;
1794 }
1795
1796 /*
1797 * Do the header flags match up with what we want?
1798 *
1799 * This is useful because it allows us to automatically regenerate
1800 * a file when settings change (e.g. verification is now mandatory),
1801 * but can cause difficulties if the thing we depend upon
1802 * were handled differently than the current options specify.
1803 *
1804 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
1805 * by limiting the match mask.
1806 *
1807 * The only thing we really can't handle is incorrect byte-ordering.
1808 */
1809
1810 val = optHdr.sourceWhen;
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001811 // TODO(sliao): Shouldn't overload sourceWhen in the future.
1812 if (!val) {
1813 mpSymbolLookupFn(mpSymbolLookupContext, "__clearThreadable");
Logan1f028c02010-11-27 01:02:48 +08001814 }
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001815 // if (val && (val != sourceWhen)) {
1816 // LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
1817 // val, sourceWhen);
1818 // goto bail;
1819 // }
1820
Logan1f028c02010-11-27 01:02:48 +08001821 val = optHdr.rslibWhen;
1822 if (val && (val != rslibWhen)) {
1823 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
1824 val, rslibWhen);
1825 goto bail;
1826 }
1827 val = optHdr.libRSWhen;
1828 if (val && (val != libRSWhen)) {
1829 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
1830 val, libRSWhen);
1831 goto bail;
1832 }
1833 val = optHdr.libbccWhen;
1834 if (val && (val != libbccWhen)) {
1835 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
1836 val, libbccWhen);
1837 goto bail;
1838 }
1839
1840 return true;
1841
1842bail:
1843 return false;
1844}
1845
1846} // namespace bcc