void BreakpointListView::updateBreakpoint(DebuggerBreakpoint* bp) { BreakpointListViewItem* item = findBreakpoint(bp); if(item) { item->setBreakpoint(bp); } }
void BreakpointListView::toggleBreakpoint(const QString& filePath, int line) { BreakpointListViewItem* item = findBreakpoint(filePath, line); if(item) { removeBreakpoint(item->breakpoint()); } else { addBreakpoint(filePath, line); } }
void BreakpointListView::slotBreakpointUnmarked(QString filePath, int line) { //note: TextEditor lines are 0 based BreakpointListViewItem* item = findBreakpoint(filePath, line+1); if(item) { takeItem(item); } emit sigBreakpointRemoved(item->breakpoint()); delete item; }
void BreakpointListView::removeBreakpoint(DebuggerBreakpoint* bp) { BreakpointListViewItem* item = findBreakpoint(bp); if(item) { takeItem(item); } emit sigBreakpointRemoved(bp); delete item; }
void BreakpointListView::toggleBreakpoint(const KURL& url, int line, bool enabled) { BreakpointListViewItem* item = findBreakpoint(url, line); if(item) { removeBreakpoint(item->breakpoint()); } else { addBreakpoint(url, line, enabled); } }
// fixBreakpoint is going to clean up the mess we made in breakpoint(). // What we are cleaning up is determined by step: // // Step = 0: We will restore our OpCode and do nothing else! This will // prove useful if we ever implement the ability to disable a breakpoint. // This also allows us to use whereAmI() without having to guess if we // are after INT 3 or at a valid instruction. // // Step = 1 we will be single stepping and then resetting the break. void fixBreakpoint(unsigned int step){ if(!step){ unsigned long breakIndex = findBreakpoint(AFTER_BREAKPOINT); unsigned long breakAddress = breakpoints[breakIndex][0]; unsigned long opCode = breakpoints[breakIndex][1]; int i = 0; ptrace(PTRACE_POKETEXT,child,breakAddress,opCode); // And now it is restored struct user_regs_struct regs; ptrace(PTRACE_GETREGS,child,NULL,®s); --regs.eip; ptrace(PTRACE_SETREGS,child,NULL,®s); } else{ unsigned long breakIndex = findBreakpoint(AT_BREAKPOINT); if(ptrace(PTRACE_SINGLESTEP,child,NULL,NULL) != 0) printf("ptrace error\n"); // Execute this one instruction wait(&status); unsigned long opCode = (breakpoints[breakIndex][1] & ~0xFF) | 0xCC; unsigned long address = breakpoints[breakIndex][0]; ptrace(PTRACE_POKETEXT,child,address,opCode); // And now it is reset } }
void ScriptMachine::executeThread(SCMThread &t, int msPassed) { if( t.wakeCounter > 0 ) { t.wakeCounter = std::max( t.wakeCounter - msPassed, 0 ); } if( t.wakeCounter > 0 ) return; bool hasDebugging = !! bpHandler; while( t.wakeCounter == 0 ) { auto pc = t.programCounter; auto opcode = _file->read<SCMOpcode>(pc); bool isNegatedConditional = ((opcode & SCM_NEGATE_CONDITIONAL_MASK) == SCM_NEGATE_CONDITIONAL_MASK); opcode = opcode & ~SCM_NEGATE_CONDITIONAL_MASK; ScriptFunctionMeta* foundcode; if( ! _ops->findOpcode(opcode, &foundcode) ) { throw IllegalInstruction(opcode, pc, t.name); } ScriptFunctionMeta& code = *foundcode; pc += sizeof(SCMOpcode); SCMParams parameters; bool hasExtraParameters = code.arguments < 0; auto requiredParams = std::abs(code.arguments); for( int p = 0; p < requiredParams || hasExtraParameters; ++p ) { auto type_r = _file->read<SCMByte>(pc); auto type = static_cast<SCMType>(type_r); if( type_r > 42 ) { // for implicit strings, we need the byte we just read. type = TString; } else { pc += sizeof(SCMByte); } parameters.push_back(SCMOpcodeParameter { type, { 0 } }); switch(type) { case EndOfArgList: hasExtraParameters = false; break; case TInt8: parameters.back().integer = _file->read<std::uint8_t>(pc); pc += sizeof(SCMByte); break; case TInt16: parameters.back().integer = _file->read<std::int16_t>(pc); pc += sizeof(SCMByte) * 2; break; case TGlobal: { auto v = _file->read<std::uint16_t>(pc); parameters.back().globalPtr = globalData.data() + v; //* SCM_VARIABLE_SIZE; if( v >= _file->getGlobalsSize() ) { state->world->logger->error("SCM", "Global Out of bounds! "+ std::to_string(v) + " " + std::to_string(_file->getGlobalsSize())); } pc += sizeof(SCMByte) * 2; } break; case TLocal: { auto v = _file->read<std::uint16_t>(pc); parameters.back().globalPtr = t.locals.data() + v * SCM_VARIABLE_SIZE; if( v >= SCM_THREAD_LOCAL_SIZE ) { state->world->logger->error("SCM", "Local Out of bounds!"); } pc += sizeof(SCMByte) * 2; } break; case TInt32: parameters.back().integer = _file->read<std::uint32_t>(pc); pc += sizeof(SCMByte) * 4; break; case TString: std::copy(_file->data()+pc, _file->data()+pc+8, parameters.back().string); pc += sizeof(SCMByte) * 8; break; case TFloat16: parameters.back().real = _file->read<std::int16_t>(pc) / 16.f; pc += sizeof(SCMByte) * 2; break; default: throw UnknownType(type, pc, t.name); break; }; } ScriptArguments sca(¶meters, &t, this); if( hasDebugging ) { auto activeBreakpoint = findBreakpoint(t, pc); if( activeBreakpoint || interupt ) { interupt = false; SCMBreakpoint bp; bp.pc = t.programCounter; bp.thread = &t; bp.vm = this; bp.function = &code; bp.args = &sca; bpHandler(bp); } } #if RW_SCRIPT_DEBUG if (strcmp(t.name, "EIGHT") == 0) { printf("% 8s %04x %04x % 25s", t.name, t.programCounter, opcode, code.signature.c_str()); for (auto& a : sca.getParameters()) { printf(" %08x", a.integerValue()); } printf("\n"); } #endif // After debugging has been completed, update the program counter t.programCounter = pc; if(code.function) { code.function(sca); } if(isNegatedConditional) { t.conditionResult = !t.conditionResult; } // Handle conditional results for IF statements. if( t.conditionCount > 0 && opcode != 0x00D6 ) /// @todo add conditional flag to opcodes instead of checking for 0x00D6 { --t.conditionCount; if ( t.conditionAND ) { if ( t.conditionResult == false ) { t.conditionMask = 0; } else { // t.conditionMask is already set to 0xFF by the if and opcode. } } else { t.conditionMask = t.conditionMask || t.conditionResult; } t.conditionResult = (t.conditionMask != 0); } } SCMOpcodeParameter p; p.globalPtr = (t.locals.data() + 16 * sizeof ( SCMByte ) * 4); *p.globalInteger += msPassed; p.globalPtr = (t.locals.data() + 17 * sizeof ( SCMByte ) * 4); *p.globalInteger += msPassed; if( t.wakeCounter == -1 ) { t.wakeCounter = 0; } }
void debugger(){ int hasStarted = 0; int hasContinued = 0; while(1){ //wait for a signal wait(&status); //if the program exited, just return if (WIFEXITED( status )){ printf("\nthe program terminated\n"); return; } // Quick overview of what's going on here: // **Variable 'done': Done will keep us within this while loop. If it is // set to 1 that means we issued the "continue" command. // // **Variable 'hasContinued': In the event that we stop at a breakpoint // and issue a command other than "continue", we will end up calling // fixBreakpoint a second time. hasContinued will tell the loop // to pump the breaks, we haven't moved on yet! int done = 0; while(!done){ //get user input, what should we do? if((breakpointCount > 0) && hasStarted && hasContinued){ printf("breakpoint %d hit\n",findBreakpoint(AFTER_BREAKPOINT)); fixBreakpoint(0); // Restore our opcode and registers hasContinued = 0; } user_command * cmd = debugger_interface_get_cmd(); if (cmd){ //now handle the input switch(cmd->command_type){ case CMD_TYPE_BREAKPOINT: if(breakpoint(cmd->value.line_number)){ printf("Could not set breakpoint at line %d.\n",cmd->value.line_number); } break; case CMD_TYPE_STACKTRACE: stacktrace(); break; case CMD_TYPE_PRINT: printVariable(cmd->value.var.format,cmd->value.var.name,0); break; case CMD_TYPE_PRINT_GEN: printVariable(cmd->value.var.format,cmd->value.var.name,1); break; case CMD_TYPE_CONTINUE: if(!hasStarted){ // If we are here, that means we are just starting to run the // program, so nothing special. hasStarted = 1; } else{ // However, if we are here that means we were "interuptted" // by a break. We fixed the breakpoint and altered our registers // At the beginning of the parent while loop, so now we want // to use SINGLE_STEP and then reset the breakpoint that we just // fixed. fixBreakpoint(1); } done = 1; hasContinued = 1; break; case CMD_TYPE_WHERE: whereAmI(); break; } } } ptrace( PTRACE_CONT, child, NULL, NULL ); } }