/* * Name: CInstrFactory * Author: Martin Perner, 0725782, 535 * E-Mail: e0725782@student.tuwien.ac.at * Purpose: Factory for creating Instruction from shared libraries * Date: 29.04.2009 */ #include "CInstrFactory.hpp" using namespace std; /** * Name: loadFromLib * Purpose: loads a command from the given library file * Parameter: std::string lib location of the library file * Preconditions: lib references to a valid library */ Iinstr* CInstrFactory::loadFromLib(string lib) { Iinstr* (*create_instruction)(); // load a Instruction from library void* instruction = dlopen(lib.c_str(), RTLD_LAZY); if (!instruction) { cerr << "Cannot load library: " << dlerror() << endl; exit(EXIT_FAILURE); } // load the symbols void* create = dlsym(instruction, "create_instruction"); void* destroy = dlsym(instruction, "destroy_instruction"); if (!create || !destroy) { cerr << "Cannot load symbols: " << dlerror() << endl; dlclose(instruction); exit(EXIT_FAILURE); } memcpy(&create_instruction, &create, sizeof(create)); Iinstr* instructionPointer = create_instruction(); m_libStore.insert(make_pair(instruction, instructionPointer)); return instructionPointer; } /** * Name: getNextInstruction * Purpose: returns a pointer to a command * Returns: Pointer to the loaded command * Throw: string * Preconditions: a command is left to load */ Iinstr* CInstrFactory::getNextInstr() { if(m_files.size() >= 1) { Iinstr* instruction; instruction = loadFromLib(m_files[0]); m_files.erase(m_files.begin()); return instruction; } else { throw string("No more instruction left!"); } } /** * Name: searchLibsInDir * Purpose: finds librarys in the given directory * Returns: number of found librarays * Parameters: std::string dir Directory where the libraries are located * Throw: string * Postconditions: all files with a trailing '.so' are ready to be used */ size_t CInstrFactory::searchLibsInDir(string dir) { DIR *dp; if((dp = opendir(dir.c_str())) == NULL) { stringstream errmsg; errmsg << "Error(" << errno << ") opening " << dir << endl; throw errmsg.str(); } struct dirent *dirp; while ((dirp = readdir(dp)) != NULL) { string file = dirp->d_name; if(file.size() >= 3) { file = file.substr(file.size()-3); std::transform(file.begin(), file.end(), file.begin(), ::tolower); if(file == ".so") { m_files.push_back(dir+"/"+string(dirp->d_name)); } } } closedir(dp); return m_files.size(); } /** * Name: getNumFiles * Purpose: returns the number of librarys left * Returns: size_t number of files left */ size_t CInstrFactory::getNumFiles() { return m_files.size(); } void CInstrFactory::loadLibsIntoMap(map& instr, string dir) { #ifdef DEBUG cout << "Loaded " << this->searchLibsInDir(dir) << " Libraryfiles" << endl; #else this->searchLibsInDir(dir); #endif while(this->getNumFiles() >= 1) { Iinstr* pinstr = this->getNextInstr(); instr.insert(make_pair(pinstr->getOpcode(),pinstr)); #ifdef DEBUG cout << "found: " << pinstr->getName() << " its opcode is : " << pinstr->getOpcode() << endl; #endif } } /** * Name: ~CInstrFactory * Purpose: Destructor of the Object */ CInstrFactory::~CInstrFactory() { void (*destroy_instruction)(Iinstr*); while(!m_libStore.empty()) { void* destroy = dlsym(m_libStore.begin()->first, "destroy_instruction"); memcpy(&destroy_instruction, &destroy, sizeof(destroy)); destroy_instruction(m_libStore.begin()->second); dlclose(m_libStore.begin()->first); m_libStore.erase(m_libStore.begin()); } }