56c37fd214bc6707a137be4c33af9d4e3ac4d060
[calu.git] / 3c_disasm / CInstrFactory.cpp
1 /*
2  * Name:     CInstrFactory
3  * Author:   Martin Perner, 0725782, 535
4  * E-Mail:   e0725782@student.tuwien.ac.at
5  * Purpose:  Factory for creating Instruction from shared libraries
6  * Date:     29.04.2009
7  */
8
9 #include "CInstrFactory.hpp"
10
11 using namespace std;
12
13 /**
14  * Name:    loadFromLib
15  * Purpose: loads a command from the given library file
16
17  * Parameter: std::string lib  location of the library file
18
19  * Preconditions:  lib references to a valid library
20  */
21 Iinstr* CInstrFactory::loadFromLib(string lib)
22 {
23         Iinstr* (*create_instruction)();
24
25         // load a Instruction from library
26         void* instruction = dlopen(lib.c_str(), RTLD_LAZY);
27         if (!instruction) {
28                 cerr << "Cannot load library: " << dlerror() << endl;
29                 exit(EXIT_FAILURE);
30         }
31
32         // load the symbols
33         void* create = dlsym(instruction, "create_instruction");
34         void* destroy = dlsym(instruction, "destroy_instruction");
35
36         if (!create || !destroy) {
37                 cerr << "Cannot load symbols: " << dlerror() << endl;
38                 dlclose(instruction);
39                 exit(EXIT_FAILURE);
40         }
41
42         memcpy(&create_instruction, &create, sizeof(create)); 
43
44         Iinstr* instructionPointer = create_instruction();
45
46         m_libStore.insert(make_pair(instruction, instructionPointer));
47
48         return instructionPointer;
49 }
50
51 /**
52  * Name:    getNextInstruction
53  * Purpose: returns a pointer to a command
54
55  * Returns: Pointer to the loaded command
56
57  * Throw:  string
58  * Preconditions:  a command is left to load
59  */
60 Iinstr* CInstrFactory::getNextInstr()
61 {
62         if(m_files.size() >= 1) {
63                 Iinstr* instruction;
64                 instruction = loadFromLib(m_files[0]);
65                 m_files.erase(m_files.begin());
66                 return instruction;
67         }
68         else {
69                 throw string("No more instruction left!");
70         }
71 }
72
73
74 /**
75  * Name:    searchLibsInDir
76  * Purpose: finds librarys in the given directory
77
78  * Returns: number of found librarays
79
80  * Parameters: std::string dir  Directory where the libraries are located
81  * Throw:  string
82  * Postconditions: all files with a trailing '.so' are ready to be used
83  */
84 size_t CInstrFactory::searchLibsInDir(string dir)
85 {
86         DIR *dp;
87
88         if((dp  = opendir(dir.c_str())) == NULL) {
89                 stringstream errmsg;
90                 errmsg << "Error(" << errno << ") opening " << dir << endl;
91                 throw errmsg.str();
92         }
93         struct dirent *dirp;
94         while ((dirp = readdir(dp)) != NULL) {
95                 string file = dirp->d_name;
96                 if(file.size() >= 3) {
97                         file = file.substr(file.size()-3);
98                         std::transform(file.begin(), file.end(), file.begin(), ::tolower);
99                         if(file == ".so") {
100                                 m_files.push_back(dir+"/"+string(dirp->d_name));
101                         }
102                 }
103         }
104         closedir(dp);
105         return m_files.size();
106 }
107
108 /**
109  * Name:    getNumFiles
110  * Purpose: returns the number of librarys left
111
112  * Returns: size_t number of files left
113  */
114 size_t CInstrFactory::getNumFiles()
115 {
116         return m_files.size();
117 }
118
119 void CInstrFactory::loadLibsIntoMap(map<short, Iinstr*>& instr, string dir)
120 {
121 #ifdef DEBUG
122                 cout << "Loaded " << this->searchLibsInDir(dir) << " Libraryfiles" << endl;
123 #else
124                 this->searchLibsInDir(dir);
125 #endif
126                 while(this->getNumFiles() >= 1) {
127                         Iinstr* pinstr = this->getNextInstr();
128                         instr.insert(make_pair(pinstr->getOpcode(),pinstr));
129 #ifdef DEBUG
130                         cout << "found: " << pinstr->getName() << " its opcode is : " << pinstr->getOpcode() << endl;
131 #endif
132                 }
133 }
134
135
136 /**
137  * Name:    ~CInstrFactory
138  * Purpose: Destructor of the Object
139  */
140 CInstrFactory::~CInstrFactory()
141 {
142         void (*destroy_instruction)(Iinstr*);
143
144         while(!m_libStore.empty()) {
145                 void* destroy = dlsym(m_libStore.begin()->first, "destroy_instruction");
146                 memcpy(&destroy_instruction, &destroy, sizeof(destroy)); 
147                 destroy_instruction(m_libStore.begin()->second);
148                 dlclose(m_libStore.begin()->first);
149                 m_libStore.erase(m_libStore.begin());
150         }
151 }