|
|
//----------------------------------------------------------------------------
//
// Functions dealing with instructions, such as assembly or disassembly.
//
// Copyright (C) Microsoft Corporation, 1997-2001.
//
//----------------------------------------------------------------------------
#include "ntsdp.hpp"
static ULONG64 s_igrepSearchStartAddress = 0L; static ULONG64 s_igrepLastPc; static CHAR s_igrepLastPattern[256];
ULONG g_AsmOptions;
// This array must be in ASMOPT bit order.
PCSTR g_AsmOptionNames[] = { "verbose" };
void ChangeAsmOptions(BOOL Set, PSTR Args) { ULONG Flags = 0; PSTR Arg; ULONG i; for (;;) { //
// Parse out a single flag argument.
//
while (isspace(*Args)) { *Args++; } if (*Args == 0) { break; } Arg = Args; while (*Args && !isspace(*Args)) { Args++; } if (isspace(*Args)) { *Args++ = 0; }
//
// Find value for argument.
//
for (i = 0; i < DIMA(g_AsmOptionNames); i++) { if (!_stricmp(Arg, g_AsmOptionNames[i])) { break; } } if (i < DIMA(g_AsmOptionNames)) { Flags |= 1 << i; } else { ErrOut("Unknown assembly option '%s'\n", Arg); } }
if (Set) { g_AsmOptions |= Flags; } else { g_AsmOptions &= ~Flags; }
dprintf("Assembly options:"); if (g_AsmOptions == 0) { dprintf(" <default>\n"); } else { for (i = 0; i < DIMA(g_AsmOptionNames); i++) { if (g_AsmOptions & (1 << i)) { dprintf(" %s", g_AsmOptionNames[i]); } } dprintf("\n"); } }
void igrep (void) { ULONG64 dwNextGrepAddr; ULONG64 dwCurrGrepAddr; CHAR SourceLine[MAX_DISASM_LEN]; BOOL NewPc; ULONG64 d; PCHAR pc = g_CurCmd; PCHAR Pattern; PCHAR Expression; CHAR Symbol[MAX_SYMBOL_LEN]; ULONG64 Displacement; ADDR TempAddr; ULONG64 dwCurrentPc;
g_Machine->GetPC(&TempAddr); dwCurrentPc = Flat(TempAddr); if ( s_igrepLastPc && s_igrepLastPc == dwCurrentPc ) { NewPc = FALSE; } else { s_igrepLastPc = dwCurrentPc; NewPc = TRUE; }
//
// check for pattern.
//
Pattern = NULL; Expression = NULL; if (*pc) { while (*pc <= ' ') { pc++; } Pattern = pc; while (*pc > ' ') { pc++; }
//
// check for an expression
//
if (*pc != '\0') { *pc = '\0'; pc++; if (*pc <= ' ') { while (*pc <= ' ') { pc++; } } if (*pc) { Expression = pc; } } }
if (Pattern) { for (pc = Pattern; *pc; pc++) { *pc = (CHAR)toupper(*pc); } s_igrepLastPattern[0] = '*'; strcpy(s_igrepLastPattern + 1, Pattern); if (Pattern[0] == '*') { strcpy(s_igrepLastPattern, Pattern); } if (Pattern[strlen(Pattern)] != '*') { strcat(s_igrepLastPattern, "*"); } }
if (Expression) { s_igrepSearchStartAddress = ExtGetExpression(Expression); } if (!s_igrepSearchStartAddress) { dprintf("Search address set to %s\n", FormatAddr64(s_igrepLastPc)); s_igrepSearchStartAddress = s_igrepLastPc; return; } dwNextGrepAddr = s_igrepSearchStartAddress; dwCurrGrepAddr = dwNextGrepAddr;
d = ExtDisasm(&dwNextGrepAddr, SourceLine, FALSE); while (d) { for (pc = SourceLine; *pc; pc++) { *pc = (CHAR)tolower(*pc); } if (MatchPattern(SourceLine, s_igrepLastPattern)) { g_LastExpressionValue = dwCurrGrepAddr; s_igrepSearchStartAddress = dwNextGrepAddr; GetSymbolStdCall(dwCurrGrepAddr, Symbol, sizeof(Symbol), &Displacement, NULL); ExtDisasm(&dwCurrGrepAddr, SourceLine, FALSE); dprintf("%s", SourceLine); return; }
if (CheckUserInterrupt()) { return; }
dwCurrGrepAddr = dwNextGrepAddr; d = ExtDisasm(&dwNextGrepAddr, SourceLine, FALSE); } }
/*** fnAssemble - interactive assembly routine
* * Purpose: * Function of "a <range>" command. * * Prompt the user with successive assembly addresses until * a blank line is input. Assembly errors do not abort the * function, but the prompt is output again for a retry. * The variables g_CommandStart, g_CurCmd, and cbPrompt * are set to make a local error context and restored on routine * exit. * * Input: * *addr - starting address for assembly * * Output: * *addr - address after the last assembled instruction. * * Notes: * all error processing is local, no errors are returned. * *************************************************************************/
void TryAssemble(PADDR paddr) { char Assemble[MAX_DISASM_LEN];
//
// Set local prompt and command.
//
g_CommandStart = Assemble; g_CurCmd = Assemble; g_PromptLength = 9;
Assemble[0] = '\0';
while (TRUE) { char ch; dprintAddr(paddr); GetInput("", Assemble, sizeof(Assemble)); g_CurCmd = Assemble; RemoveDelChar(g_CurCmd); do { ch = *g_CurCmd++; } while (ch == ' ' || ch == '\t'); if (ch == '\0') { break; } g_CurCmd--;
assert(fFlat(*paddr) || fInstrPtr(*paddr)); g_Machine->Assemble(paddr, g_CurCmd); } }
void fnAssemble(PADDR paddr) { //
// Save present prompt and command.
//
PSTR StartSave = g_CommandStart; // saved start of cmd buffer
PSTR CommandSave = g_CurCmd; // current ptr in cmd buffer
ULONG PromptSave = g_PromptLength; // size of prompt string
BOOL Done = FALSE;
while (!Done) { __try { TryAssemble(paddr);
// If assembly returned normally we're done.
Done = TRUE; } __except(CommandExceptionFilter(GetExceptionInformation())) { // If illegal input was encountered keep looping.
} }
//
// Restore entry prompt and command.
//
g_CommandStart = StartSave; g_CurCmd = CommandSave; g_PromptLength = PromptSave; }
/*** fnUnassemble - disassembly of an address range
* * Purpose: * Function of "u<range>" command. * * Output the disassembly of the instruction in the given * address range. Since some processors have variable * instruction lengths, use fLength value to determine if * instruction count or inclusive range should be used. * * Input: * *addr - pointer to starting address to disassemble * value - if fLength = TRUE, count of instructions to output * if fLength = FALSE, ending address of inclusive range * * Output: * *addr - address after last instruction disassembled * * Exceptions: * error exit: MEMORY - memory access error * * Notes: * *************************************************************************/
void fnUnassemble ( PADDR Addr, ULONG64 Value, BOOL Length ) { if (!IS_MACHINE_ACCESSIBLE()) { error(BADTHREAD); } CHAR Buffer[MAX_DISASM_LEN]; BOOL Status; ADDR EndAddr; ULONG SymAddrFlags = SYMADDR_FORCE | SYMADDR_LABEL | SYMADDR_SOURCE;
Flat(EndAddr) = Value;
while ((Length && Value--) || (!Length && AddrLt(*Addr, EndAddr))) { OutputSymAddr(Flat(*Addr), SymAddrFlags); Status = g_Machine->Disassemble(Addr, Buffer, FALSE); dprintf("%s", Buffer); if (!Status) { error(MEMORY); }
SymAddrFlags &= ~SYMADDR_FORCE;
if (CheckUserInterrupt()) { return; } } }
|