Exemple #1
0
static void test_instr(Disassembler &disassembler, const char *inBuf, size_t len, const std::string &expectedOpCode, TestHarness &harness) {
  std::ostringstream out;
  std::istringstream in(std::string(inBuf, len));

  try {
    disassembler.disassemble(&in, &out);
  } catch (...) {
    harness.assertAlways(expectedOpCode);
    return;
  }

  std::string outString = out.str();

  trim_left(outString);
  trim_right(outString);
  harness.assertTrue(outString == expectedOpCode, expectedOpCode);
}
Exemple #2
0
int main(int argc, char** argv) {
	try {
		std::map<std::string, std::string> engines;
		ObjectFactory<std::string, Engine> engineFactory;

		ENGINE("groovie", "Groovie", Groovie::GroovieEngine);
		ENGINE("kyra2", "Legend of Kyrandia: Hand of Fate", Kyra::Kyra2Engine);
		ENGINE("scummv6", "SCUMM v6", Scumm::v6::Scummv6Engine);

		po::options_description visible("Options");
		visible.add_options()
			("help,h", "Produce this help message.")
			("engine,e", po::value<std::string>(), "Engine the script originates from.")
			("list,l", "List the supported engines.")
			("dump-disassembly,d", po::value<std::string>()->implicit_value(""), "Dump the disassembly to a file. Leave out filename to output to stdout.")
			("dump-graph,g", po::value<std::string>()->implicit_value(""), "Output the control flow graph in dot format to a file. Leave out filename to output to stdout.")
			("only-disassembly,D", "Stops after disassembly. Implies -d.")
			("only-graph,G", "Stops after control flow graph has been generated. Implies -g.")
			("show-unreachable,u", "Show the address and contents of unreachable groups in the script.")
			("variant,v", po::value<std::string>()->default_value(""), "Tell the engine that the script is from a specific variant. To see a list of variants supported by a specific engine, use the -h option and the -e option together.")
			("no-stack-effect,s", "Leave out the stack effect when printing raw instructions.");

		po::options_description args("");
		args.add(visible).add_options()
			("input-file", po::value<std::string>(), "Input file");

		po::positional_options_description fileArg;
		fileArg.add("input-file", -1);

		po::variables_map vm;
		try {
			// FIXME: If specified as the last parameter before the input file name, -d currently requires a filename to specified. -d must be specified earlier than that if outputting to stdout.
			po::store(po::command_line_parser(argc, argv).options(args).positional(fileArg).run(), vm);
			po::notify(vm);
		} catch (std::exception& e) {
			std::cout << e.what() << std::endl;
		}

		if (vm.count("list")) {
			std::cout << "Available engines:" << "\n";

			std::map<std::string, std::string>::iterator it;
			for (it = engines.begin(); it != engines.end(); it++)
				std::cout << (*it).first << " " << (*it).second << "\n";

			return 0;
		}

		if (vm.count("help") || !vm.count("input-file")) {
			std::cout << "Usage: " << argv[0] << " [option...] file" << "\n";
			std::cout << visible << "\n";
			if (vm.count("engine") && engines.find(vm["engine"].as<std::string>()) != engines.end()) {
				Engine *engine = engineFactory.create(vm["engine"].as<std::string>());
				std::vector<std::string> variants;
				engine->getVariants(variants);
				if (variants.empty()) {
					std::cout << engines[vm["engine"].as<std::string>()] << " does not use variants.\n";
				} else {
					std::cout << "Supported variants for " << engines[vm["engine"].as<std::string>()] << ":\n";
					for (std::vector<std::string>::iterator i = variants.begin(); i != variants.end(); ++i) {
						std::cout << "  " << *i << "\n";
					}
				}
				delete engine;
				std::cout << "\n";
			}
			std::cout << "Note: If outputting to stdout, -d or -g must NOT be specified immediately before the input file.\n";
			return 1;
		}

		if (!vm.count("engine")) {
			std::cout << "Engine must be specified.\n";
			return 2;
		} else if (engines.find(vm["engine"].as<std::string>()) == engines.end()) {
			std::cout << "Unknown engine.\n";
			return 2;
		}

		if (vm.count("no-stack-effect")) {
			setOutputStackEffect(false);
		}

		Engine *engine = engineFactory.create(vm["engine"].as<std::string>());
		engine->_variant = vm["variant"].as<std::string>();
		std::string inputFile = vm["input-file"].as<std::string>();

		// Disassembly
		InstVec insts;
		Disassembler *disassembler = engine->getDisassembler(insts);
		disassembler->open(inputFile.c_str());

		disassembler->disassemble();
		if (vm.count("dump-disassembly")) {
			std::streambuf *buf;
			std::ofstream of;

			if (vm["dump-disassembly"].as<std::string>() != "") {
				of.open(vm["dump-disassembly"].as<std::string>().c_str());
				buf = of.rdbuf();
			} else {
				buf = std::cout.rdbuf();
			}
			std::ostream out(buf);
			disassembler->dumpDisassembly(out);
		}

		if (!engine->supportsCodeFlow() || vm.count("only-disassembly") || insts.empty()) {
			if (!vm.count("dump-disassembly")) {
				disassembler->dumpDisassembly(std::cout);
			}
			delete disassembler;
			delete engine;
			return 0;
		}

		delete disassembler;

		// Control flow analysis
		ControlFlow *cf = new ControlFlow(insts, engine);
		cf->createGroups();
		Graph g = cf->analyze();

		if (vm.count("dump-graph")) {
			std::streambuf *buf;
			std::ofstream of;

			if (vm["dump-graph"].as<std::string>() != "") {
				of.open(vm["dump-graph"].as<std::string>().c_str());
				buf = of.rdbuf();
			} else {
				buf = std::cout.rdbuf();
			}
			std::ostream out(buf);
			boost::write_graphviz(out, g, boost::make_label_writer(get(boost::vertex_name, g)), boost::makeArrowheadWriter(get(boost::edge_attribute, g)), GraphProperties(engine, g));
		}

		if (!engine->supportsCodeGen() || vm.count("only-graph")) {
			if (!vm.count("dump-graph")) {
				boost::write_graphviz(std::cout, g, boost::make_label_writer(get(boost::vertex_name, g)), boost::makeArrowheadWriter(get(boost::edge_attribute, g)), GraphProperties(engine, g));
			}
			delete cf;
			delete engine;
			return 0;
		}

		// Post-processing of CFG
		engine->postCFG(insts, g);

		// Code generation
		CodeGenerator *cg = engine->getCodeGenerator(std::cout);
		cg->generate(g);

		if (vm.count("show-unreachable")) {
			std::vector<GroupPtr> unreachable;
			VertexRange vr = boost::vertices(g);
			for (VertexIterator v = vr.first; v != vr.second; ++v)
			{
				GroupPtr gr = boost::get(boost::vertex_name, g, *v);
				if (gr->_stackLevel == -1)
					unreachable.push_back(gr);
			}
			if (!unreachable.empty()) {
				for (size_t i = 0; i < unreachable.size(); i++) {
					if (i == 0) {
						if (unreachable.size() == 1)
							std::cout << boost::format("\n%d unreachable group detected.\n") % unreachable.size();
						else
							std::cout << boost::format("\n%d unreachable groups detected.\n") % unreachable.size();
					}
					std::cout << "Group " << (i + 1) << ":\n";
					ConstInstIterator inst = unreachable[i]->_start;
					do {
						std::cout << *inst;
					} while (inst++ != unreachable[i]->_end);
					std::cout << "----------\n";
				}
			}
		}

		// Free memory
		delete cf;
		delete cg;
		delete engine;
	} catch (UnknownOpcodeException &e) {
		std::cerr << "ERROR: " << e.what() << "\n";
		return 3;
	} catch (std::exception &e) {
		std::cerr << "ERROR: " << e.what() << "\n";
		return 4;
	}

	return 0;
}
Exemple #3
0
int main(int argc, char** argv)
{
    if (argc != 2 ) {
        fprintf(stderr, "Invalid input to [MIPSsim]\n");
        printf("Usage: MIPSsim [input file name]\n");
        return 1;
    }
    
//	FILE *fp = fopen(INPUTFILE, "r");
    FILE *fp =fopen(argv[1], "r");
    
	if(!fp){
        fprintf(stderr, "Can't open input file");
        return 1;
	}
    
    FILE *out_dis = fopen(OUTPUT_DIS, "w");
    
	char line[INSTRUCTION_LENGTH + 1];
	bool is_instruction = true;
	int address = INITIAL_COM_ADDR;
    char out[100];
	Disassembler disassembler;
    map<MEMORY,int> inital_mem;
    MEMORY data_addr_start = -1;
    MEMORY data_addr_end;
	
    
	while(fscanf(fp,"%s\n",&line) != -1){
        
		assert(strlen(line) == INSTRUCTION_LENGTH);
        
		if(is_instruction){
			char head[3] = {line[0],line[1]};
            
			if(strcmp(head, "01") == 0){
                disassembler.disassemble(1, address, line, out);

                fprintf(out_dis, "%s\n",out);
                //printf("%s\n", out);
				if(strcmp(line, BREAK_CODE) == 0)
					is_instruction = false;
			}
			else if (strcmp(head, "11") == 0)
            {
				disassembler.disassemble(2, address, line, out);
                //printf("%s\n", out);
                fprintf(out_dis, "%s\n",out);
            }
		}
		else {
            //printf("%s\t%d\t%d\n",line,address,disassembler.ImmediateTransform(line,INSTRUCTION_LENGTH));
            int num = disassembler.SignedImmediateTransform(line,INSTRUCTION_LENGTH);
			fprintf(out_dis,"%s\t%d\t%d\n",line,address, num);
            inital_mem[address] = num;
            
            if (data_addr_start == -1) {
                data_addr_start = address;
            }
		}
        
		address += 4;
	}
    
    data_addr_end = address - 4;

    
//    for (map<MEMORY, char*>::iterator it = disassembler.result.begin(); it != disassembler.result.end(); it++) {
//        printf("%d:%s\n", it->first, it->second);
//    }
    
	fclose(fp);
    fclose(out_dis);
    
    //simulation
    Console console(INITIAL_COM_ADDR, data_addr_start/4,data_addr_end/4, OUTPUT_SIM);
    
    map<MEMORY, int>::iterator it;
    for (it = inital_mem.begin(); it != inital_mem.end(); it++) {
        console.memory_set(it->first/4, it->second);
    }
    
    while (console.PC != FLAG_COM_ADDR) {
        console.execute(disassembler.result[console.PC]);
//        printf("%d\n", console.PC);
    }
}