void SymbolTable::print(){ char tmpstr[__MAX_STRING_SIZE]; PRINT_INFOR("SymbolTable : %d aka sect %d with %d symbols",index,getSectionIndex(),symbols.size()); PRINT_INFOR("\tdyn? : %s", isDynamic() ? "yes" : "no"); for (uint32_t i = 0; i < symbols.size(); i++){ symbols[i]->print(); } }
void DataReference::print(){ uint16_t sidx = 0; if (rawSection){ sidx = rawSection->getSectionIndex(); } PRINT_INFOR("DATAREF %#llx: Offset %#llx in section %d -- %#llx", getBaseAddress(), sectionOffset, sidx, data); }
void DataSection::setBytesAtOffset(uint64_t offset, uint32_t size, char* content){ if (offset + size > getSizeInBytes()){ PRINT_INFOR("offset %ld size %d GetSize %ld", offset, size, getSizeInBytes()); } ASSERT(offset + size <= getSizeInBytes()); ASSERT(rawBytes); memcpy(rawBytes + offset, content, size); }
void DataSection::printBytes(uint64_t offset, uint32_t bytesPerWord, uint32_t bytesPerLine){ fprintf(stdout, "\n"); PRINT_INFOR("Raw bytes for DATA section %d:", sectionIndex); uint32_t printMax = getSectionHeader()->GET(sh_size); if (0x400 < printMax){ printMax = 0x400; } printBufferPretty(charStream() + offset, printMax, getSectionHeader()->GET(sh_addr) + offset, bytesPerWord, bytesPerLine); }
void RelocationTable::print(){ PRINT_INFOR("RelocTable : %d aka sect %d with %d relocations",index,getSectionIndex(),relocations.size()); PRINT_INFOR("\tadd? : %s", type == ElfRelType_rela ? "yes" : "no"); PRINT_INFOR("\tsect : %d", elfFile->getSectionHeader(getSectionIndex())->GET(sh_info)); PRINT_INFOR("\tstbs : %d", elfFile->getSectionHeader(getSectionIndex())->GET(sh_link)); ASSERT(elfFile->getSectionHeader(getSectionIndex()) && "Section header doesn't exist"); for (uint32_t i = 0; i < relocations.size(); i++){ char* namestr = NULL; Symbol* foundsymbols[3]; for (uint32_t j = 0; j < 3; j++){ foundsymbols[j] = NULL; } symbolTable->findSymbol4Addr(relocations[i]->GET(r_offset),foundsymbols,3,&namestr); relocations[i]->print(namestr); for (uint32_t j = 0; j < 3; j++){ if (foundsymbols[j]){ foundsymbols[j]->print(); } } delete[] namestr; } }
CallReplace::CallReplace(ElfFile* elf, char* traceFile, char* libList) : InstrumentationTool(elf) { programEntry = NULL; programExit = NULL; functionList = new Vector<char*>(); initializeFileList(traceFile, functionList); // replace any ':' character with a '\0' for (uint32_t i = 0; i < (*functionList).size(); i++){ char* both = (*functionList)[i]; uint32_t numrepl = 0; for (uint32_t j = 0; j < strlen(both); j++){ if (both[j] == ':'){ both[j] = '\0'; numrepl++; } } if (numrepl != 1){ PRINT_ERROR("input file %s line %d should contain a ':'", traceFile, i+1); } } Vector<uint32_t> libIdx; libIdx.append(0); uint32_t listSize = strlen(libList); for (uint32_t i = 0; i < listSize; i++){ if (libList[i] == ','){ libList[i] = '\0'; libIdx.append(i+1); } } for (uint32_t i = 0; i < libIdx.size(); i++){ if (libIdx[i] < listSize){ libraries.append(libList + libIdx[i]); } else { PRINT_ERROR("improperly formatted library list given to call replacement tool"); __SHOULD_NOT_ARRIVE; } } for (uint32_t i = 0; i < libraries.size(); i++){ PRINT_INFOR("library -- %s", libraries[i]); } }
void ProgramHeader::print() { PRINT_INFOR("PHeader : %d",index); if(GET(p_type) <= PT_PHDR){ PRINT_INFOR("\tPtyp : %s",PTypeNames[GET(p_type)]); } else { char* ptr = "UNK"; switch(GET(p_type)){ case PT_LOOS : ptr = "LOOS"; break; case PT_GNU_EH_FRAME : ptr = "GNU_EH_FRAME"; break; case PT_GNU_STACK : ptr = "GNU_STACK"; break; case PT_LOSUNW : ptr = "LOSUNW"; break; case PT_SUNWSTACK : ptr = "SUNWSTACK"; break; case PT_HIOS : ptr = "HIOS"; break; case PT_LOPROC : ptr = "LOPROC"; break; case PT_HIPROC : ptr = "HIPROC"; break; default : ptr = "UNK"; break; } PRINT_INFOR("\tPtyp : %s (%#x)",ptr,GET(p_type)); } PRINT_INFOR("\tPoff : @%llx for %lluB",GET(p_offset),GET(p_filesz)); PRINT_INFOR("\tPvad : %#llx for %lluB",GET(p_vaddr),GET(p_memsz)); PRINT_INFOR("\tPpad : %#llx",GET(p_paddr)); uint32_t alignment = GET(p_align); for(uint32_t i=0;i<32;i++){ if((alignment >> i) & 0x1){ alignment = i; } } PRINT_INFOR("\talig : 2**%u",alignment); uint32_t flags = GET(p_flags); PRINT_INFOR("\tflgs : %c%c%c%c%c",ISPF_R(flags) ? 'r' : '-', ISPF_W(flags) ? 'w' : '-', ISPF_X(flags) ? 'x' : '-', flags == PF_MASKOS ? 'o' : '-', flags == PF_MASKPROC ? 'p' : '-'); }
void Symbol::print(){ char* bindstr = "UNK"; switch(ELF32_ST_BIND(GET(st_info))){ case STB_LOCAL: bindstr="LOC";break; case STB_GLOBAL:bindstr="GLB";break; case STB_WEAK: bindstr="WEA";break; case STB_NUM: bindstr="NUM";break; case STB_LOOS: bindstr="LOS";break; case STB_HIOS: bindstr="HIS";break; case STB_LOPROC:bindstr="LOP";break; case STB_HIPROC:bindstr="HIP";break; default: break; } char* typestr = "UNK"; switch(ELF32_ST_TYPE(GET(st_info))){ case STT_NOTYPE: typestr="NOTY";break; case STT_OBJECT: typestr="OBJT";break; case STT_FUNC: typestr="FUNC";break; case STT_SECTION:typestr="SECT";break; case STT_FILE: typestr="FILE";break; case STT_COMMON: typestr="COMM";break; case STT_TLS: typestr="TLS ";break; case STT_NUM: typestr="NUM ";break; case STT_LOOS: typestr="LOOS";break; case STT_HIOS: typestr="HIOS";break; case STT_LOPROC: typestr="LOPR";break; case STT_HIPROC: typestr="HIPR";break; default:break; } char* symbolName = table->getSymbolName(index); PRINT_INFOR("\tsym%5d -- sx:%5d sz:%8lld bxt: %3s.%4s vl:%#12llx ot:%3d nx:%8u\t%s",index, GET(st_shndx),GET(st_size),bindstr,typestr,GET(st_value),GET(st_other), GET(st_name),symbolName ? symbolName : ""); }
int main(int argc,char* argv[]){ int overflow = 0xbeefbeef; char* inptName = NULL; char* extension = ""; char* libPath = NULL; int32_t phaseNo = 0; uint32_t instType = unknown_inst_type; uint32_t argApp = 0; uint32_t argTyp = 0; uint32_t argExt = 0; uint32_t argPhs = 0; uint32_t argInp = 0; bool loopIncl = false; bool extdPrnt = false; bool verbose = false; bool dryRun = false; uint32_t printCodes = 0x00000000; char* rawPrintCodes = NULL; char* inputFuncList = NULL; char* inputTrackList = NULL; char* libList = NULL; bool deleteInpList = false; char* execName = NULL; TIMER(double t = timer()); for (int32_t i = 1; i < argc; i++){ if (!strcmp(argv[i],"--app")){ if (argApp++){ fprintf(stderr,"\nError : Duplicate %s option\n",argv[i]); printUsage(); } execName = argv[++i]; } else if (!strcmp(argv[i],"--typ")){ if (argTyp++){ fprintf(stderr,"\nError : Duplicate %s option\n",argv[i]); printUsage(); } ++i; if (!strcmp(argv[i],"ide")){ instType = identical_inst_type; extension = "ideinst"; } else if (!strcmp(argv[i],"fnc")){ instType = function_counter_type; extension = "fncinst"; } else if (!strcmp(argv[i],"jbb")){ instType = frequency_inst_type; extension = "jbbinst"; } else if (!strcmp(argv[i],"sim")){ instType = simulation_inst_type; extension = "siminst"; } else if (!strcmp(argv[i],"csc")){ instType = simucntr_inst_type; extension = "cscinst"; } else if (!strcmp(argv[i],"ftm")){ instType = func_timer_type; extension = "ftminst"; } else if (!strcmp(argv[i],"crp")){ instType = call_wrapper_type; extension = "crpinst"; } } else if (!strcmp(argv[i],"--help")){ printUsage(true, true); } } if (!execName){ fprintf(stderr,"\nError : No executable is specified\n\n"); printUsage(); } if ((instType <= unknown_inst_type) || (instType >= Total_InstrumentationType)){ fprintf(stderr,"\nError : Unknown instrumentation type\n"); printUsage(); } for (int32_t i = 1; i < argc; i++){ if (!strcmp(argv[i],"--app") || !strcmp(argv[i],"--typ")){ ++i; } else if (!strcmp(argv[i],"--ext")){ if (argExt++){ fprintf(stderr,"\nError : Duplicate %s option\n",argv[i]); printUsage(); } extension = argv[++i]; } else if(!strcmp(argv[i],"--phs")){ if (argPhs++){ fprintf(stderr,"\nError : Duplicate %s option\n",argv[i]); printUsage(); } if ((instType != simulation_inst_type) && (instType != simucntr_inst_type)){ fprintf(stderr,"\nError : Option %s is not valid other than simulation\n",argv[i]); printUsage(); } ++i; char* endptr = NULL; phaseNo = strtol(argv[i],&endptr,10); if ((endptr == argv[i]) || !phaseNo){ fprintf(stderr,"\nError : Given phase number is not correct, requires > 0\n\n"); printUsage(); } } else if (!strcmp(argv[i],"--inp")){ if (argInp++){ fprintf(stderr,"\nError : Duplicate %s option\n",argv[i]); printUsage(); } if ((instType != simulation_inst_type) && (instType != simucntr_inst_type)){ fprintf(stderr,"\nError : Option %s is not valid other than simulation\n",argv[i]); printUsage(); } inptName = argv[++i]; } else if (!strcmp(argv[i],"--lpi")){ loopIncl = true; if ((instType != simulation_inst_type) && (instType != simucntr_inst_type)){ fprintf(stderr,"\nError : Option %s is not valid other than simulation\n",argv[i++]); printUsage(); } } else if (!strcmp(argv[i],"--ver")){ verbose = true; rawPrintCodes = argv[++i]; } else if (!strcmp(argv[i],"--dtl")){ extdPrnt = true; } else if (!strcmp(argv[i],"--lib")){ libPath = argv[++i]; } else if (!strcmp(argv[i],"--dry")){ dryRun = true; } else if (!strcmp(argv[i],"--fbl")){ if (inputFuncList){ printUsage(); } inputFuncList = argv[++i]; } else if (!strcmp(argv[i],"--trk")){ if (inputTrackList){ printUsage(); } inputTrackList = argv[++i]; } else if (!strcmp(argv[i],"--lnc")){ if (libList){ printUsage(); } libList = argv[++i]; } else { fprintf(stderr,"\nError : Unknown switch at %s\n\n",argv[i]); printUsage(); } } if (((instType == simulation_inst_type) || (instType == simucntr_inst_type)) && !inptName){ fprintf(stderr,"\nError : Input is required for cache simulation instrumentation\n\n"); printUsage(); } ASSERT((instType == simulation_inst_type) || (instType == simucntr_inst_type) || (phaseNo == 0)); if (verbose){ if (!rawPrintCodes){ fprintf(stderr,"\tError: verbose option used without argument"); printUsage(); } printCodes = processPrintCodes(rawPrintCodes); } if(!libPath){ libPath = getenv("PEBIL_LIB"); if (!libPath){ PRINT_ERROR("Use the -lib option or define the PEBIL_LIB variable"); } } PRINT_INFOR("The instrumentation libraries will be used from %s",libPath); if (!inputFuncList){ deleteInpList = true; char* pebilRoot = getenv("PEBIL_ROOT"); if (!pebilRoot){ PRINT_ERROR("Set the PEBIL_ROOT variable"); } inputFuncList = new char[__MAX_STRING_SIZE]; sprintf(inputFuncList, "%s/%s", pebilRoot, DEFAULT_FUNC_BLACKLIST); } PRINT_INFOR("The function blacklist is taken from %s", inputFuncList); if (dryRun){ PRINT_INFOR("--dry option was used, exiting..."); exit(0); } uint32_t stepNumber = 0; TIMER(double t1 = timer(), t2); PRINT_INFOR("******** Instrumentation Beginning ********"); ElfFile elfFile(execName); elfFile.parse(); TIMER(t2 = timer();PRINT_INFOR("___timer: Step %d Parse : %.2f seconds",++stepNumber,t2-t1);t1=t2); elfFile.initSectionFilePointers(); TIMER(t2 = timer();PRINT_INFOR("___timer: Step %d Disasm : %.2f seconds",++stepNumber,t2-t1);t1=t2); elfFile.generateCFGs(); TIMER(t2 = timer();PRINT_INFOR("___timer: Step %d GenCFG : %.2f seconds",++stepNumber,t2-t1);t1=t2); if (extdPrnt){ elfFile.findLoops(); TIMER(t2 = timer();PRINT_INFOR("___timer: Step %d Loop : %.2f seconds",++stepNumber,t2-t1);t1=t2); } PRINT_MEMTRACK_STATS(__LINE__, __FILE__, __FUNCTION__); if (verbose){ elfFile.print(printCodes); TIMER(t2 = timer();PRINT_INFOR("___timer: Step %d Print : %.2f seconds",++stepNumber,t2-t1);t1=t2); } elfFile.verify(); TIMER(t2 = timer();PRINT_INFOR("___timer: Step %d Verify : %.2f seconds",++stepNumber,t2-t1);t1=t2); ElfFileInst* elfInst = NULL; if (instType == identical_inst_type){ elfFile.dump(extension); return 0; } else if (instType == function_counter_type){ elfInst = new FunctionCounter(&elfFile); } else if (instType == frequency_inst_type){ elfInst = new BasicBlockCounter(&elfFile); } else if (instType == simulation_inst_type){ elfInst = new CacheSimulation(&elfFile, inptName); } else if (instType == func_timer_type){ elfInst = new FunctionTimer(&elfFile); } else if (instType == call_wrapper_type){ if (!inputTrackList){ fprintf(stderr, "\nError: option --trk needs to be given with call wrapper inst\n"); printUsage(); } ASSERT(inputTrackList); if (!libList){ fprintf(stderr, "\nError: option --lnc needs to be given with call wrapper inst\n"); } ASSERT(libList); elfInst = new CallReplace(&elfFile, inputTrackList, libList); } else { PRINT_ERROR("Error : invalid instrumentation type"); } PRINT_MEMTRACK_STATS(__LINE__, __FILE__, __FUNCTION__); ASSERT(elfInst); ASSERT(libPath); ASSERT(extension); elfInst->setPathToInstLib(libPath); elfInst->setInstExtension(extension); if (inputFuncList){ elfInst->setInputFunctions(inputFuncList); } elfInst->phasedInstrumentation(); PRINT_MEMTRACK_STATS(__LINE__, __FILE__, __FUNCTION__); elfInst->print(Print_Code_Instrumentation); TIMER(t2 = timer();PRINT_INFOR("___timer: Instrumentation Step %d Instr : %.2f seconds",++stepNumber,t2-t1);t1=t2); if (verbose){ elfInst->print(printCodes); TIMER(t2 = timer();PRINT_INFOR("___timer: Instrumentation Step %d Print : %.2f seconds",++stepNumber,t2-t1);t1=t2); } elfInst->dump(); TIMER(t2 = timer();PRINT_INFOR("___timer: Instrumentation Step %d Dump : %.2f seconds",++stepNumber,t2-t1);t1=t2); if (verbose){ elfInst->print(printCodes); TIMER(t2 = timer();PRINT_INFOR("___timer: Instrumentation Step %d Print : %.2f seconds",++stepNumber,t2-t1);t1=t2); } // arrrrrg. i can't figure out why just deleting elfInst doesn't // call the CallReplace destructor in this case without the cast if (instType == call_wrapper_type){ delete (CallReplace*)elfInst; // delete (CallReplace*)elfInst; } else if (instType == simulation_inst_type){ delete (CacheSimulation*)elfInst; } else { delete elfInst; } if (deleteInpList){ delete[] inputFuncList; } PRINT_INFOR("******** Instrumentation Successfull ********"); TIMER(t = timer()-t;PRINT_INFOR("___timer: Total Execution Time : %.2f seconds",t););
void CallReplace::instrument(){ uint32_t temp32; uint64_t temp64; LineInfoFinder* lineInfoFinder = NULL; if (hasLineInformation()){ lineInfoFinder = getLineInfoFinder(); } InstrumentationPoint* p = addInstrumentationPoint(getProgramEntryBlock(), programEntry, InstrumentationMode_tramp, FlagsProtectionMethod_full, InstLocation_prior); ASSERT(p); if (!p->getInstBaseAddress()){ PRINT_ERROR("Cannot find an instrumentation point at the exit function"); } p = addInstrumentationPoint(getProgramExitBlock(), programExit, InstrumentationMode_tramp, FlagsProtectionMethod_full, InstLocation_prior); ASSERT(p); if (!p->getInstBaseAddress()){ PRINT_ERROR("Cannot find an instrumentation point at the exit function"); } uint64_t siteIndex = reserveDataOffset(sizeof(uint32_t)); programEntry->addArgument(siteIndex); Vector<X86Instruction*> myInstPoints; Vector<uint32_t> myInstList; Vector<LineInfo*> myLineInfos; for (uint32_t i = 0; i < getNumberOfExposedInstructions(); i++){ X86Instruction* instruction = getExposedInstruction(i); ASSERT(instruction->getContainer()->isFunction()); Function* function = (Function*)instruction->getContainer(); if (instruction->isFunctionCall()){ Symbol* functionSymbol = getElfFile()->lookupFunctionSymbol(instruction->getTargetAddress()); if (functionSymbol){ //PRINT_INFOR("looking for function %s", functionSymbol->getSymbolName()); uint32_t funcIdx = searchFileList(functionList, functionSymbol->getSymbolName()); if (funcIdx < (*functionList).size()){ BasicBlock* bb = function->getBasicBlockAtAddress(instruction->getBaseAddress()); ASSERT(bb->containsCallToRange(0,-1)); ASSERT(instruction->getSizeInBytes() == Size__uncond_jump); myInstPoints.append(instruction); myInstList.append(funcIdx); LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(bb); } myLineInfos.append(li); } } } } ASSERT(myInstPoints.size() == myInstList.size()); ASSERT(myLineInfos.size() == myInstList.size()); uint64_t fileNames = reserveDataOffset(sizeof(char*) * myInstList.size()); uint64_t lineNumbers = reserveDataOffset(sizeof(uint32_t) * myInstList.size()); for (uint32_t i = 0; i < myInstList.size(); i++){ uint32_t line = 0; char* fname = NOSTRING; if (myLineInfos[i]){ line = myLineInfos[i]->GET(lr_line); fname = myLineInfos[i]->getFileName(); } uint64_t filenameaddr = getInstDataAddress() + reserveDataOffset(strlen(fname) + 1); initializeReservedData(getInstDataAddress() + fileNames + i*sizeof(char*), sizeof(char*), &filenameaddr); initializeReservedData(filenameaddr, strlen(fname), fname); initializeReservedData(getInstDataAddress() + lineNumbers + i*sizeof(uint32_t), sizeof(uint32_t), &line); } programEntry->addArgument(fileNames); programEntry->addArgument(lineNumbers); for (uint32_t i = 0; i < myInstPoints.size(); i++){ PRINT_INFOR("(site %d) %#llx: replacing call %s -> %s in function %s", i, myInstPoints[i]->getBaseAddress(), getFunctionName(myInstList[i]), getWrapperName(myInstList[i]), myInstPoints[i]->getContainer()->getName()); InstrumentationPoint* pt = addInstrumentationPoint(myInstPoints[i], functionWrappers[myInstList[i]], InstrumentationMode_tramp, FlagsProtectionMethod_none, InstLocation_replace); if (getElfFile()->is64Bit()){ pt->addPrecursorInstruction(X86InstructionFactory64::emitMoveRegToMem(X86_REG_CX, getInstDataAddress() + getRegStorageOffset())); pt->addPrecursorInstruction(X86InstructionFactory64::emitMoveImmToReg(i, X86_REG_CX)); pt->addPrecursorInstruction(X86InstructionFactory64::emitMoveRegToMem(X86_REG_CX, getInstDataAddress() + siteIndex)); pt->addPrecursorInstruction(X86InstructionFactory64::emitMoveMemToReg(getInstDataAddress() + getRegStorageOffset(), X86_REG_CX, true)); } else { pt->addPrecursorInstruction(X86InstructionFactory32::emitMoveRegToMem(X86_REG_CX, getInstDataAddress() + getRegStorageOffset())); pt->addPrecursorInstruction(X86InstructionFactory32::emitMoveImmToReg(i, X86_REG_CX)); pt->addPrecursorInstruction(X86InstructionFactory32::emitMoveRegToMem(X86_REG_CX, getInstDataAddress() + siteIndex)); pt->addPrecursorInstruction(X86InstructionFactory32::emitMoveMemToReg(getInstDataAddress() + getRegStorageOffset(), X86_REG_CX)); } } }
void RawSection::printBytes(uint64_t offset, uint32_t bytesPerWord, uint32_t bytesPerLine){ fprintf(stdout, "\n"); PRINT_INFOR("Raw bytes for RAW section %d:", sectionIndex); printBufferPretty(charStream() + offset, getSizeInBytes(), getSectionHeader()->GET(sh_offset) + offset, bytesPerWord, bytesPerLine); }
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 SectionHeader::print() { char tmpstr[__MAX_STRING_SIZE]; PRINT_INFOR("SHeader : %d",index); PRINT_INFOR("\tSnam : %s",getSectionNamePtr() ? getSectionNamePtr() : "<none>"); if(GET(sh_type) <= SHT_DYNSYM){ PRINT_INFOR("\tStyp : %s",STypeNames[GET(sh_type)]); } else { char* ptr = "UNK"; switch(GET(sh_type)){ case SHT_INIT_ARRAY: ptr="INIT_ARRAY"; break; case SHT_FINI_ARRAY: ptr="FINI_ARRAY"; break; case SHT_PREINIT_ARRAY: ptr="PREINIT_ARRAY"; break; case SHT_GROUP: ptr="GROUP"; break; case SHT_SYMTAB_SHNDX: ptr="SYMTAB_SHNDX"; break; case SHT_NUM: ptr="NUM"; break; case SHT_LOOS: ptr="LOOS"; break; case SHT_GNU_HASH: ptr="GNU_HASH"; break; case SHT_GNU_LIBLIST: ptr="GNU_LIBLIST"; break; case SHT_CHECKSUM: ptr="CHECKSUM"; break; case SHT_LOSUNW: ptr="LOSUNW"; break; case SHT_SUNW_COMDAT: ptr="SUNW_COMDAT"; break; case SHT_SUNW_syminfo: ptr="SUNW_syminfo"; break; case SHT_GNU_verdef: ptr="GNU_verdef"; break; case SHT_GNU_verneed: ptr="GNU_verneed"; break; case SHT_GNU_versym: ptr="GNU_versym"; break; case SHT_LOPROC: ptr="LOPROC"; break; case SHT_HIPROC: ptr="HIPROC"; break; case SHT_LOUSER: ptr="LOUSER"; break; case SHT_HIUSER: ptr="HIUSER"; break; default: break; } PRINT_INFOR("\tStyp : %s",ptr); } sprintf(tmpstr,"READ"); for(uint32_t i=0;i<=10;i++){ if(GET(sh_flags) & (0x1 << i)){ strcat(tmpstr," + "); strcat(tmpstr,SFlagNames[i]); } } PRINT_INFOR("\tSflg : %s",tmpstr); PRINT_INFOR("\tSoff : @%llx with %lluB",GET(sh_offset),GET(sh_size)); if(GET(sh_addr)){ PRINT_INFOR("\tSvad : %#llx",GET(sh_addr)); } else { PRINT_INFOR("\tSvad : <no virtual address>"); } if(GET(sh_entsize)){ PRINT_INFOR("\tSent : %lldB each",GET(sh_entsize)); } else { PRINT_INFOR("\tSent : <no fixed-size entries>",GET(sh_addr)); } uint64_t alignment = GET(sh_addralign); for(uint32_t i=0;i<64;i++){ if((alignment >> i) & 0x1){ alignment = i; } } PRINT_INFOR("\talig : 2**%llu",alignment); uint32_t linkValue = GET(sh_link); uint32_t infoValue = GET(sh_info); PRINT_INFOR("\tlink: %d", linkValue); PRINT_INFOR("\tinfo: %d", infoValue); switch(GET(sh_type)){ case SHT_DYNAMIC: { sprintf(tmpstr,"string table at sect %d",linkValue); ASSERT(!infoValue); break; } case SHT_HASH: { sprintf(tmpstr,"symbol table at sect %d",linkValue); ASSERT(!infoValue); break; } case SHT_REL: case SHT_RELA: sprintf(tmpstr,"symbol table at sect %d and relocation applies to sect %d",linkValue,infoValue); break; case SHT_SYMTAB: case SHT_DYNSYM: sprintf(tmpstr,"string table at sect %d and symbol table index of last local sym %d",linkValue,infoValue-1); break; default: { if((linkValue != SHN_UNDEF) || infoValue){ sprintf(tmpstr,"unknown link %d and %d",linkValue,infoValue-1); } else { sprintf(tmpstr,"<no extra info>"); ASSERT(linkValue == SHN_UNDEF); ASSERT(!infoValue); } } } PRINT_INFOR("\tinfo : %s",tmpstr); }
void RelocationAddend64::print(char* str){ if(!str) str = ""; PRINT_INFOR("\trel%5d -- off:%#12llx stx:%5lld ad:%12lld %25s -- %s",index,GET(r_offset),ELF64_R_SYM(GET(r_info)), GET(r_addend), ELF64_R_TYPE(GET(r_info)) <= R_386_NUM ? RTypeNames[ELF64_R_TYPE(GET(r_info))] : "UNK",str); }