static void enter_debugger(void) { sUseUHCI = has_debugger_command("uhci_process_transfer"); sUseOHCI = has_debugger_command("ohci_process_transfer"); sUseEHCI = has_debugger_command("ehci_process_transfer"); sUseXHCI = has_debugger_command("xhci_process_transfer"); if (!has_debugger_command("get_usb_keyboard_config") || !has_debugger_command("get_usb_pipe_for_id") || (!sUseUHCI && !sUseOHCI && !sUseEHCI && !sUseXHCI)) { return; } unset_debug_variable("_usbPipe"); unset_debug_variable("_usbReportSize"); evaluate_debug_command("get_usb_keyboard_config"); sUSBTransferLength = get_debug_variable("_usbReportSize", 0); if (sUSBTransferLength == 0 || sUSBTransferLength > sizeof(sUSBTransferData)) return; evaluate_debug_command("get_usb_pipe_for_id"); sUSBPipe = (void *)get_debug_variable("_usbPipe", 0); if (sUSBPipe == NULL) return; sUseUSBKeyboard = true; }
uint64 ExpressionParser::_ParseCommandPipe(int& returnCode) { debugger_command_pipe* pipe = (debugger_command_pipe*)checked_malloc( sizeof(debugger_command_pipe)); pipe->segment_count = 0; pipe->broken = false; do { if (pipe->segment_count >= MAX_DEBUGGER_COMMAND_PIPE_LENGTH) parse_exception("Pipe too long", fTokenizer.NextToken().position); debugger_command_pipe_segment& segment = pipe->segments[pipe->segment_count]; segment.index = pipe->segment_count++; _ParseCommand(segment); } while (fTokenizer.NextToken().type == TOKEN_PIPE); fTokenizer.RewindToken(); // invoke the pipe returnCode = invoke_debugger_command_pipe(pipe); debug_free(pipe); return get_debug_variable("_", 0); }
uint64 ExpressionParser::_ParseAtom() { const Token& token = fTokenizer.NextToken(); if (token.type == TOKEN_END_OF_LINE) parse_exception("unexpected end of expression", token.position); if (token.type == TOKEN_CONSTANT) return token.value; if (token.type == TOKEN_IDENTIFIER) { if (!is_debug_variable_defined(token.string)) { snprintf(sTempBuffer, sizeof(sTempBuffer), "variable '%s' undefined", token.string); parse_exception(sTempBuffer, token.position); } return get_debug_variable(token.string, 0); } if (token.type == TOKEN_OPENING_PARENTHESIS) { uint64 value = _ParseExpression(); _EatToken(TOKEN_CLOSING_PARENTHESIS); return value; } // it can only be a "[ command ]" expression now fTokenizer.RewindToken(); _EatToken(TOKEN_OPENING_BRACKET); fTokenizer.SetCommandMode(true); int returnValue; uint64 value = _ParseCommandPipe(returnValue); fTokenizer.SetCommandMode(false); _EatToken(TOKEN_CLOSING_BRACKET); return value; }
static int debug_get_pipe_for_id(int argc, char **argv) { if (gUSBStack == NULL) return 1; if (!is_debug_variable_defined("_usbPipeID")) return 2; uint64 id = get_debug_variable("_usbPipeID", 0); Object *object = gUSBStack->GetObjectNoLock((usb_id)id); if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) return 3; // check if we support debug transfers for this pipe (only on UHCI for now) if (object->GetBusManager()->TypeName()[0] != 'u') return 4; set_debug_variable("_usbPipe", (uint64)object); return 0; }
uint64 ExpressionParser::_ParseExpression(bool expectAssignment) { const Token& token = fTokenizer.NextToken(); int32 position = token.position; if (token.type == TOKEN_IDENTIFIER) { char variable[MAX_DEBUG_VARIABLE_NAME_LEN]; strlcpy(variable, token.string, sizeof(variable)); int32 assignmentType = fTokenizer.NextToken().type; if (assignmentType & TOKEN_ASSIGN_FLAG) { // an assignment uint64 rhs = _ParseExpression(); // handle the standard assignment separately -- the other kinds // need the variable to be defined if (assignmentType == TOKEN_ASSIGN) { if (!set_debug_variable(variable, rhs)) { snprintf(sTempBuffer, sizeof(sTempBuffer), "failed to set value for variable \"%s\"", variable); parse_exception(sTempBuffer, position); } return rhs; } // variable must be defined if (!is_debug_variable_defined(variable)) { snprintf(sTempBuffer, sizeof(sTempBuffer), "variable \"%s\" not defined in modifying assignment", variable); parse_exception(sTempBuffer, position); } uint64 variableValue = get_debug_variable(variable, 0); // check for division by zero for the respective assignment types if ((assignmentType == TOKEN_SLASH_ASSIGN || assignmentType == TOKEN_MODULO_ASSIGN) && rhs == 0) { parse_exception("division by zero", position); } // compute the new variable value switch (assignmentType) { case TOKEN_PLUS_ASSIGN: variableValue += rhs; break; case TOKEN_MINUS_ASSIGN: variableValue -= rhs; break; case TOKEN_STAR_ASSIGN: variableValue *= rhs; break; case TOKEN_SLASH_ASSIGN: variableValue /= rhs; break; case TOKEN_MODULO_ASSIGN: variableValue %= rhs; break; default: parse_exception("internal error: unknown assignment token", position); break; } set_debug_variable(variable, variableValue); return variableValue; } } else if (token.type == TOKEN_STAR) { void* address; uint32 size; uint64 value = _ParseDereference(&address, &size); int32 assignmentType = fTokenizer.NextToken().type; if (assignmentType & TOKEN_ASSIGN_FLAG) { // an assignment uint64 rhs = _ParseExpression(); // check for division by zero for the respective assignment types if ((assignmentType == TOKEN_SLASH_ASSIGN || assignmentType == TOKEN_MODULO_ASSIGN) && rhs == 0) { parse_exception("division by zero", position); } // compute the new value switch (assignmentType) { case TOKEN_ASSIGN: value = rhs; break; case TOKEN_PLUS_ASSIGN: value += rhs; break; case TOKEN_MINUS_ASSIGN: value -= rhs; break; case TOKEN_STAR_ASSIGN: value *= rhs; break; case TOKEN_SLASH_ASSIGN: value /= rhs; break; case TOKEN_MODULO_ASSIGN: value %= rhs; break; default: parse_exception("internal error: unknown assignment token", position); break; } // convert the value for writing to the address uint64 buffer = 0; switch (size) { case 1: *(uint8*)&buffer = value; break; case 2: *(uint16*)&buffer = value; break; case 4: *(uint32*)&buffer = value; break; case 8: value = buffer; break; } if (debug_memcpy(B_CURRENT_TEAM, address, &buffer, size) != B_OK) { snprintf(sTempBuffer, sizeof(sTempBuffer), "failed to write to address %p", address); parse_exception(sTempBuffer, position); } return value; } } if (expectAssignment) { parse_exception("expected assignment", fTokenizer.CurrentToken().position); } // no assignment -- reset to the identifier position and parse a sum fTokenizer.SetPosition(position); return _ParseSum(false, 0); }