diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-03-06 23:40:34 +0100 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-03-06 23:40:34 +0100 |
commit | 8d0f4806a7ad55710cb190e5a5c9388bd00c50a8 (patch) | |
tree | 16d5ac856513f44c4b1ecbccdebee151772f64e2 | |
parent | 1536045c0d28113892abc9d1023ce395a0e82e94 (diff) | |
download | qtmips-8d0f4806a7ad55710cb190e5a5c9388bd00c50a8.tar.gz qtmips-8d0f4806a7ad55710cb190e5a5c9388bd00c50a8.tar.bz2 qtmips-8d0f4806a7ad55710cb190e5a5c9388bd00c50a8.zip |
Enable configuration of syscalls emulation and stop on exception.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r-- | qtmips_gui/NewDialog.ui | 47 | ||||
-rw-r--r-- | qtmips_gui/mainwindow.cpp | 20 | ||||
-rw-r--r-- | qtmips_gui/newdialog.cpp | 32 | ||||
-rw-r--r-- | qtmips_gui/newdialog.h | 5 | ||||
-rw-r--r-- | qtmips_machine/core.cpp | 47 | ||||
-rw-r--r-- | qtmips_machine/core.h | 6 | ||||
-rw-r--r-- | qtmips_machine/machineconfig.cpp | 51 | ||||
-rw-r--r-- | qtmips_machine/machineconfig.h | 13 | ||||
-rw-r--r-- | qtmips_machine/machinedefs.h | 1 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.cpp | 33 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.h | 4 | ||||
-rw-r--r-- | qtmips_osemu/ossyscall.cpp | 30 | ||||
-rw-r--r-- | qtmips_osemu/ossyscall.h | 5 |
13 files changed, 270 insertions, 24 deletions
diff --git a/qtmips_gui/NewDialog.ui b/qtmips_gui/NewDialog.ui index 411b075..1189e21 100644 --- a/qtmips_gui/NewDialog.ui +++ b/qtmips_gui/NewDialog.ui @@ -305,9 +305,52 @@ </attribute> <layout class="QVBoxLayout" name="verticalLayout_7"> <item> - <widget class="QCheckBox" name="osemu_enablecheck"> + <widget class="QCheckBox" name="osemu_enable"> <property name="text"> - <string>Enable OS Emulation</string> + <string>Enable emulation of operating system services</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="osemu_known_syscall_stop"> + <property name="text"> + <string>Stop on known system call</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="osemu_unknown_syscall_stop"> + <property name="text"> + <string>Stop on unknown system call</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="osemu_interrupt_stop"> + <property name="text"> + <string>Stop on interrupt entry</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="osemu_exception_stop"> + <property name="text"> + <string>Stop and step over exceptions (overflow, etc.)</string> + </property> + <property name="checked"> + <bool>true</bool> </property> </widget> </item> diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index 3cefe94..d6d0b35 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -153,13 +153,21 @@ void MainWindow::create_core(const machine::MachineConfig &config) { set_speed(); // Update machine speed to current settings -#if 1 - osemu::OsSyscallExceptionHandler *osemu_handler = new osemu::OsSyscallExceptionHandler; - machine->register_exception_handler(machine::EXCAUSE_SYSCALL, osemu_handler); - connect(osemu_handler, SIGNAL(char_written(int,uint)), terminal, SLOT(tx_byte(int,uint))); - connect(osemu_handler, SIGNAL(rx_byte_pool(int,uint&,bool&)), + if (config.osemu_enable()) { + osemu::OsSyscallExceptionHandler *osemu_handler = + new osemu::OsSyscallExceptionHandler(config.osemu_known_syscall_stop(), + config.osemu_unknown_syscall_stop()); + machine->register_exception_handler(machine::EXCAUSE_SYSCALL, osemu_handler); + connect(osemu_handler, SIGNAL(char_written(int,uint)), terminal, SLOT(tx_byte(int,uint))); + connect(osemu_handler, SIGNAL(rx_byte_pool(int,uint&,bool&)), terminal, SLOT(rx_byte_pool(int,uint&,bool&))); -#endif + machine->set_step_over_exception(machine::EXCAUSE_SYSCALL, true); + machine->set_stop_on_exception(machine::EXCAUSE_SYSCALL, false); + } else { + machine->set_step_over_exception(machine::EXCAUSE_SYSCALL, false); + machine->set_stop_on_exception(machine::EXCAUSE_SYSCALL, + config.osemu_exception_stop()); + } // Connect machine signals and slots connect(ui->actionRun, SIGNAL(triggered(bool)), machine, SLOT(play())); diff --git a/qtmips_gui/newdialog.cpp b/qtmips_gui/newdialog.cpp index 3e37357..53b2a05 100644 --- a/qtmips_gui/newdialog.cpp +++ b/qtmips_gui/newdialog.cpp @@ -72,6 +72,12 @@ NewDialog::NewDialog(QWidget *parent, QSettings *settings) : QDialog(parent) { connect(ui->mem_time_write, SIGNAL(valueChanged(int)), this, SLOT(mem_time_write_change(int))); connect(ui->mem_time_burst, SIGNAL(valueChanged(int)), this, SLOT(mem_time_burst_change(int))); + connect(ui->osemu_enable, SIGNAL(clicked(bool)), this, SLOT(osemu_enable_change(bool))); + connect(ui->osemu_known_syscall_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_known_syscall_stop_change(bool))); + connect(ui->osemu_unknown_syscall_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_unknown_syscall_stop_change(bool))); + connect(ui->osemu_interrupt_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_interrupt_stop_change(bool))); + connect(ui->osemu_exception_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_exception_stop_change(bool))); + cache_handler_d = new NewDialogCacheHandler(this, ui_cache_d); cache_handler_p = new NewDialogCacheHandler(this, ui_cache_p); @@ -196,6 +202,26 @@ void NewDialog::mem_time_burst_change(int v) { } } +void NewDialog::osemu_enable_change(bool v) { + config->set_osemu_enable(v); +} + +void NewDialog::osemu_known_syscall_stop_change(bool v) { + config->set_osemu_known_syscall_stop(v); +} + +void NewDialog::osemu_unknown_syscall_stop_change(bool v) { + config->set_osemu_unknown_syscall_stop(v); +} + +void NewDialog::osemu_interrupt_stop_change(bool v) { + config->set_osemu_interrupt_stop(v); +} + +void NewDialog::osemu_exception_stop_change(bool v) { + config->set_osemu_exception_stop(v); +} + void NewDialog::config_gui() { // Basic ui->elf_file->setText(config->elf()); @@ -214,6 +240,12 @@ void NewDialog::config_gui() { // Cache cache_handler_d->config_gui(); cache_handler_p->config_gui(); + // Operating system and exceptions + ui->osemu_enable->setChecked(config->osemu_enable()); + ui->osemu_known_syscall_stop->setChecked(config->osemu_known_syscall_stop()); + ui->osemu_unknown_syscall_stop->setChecked(config->osemu_unknown_syscall_stop()); + ui->osemu_interrupt_stop->setChecked(config->osemu_interrupt_stop()); + ui->osemu_exception_stop->setChecked(config->osemu_exception_stop()); // Disable various sections according to configuration ui->delay_slot->setEnabled(!config->pipelined()); diff --git a/qtmips_gui/newdialog.h b/qtmips_gui/newdialog.h index 2b1b7c4..edd633e 100644 --- a/qtmips_gui/newdialog.h +++ b/qtmips_gui/newdialog.h @@ -70,6 +70,11 @@ private slots: void mem_time_read_change(int); void mem_time_write_change(int); void mem_time_burst_change(int); + void osemu_enable_change(bool); + void osemu_known_syscall_stop_change(bool); + void osemu_unknown_syscall_stop_change(bool); + void osemu_interrupt_stop_change(bool); + void osemu_exception_stop_change(bool); private: Ui::NewDialog *ui; diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 2b8c3bc..2d52203 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -52,6 +52,11 @@ Core::Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, this->hwr_userlocal = 0xe0000000; if (cop0state != nullptr) cop0state->setup_core(this); + for (int i = 0; i < EXCAUSE_COUNT; i++) { + stop_on_exception[i] = true; + step_over_exception[i] = true; + } + step_over_exception[EXCAUSE_INT] = false; } void Core::step(bool skip_break) { @@ -107,6 +112,22 @@ bool Core::is_hwbreak(std::uint32_t address) { return hwbrk != nullptr; } +void Core::set_stop_on_exception(enum ExceptionCause excause, bool value) { + stop_on_exception[excause] = value; +} + +bool Core::get_stop_on_exception(enum ExceptionCause excause) const { + return stop_on_exception[excause]; +} + +void Core::set_step_over_exception(enum ExceptionCause excause, bool value) { + step_over_exception[excause] = value; +} + +bool Core::get_step_over_exception(enum ExceptionCause excause) const { + return step_over_exception[excause]; +} + void Core::register_exception_handler(ExceptionCause excause, ExceptionHandler *exhandler) { if (excause == EXCAUSE_NONE ) { @@ -125,6 +146,7 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause, std::uint32_t jump_branch_pc, bool in_delay_slot, std::uint32_t mem_ref_addr) { + bool ret = false; if (excause == EXCAUSE_HWBREAK) { if (in_delay_slot) regs->pc_abs_jmp(jump_branch_pc); @@ -138,24 +160,26 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause, else cop0state->write_cop0reg(Cop0State::EPC, inst_addr); cop0state->update_execption_cause(excause, in_delay_slot); - if (cop0state->read_cop0reg(Cop0State::EBase) != 0) { - if (excause == EXCAUSE_INT) { - cop0state->set_status_exl(true); - regs->pc_abs_jmp(cop0state->exception_pc_address()); - } + if (cop0state->read_cop0reg(Cop0State::EBase) != 0 && + !get_step_over_exception(excause)) { + cop0state->set_status_exl(true); + regs->pc_abs_jmp(cop0state->exception_pc_address()); } } ExceptionHandler *exhandler = ex_handlers.value(excause); if (exhandler != nullptr) - return exhandler->handle_exception(core, regs, excause, inst_addr, + ret = exhandler->handle_exception(core, regs, excause, inst_addr, next_addr, jump_branch_pc, in_delay_slot, mem_ref_addr); - if (ex_default_handler != nullptr) - return ex_default_handler->handle_exception(core, regs, excause, inst_addr, - next_addr, jump_branch_pc, in_delay_slot, - mem_ref_addr); - return false; + else if (ex_default_handler != nullptr) + ret = ex_default_handler->handle_exception(core, regs, excause, inst_addr, + next_addr, jump_branch_pc, in_delay_slot, + mem_ref_addr); + if (get_stop_on_exception(excause)) + emit core->stop_on_exception_reached(); + + return ret; } void Core::set_c0_userlocal(std::uint32_t address) { @@ -883,6 +907,5 @@ bool StopExceptionHandler::handle_exception(Core *core, Registers *regs, (void)excause; (void)inst_addr; (void)next_addr; (void)mem_ref_addr; (void)regs; (void)jump_branch_pc; (void)in_delay_slot; #endif - emit core->stop_on_exception_reached(); return true; }; diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index d5ac4e2..52cadb4 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -86,6 +86,10 @@ public: void insert_hwbreak(std::uint32_t address); void remove_hwbreak(std::uint32_t address); bool is_hwbreak(std::uint32_t address); + void set_stop_on_exception(enum ExceptionCause excause, bool value); + bool get_stop_on_exception(enum ExceptionCause excause) const; + void set_step_over_exception(enum ExceptionCause excause, bool value); + bool get_step_over_exception(enum ExceptionCause excause) const; void set_c0_userlocal(std::uint32_t address); @@ -275,6 +279,8 @@ private: unsigned int min_cache_row_size; std::uint32_t hwr_userlocal; QMap<std::uint32_t, hwBreak *> hw_breaks; + bool stop_on_exception[EXCAUSE_COUNT]; + bool step_over_exception[EXCAUSE_COUNT]; }; class CoreSingle : public Core { diff --git a/qtmips_machine/machineconfig.cpp b/qtmips_machine/machineconfig.cpp index 4d9728d..36b376f 100644 --- a/qtmips_machine/machineconfig.cpp +++ b/qtmips_machine/machineconfig.cpp @@ -201,6 +201,11 @@ MachineConfig::MachineConfig(const MachineConfig *cc) { mem_acc_read = cc->memory_access_time_read(); mem_acc_write = cc->memory_access_time_write(); mem_acc_burst = cc->memory_access_time_burst(); + osem_enable = cc->osemu_enable(); + osem_known_syscall_stop = cc->osemu_known_syscall_stop(); + osem_unknown_syscall_stop = cc->osemu_unknown_syscall_stop(); + osem_interrupt_stop = cc->osemu_interrupt_stop(); + osem_exception_stop = cc->osemu_exception_stop(); elf_path = cc->elf(); cch_program = cc->cache_program(); cch_data = cc->cache_data(); @@ -217,6 +222,11 @@ MachineConfig::MachineConfig(const QSettings *sts, const QString &prefix) { mem_acc_read = sts->value(N("MemoryRead"), DF_MEM_ACC_READ).toUInt(); mem_acc_write = sts->value(N("MemoryWrite"), DF_MEM_ACC_WRITE).toUInt(); mem_acc_burst = sts->value(N("MemoryBurts"), DF_MEM_ACC_BURST).toUInt(); + osem_enable = sts->value(N("OsemuEnable"), true).toBool(); + osem_known_syscall_stop = sts->value(N("OsemuKnownSyscallStop"), true).toBool(); + osem_unknown_syscall_stop = sts->value(N("OsemuUnknownSyscallStop"), true).toBool(); + osem_interrupt_stop = sts->value(N("OsemuInterruptStop"), true).toBool(); + osem_exception_stop = sts->value(N("OsemuExceptionStop"), true).toBool(); elf_path = sts->value(N("Elf"), DF_ELF).toString(); cch_program = MachineConfigCache(sts, N("ProgramCache_")); cch_data = MachineConfigCache(sts, N("DataCache_")); @@ -229,6 +239,11 @@ void MachineConfig::store(QSettings *sts, const QString &prefix) { sts->setValue(N("MemoryRead"), memory_access_time_read()); sts->setValue(N("MemoryWrite"), memory_access_time_write()); sts->setValue(N("MemoryBurts"), memory_access_time_burst()); + sts->setValue(N("OsemuEnable"), osemu_enable()); + sts->setValue(N("OsemuKnownSyscallStop"), osemu_known_syscall_stop()); + sts->setValue(N("OsemuUnknownSyscallStop"), osemu_unknown_syscall_stop()); + sts->setValue(N("OsemuInterruptStop"), osemu_interrupt_stop()); + sts->setValue(N("OsemuExceptionStop"), osemu_exception_stop()); sts->setValue(N("Elf"), elf_path); cch_program.store(sts, N("ProgramCache_")); cch_data.store(sts, N("DataCache_")); @@ -296,6 +311,26 @@ void MachineConfig::set_memory_access_time_burst(unsigned v) { mem_acc_burst = v; } +void MachineConfig::set_osemu_enable(bool v) { + osem_enable = v; +} + +void MachineConfig::set_osemu_known_syscall_stop(bool v) { + osem_known_syscall_stop = v; +} + +void MachineConfig::set_osemu_unknown_syscall_stop(bool v) { + osem_unknown_syscall_stop = v; +} + +void MachineConfig::set_osemu_interrupt_stop(bool v) { + osem_interrupt_stop = v; +} + +void MachineConfig::set_osemu_exception_stop(bool v) { + osem_exception_stop = v; +} + void MachineConfig::set_elf(QString path) { elf_path = path; } @@ -342,6 +377,22 @@ unsigned MachineConfig::memory_access_time_burst() const { return mem_acc_burst; } +bool MachineConfig::osemu_enable() const { + return osem_enable; +} +bool MachineConfig::osemu_known_syscall_stop() const { + return osem_known_syscall_stop; +} +bool MachineConfig::osemu_unknown_syscall_stop() const { + return osem_unknown_syscall_stop; +} +bool MachineConfig::osemu_interrupt_stop() const { + return osem_interrupt_stop; +} +bool MachineConfig::osemu_exception_stop() const { + return osem_exception_stop; +} + QString MachineConfig::elf() const { return elf_path; } diff --git a/qtmips_machine/machineconfig.h b/qtmips_machine/machineconfig.h index 6f53d87..9fbbf18 100644 --- a/qtmips_machine/machineconfig.h +++ b/qtmips_machine/machineconfig.h @@ -127,6 +127,12 @@ public: void set_memory_access_time_read(unsigned); void set_memory_access_time_write(unsigned); void set_memory_access_time_burst(unsigned); + // Operating system and exceptions setup + void set_osemu_enable(bool); + void set_osemu_known_syscall_stop(bool); + void set_osemu_unknown_syscall_stop(bool); + void set_osemu_interrupt_stop(bool); + void set_osemu_exception_stop(bool); // Set path to source elf file. This has to be set before core is initialized. void set_elf(QString path); // Configure cache @@ -141,6 +147,11 @@ public: unsigned memory_access_time_read() const; unsigned memory_access_time_write() const; unsigned memory_access_time_burst() const; + bool osemu_enable() const; + bool osemu_known_syscall_stop() const; + bool osemu_unknown_syscall_stop() const; + bool osemu_interrupt_stop() const; + bool osemu_exception_stop() const; QString elf() const; const MachineConfigCache &cache_program() const; const MachineConfigCache &cache_data() const; @@ -156,6 +167,8 @@ private: enum HazardUnit hunit; bool exec_protect, write_protect; unsigned mem_acc_read, mem_acc_write, mem_acc_burst; + bool osem_enable, osem_known_syscall_stop, osem_unknown_syscall_stop; + bool osem_interrupt_stop, osem_exception_stop; QString elf_path; MachineConfigCache cch_program, cch_data; }; diff --git a/qtmips_machine/machinedefs.h b/qtmips_machine/machinedefs.h index 8ccc81c..d8219b6 100644 --- a/qtmips_machine/machinedefs.h +++ b/qtmips_machine/machinedefs.h @@ -69,6 +69,7 @@ enum ExceptionCause { EXCAUSE_OVERFLOW = 12, EXCAUSE_TRAP = 13, EXCAUSE_HWBREAK = 14, + EXCAUSE_COUNT = 15, }; enum AluOp : std::uint8_t { diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index afcae54..c8b072b 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -95,6 +95,17 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc, bool load_symtab) : run_t = new QTimer(this); set_speed(0); // In default run as fast as possible connect(run_t, SIGNAL(timeout()), this, SLOT(step_timer())); + + for (int i = 0; i < EXCAUSE_COUNT; i++) { + if (i != EXCAUSE_INT && i != EXCAUSE_BREAK && i != EXCAUSE_HWBREAK) { + + } + set_stop_on_exception((enum ExceptionCause)i, cc.osemu_exception_stop()); + set_step_over_exception((enum ExceptionCause)i, cc.osemu_exception_stop()); + } + + set_stop_on_exception(EXCAUSE_INT, cc.osemu_interrupt_stop()); + set_step_over_exception(EXCAUSE_INT, false); } QtMipsMachine::~QtMipsMachine() { @@ -300,3 +311,25 @@ bool QtMipsMachine::is_hwbreak(std::uint32_t address) { return cr->is_hwbreak(address); return false; } + +void QtMipsMachine::set_stop_on_exception(enum ExceptionCause excause, bool value) { + if (cr != nullptr) + cr->set_stop_on_exception(excause, value); +} + +bool QtMipsMachine::get_stop_on_exception(enum ExceptionCause excause) const { + if (cr != nullptr) + return cr->get_stop_on_exception(excause); + return false; +} + +void QtMipsMachine::set_step_over_exception(enum ExceptionCause excause, bool value) { + if (cr != nullptr) + cr->set_step_over_exception(excause, value); +} + +bool QtMipsMachine::get_step_over_exception(enum ExceptionCause excause) const { + if (cr != nullptr) + return cr->get_step_over_exception(excause); + return false; +} diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index 349e0df..b90b96e 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -93,6 +93,10 @@ public: void insert_hwbreak(std::uint32_t address); void remove_hwbreak(std::uint32_t address); bool is_hwbreak(std::uint32_t address); + void set_stop_on_exception(enum ExceptionCause excause, bool value); + bool get_stop_on_exception(enum ExceptionCause excause) const; + void set_step_over_exception(enum ExceptionCause excause, bool value); + bool get_step_over_exception(enum ExceptionCause excause) const; public slots: void play(); diff --git a/qtmips_osemu/ossyscall.cpp b/qtmips_osemu/ossyscall.cpp index aeee079..fed4548 100644 --- a/qtmips_osemu/ossyscall.cpp +++ b/qtmips_osemu/ossyscall.cpp @@ -60,7 +60,7 @@ struct mips_syscall_desc_t { &OsSyscallExceptionHandler::handler}, static const mips_syscall_desc_t mips_syscall_args[] = { MIPS_SYS(sys_syscall , 8, syscall_default_handler) /* 4000 */ - MIPS_SYS(sys_exit , 1, syscall_default_handler) + MIPS_SYS(sys_exit , 1, do_sys_exit) MIPS_SYS(sys_fork , 0, syscall_default_handler) MIPS_SYS(sys_read , 3, do_sys_read) MIPS_SYS(sys_write , 3, do_sys_write) @@ -427,10 +427,13 @@ static const mips_syscall_desc_t mips_syscall_args[] = { const unsigned mips_syscall_args_size = sizeof(mips_syscall_args)/sizeof(*mips_syscall_args); -OsSyscallExceptionHandler::OsSyscallExceptionHandler() { +OsSyscallExceptionHandler::OsSyscallExceptionHandler(bool known_syscall_stop, + bool unknown_syscall_stop) { brk_limit = 0; anonymous_base = 0x60000000; anonymous_last = anonymous_base; + this->known_syscall_stop = known_syscall_stop; + this->unknown_syscall_stop = unknown_syscall_stop; } bool OsSyscallExceptionHandler::handle_exception(Core *core, Registers *regs, @@ -496,7 +499,8 @@ bool OsSyscallExceptionHandler::handle_exception(Core *core, Registers *regs, #endif status = (this->*sdesc->handler)(result, core, syscall_num, a1, a2, a3, a4, a5, a6, a7, a8); - emit core->stop_on_exception_reached(); + if (known_syscall_stop) + emit core->stop_on_exception_reached(); regs->write_gp(7, status); if (status < 0) @@ -524,6 +528,26 @@ int OsSyscallExceptionHandler::syscall_default_handler(std::uint32_t &result, Co (void)core; (void)syscall_num; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8; result = 0; + if (unknown_syscall_stop) + emit core->stop_on_exception_reached(); + return 0; +} + +// void exit(int status); +int OsSyscallExceptionHandler::do_sys_exit(std::uint32_t &result, Core *core, + std::uint32_t syscall_num, + std::uint32_t a1, std::uint32_t a2, std::uint32_t a3, + std::uint32_t a4, std::uint32_t a5, std::uint32_t a6, + std::uint32_t a7, std::uint32_t a8) { + (void)core; (void)syscall_num; + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8; + + result = 0; + int status = a1; + + printf("sys_exit status %d\n", status); + emit core->stop_on_exception_reached(); + return 0; } diff --git a/qtmips_osemu/ossyscall.h b/qtmips_osemu/ossyscall.h index 0c02699..bcb202f 100644 --- a/qtmips_osemu/ossyscall.h +++ b/qtmips_osemu/ossyscall.h @@ -57,12 +57,13 @@ int name(std::uint32_t &result, machine::Core *core, \ class OsSyscallExceptionHandler : public machine::ExceptionHandler { Q_OBJECT public: - OsSyscallExceptionHandler(); + OsSyscallExceptionHandler(bool known_syscall_stop = false, bool unknown_syscall_stop = false); bool handle_exception(machine::Core *core, machine::Registers *regs, machine::ExceptionCause excause, std::uint32_t inst_addr, std::uint32_t next_addr, std::uint32_t jump_branch_pc, bool in_delay_slot, std::uint32_t mem_ref_addr); OSSYCALL_HANDLER_DECLARE(syscall_default_handler); + OSSYCALL_HANDLER_DECLARE(do_sys_exit); OSSYCALL_HANDLER_DECLARE(do_sys_set_thread_area); OSSYCALL_HANDLER_DECLARE(do_sys_writev); OSSYCALL_HANDLER_DECLARE(do_sys_write); @@ -77,6 +78,8 @@ private: std::uint32_t brk_limit; std::uint32_t anonymous_base; std::uint32_t anonymous_last; + bool known_syscall_stop; + bool unknown_syscall_stop; }; #undef OSSYCALL_HANDLER_DECLARE |