mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-30 20:35:03 +01:00
vm86 mode. MFC r304085 (by bde): Fix the variables $esp, $ds, $es, $fs, $gs and $ss in vm86 mode. Fix PC_REGS() so that printing of instructions works in some useful cases. MFC r304962 (by bde): Expand error messages: print symbol names, parentheses and shift tokens, and negative shift counts. Fix error messages. MFC r305612 (by bde): Fix single-stepping of instructions emulated by vm86. MFC r305661 (by bde): Give the full syntax of the 'count' arg for all commmands that support it. Give the full syntax of the 'addr' arg for these commands and some others. Rename it from 'address' for the generic command. Fix description of how 'count' is supposed to work for the 'break' command. Don't (mis)describe the syntax of the comma for the 'step' command. Expand the description for the generic command. Give the full syntax for the 'examine' command. It was also missing the possible values for the modifier. MFC r305663 (by bde): Fix stopping when the specified breakpoint count is reached. MFC r305665 (by bde): Pass the trap type and code down from db_trap() to db_stop_at_pc() so that the latter can easily determine what the trap type actually is after callers are fixed to encode the type unambigously. MFC r305807 (by bde): Use the MI macro TRAPF_USERMODE() instead of open-coded checks for SEL_UPL and sometimes PSL_VM. Fix logic errors in treating vm86 bioscall mode as kernel mode. The main place checked all the necessary flags, but put the necessary parentheses for the PSL_VM and PCB_VM86CALL checks in the wrong place. MFC r305811 (by bz): Try to fix LINT builds after r305807. MFC r305840 (by bde): Abort single stepping in ddb if the trap is not for single-stepping. MFC r305862 (by bde): Ifdef the new dr6 variable for KDB. MFC r305864 (by bde): Statically initialize the run mode to the one that will become current on first entry. Don't reset to the run mode to STEP_NONE when stopping, and remove STEP_NONE. MFC r305865 (by bde): Fix decoding of tf_rsp on amd64, and move TF_HAS_STACKREGS() to the i386-only section, and fix a comment about the amd64 kernel trapframe not having stackregs. MFC r305897 (by bde): Silently ignore unexpected single-step traps. MFC r306311 (by bde): Determine the operand/address size of %cs in a new function db_segsize(). Use db_segsize() to set the default operand/address size for disassembling. Fix db_print_loc_and_inst() to ask for the normal format and not the alternate in normal operation. Use db_segsize() to avoid trying to print a garbage stack trace if %cs is 16 bits.
378 lines
7.8 KiB
C
378 lines
7.8 KiB
C
/*-
|
|
* Mach Operating System
|
|
* Copyright (c) 1991,1990 Carnegie Mellon University
|
|
* All Rights Reserved.
|
|
*
|
|
* Permission to use, copy, modify and distribute this software and its
|
|
* documentation is hereby granted, provided that both the copyright
|
|
* notice and this permission notice appear in all copies of the
|
|
* software, derivative works or modified versions, and any portions
|
|
* thereof, and that both notices appear in supporting documentation.
|
|
*
|
|
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
|
|
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
|
|
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
|
*
|
|
* Carnegie Mellon requests users of this software to return to
|
|
*
|
|
* Software Distribution Coordinator or [email protected]
|
|
* School of Computer Science
|
|
* Carnegie Mellon University
|
|
* Pittsburgh PA 15213-3890
|
|
*
|
|
* any improvements or extensions that they make and grant Carnegie the
|
|
* rights to redistribute these changes.
|
|
*/
|
|
/*
|
|
* Author: David B. Golub, Carnegie Mellon University
|
|
* Date: 7/90
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <ddb/ddb.h>
|
|
#include <ddb/db_lex.h>
|
|
#include <ddb/db_access.h>
|
|
#include <ddb/db_command.h>
|
|
|
|
static bool db_add_expr(db_expr_t *valuep);
|
|
static bool db_mult_expr(db_expr_t *valuep);
|
|
static bool db_shift_expr(db_expr_t *valuep);
|
|
static bool db_term(db_expr_t *valuep);
|
|
static bool db_unary(db_expr_t *valuep);
|
|
static bool db_logical_or_expr(db_expr_t *valuep);
|
|
static bool db_logical_and_expr(db_expr_t *valuep);
|
|
static bool db_logical_relation_expr(db_expr_t *valuep);
|
|
|
|
static bool
|
|
db_term(db_expr_t *valuep)
|
|
{
|
|
int t;
|
|
|
|
t = db_read_token();
|
|
if (t == tIDENT) {
|
|
if (!db_value_of_name(db_tok_string, valuep) &&
|
|
!db_value_of_name_pcpu(db_tok_string, valuep) &&
|
|
!db_value_of_name_vnet(db_tok_string, valuep)) {
|
|
db_printf("Symbol '%s' not found\n", db_tok_string);
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
return (true);
|
|
}
|
|
if (t == tNUMBER) {
|
|
*valuep = (db_expr_t)db_tok_number;
|
|
return (true);
|
|
}
|
|
if (t == tDOT) {
|
|
*valuep = (db_expr_t)db_dot;
|
|
return (true);
|
|
}
|
|
if (t == tDOTDOT) {
|
|
*valuep = (db_expr_t)db_prev;
|
|
return (true);
|
|
}
|
|
if (t == tPLUS) {
|
|
*valuep = (db_expr_t) db_next;
|
|
return (true);
|
|
}
|
|
if (t == tDITTO) {
|
|
*valuep = (db_expr_t)db_last_addr;
|
|
return (true);
|
|
}
|
|
if (t == tDOLLAR) {
|
|
if (!db_get_variable(valuep))
|
|
return (false);
|
|
return (true);
|
|
}
|
|
if (t == tLPAREN) {
|
|
if (!db_expression(valuep)) {
|
|
db_printf("Expression syntax error after '%c'\n", '(');
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
t = db_read_token();
|
|
if (t != tRPAREN) {
|
|
db_printf("Expression syntax error -- expected '%c'\n", ')');
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
return (true);
|
|
}
|
|
db_unread_token(t);
|
|
return (false);
|
|
}
|
|
|
|
static bool
|
|
db_unary(db_expr_t *valuep)
|
|
{
|
|
int t;
|
|
|
|
t = db_read_token();
|
|
if (t == tMINUS) {
|
|
if (!db_unary(valuep)) {
|
|
db_printf("Expression syntax error after '%c'\n", '-');
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
*valuep = -*valuep;
|
|
return (true);
|
|
}
|
|
if (t == tEXCL) {
|
|
if(!db_unary(valuep)) {
|
|
db_printf("Expression syntax error after '%c'\n", '!');
|
|
db_error(NULL);
|
|
/* NOTREACHED */
|
|
}
|
|
*valuep = (!(*valuep));
|
|
return (true);
|
|
}
|
|
if (t == tBIT_NOT) {
|
|
if(!db_unary(valuep)) {
|
|
db_printf("Expression syntax error after '%c'\n", '~');
|
|
db_error(NULL);
|
|
/* NOTREACHED */
|
|
}
|
|
*valuep = (~(*valuep));
|
|
return (true);
|
|
}
|
|
if (t == tSTAR) {
|
|
/* indirection */
|
|
if (!db_unary(valuep)) {
|
|
db_printf("Expression syntax error after '%c'\n", '*');
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
*valuep = db_get_value((db_addr_t)*valuep, sizeof(void *),
|
|
false);
|
|
return (true);
|
|
}
|
|
db_unread_token(t);
|
|
return (db_term(valuep));
|
|
}
|
|
|
|
static bool
|
|
db_mult_expr(db_expr_t *valuep)
|
|
{
|
|
db_expr_t lhs, rhs;
|
|
int t;
|
|
|
|
if (!db_unary(&lhs))
|
|
return (false);
|
|
|
|
t = db_read_token();
|
|
while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH ||
|
|
t == tBIT_AND ) {
|
|
if (!db_term(&rhs)) {
|
|
db_printf("Expression syntax error after '%c'\n",
|
|
t == tSTAR ? '*' : t == tSLASH ? '/' : t == tPCT ? '%' :
|
|
t == tHASH ? '#' : '&');
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
switch(t) {
|
|
case tSTAR:
|
|
lhs *= rhs;
|
|
break;
|
|
case tBIT_AND:
|
|
lhs &= rhs;
|
|
break;
|
|
default:
|
|
if (rhs == 0) {
|
|
db_error("Division by 0\n");
|
|
/*NOTREACHED*/
|
|
}
|
|
if (t == tSLASH)
|
|
lhs /= rhs;
|
|
else if (t == tPCT)
|
|
lhs %= rhs;
|
|
else
|
|
lhs = roundup(lhs, rhs);
|
|
}
|
|
t = db_read_token();
|
|
}
|
|
db_unread_token(t);
|
|
*valuep = lhs;
|
|
return (true);
|
|
}
|
|
|
|
static bool
|
|
db_add_expr(db_expr_t *valuep)
|
|
{
|
|
db_expr_t lhs, rhs;
|
|
int t;
|
|
|
|
if (!db_mult_expr(&lhs))
|
|
return (false);
|
|
|
|
t = db_read_token();
|
|
while (t == tPLUS || t == tMINUS || t == tBIT_OR) {
|
|
if (!db_mult_expr(&rhs)) {
|
|
db_printf("Expression syntax error after '%c'\n",
|
|
t == tPLUS ? '+' : t == tMINUS ? '-' : '|');
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
switch (t) {
|
|
case tPLUS:
|
|
lhs += rhs;
|
|
break;
|
|
case tMINUS:
|
|
lhs -= rhs;
|
|
break;
|
|
case tBIT_OR:
|
|
lhs |= rhs;
|
|
break;
|
|
default:
|
|
__unreachable();
|
|
}
|
|
t = db_read_token();
|
|
}
|
|
db_unread_token(t);
|
|
*valuep = lhs;
|
|
return (true);
|
|
}
|
|
|
|
static bool
|
|
db_shift_expr(db_expr_t *valuep)
|
|
{
|
|
db_expr_t lhs, rhs;
|
|
int t;
|
|
|
|
if (!db_add_expr(&lhs))
|
|
return (false);
|
|
t = db_read_token();
|
|
while (t == tSHIFT_L || t == tSHIFT_R) {
|
|
if (!db_add_expr(&rhs)) {
|
|
db_printf("Expression syntax error after '%s'\n",
|
|
t == tSHIFT_L ? "<<" : ">>");
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
if (rhs < 0) {
|
|
db_printf("Negative shift amount %jd\n", (intmax_t)rhs);
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
if (t == tSHIFT_L)
|
|
lhs <<= rhs;
|
|
else {
|
|
/* Shift right is unsigned */
|
|
lhs = (unsigned) lhs >> rhs;
|
|
}
|
|
t = db_read_token();
|
|
}
|
|
db_unread_token(t);
|
|
*valuep = lhs;
|
|
return (true);
|
|
}
|
|
|
|
static bool
|
|
db_logical_relation_expr(
|
|
db_expr_t *valuep)
|
|
{
|
|
db_expr_t lhs, rhs;
|
|
int t;
|
|
|
|
if (!db_shift_expr(&lhs))
|
|
return (false);
|
|
|
|
t = db_read_token();
|
|
while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER ||
|
|
t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) {
|
|
if (!db_shift_expr(&rhs)) {
|
|
db_printf("Expression syntax error after '%s'\n",
|
|
t == tLOG_EQ ? "==" : t == tLOG_NOT_EQ ? "!=" :
|
|
t == tGREATER ? ">" : t == tGREATER_EQ ? ">=" :
|
|
t == tLESS ? "<" : "<=");
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
switch(t) {
|
|
case tLOG_EQ:
|
|
lhs = (lhs == rhs);
|
|
break;
|
|
case tLOG_NOT_EQ:
|
|
lhs = (lhs != rhs);
|
|
break;
|
|
case tGREATER:
|
|
lhs = (lhs > rhs);
|
|
break;
|
|
case tGREATER_EQ:
|
|
lhs = (lhs >= rhs);
|
|
break;
|
|
case tLESS:
|
|
lhs = (lhs < rhs);
|
|
break;
|
|
case tLESS_EQ:
|
|
lhs = (lhs <= rhs);
|
|
break;
|
|
default:
|
|
__unreachable();
|
|
}
|
|
t = db_read_token();
|
|
}
|
|
db_unread_token(t);
|
|
*valuep = lhs;
|
|
return (true);
|
|
}
|
|
|
|
static bool
|
|
db_logical_and_expr(
|
|
db_expr_t *valuep)
|
|
{
|
|
db_expr_t lhs, rhs;
|
|
int t;
|
|
|
|
if (!db_logical_relation_expr(&lhs))
|
|
return (false);
|
|
|
|
t = db_read_token();
|
|
while (t == tLOG_AND) {
|
|
if (!db_logical_relation_expr(&rhs)) {
|
|
db_printf("Expression syntax error after '%s'\n", "&&");
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
lhs = (lhs && rhs);
|
|
t = db_read_token();
|
|
}
|
|
db_unread_token(t);
|
|
*valuep = lhs;
|
|
return (true);
|
|
}
|
|
|
|
static bool
|
|
db_logical_or_expr(
|
|
db_expr_t *valuep)
|
|
{
|
|
db_expr_t lhs, rhs;
|
|
int t;
|
|
|
|
if (!db_logical_and_expr(&lhs))
|
|
return(false);
|
|
|
|
t = db_read_token();
|
|
while (t == tLOG_OR) {
|
|
if (!db_logical_and_expr(&rhs)) {
|
|
db_printf("Expression syntax error after '%s'\n", "||");
|
|
db_error(NULL);
|
|
/*NOTREACHED*/
|
|
}
|
|
lhs = (lhs || rhs);
|
|
t = db_read_token();
|
|
}
|
|
db_unread_token(t);
|
|
*valuep = lhs;
|
|
return (true);
|
|
}
|
|
|
|
int
|
|
db_expression(db_expr_t *valuep)
|
|
{
|
|
return (db_logical_or_expr(valuep));
|
|
}
|