void UVDFlirtutilFixture::verifyDump(const std::string &sigFileNameIn, const std::string &expectedDumpFileNameIn) { std::string tempFile; std::string unitTestDir; //std::string outputPatFileName = getTempFileName(); std::string output; std::string expectedOutput; std::string inputFileName; std::string expectedOutputFileName; unitTestDir = getUnitTestDir(); inputFileName = unitTestDir + "/flirt/ELF/" + sigFileNameIn; expectedOutputFileName = unitTestDir + "/flirt/ELF/" + expectedDumpFileNameIn; m_args.clear(); init(); UVCPPUNIT_ASSERT(m_flirt->dumpSigFile(inputFileName)); deinit(); //FIXME: we aren't verifying right now... //we need a way to capture the output //probably by changing the dump API printf_warn("FIXME: no dump verify support\n"); }
uv_err_t UVDPluginEngine::activatePluginByName(const std::string &name) { std::map<std::string, UVDPlugin *>::iterator iter = m_plugins.find(name); UVDPlugin *plugin = NULL; printf_plugin_debug("initializing plugin %s\n", name.c_str()); if( iter == m_plugins.end() ) { printf_error("no plugin loaded named %s\n", name.c_str()); return UV_DEBUG(UV_ERR_GENERAL); } if( m_loadedPlugins.find(name) != m_loadedPlugins.end() ) { printf_warn("skipping double load of plugin %s\n", name.c_str()); return UV_DEBUG(UV_ERR_WARNING); } plugin = (*iter).second; uv_assert_ret(plugin); /* Initialize dependencies TODO: check for circular refs */ std::vector<UVDPlugin *> dependencies; uv_assert_err_ret(getAllPluginDependencies(name, dependencies)); //std::string pluginName; for( std::vector<UVDPlugin *>::iterator iter = dependencies.begin(); iter != dependencies.end(); ++iter ) { //std::string dependentPluginName = *iter; UVDPlugin *dependentPlugin = *iter; uv_assert_err_ret(ensurePluginActiveByName(dependentPlugin->getName())); } uv_assert_err_ret(plugin->init(g_config)); m_loadedPlugins[name] = plugin; //Notify callbacks for( std::set<OnPluginActivatedItem>::iterator iter = m_onPluginActivated.begin(); iter != m_onPluginActivated.end(); ++iter ) { OnPluginActivated callback = (*iter).first; void *user = (*iter).second; if( !callback ) { printf_error("bad callback\n"); continue; } //Ready to roll UV_DEBUG(callback(plugin, user)); } return UV_ERR_OK; }
/* TODO: branch to sub tables */ void UVDDisasmOpcodeLookupTable::usageStats(void) { int i = 0; int used = 0; int unused = 0; for( i = 0; i < 256; ++i ) { if( m_lookupTable[i] ) { ++used; } else { printf_warn("opcode 0x%.2X is non-encoding\n", i); ++unused; } } printf_debug("Used opcodes: %d, unused opcodes: %d\n", used, unused); }
uv_err_t UVD::analyzeControlFlowTrace() { printf_debug_level(UVD_DEBUG_PASSES, "control flow analysis trace / recursive descent\n"); //For now only try to find where code is, so it doesn't matter how we arrived std::set<uint32_t> openSet; std::set<uint32_t> closedSet; //Probably need full ranges, do only start for now std::set<uint32_t> calls; std::set<uint32_t> jumps; //uv_addr_t numberAnalyzedBytes = 0; uv_assert_ret(m_runtime->m_architecture); uv_assert_ret(m_config); //uv_assert_err_ret(m_analyzer->getNumberAnalyzedBytes(&numberAnalyzedBytes)); //Another way to do with would be to do "START" and then all other vectors for( std::vector<UVDCPUVector *>::iterator iter = m_runtime->m_architecture->m_vectors.begin(); iter != m_runtime->m_architecture->m_vectors.end(); ++iter ) { UVDCPUVector *vector = *iter; uv_assert_ret(vector); openSet.insert(vector->m_offset); } UVDInstructionIterator end; uv_assert_err_ret(instructionEnd(end)); while( !openSet.empty() ) { uint32_t nextStartAddress = *openSet.begin(); UVDInstructionIterator iter; int isVectorValid = 0; openSet.erase(openSet.begin()); //Did we already try to process it? if( closedSet.find(nextStartAddress) != closedSet.end() ) { continue; } closedSet.insert(nextStartAddress); //Make sure it seems reasonable uv_assert_err_ret(suspectValidInstruction(nextStartAddress, &isVectorValid)); { if( !isVectorValid ) printf_warn("ignoring address: 0x%08X\n", nextStartAddress); continue; } //Keep going until we hit a branch point //uint32_t printPercentage = 1; //uint32_t printNext = printPercentage; uv_assert_err_ret(instructionBeginByAddress(nextStartAddress, iter)); for( ;; ) { UVDInstructionAnalysis instructionAnalysis; //std::string action; //uint32_t startPos = iter.getPosition(); //uint32_t endPos = 0; /* if( numberAnalyzedBytes ) { uint32_t curPercent = 100 * startPos / numberAnalyzedBytes; if( curPercent >= printNext ) { printf_debug_level(UVD_DEBUG_SUMMARY, "uvd: raw control structure analysis: %d %%\n", curPercent); printNext += printPercentage; } } */ UVDInstruction *instruction = NULL; //printf_debug("\n\nAnalysis at: 0x%.8X\n", startPos); //XXX is this really correct? what if we jumped towards the end //should be more of a continue if( iter == end ) { printf_debug("disassemble: end"); break; } uv_assert_err_ret(iter.get(&instruction)); //endPos = iter.getPosition(); //action = instruction.m_shared->m_action; //printf_debug("Next instruction (start: 0x%.8X, end: 0x%.8X): %s\n", startPos, endPos, instruction.m_shared->m_memoric.c_str()); //printf_debug("Action: %s, type: %d\n", action.c_str(), instruction.m_shared->m_inst_class); uv_assert_err_ret(instruction->analyzeControlFlow(&instructionAnalysis)); //Only care about resolved targets if( instructionAnalysis.m_isJump == UVD_TRI_TRUE || instructionAnalysis.m_isCall == UVD_TRI_TRUE ) { openSet.insert(nextStartAddress); } //Unconditional jumps mean end of sweep //TODO: also consider adding something for noreturn type functions? //rare on embedded platforms? if( instructionAnalysis.m_isJump == UVD_TRI_TRUE && !instructionAnalysis.m_isConditional ) { //Straight JMP style instruction break; } //If we aren't at end, there should be more data uv_assert_err_ret(iter.next()); } } return UV_DEBUG(UV_ERR_GENERAL); }
uv_err_t UVD::analyzeControlFlowLinear() { /* Linear flow anlaysis constructs functions in a greedy manner: A function is defined as all of the code between one function entry and the next function entry Each time a function is found we will add it and it will take up the remaining data, spliting as necessary */ UVDInstructionIterator iter; UVDInstructionIterator iterEnd; //uint32_t printPercentage = 1; //uint32_t printNext = printPercentage; //uv_addr_t numberAnalyzedBytes = 0; uv_addr_t startPosition = 0; printf_debug_level(UVD_DEBUG_PASSES, "control flow analysis linear\n"); //Need at least one start location uv_assert_ret(!m_runtime->m_architecture->m_vectors.empty()); //FIXME: take the lowest vector startPosition = m_runtime->m_architecture->m_vectors[0]->m_offset; if( m_runtime->m_architecture->m_vectors.size() != 1 ) { printf_warn("%d vectors, only sweeping from 0x%08X, consider using recursive descent or specify start\n", m_runtime->m_architecture->m_vectors.size(), startPosition); } uv_assert_err_ret(instructionBegin(iter)); uv_assert_err_ret(instructionEnd(iterEnd)); uv_assert_err_ret(iterEnd.check()); uv_assert_ret(m_config); //FIXME: iterator rework //uv_assert_err_ret(iter.m_address.m_space->getNumberAnalyzedBytes(&numberAnalyzedBytes)); for( ;; ) { UVDAddress startPos; uv_assert_err_ret(iter.getAddress(&startPos)); UVDInstruction *instruction = NULL; //printf("analysis: ITERATING\n"); uv_assert_err_ret(iter.check()); if( iter == iterEnd ) { printf_debug("disassemble: end"); break; } uv_assert_err_ret(iter.get(&instruction)); if( instruction ) { //printf("\n\nAnalysis at: 0x%.8X\n", startPos); uv_assert_err_ret(instruction->analyzeControlFlow()); } //If we aren't at end, there should be more data uv_assert_err_ret(iter.next()); } return UV_ERR_OK; }
void NokiaComposer(int argc UNUSED, char *argv[]) { GSM_Error error; GSM_Ringtone ringtone; gboolean started; int i,j; GSM_RingNote *Note; GSM_RingNoteDuration Duration; GSM_RingNoteDuration DefNoteDuration = 32; /* 32 = Duration_1_4 */ unsigned int DefNoteScale = Scale_880; ringtone.Format = 0; error=GSM_ReadRingtoneFile(argv[2],&ringtone); Print_Error(error); if (ringtone.Format != RING_NOTETONE) { printf("%s\n", _("It can be RTTL ringtone only used with this option")); Terminate(2); } started = FALSE; j = 0; for (i=0;i<ringtone.NoteTone.NrCommands;i++) { if (ringtone.NoteTone.Commands[i].Type == RING_Note) { Note = &ringtone.NoteTone.Commands[i].Note; if (!started) { if (Note->Note != Note_Pause) { printf(_("Ringtone \"%s\" (tempo = %i Beats Per Minute)"),DecodeUnicodeConsole(ringtone.Name),GSM_RTTLGetTempo(Note->Tempo)); printf("\n\n"); started = TRUE; } } if (started) j++; } } if (j>50) { printf_warn(_("length=%i notes, but you will enter only first 50 tones."), j); } printf("\n\n%s ", _("This ringtone in Nokia Composer in phone should look:")); started = FALSE; for (i=0;i<ringtone.NoteTone.NrCommands;i++) { if (ringtone.NoteTone.Commands[i].Type == RING_Note) { Note = &ringtone.NoteTone.Commands[i].Note; if (!started) { if (Note->Note != Note_Pause) started = TRUE; } if (started) { switch (Note->Duration) { case Duration_Full: printf("1"); break; case Duration_1_2 : printf("2"); break; case Duration_1_4 : printf("4"); break; case Duration_1_8 : printf("8"); break; case Duration_1_16: printf("16");break; case Duration_1_32: printf("32");break; } if (Note->DurationSpec == DottedNote) printf("."); switch (Note->Note) { case Note_C : printf("c"); break; case Note_Cis : printf("#c"); break; case Note_D :printf("d"); break; case Note_Dis : printf("#d"); break; case Note_E : printf("e"); break; case Note_F : printf("f"); break; case Note_Fis : printf("#f"); break; case Note_G : printf("g"); break; case Note_Gis : printf("#g"); break; case Note_A : printf("a"); break; case Note_Ais : printf("#a"); break; case Note_H : printf("h"); break; case Note_Pause : printf("-"); break; } if (Note->Note != Note_Pause) printf("%i",Note->Scale - 4); printf(" "); } } } printf("\n\n%s ", _("To enter it please press:")); started = FALSE; for (i=0;i<ringtone.NoteTone.NrCommands;i++) { if (ringtone.NoteTone.Commands[i].Type == RING_Note) { Note = &ringtone.NoteTone.Commands[i].Note; if (!started) { if (Note->Note != Note_Pause) started = TRUE; } if (started) { switch (Note->Note) { case Note_C : case Note_Cis: printf("1");break; case Note_D : case Note_Dis: printf("2");break; case Note_E : printf("3");break; case Note_F : case Note_Fis: printf("4");break; case Note_G : case Note_Gis: printf("5");break; case Note_A : case Note_Ais: printf("6");break; case Note_H : printf("7");break; default : printf("0");break; } if (Note->DurationSpec == DottedNote) printf("%s", _("(longer)")); switch (Note->Note) { case Note_Cis: case Note_Dis: case Note_Fis: case Note_Gis: case Note_Ais: printf("#"); break; default : break; } if (Note->Note != Note_Pause) { if ((unsigned int)Note->Scale != DefNoteScale) { while (DefNoteScale != (unsigned int)Note->Scale) { printf("*"); DefNoteScale++; if (DefNoteScale==Scale_7040) DefNoteScale = Scale_880; } } } Duration = 0; switch (Note->Duration) { case Duration_Full : Duration = 128; break; case Duration_1_2 : Duration = 64; break; case Duration_1_4 : Duration = 32; break; case Duration_1_8 : Duration = 16; break; case Duration_1_16 : Duration = 8; break; case Duration_1_32 : Duration = 4; break; default : fprintf(stderr, "error\n");break; } if (Duration > DefNoteDuration) { while (DefNoteDuration != Duration) { printf("9"); DefNoteDuration = DefNoteDuration * 2; } } if (Duration < DefNoteDuration) { while (DefNoteDuration != Duration) { printf("8"); DefNoteDuration = DefNoteDuration / 2; } } printf(" "); } } } printf("\n"); fflush(stdout); }
uv_err_t uvmain(int argc, char **argv) { uv_err_t rc = UV_ERR_GENERAL; UVDConfig *config = NULL; UVDFLIRTConfig *flirtConfig = NULL; uv_err_t parseMainRc = UV_ERR_GENERAL; if( strcmp(GetVersion(), UVDGetVersion()) ) { printf_warn("libuvudec version mismatch (exe: %s, libuvudec: %s)\n", GetVersion(), UVDGetVersion()); fflush(stdout); } //Early library initialization. Logging and arg parsing structures uv_assert_err_ret(UVDInit()); config = g_config; uv_assert_ret(config); //Early local initialization uv_assert_err_ret(initProgConfig()); //Grab our command line options parseMainRc = config->parseMain(argc, argv); uv_assert_err_ret(parseMainRc); if( parseMainRc == UV_ERR_DONE ) { rc = UV_ERR_OK; goto error; } //Create a doConvertr engine active on that input printf_debug_level(UVD_DEBUG_SUMMARY, "doConvert: initializing FLIRT engine...\n"); if( UV_FAILED(UVDFLIRT::getFLIRT(&g_flirt)) ) { printf_error("Failed to initialize FLIRT engine\n"); rc = UV_ERR_OK; goto error; } uv_assert_ret(g_flirt); flirtConfig = g_UVDFLIRTConfig; uv_assert_ret(flirtConfig); //Source .pat files if( flirtConfig->m_targetFiles.empty() ) { printf_error("Target file(s) not specified\n"); config->printHelp(); uv_assert_err(UV_ERR_GENERAL); } if( UV_FAILED(doConvert()) ) { printf_error("Top level doConvert failed\n"); uv_assert(UV_ERR_GENERAL); } rc = UV_ERR_OK; error: uv_assert_err_ret(UVDDeinit()); return UV_DEBUG(rc); }
//int init_count = 0; uv_err_t UVD::init(UVDObject *object, UVDArchitecture *architecture) { UVDBenchmark engineInitBenchmark; if( !m_config->m_argv ) { printf_warn("initializing UVD without parsing main\n"); } uv_assert_err(initEarly()); printf_debug_level(UVD_DEBUG_PASSES, "UVD::init(): initializing runtime...\n"); //We might want to make this more dynamic just in case m_runtime = new UVDRuntime(); uv_assert(m_runtime); uv_assert_err(m_runtime->init(object, architecture)); printf_debug_level(UVD_DEBUG_PASSES, "UVD::init(): initializing engine...\n"); engineInitBenchmark.start(); uv_assert(m_config); m_config->m_verbose = m_config->m_verbose_init; /* m_CPU = new UVDCPU(); uv_assert(m_CPU); uv_assert_err(m_CPU->init()); */ m_analyzer = new UVDAnalyzer(); uv_assert(m_analyzer); uv_assert_err(m_analyzer->init(this)); m_format = new UVDFormat(); uv_assert(m_format); m_eventEngine = new UVDEventEngine(); uv_assert(m_eventEngine); uv_assert_err(m_eventEngine->init()); /* Read file This is raw dat, NOT null terminated string */ uv_assert_err(m_config->m_plugin.m_pluginEngine.onUVDInit()); printFormatting(); printf_debug("UVD: init OK!\n\n\n"); m_config->m_verbose = m_config->m_verbose_processing; engineInitBenchmark.stop(); printf_debug_level(UVD_DEBUG_PASSES, "engine init time: %s\n", engineInitBenchmark.toString().c_str()); //printf("Address spaces: %d\n", m_runtime->m_addressSpaces.m_addressSpaces.size()); return UV_ERR_OK; error: //If we fail, we do not own its subobjects if( m_runtime ) { m_runtime->m_object = NULL; m_runtime->m_architecture = NULL; delete m_runtime; m_runtime = NULL; } return UV_DEBUG(UV_ERR_GENERAL); }
uv_err_t UVD::initArchitecture(UVDObject *object, const UVDRuntimeHints &hints, UVDArchitecture **out) { //FIXME: replace this with a config based selection //Must be able to feed into plugins //This should be a switch instead //m_architecture->m_architecture = architecture; UVDArchitecture *architecture = NULL; std::vector<UVDPlugin *> best; uvd_priority_t bestPriority = UVD_MATCH_NONE; printf_debug_level(UVD_DEBUG_PASSES, "UVD::initArchitecture()...\n"); for( std::map<std::string, UVDPlugin *>::iterator iter = m_pluginEngine->m_loadedPlugins.begin(); iter != m_pluginEngine->m_loadedPlugins.end(); ++iter ) { UVDPlugin *plugin = (*iter).second; uv_err_t rcTemp = UV_ERR_GENERAL; uvd_priority_t loadPriority = 0; uv_assert_ret(plugin); rcTemp = plugin->canGetArchitecture(object, hints, &loadPriority); if( UV_FAILED(rcTemp) ) { printf_plugin_debug("plugin %s failed to canLoad architecture\n", (*iter).first.c_str()); continue; } printf_plugin_debug("plugin %s returned from canLoad architecture with priority 0x%08X\n", (*iter).first.c_str(), loadPriority); if( loadPriority <= bestPriority ) { if( loadPriority < bestPriority ) { best.clear(); bestPriority = loadPriority; } best.push_back(plugin); } } printf_plugin_debug("best priorty: 0x%08X, plugins: %d\n", bestPriority, best.size()); if( bestPriority == UVD_MATCH_NONE ) { printf_warn("could not find a suitable architecture loader\n"); return UV_ERR_NOTFOUND; } uv_assert_ret(!best.empty()); //Iterate over all plugins until one accepts our input for( std::vector<UVDPlugin *>::iterator iter = best.begin(); iter != best.end(); ++iter ) { UVDPlugin *plugin = *iter; uv_err_t rcTemp = UV_ERR_GENERAL; uv_assert_ret(plugin); rcTemp = plugin->getArchitecture(object, hints, &architecture); if( UV_FAILED(rcTemp) ) { printf_error("plugin %s failed to load architecture\n", plugin->getName().c_str()); continue; } else if( !architecture ) { printf_error("plugin %s claimed successed but didn't set architecture\n", plugin->getName().c_str()); continue; } else { printf_debug_level(UVD_DEBUG_PASSES, "loaded architecture from plugin %s\n", plugin->getName().c_str()); break; } } if( !architecture ) { printf_error("could not find a suitable architecture loader\n"); return UV_ERR_NOTFOUND; } uv_assert_err_ret(architecture->doInit()); uv_assert_err_ret(architecture->fixupDefaults()); uv_assert_ret(out); *out = architecture; return UV_ERR_OK; }
uv_err_t UVD::initObject(UVDData *data, const UVDRuntimeHints &hints, UVDObject **out) { //FIXME: replace this with a config based selection //Must be able to feed into plugins //This should be a switch instead //m_architecture->m_architecture = architecture; UVDObject *object = NULL; std::vector<UVDPlugin *> best; uvd_priority_t bestPriority = UVD_MATCH_NONE; printf_debug_level(UVD_DEBUG_PASSES, "UVD::initObject()...\n"); UVD_POKE(data); //Iterate over all plugins until one accepts our input uv_assert_ret(m_pluginEngine); for( std::map<std::string, UVDPlugin *>::iterator iter = m_pluginEngine->m_loadedPlugins.begin(); iter != m_pluginEngine->m_loadedPlugins.end(); ++iter ) { UVDPlugin *plugin = (*iter).second; uv_err_t rcTemp = UV_ERR_GENERAL; uvd_priority_t loadPriority = 0; uv_assert_ret(plugin); printf_plugin_debug("plugin %s trying canLoad object\n", (*iter).first.c_str()); rcTemp = plugin->canLoadObject(data, hints, &loadPriority); if( UV_FAILED(rcTemp) ) { printf_plugin_debug("plugin %s failed to canLoad object\n", (*iter).first.c_str()); continue; } if( loadPriority <= bestPriority ) { printf_plugin_debug("plugin %s candidate at priority 0x%08X\n", (*iter).first.c_str(), loadPriority); if( loadPriority < bestPriority ) { if( !best.empty() ) { printf_plugin_debug("clearing %d plugins due to better priorty\n", best.size()); } best.clear(); bestPriority = loadPriority; } best.push_back(plugin); } else { printf_plugin_debug("plugin %s skipped due to worse priority (cur: %d, plugin: %d)\n", (*iter).first.c_str(), bestPriority, loadPriority); } } UVD_POKE(data); printf_plugin_debug("best priorty: 0x%08X, plugins: %d\n", bestPriority, best.size()); if( bestPriority == UVD_MATCH_NONE ) { printf_warn("could not find a suitable object loader\n"); return UV_ERR_NOTFOUND; } uv_assert_ret(!best.empty()); //Iterate over all plugins until one accepts our input uv_assert_ret(m_pluginEngine); for( std::vector<UVDPlugin *>::iterator iter = best.begin(); iter != best.end(); ++iter ) { UVDPlugin *plugin = *iter; uv_err_t rcTemp = UV_ERR_GENERAL; uv_assert_ret(plugin); rcTemp = plugin->loadObject(data, hints, &object); if( UV_FAILED(rcTemp) ) { printf_error("plugin %s failed to load object\n", plugin->getName().c_str()); continue; } else if( !object ) { printf_error("plugin %s claimed successed but didn't set object\n", plugin->getName().c_str()); continue; } else { printf_debug_level(UVD_DEBUG_PASSES, "loaded object from plugin %s (%p)\n", plugin->getName().c_str(), object); break; } } if( !object ) { printf_error("could not find a suitable object module\n"); return UV_ERR_GENERAL; } //Its probably better to let the object take care of this //For example, if init fails, we can try another candidate //uv_assert_err_ret(object->init(data)); uv_assert_ret(out); *out = object; return UV_ERR_OK; }
uv_err_t UVDPluginEngine::loadByDir(const std::string &pluginDir, UVDConfig *config, bool recursive, bool failOnError, bool failOnPluginError) { //boost throws exceptions //TODO: move to UVD friendly adapter interface try { for( boost::filesystem::directory_iterator iter(pluginDir); iter != boost::filesystem::directory_iterator(); ++iter ) { //Not necessarily canonical std::string path; uv_err_t loadByPathRc = UV_ERR_GENERAL; path = pluginDir + "/" + iter->path().filename(); if( is_directory(iter->status()) ) { if( recursive ) { uv_assert_err_ret(loadByDir(path, config, recursive, failOnError, failOnPluginError)); } continue; } //Try loading it, ignoring errors since it might just be a plugin config file or something //We should print a warning if loadByPathRc = loadByPath(path, false); if( UV_FAILED(loadByPathRc) ) { if( loadByPathRc == UV_ERR_NOTSUPPORTED ) { if( failOnError ) { printf_error("failed to load possible plugin: %s\n", path.c_str()); return UV_DEBUG(UV_ERR_GENERAL); } else { printf_plugin_debug("failed to load possible plugin: %s\n", path.c_str()); } } else { if( failOnError || failOnPluginError ) { printf_error("failed to load plugin: %s\n", path.c_str()); return UV_DEBUG(UV_ERR_GENERAL); } else { printf_warn("failed to load plugin: %s\n", path.c_str()); } } } } return UV_ERR_OK; } catch(...) { if( !config->m_suppressErrors ) { printf_error("failed to load plugin dir %s\n", pluginDir.c_str()); } if( config->m_ignoreErrors ) { return UV_DEBUG(UV_ERR_WARNING); } else { return UV_DEBUG(UV_ERR_GENERAL); } } }