History

Additional debugger command (term) Add command line arguments for enabling debugger from exec

Remove tabs from all logging

arr committed 10 years ago

Commit 660681b1 parent e2f8e255 files · +190 −23Browse files

Showing the changes to src/exec/main.cpp (1 of 5 files). Show all

Unified · Split

src/exec/main.cpp+140−15
@@ -30,10 +30,14 @@ namespace · 29 unmodified lines
30 30
31 std::shared_ptr<const vm_module_t> command_module;31 std::shared_ptr<const vm_module_t> command_module;
32 32
33 std::unique_ptr<vm_module_t> create_entry_module(vm_t &vm, int argc, char* argv[])33 std::unique_ptr<vm_module_t> create_entry_module(vm_t &vm, const std::vector<char *> &vm_args)
34 {34 {
35 if (vm_args.size() == 0)
36 throw vm_user_exception{ "Entry module not supplied" };
37
35 // First argument is the module to load38 // First argument is the module to load
36 auto command_module_path = new vm_string_t{ std::strlen(argv[0]), reinterpret_cast<uint8_t *>(argv[0]) };39 auto entry_module_path = vm_args[0];
40 auto command_module_path = new vm_string_t{ std::strlen(entry_module_path), reinterpret_cast<uint8_t *>(entry_module_path) };
37 41
38 // Pre-load the command module in the VM.42 // Pre-load the command module in the VM.
39 command_module = vm.load_module(command_module_path->str());43 command_module = vm.load_module(command_module_path->str());
@@ -41,9 +45,9 @@ namespace · 1 unmodified line
41 // Convert arguments to a list45 // Convert arguments to a list
42 vm_list_t *args = nullptr;46 vm_list_t *args = nullptr;
43 vm_list_t *last = nullptr;47 vm_list_t *last = nullptr;
44 for (auto i = 1; i < argc; ++i)48 for (auto i = std::size_t{ 1 }; i < vm_args.size(); ++i)
45 {49 {
46 auto tmp = argv[i];50 auto tmp = vm_args[i];
47 auto arg = new vm_string_t{ std::strlen(tmp), reinterpret_cast<uint8_t *>(tmp) };51 auto arg = new vm_string_t{ std::strlen(tmp), reinterpret_cast<uint8_t *>(tmp) };
48 if (args == nullptr)52 if (args == nullptr)
49 {53 {
@@ -165,39 +169,160 @@ namespace · 115 unmodified lines
165 }169 }
166}170}
167 171
172struct arg_exception_t : std::runtime_error
173{
174 arg_exception_t(const char *m, const char *arg)
175 : std::runtime_error{ m }
176 , arg{ arg }
177 { }
178
179 const char * const arg;
180};
181
182struct exec_options
183{
184 std::vector<char *> vm_args;
185
186 bool print_help;
187 bool quiet_start;
188 bool enabled_debugger;
189 debugger_options debugger;
190};
191
192void print_banner(const exec_options &options)
193{
194 std::cout
195 << "DisVM\n"
196 << "----------------\n"
197 << "Debugger enabled: " << std::boolalpha << options.enabled_debugger << "\n";
198
199 if (options.enabled_debugger)
200 std::cout << options.debugger << "\n";
201
202 std::cout << std::endl;
203}
204
205void print_help()
206{
207 std::cout
208 << "Usage: disvm-exec [-d[e|m|x]*] [-q] [-?] <entry module> <args>*\n"
209 << " d - Enable debugger\n"
210 << " e - Break on entry\n"
211 << " m - Break on module load\n"
212 << " x - Break on exception (first chance)\n"
213 << " q - Suppress banner and configuration\n"
214 << " ? - Print help\n";
215}
216
217void process_arg(char* arg, std::function<char *()> next, exec_options &options)
218{
219 assert(arg != nullptr && next != nullptr);
220 if (arg[0] != '-')
221 {
222 for (; arg != nullptr; arg = next())
223 options.vm_args.push_back(arg);
224
225 return;
226 }
227
228 auto arg_len = std::strlen(arg);
229 if (arg_len < 2)
230 throw arg_exception_t{ "Invalid flag format", arg };
231
232 switch (arg[1])
233 {
234 case 'd':
235 options.enabled_debugger = true;
236 for (auto i = std::size_t{ 2 }; i < arg_len; ++i)
237 {
238 switch (arg[i])
239 {
240 case 'e': options.debugger.break_on_enter = true;
241 break;
242 case 'm': options.debugger.break_on_module_load = true;
243 break;
244 case 'x': options.debugger.break_on_exception = true;
245 break;
246 }
247 }
248
249 break;
250
251 case 'q':
252 options.quiet_start = true;
253 break;
254
255 case '?':
256 options.print_help = true;
257 break;
258
259 default:
260 throw arg_exception_t{ "Unknown flag", arg };
261 }
262}
263
168int main(int argc, char* argv[])264int main(int argc, char* argv[])
169{265{
170 // [TODO] Handle command line arguments266 exec_options options = {};
171 assert(argc > 1);267
268 try
269 {
270 // Ignore the process name
271 auto arg_idx = int{ 1 };
272 auto next_arg = [&]()
273 {
274 return arg_idx < argc ? argv[arg_idx++] : nullptr;
275 };
276
277 for (auto curr_arg = next_arg(); curr_arg != nullptr; curr_arg = next_arg())
278 process_arg(curr_arg, next_arg, options);
279 }
280 catch (const arg_exception_t &ae)
281 {
282 std::cerr << ae.what();
283 if (ae.arg != nullptr)
284 std::cerr << ": " << ae.arg << std::endl;
285
286 return EXIT_FAILURE;
287 }
288
289 if (!options.quiet_start)
290 print_banner(options);
291
292 if (options.print_help)
293 {
294 print_help();
295 return EXIT_SUCCESS;
296 }
172 297
173 vm_t vm;298 vm_t vm;
174 299
175 //vm.load_tool(std::make_shared<debugger>());300 if (options.enabled_debugger)
301 vm.load_tool(std::make_shared<debugger>(options.debugger));
176 302
177 try303 try
178 {304 {
179 // Ignore the process name305 auto entry = create_entry_module(vm, options.vm_args);
180 auto entry = create_entry_module(vm, argc - 1, argv + 1);
181 306
182 vm.exec(std::move(entry));307 vm.exec(std::move(entry));
183 308
184 vm.spin_sleep_till_idle(std::chrono::milliseconds(100));309 vm.spin_sleep_till_idle(std::chrono::milliseconds(100));
185 }310 }
186 catch (vm_user_exception &ue)311 catch (const vm_user_exception &ue)
187 {312 {
188 std::cout << ue.what() << std::endl;313 std::cerr << ue.what() << std::endl;
189 314
190 return EXIT_FAILURE;315 return EXIT_FAILURE;
191 }316 }
192 catch (vm_system_exception &se)317 catch (const vm_system_exception &se)
193 {318 {
194 std::cout319 std::cerr
195 << "Internal exception:\n\t"320 << "Internal exception:\n "
196 << se.what()321 << se.what()
197 << std::endl;322 << std::endl;
198 323
199 return EXIT_FAILURE;324 return EXIT_FAILURE;
200 }325 }
201 326
202 return 0;327 return EXIT_SUCCESS;
203}328}