double OOPLyric::GetLineProgress() const { LineInfo *currLine = *m_currLine; size_t lineHasGone = m_stopWatch->Time() - currLine->GetStartTime(); if (lineHasGone >= currLine->GetMilSeconds()) { return 1; } // 假如除数为 0,不会来到这里 return double(lineHasGone) / currLine->GetMilSeconds(); }
InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, WordMeasurements& wordMeasurements) { reset(); ASSERT(resolver.position().root() == m_block); bool appliedStartWidth = resolver.position().offset() > 0; LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.isFirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style())); skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); if (resolver.position().atEnd()) return resolver.position(); BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloatFromPreviousLine, appliedStartWidth, m_block); while (context.currentObject()) { context.initializeForCurrentObject(); if (context.currentObject()->isBR()) { context.handleBR(m_clear); } else if (context.currentObject()->isOutOfFlowPositioned()) { context.handleOutOfFlowPositioned(m_positionedObjects); } else if (context.currentObject()->isFloating()) { context.handleFloat(); } else if (context.currentObject()->isRenderInline()) { context.handleEmptyInline(); } else if (context.currentObject()->isReplaced()) { context.handleReplaced(); } else if (context.currentObject()->isText()) { if (context.handleText(wordMeasurements, m_hyphenated)) { // We've hit a hard text line break. Our line break iterator is updated, so go ahead and early return. return context.lineBreak(); } } else { ASSERT_NOT_REACHED(); } if (context.atEnd()) return context.handleEndOfLine(); context.commitAndUpdateLineBreakIfNeeded(); if (context.atEnd()) return context.handleEndOfLine(); context.increment(); } context.clearLineBreakIfFitsOnLine(); return context.handleEndOfLine(); }
int searchLineInfoAddress(const void* arg1,const void* arg2){ uint64_t key = *((uint64_t*)arg1); LineInfo* li = *((LineInfo**)arg2); ASSERT(li && "LineInfo should exist"); uint64_t val = li->GET(lr_address); if(key < val) return -1; if(key >= val + li->getAddressSpan()) return 1; return 0; }
void unreachable(const LineInfo& line_info) { System::println(System::Color::error, "Error: Unreachable code was reached"); System::println(System::Color::error, line_info.to_string()); // Always print line_info here #ifndef NDEBUG std::abort(); #else cleanup_and_exit(EXIT_FAILURE); #endif }
void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo, FloatingObject* lastFloatFromPreviousLine, LineWidth& width) { while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) { RenderObject* object = resolver.position().object(); if (object->isOutOfFlowPositioned() && object->style()->isOriginalDisplayInlineType()) { resolver.runs().addRun(createRun(0, 1, object, resolver)); lineInfo.incrementRunsFromLeadingWhitespace(); } resolver.position().increment(&resolver); } resolver.commitExplicitEmbedding(resolver.runs()); }
void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo, LineWidth& width) { while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) { LineLayoutItem lineLayoutItem = resolver.position().getLineLayoutItem(); if (lineLayoutItem.isOutOfFlowPositioned()) { setStaticPositions(m_block, LineLayoutBox(lineLayoutItem), width.indentText()); if (lineLayoutItem.style()->isOriginalDisplayInlineType()) { resolver.runs().addRun(createRun(0, 1, LineLayoutItem(lineLayoutItem), resolver)); lineInfo.incrementRunsFromLeadingWhitespace(); } } else if (lineLayoutItem.isFloating()) { m_block.insertFloatingObject(LineLayoutBox(lineLayoutItem)); m_block.positionNewFloats(&width); } resolver.position().increment(&resolver); } resolver.commitExplicitEmbedding(resolver.runs()); }
void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo, FloatingObject* lastFloatFromPreviousLine, LineWidth& width) { while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) { RenderObject& object = *resolver.position().renderer(); if (object.isOutOfFlowPositioned()) { setStaticPositions(m_block, downcast<RenderBox>(object)); if (object.style().isOriginalDisplayInlineType()) { resolver.runs().addRun(new BidiRun(0, 1, object, resolver.context(), resolver.dir())); lineInfo.incrementRunsFromLeadingWhitespace(); } } else if (object.isFloating()) m_block.positionNewFloatOnLine(m_block.insertFloatingObject(downcast<RenderBox>(object)), lastFloatFromPreviousLine, lineInfo, width); else if (is<RenderCombineText>(object) && object.style().hasTextCombine() && !downcast<RenderCombineText>(object).isCombined()) { downcast<RenderCombineText>(object).combineText(); if (downcast<RenderCombineText>(object).isCombined()) continue; } resolver.increment(); } resolver.commitExplicitEmbedding(); }
void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo, FloatingObject* lastFloatFromPreviousLine, LineWidth& width) { while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) { RenderObject* object = resolver.position().object(); if (object->isOutOfFlowPositioned()) { setStaticPositions(m_block, toRenderBox(object)); if (object->style()->isOriginalDisplayInlineType()) { resolver.runs().addRun(createRun(0, 1, object, resolver)); lineInfo.incrementRunsFromLeadingWhitespace(); } } else if (object->isFloating()) { m_block->positionNewFloatOnLine(m_block->insertFloatingObject(*toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width); } else if (object->isText() && object->style()->hasTextCombine() && object->isCombineText() && !toRenderCombineText(object)->isCombined()) { toRenderCombineText(object)->combineText(); if (toRenderCombineText(object)->isCombined()) continue; } resolver.position().increment(&resolver); } resolver.commitExplicitEmbedding(resolver.runs()); }
void TauFunctionTrace::instrument(){ //InstrumentationTool::instrument(); LineInfoFinder* lineInfoFinder = NULL; if (hasLineInformation()){ lineInfoFinder = getLineInfoFinder(); } InstrumentationPoint* p; uint64_t nameAddr = reserveDataOffset(sizeof(uint64_t)); uint64_t fileAddr = reserveDataOffset(sizeof(uint64_t)); uint64_t lineAddr = reserveDataOffset(sizeof(uint32_t)); uint64_t siteIndexAddr = reserveDataOffset(sizeof(uint32_t)); uint32_t site = functionEntry->addConstantArgument(); ASSERT(site == functionExit->addConstantArgument()); std::pebil_map_type<uint64_t, ControlInfo> functions; std::vector<uint64_t> orderedfuncs; uint32_t sequenceId = 0; if (doIntro){ // go over all functions and intrument entries/exits for (uint32_t i = 0; i < getNumberOfExposedFunctions(); i++){ Function* function = getExposedFunction(i); uint64_t addr = function->getBaseAddress(); if (instrumentList && !instrumentList->functionMatches(function->getName())){ continue; } if (!strcmp(function->getName(), "_fini")){ continue; } BasicBlock* entryBlock = function->getFlowGraph()->getEntryBlock(); Vector<BasicBlock*>* exitPoints = function->getFlowGraph()->getExitBlocks(); std::string c; c.append(function->getName()); if (c == "_start"){ exitPoints->append(getProgramExitBlock()); PRINT_INFOR("Special case: inserting exit for _start inside _fini since control generally doesn't reach its exit"); } ASSERT(functions.count(addr) == 0 && "Multiple functions have the same base address?"); PRINT_INFOR("[FUNCTION index=%d] internal instrumentation: %s", sequenceId, function->getName()); ControlInfo f = ControlInfo(); f.name = c; f.file = ""; f.line = 0; f.index = sequenceId++; f.baseaddr = addr; f.type = ControlType_Function; LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(addr); } if (li){ f.file.append(li->getFileName()); f.line = li->GET(lr_line); } functions[addr] = f; orderedfuncs.push_back(addr); InstrumentationPoint* prior = addInstrumentationPoint(entryBlock->getLeader(), functionEntry, InstrumentationMode_tramp, InstLocation_prior); prior->setPriority(InstPriority_custom3); assignStoragePrior(prior, f.index, site); for (uint32_t j = 0; j < exitPoints->size(); j++){ InstrumentationPoint* after = addInstrumentationPoint((*exitPoints)[j]->getExitInstruction(), functionExit, InstrumentationMode_tramp, InstLocation_prior); after->setPriority(InstPriority_custom5); if (c == "_start" && j == exitPoints->size() - 1){ after->setPriority(InstPriority_custom6); } assignStoragePrior(after, f.index, site); } delete exitPoints; } } else { // go over all instructions. when we find a call, instrument it for (uint32_t i = 0; i < getNumberOfExposedInstructions(); i++){ X86Instruction* x = getExposedInstruction(i); ASSERT(x->getContainer()->isFunction()); Function* function = (Function*)x->getContainer(); if (x->isFunctionCall()){ uint64_t addr = x->getTargetAddress(); Symbol* functionSymbol = getElfFile()->lookupFunctionSymbol(addr); if (functionSymbol){ if (instrumentList && !instrumentList->functionMatches(functionSymbol->getSymbolName())){ continue; } ASSERT(x->getSizeInBytes() == Size__uncond_jump); std::string c; c.append(functionSymbol->getSymbolName()); if (functions.count(addr) == 0){ PRINT_INFOR("[FUNCTION index=%d] call site instrumentation: %#lx(%s) -> %s", sequenceId, addr, function->getName(), functionSymbol->getSymbolName()); ControlInfo f = ControlInfo(); f.name = c; f.file = ""; f.line = 0; f.index = sequenceId++; f.baseaddr = addr; f.type = ControlType_Function; LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(addr); } if (li){ f.file.append(li->getFileName()); f.line = li->GET(lr_line); } functions[addr] = f; orderedfuncs.push_back(addr); } uint32_t idx = functions[addr].index; Base* exitpoint = (Base*)x; if (c == "__libc_start_main"){ PRINT_INFOR("Special case: inserting exit for __libc_start_main inside _fini since this call generally doesn't return"); exitpoint = (Base*)getProgramExitBlock(); } InstrumentationPoint* prior = addInstrumentationPoint(x, functionEntry, InstrumentationMode_tramp, InstLocation_prior); InstrumentationPoint* after = addInstrumentationPoint(exitpoint, functionExit, InstrumentationMode_tramp, InstLocation_after); assignStoragePrior(prior, idx, site); assignStoragePrior(after, idx, site); } } } } // set up argument passing for function registration functionRegister->addArgument(nameAddr); functionRegister->addArgument(fileAddr); functionRegister->addArgument(lineAddr); uint32_t siteReg = functionRegister->addConstantArgument(); // go over every function that was found, insert a registration call at program start for (std::vector<uint64_t>::iterator it = orderedfuncs.begin(); it != orderedfuncs.end(); it++){ uint64_t addr = *it; ControlInfo f = functions[addr]; ASSERT(f.baseaddr == addr); InstrumentationPoint* p = addInstrumentationPoint(getProgramEntryBlock(), functionRegister, InstrumentationMode_tramp); p->setPriority(InstPriority_custom1); const char* cstring = f.name.c_str(); uint64_t storage = reserveDataOffset(strlen(cstring) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring), (void*)cstring); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + nameAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); const char* cstring2 = f.file.c_str(); if (f.file == ""){ assignStoragePrior(p, NULL, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } else { storage = reserveDataOffset(strlen(cstring2) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring2), (void*)cstring2); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } assignStoragePrior(p, f.line, getInstDataAddress() + lineAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); assignStoragePrior(p, f.index, siteReg); } if (!instrumentList){ return; } // instrument loops std::pebil_map_type<uint64_t, ControlInfo> loops; std::vector<uint64_t> orderedloops; loopRegister->addArgument(nameAddr); loopRegister->addArgument(fileAddr); loopRegister->addArgument(lineAddr); ASSERT(siteReg == loopRegister->addConstantArgument()); for (uint32_t i = 0; i < getNumberOfExposedFunctions(); i++){ Function* function = getExposedFunction(i); FlowGraph* flowgraph = function->getFlowGraph(); if (!instrumentList->loopMatches(function->getName())){ continue; } for (uint32_t j = 0; j < flowgraph->getNumberOfLoops(); j++){ Loop* loop = flowgraph->getLoop(j); uint32_t depth = flowgraph->getLoopDepth(loop); BasicBlock* head = loop->getHead(); uint64_t addr = head->getBaseAddress(); // only want outer-most (depth == 1) loops if (depth != 1){ continue; } BasicBlock** allLoopBlocks = new BasicBlock*[loop->getNumberOfBlocks()]; loop->getAllBlocks(allLoopBlocks); // reject any loop that contains an indirect branch since it is difficult to guarantee that we will find all exits bool badLoop = false; for (uint32_t k = 0; k < loop->getNumberOfBlocks() && !badLoop; k++){ BasicBlock* bb = allLoopBlocks[k]; if (bb->getExitInstruction()->isIndirectBranch()){ badLoop = true; } } if (badLoop){ PRINT_WARN(20, "Loop at %#lx in %s contains an indirect branch so we can't guarantee that all exits will be found. skipping!", addr, function->getName()); delete[] allLoopBlocks; continue; } std::string c; c.append(function->getName()); uint32_t entryc = 0; Vector<LoopPoint*>* points = NULL; // if addr already exists, it means that two loops share a head and we are going to merge them logically here if (loops.count(addr) == 0){ ControlInfo f = ControlInfo(); f.name = c; f.file = ""; f.line = 0; f.index = sequenceId++; f.baseaddr = addr; f.type = ControlType_Loop; points = new Vector<LoopPoint*>(); f.info = points; LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(addr); } if (li){ f.file.append(li->getFileName()); f.line = li->GET(lr_line); } loops[addr] = f; orderedloops.push_back(addr); // find entries into this loop for (uint32_t k = 0; k < head->getNumberOfSources(); k++){ BasicBlock* source = head->getSourceBlock(k); if (!loop->isBlockIn(source->getIndex())){ LoopPoint* lp = new LoopPoint(); points->append(lp); lp->flowgraph = flowgraph; lp->source = source; lp->target = NULL; lp->entry = true; lp->interpose = false; if (source->getBaseAddress() + source->getNumberOfBytes() != head->getBaseAddress()){ lp->interpose = true; lp->target = head; } entryc++; } } } ControlInfo f = loops[addr]; points = f.info; // find exits from this loop uint32_t exitc = 0; for (uint32_t k = 0; k < loop->getNumberOfBlocks(); k++){ BasicBlock* bb = allLoopBlocks[k]; if (bb->endsWithReturn()){ LoopPoint* lp = new LoopPoint(); points->append(lp); lp->flowgraph = flowgraph; lp->source = bb; lp->target = NULL; lp->entry = false; lp->interpose = false; exitc++; } for (uint32_t m = 0; m < bb->getNumberOfTargets(); m++){ BasicBlock* target = bb->getTargetBlock(m); if (!loop->isBlockIn(target->getIndex())){ LoopPoint* lp = new LoopPoint(); points->append(lp); lp->flowgraph = flowgraph; lp->source = bb; lp->target = NULL; lp->entry = false; lp->interpose = false; if (target->getBaseAddress() != bb->getBaseAddress() + bb->getNumberOfBytes()){ lp->interpose = true; lp->target = target; } exitc++; } } } PRINT_INFOR("[LOOP index=%d] loop instrumentation %#lx(%s) has %d entries and %d exits", sequenceId-1, addr, function->getName(), entryc, exitc); delete[] allLoopBlocks; } } // go over every loop that was found, insert a registration call at program start // [source_addr -> [target_addr -> interposed]] std::pebil_map_type<uint64_t, std::pebil_map_type<uint64_t, BasicBlock*> > idone; for (std::vector<uint64_t>::iterator it = orderedloops.begin(); it != orderedloops.end(); it++){ uint64_t addr = *it; ControlInfo f = loops[addr]; ASSERT(f.baseaddr == addr); InstrumentationPoint* p = addInstrumentationPoint(getProgramEntryBlock(), loopRegister, InstrumentationMode_tramp); p->setPriority(InstPriority_custom2); const char* cstring = f.name.c_str(); uint64_t storage = reserveDataOffset(strlen(cstring) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring), (void*)cstring); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + nameAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); const char* cstring2 = f.file.c_str(); if (f.file == ""){ assignStoragePrior(p, NULL, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } else { storage = reserveDataOffset(strlen(cstring2) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring2), (void*)cstring2); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } assignStoragePrior(p, f.line, getInstDataAddress() + lineAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); assignStoragePrior(p, f.index, siteReg); // now add instrumentation for each loop entry/exit Vector<LoopPoint*>* v = (Vector<LoopPoint*>*)f.info; for (uint32_t i = 0; i < v->size(); i++){ LoopPoint* lp = (*v)[i]; ASSERT(lp->flowgraph && lp->source); BasicBlock* bb = lp->source; if (lp->interpose){ ASSERT(lp->target); if (idone.count(lp->source->getBaseAddress()) == 0){ idone[lp->source->getBaseAddress()] = std::pebil_map_type<uint64_t, BasicBlock*>(); } if (idone[lp->source->getBaseAddress()].count(lp->target->getBaseAddress()) == 0){ idone[lp->source->getBaseAddress()][lp->target->getBaseAddress()] = initInterposeBlock(lp->flowgraph, lp->source->getIndex(), lp->target->getIndex()); } bb = idone[lp->source->getBaseAddress()][lp->target->getBaseAddress()]; } else { ASSERT(lp->target == NULL); } Base* pt = (Base*)bb; InstLocations loc = InstLocation_prior; // if exit block falls through, we must place the instrumentation point at the very end of the block if (!lp->entry && !lp->interpose){ pt = (Base*)bb->getExitInstruction(); if (!bb->getExitInstruction()->isReturn()){ loc = InstLocation_after; } } InstrumentationFunction* inf = functionExit; if (lp->entry){ inf = functionEntry; } InstrumentationPoint* p = addInstrumentationPoint(pt, inf, InstrumentationMode_tramp, loc); p->setPriority(InstPriority_custom4); assignStoragePrior(p, f.index, site); delete lp; } delete v; } }
void BasicBlockCounter::instrument() { InstrumentationTool::instrument(); ASSERT(currentPhase == ElfInstPhase_user_reserve && "Instrumentation phase order must be observed"); uint32_t temp32; LineInfoFinder* lineInfoFinder = NULL; if (hasLineInformation()){ lineInfoFinder = getLineInfoFinder(); } uint64_t lineArray = reserveDataOffset(getNumberOfExposedBasicBlocks() * sizeof(uint32_t)); uint64_t fileNameArray = reserveDataOffset(getNumberOfExposedBasicBlocks() * sizeof(char*)); uint64_t funcNameArray = reserveDataOffset(getNumberOfExposedBasicBlocks() * sizeof(char*)); uint64_t hashCodeArray = reserveDataOffset(getNumberOfExposedBasicBlocks() * sizeof(uint64_t)); uint64_t appName = reserveDataOffset((strlen(getApplicationName()) + 1) * sizeof(char)); initializeReservedData(getInstDataAddress() + appName, strlen(getApplicationName()) + 1, getApplicationName()); uint64_t instExt = reserveDataOffset((strlen(getInstSuffix()) + 1) * sizeof(char)); initializeReservedData(getInstDataAddress() + instExt, strlen(getInstSuffix()) + 1, getInstSuffix()); // the number blocks in the code uint64_t counterArrayEntries = reserveDataOffset(sizeof(uint32_t)); // an array of counters. note that everything is passed by reference uint64_t counterArray = reserveDataOffset(getNumberOfExposedBasicBlocks() * sizeof(uint32_t)); exitFunc->addArgument(counterArray); exitFunc->addArgument(appName); exitFunc->addArgument(instExt); InstrumentationPoint* p = addInstrumentationPoint(getProgramExitBlock(), exitFunc, InstrumentationMode_tramp); if (!p->getInstBaseAddress()){ PRINT_ERROR("Cannot find an instrumentation point at the exit function"); } temp32 = 0; for (uint32_t i = 0; i < getNumberOfExposedBasicBlocks(); i++){ initializeReservedData(getInstDataAddress() + counterArray + i*sizeof(uint32_t), sizeof(uint32_t), &temp32); } // the number of inst points entryFunc->addArgument(counterArrayEntries); temp32 = getNumberOfExposedBasicBlocks(); initializeReservedData(getInstDataAddress() + counterArrayEntries, sizeof(uint32_t), &temp32); // an array for line numbers entryFunc->addArgument(lineArray); // an array for file name pointers entryFunc->addArgument(fileNameArray); // an array for function name pointers entryFunc->addArgument(funcNameArray); // an array for hashcodes entryFunc->addArgument(hashCodeArray); p = addInstrumentationPoint(getProgramEntryBlock(), entryFunc, InstrumentationMode_tramp, FlagsProtectionMethod_full, InstLocation_prior); p->setPriority(InstPriority_userinit); if (!p->getInstBaseAddress()){ PRINT_ERROR("Cannot find an instrumentation point at the entry block"); } uint64_t noDataAddr = getInstDataAddress() + reserveDataOffset(strlen(NOSTRING) + 1); char* nostring = new char[strlen(NOSTRING) + 1]; sprintf(nostring, "%s\0", NOSTRING); initializeReservedData(noDataAddr, strlen(NOSTRING) + 1, nostring); PRINT_DEBUG_MEMTRACK("There are %d instrumentation points", getNumberOfExposedBasicBlocks()); Vector<BasicBlock*>* allBlocks = new Vector<BasicBlock*>(); Vector<LineInfo*>* allLineInfos = new Vector<LineInfo*>(); uint32_t noProtPoints = 0; uint32_t complexSelection = 0; for (uint32_t i = 0; i < getNumberOfExposedBasicBlocks(); i++){ BasicBlock* bb = getExposedBasicBlock(i); LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(bb); } Function* f = bb->getFunction(); (*allBlocks).append(bb); (*allLineInfos).append(li); if (i % 1000 == 0){ PRINT_DEBUG_MEMTRACK("inst point %d", i); PRINT_MEMTRACK_STATS(__LINE__, __FILE__, __FUNCTION__); } if (li){ uint32_t line = li->GET(lr_line); initializeReservedData(getInstDataAddress() + lineArray + sizeof(uint32_t)*i, sizeof(uint32_t), &line); uint64_t filename = reserveDataOffset(strlen(li->getFileName()) + 1); uint64_t filenameAddr = getInstDataAddress() + filename; initializeReservedData(getInstDataAddress() + fileNameArray + i*sizeof(char*), sizeof(char*), &filenameAddr); initializeReservedData(getInstDataAddress() + filename, strlen(li->getFileName()) + 1, (void*)li->getFileName()); } else { temp32 = 0; initializeReservedData(getInstDataAddress() + lineArray + sizeof(uint32_t)*i, sizeof(uint32_t), &temp32); initializeReservedData(getInstDataAddress() + fileNameArray + i*sizeof(char*), sizeof(char*), &noDataAddr); } uint64_t funcname = reserveDataOffset(strlen(f->getName()) + 1); uint64_t funcnameAddr = getInstDataAddress() + funcname; initializeReservedData(getInstDataAddress() + funcNameArray + i*sizeof(char*), sizeof(char*), &funcnameAddr); initializeReservedData(getInstDataAddress() + funcname, strlen(f->getName()) + 1, (void*)f->getName()); uint64_t hashValue = bb->getHashCode().getValue(); initializeReservedData(getInstDataAddress() + hashCodeArray + i*sizeof(uint64_t), sizeof(uint64_t), &hashValue); InstrumentationSnippet* snip = new InstrumentationSnippet(); uint64_t counterOffset = counterArray + (i * sizeof(uint32_t)); // snippet contents, in this case just increment a counter if (is64Bit()){ snip->addSnippetInstruction(X86InstructionFactory64::emitAddImmByteToMem(1, getInstDataAddress() + counterOffset)); } else { snip->addSnippetInstruction(X86InstructionFactory32::emitAddImmByteToMem(1, getInstDataAddress() + counterOffset)); } // do not generate control instructions to get back to the application, this is done for // the snippet automatically during code generation // register the snippet we just created addInstrumentationSnippet(snip); // register an instrumentation point at the function that uses this snippet FlagsProtectionMethods prot = FlagsProtectionMethod_light; #ifndef NO_REG_ANALYSIS if (bb->getLeader()->allFlagsDeadIn()){ prot = FlagsProtectionMethod_none; noProtPoints++; } for (uint32_t j = 0; j < bb->getNumberOfInstructions(); j++){ if (bb->getInstruction(j)->allFlagsDeadIn() || bb->getInstruction(j)->allFlagsDeadOut()){ complexSelection++; break; } } #endif InstrumentationPoint* p = addInstrumentationPoint(bb, snip, InstrumentationMode_inline, prot); } PRINT_MEMTRACK_STATS(__LINE__, __FILE__, __FUNCTION__); #ifdef NO_REG_ANALYSIS PRINT_WARN(10, "Warning: register analysis disabled"); #endif PRINT_INFOR("Excluding flags protection for %d/%d instrumentation points", noProtPoints, getNumberOfExposedBasicBlocks()); //PRINT_INFOR("complex inst point selection: %d/%d instrumentation points", complexSelection, getNumberOfExposedBasicBlocks()); printStaticFile(allBlocks, allLineInfos); delete[] nostring; delete allBlocks; delete allLineInfos; ASSERT(currentPhase == ElfInstPhase_user_reserve && "Instrumentation phase order must be observed"); }
void exit_with_code(const LineInfo& line_info, const int exit_code) { Debug::println(System::Color::error, line_info.to_string()); cleanup_and_exit(exit_code); }
void OOPLyric::OnMouseEvent(VdkMouseEvent &e) { switch (e.evtCode) { case RIGHT_UP: { // 拖动歌词时不要响应右键事件 if (TestState(OLST_DRAGGING)) { return; } wxPoint menuPos(AbsoluteRect().GetPosition()); menuPos.x += e.mousePos.x; menuPos.y += e.mousePos.y; m_Window->ShowContextMenu(this, menuPos); break; } case LEFT_DOWN: { m_draggDistance = e.mousePos.y; SetAddinState(OLST_DRAGGING_STARTED); break; } case DRAGGING: { // 不接受先在一首歌的会话中拖动歌词,然后在未释放鼠标的情况下 // 另一首歌开始播放,继续前面的拖动事件 if (!TestState(OLST_DRAGGING_STARTED)) { break; } if (!IsOk()) { break; } if (m_timer.IsRunning()) { Pause(); SetAddinState(OLST_RUNNING_BEFORE_DRAGGING); } SetAddinState(OLST_DRAGGING); //====================================================== int ystart; GetViewStartCoord(NULL, &ystart); int dY = e.mousePos.y - m_draggDistance; m_draggDistance = e.mousePos.y; // 这是一行我们手工加上去的空行 int rowHeight = GetRowHeight(); int upperBound = (*(m_parser->begin()))->GetLyric().empty() ? rowHeight : 0; // 无法继续将帘布向上卷(再拖下去就到下一首了) // 我们将拖到尽头的事件视为无效 bool lastLine = false; // 情景:将虚拟画布像窗帘一样向下拖 // 拖动尽头了,不能再把窗帘哪怕拖下一寸 if (ystart - dY < upperBound) { dY = ystart - upperBound; // 加加减减的原因参照(*) } else { int maxy; GetMaxViewStartCoord(NULL, &maxy); // 将帘布向上卷,卷到尽头了,再卷下去就会导致 // 无法完整遮住窗口 if (ystart - dY > maxy) { dY = ystart - maxy; // 加加减减的原因参照(*) // 无效拖动事件 lastLine = true; } } if (dY) { SetViewStart(0, ystart - dY, &e.dc); //………………(*) } // 无效拖动事件 if (lastLine) { m_draggHit = m_parser->end(); } //=================================================== // 绘制中间线段 wxRect rc(GetAbsoluteRect()); int y = rc.y + m_blankLinesTop * GetRowHeight(); m_Window->ResetDcOrigin(e.dc); e.dc.SetPen(wxPen(m_TextColor)); e.dc.DrawLine(rc.x, y, rc.GetRight(), y); break; } case NORMAL: case LEFT_UP: { if (!TestState(OLST_DRAGGING) || !TestState(OLST_DRAGGING_STARTED)) { break; } wxASSERT(IsOk()); //----------------------------------------------------- RemoveState(OLST_DRAGGING | OLST_DRAGGING_STARTED); // 拖到最下面了,尽头 if (m_draggHit == m_parser->end()) { RefreshState(&e.dc); } else { int ystart; // 起始绘图坐标 GetViewStartCoord(NULL, &ystart); LineInfo *lineDraggHit = *m_draggHit; size_t timeToGo = lineDraggHit->GetStartTime(); int rowHeight = GetRowHeight(); double linePercentage = double(ystart % rowHeight) / rowHeight ; timeToGo += lineDraggHit->GetMilSeconds() * linePercentage; // 歌词可能并不匹配正在播放的歌曲 if (timeToGo < m_parser->GetTimeSum()) { m_currLine = m_draggHit; if (IsReadyForEvent()) { FireEvent(&e.dc, (void *) timeToGo); } } } bool resume = TestState(OLST_RUNNING_BEFORE_DRAGGING); if (resume) { RemoveState(OLST_RUNNING_BEFORE_DRAGGING); Resume(); } break; } default: break; } }
VdkCusdrawReturnFlag OOPLyric::DoDrawCellText (const VdkLcCell *cell, int col_index, int index0, wxDC &dc, VdkLcHilightState state) { wxASSERT(m_parser); // 注意:index 是不计算加入的空行的 int index = (int) (cell->GetClientData()) - 1; if (index == -1) { // 此时 ClientData == NULL,是我们添加的空行 return VCCDRF_DODEFAULT; } dc.SetTextForeground(m_TextColor); // 暂停时高亮当前行,情景见于用户正在拖动歌词。 // 另外先暂停,然后拖动歌词完毕,此时假如歌词秀是以卡拉OK // 方式进行显示时,那么不会保持半高亮的状态,而是全高亮。 if (TestState(OLST_PAUSED)) { int yStart; GetViewStartCoord(NULL, &yStart); int rowHeight = GetRowHeight(); int dragRegion = yStart + rowHeight * m_blankLinesTop; int index2 = index + m_blankLinesTop; // 检测拖动歌词时中间线下面的一行 if (rowHeight * index2 <= dragRegion && rowHeight * (index2 + 1) > dragRegion) { m_draggHit = m_parser->GetLine(index); dc.SetTextForeground(m_HilightColor); } return VCCDRF_DODEFAULT; } LineInfo *currLine = *m_currLine; // TODO: 是否考虑优化? size_t currLineIndex = m_parser->IndexOf(m_currLine); int lineHasGone = m_stopWatch->Time() - currLine->GetStartTime(); if ((index == currLineIndex - 1) && !cell->GetLabel().empty()) { // 使用渐变色还原上一句歌词 if (lineHasGone < ALPHA_SHOW_LAST_LINE_MS) { unsigned char r, g, b; double alpha2 = double(lineHasGone) / ALPHA_SHOW_LAST_LINE_MS; double alpha1 = 1 - alpha2; r = m_HilightColor.Red() * alpha1 + m_TextColor.Red() * alpha2; g = m_HilightColor.Green() * alpha1 + m_TextColor.Green() * alpha2; b = m_HilightColor.Blue() * alpha1 + m_TextColor.Blue() * alpha2; dc.SetTextForeground(wxColour(r, g, b)); } } else if (index == currLineIndex) { // 高亮当前文本行 // 尽管这是一种很罕见的情况,但一旦出现了就会导致下面 (*) 表达式 // 的除数为 0 if (currLine->GetMilSeconds() == 0) { return VCCDRF_DODEFAULT; } if (!cell->IsEmpty()) { /* 经验教训: 1. SetClippingRegiion 有叠加效应,因此在执行新的 SetClippingRegiion 前别忘了销毁原来的 ClippingRegiion 。 2. 关于表达式中整数与浮点数混用:注意中间运算结果会 被强制转换成 int 然后参加下一步的运算,并不是对 最终结果进行转换,使之成为一个浮点数。 */ const int rowHeight = GetRowHeight(); int y = (currLineIndex + m_blankLinesTop) * rowHeight; cell->DrawLabel(dc, 0, y); // (*) double lineProgress = double(lineHasGone) / currLine->GetMilSeconds(); // 要实现 KALA-OK 效果的文本宽度 int w = (m_Rect.width - cell->GetX_Padding() * 2) * lineProgress; wxRect rc(GetAbsoluteRect()); const int bottom = rc.y + rc.height; int yStart; VdkScrolledWindow::GetViewStartCoord(NULL, &yStart); rc.y += y - yStart; rc.width = cell->GetX_Padding() + w; rc.height = rowHeight; // 不能使 KALA-OK 效果的 ClippingRegion 超出列表窗口 if ((rc.y + rc.height) > bottom) { rc.height = bottom - rc.y; } VdkDcDeviceOriginSaver saver(dc); dc.SetDeviceOrigin(0, 0); VdkDcClippingRegionDestroyer destroyer(dc, rc); # ifdef __WXGTK__ dc.SetBrush(m_crossBrush1); dc.DrawRectangle(rc); # endif dc.SetTextForeground(m_HilightColor); cell->DrawLabel(dc, rc.x, rc.y); } return VCCDRF_SKIPDEFAULT; } return VCCDRF_DODEFAULT; }