Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

400 lines
9.7 KiB

//----------------------------------------------------------------------------
//
// Functions dealing with instructions, such as assembly or disassembly.
//
// Copyright (C) Microsoft Corporation, 1997-2002.
//
//----------------------------------------------------------------------------
#include "ntsdp.hpp"
ADDR g_DisasmSearchStartAddress;
ADDR g_DisasmSearchLastPc;
char g_DisasmSearchLastPattern[256];
ULONG g_AsmOptions;
ULONG g_X86BiosBaseAddress;
// This array must be in DEBUG_ASMOPT bit order.
PCSTR g_AsmOptionNames[] =
{
"verbose",
"no_code_bytes",
"ignore_output_width",
};
void
DotAsm(PDOT_COMMAND Cmd, DebugClient* Client)
{
ULONG Flags = 0;
PSTR Arg;
ULONG i;
for (;;)
{
//
// Parse out a single flag argument.
//
if (!PeekChar() || *g_CurCmd == ';')
{
break;
}
Arg = g_CurCmd;
while (*g_CurCmd && !isspace(*g_CurCmd))
{
g_CurCmd++;
}
if (isspace(*g_CurCmd))
{
*g_CurCmd++ = 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 (Cmd->Name[3] != '-')
{
g_AsmOptions |= Flags;
}
else
{
g_AsmOptions &= ~Flags;
}
NotifyChangeEngineState(DEBUG_CES_ASSEMBLY_OPTIONS, g_AsmOptions, TRUE);
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
ParseInstrGrep(void)
{
ADDR NextGrepAddr;
ADDR CurrGrepAddr;
char SourceLine[MAX_DISASM_LEN];
PSTR Pattern;
char Save;
ULONG64 Length;
if (IS_CUR_CONTEXT_ACCESSIBLE())
{
g_Machine->GetPC(&g_DisasmSearchLastPc);
}
Pattern = StringValue(STRV_SPACE_IS_SEPARATOR |
STRV_ESCAPED_CHARACTERS |
STRV_ALLOW_EMPTY_STRING, &Save);
if (Pattern)
{
g_DisasmSearchLastPattern[0] = '*';
g_DisasmSearchLastPattern[1] = 0;
while (Pattern[0] == '*')
{
Pattern++;
}
CatString(g_DisasmSearchLastPattern, Pattern,
DIMA(g_DisasmSearchLastPattern));
if (Pattern[strlen(Pattern) - 1] != '*')
{
CatString(g_DisasmSearchLastPattern, "*",
DIMA(g_DisasmSearchLastPattern));
}
*g_CurCmd = Save;
Length = DEBUG_INVALID_OFFSET;
g_PrefixSymbols = TRUE;
GetRange(&g_DisasmSearchStartAddress, &Length, 1,
SEGREG_CODE, DEFAULT_RANGE_LIMIT);
g_PrefixSymbols = FALSE;
}
if (!Flat(g_DisasmSearchStartAddress))
{
if (IS_CUR_CONTEXT_ACCESSIBLE())
{
dprintf("Search address set to ");
dprintAddr(&g_DisasmSearchLastPc);
dprintf("\n");
g_DisasmSearchStartAddress = g_DisasmSearchLastPc;
}
else
{
ErrOut("Search address required\n");
}
return;
}
NextGrepAddr = g_DisasmSearchStartAddress;
while (Length == DEBUG_INVALID_OFFSET ||
Length-- > 0)
{
CurrGrepAddr = NextGrepAddr;
if (!g_Machine->
Disassemble(g_Process, &NextGrepAddr, SourceLine, FALSE))
{
break;
}
if (MatchPattern(SourceLine, g_DisasmSearchLastPattern))
{
g_LastEvalResult.SetU64(Flat(CurrGrepAddr));
g_DisasmSearchStartAddress = NextGrepAddr;
OutputSymAddr(Flat(CurrGrepAddr),
SYMADDR_FORCE | SYMADDR_LABEL | SYMADDR_SOURCE,
NULL);
dprintf("%s", SourceLine);
if (Length == DEBUG_INVALID_OFFSET)
{
return;
}
}
if (CheckUserInterrupt())
{
return;
}
}
}
void
TryAssemble(PADDR Addr)
{
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(Addr);
GetInput("", Assemble, sizeof(Assemble), GETIN_LOG_INPUT_LINE);
g_CurCmd = Assemble;
RemoveDelChar(g_CurCmd);
do
{
Ch = *g_CurCmd++;
}
while (Ch == ' ' || Ch == '\t');
if (Ch == '\0')
{
break;
}
g_CurCmd--;
DBG_ASSERT(fFlat(*Addr) || fInstrPtr(*Addr));
g_Machine->Assemble(g_Process, Addr, g_CurCmd);
}
}
void
ParseAssemble(void)
{
//
// 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;
char Ch;
if (!IS_CUR_MACHINE_ACCESSIBLE())
{
error(BADTHREAD);
}
if ((Ch = PeekChar()) != '\0' && Ch != ';')
{
GetAddrExpression(SEGREG_CODE, &g_AssemDefault);
}
while (!Done)
{
__try
{
TryAssemble(&g_AssemDefault);
// 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;
}
void
ParseUnassemble(void)
{
char Ch;
ULONG64 Length;
BOOL HasLength;
char Text[MAX_DISASM_LEN];
if (!IS_CUR_MACHINE_ACCESSIBLE())
{
error(BADTHREAD);
}
Ch = (char)tolower(*g_CurCmd);
if (Ch == 'r')
{
g_CurCmd++;
}
else if (IS_KERNEL_TARGET(g_Target) && Ch == 'x')
{
g_CurCmd += 1;
}
Length = (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_IA64) ? 9 : 8;
g_PrefixSymbols = TRUE;
HasLength = GetRange(&g_UnasmDefault, &Length, 0, SEGREG_CODE,
DEFAULT_RANGE_LIMIT);
g_PrefixSymbols = FALSE;
if (IS_KERNEL_TARGET(g_Target) && Ch == 'x')
{
ADDR Addr;
if (g_X86BiosBaseAddress == 0)
{
ULONG64 SymAddr;
if (GetOffsetFromSym(g_Process, "hal!HalpEisaMemoryBase",
&SymAddr, NULL) != 1)
{
error(VARDEF);
}
if (g_Target->
ReadAllVirtual(g_Process, SymAddr,
&g_X86BiosBaseAddress,
sizeof(ULONG)) != S_OK)
{
g_X86BiosBaseAddress = 0;
error(MEMORY);
}
}
Addr = g_UnasmDefault;
Addr.flat += (g_X86BiosBaseAddress + (Addr.seg << 4));
Addr.off = Addr.flat;
Addr.type = ADDR_V86 | INSTR_POINTER;
while (Length-- > 0)
{
g_Target->m_Machines[MACHIDX_I386]->
Disassemble(g_Process, &Addr, Text, TRUE);
Addr.flat = Addr.off;
dprintf("%s", Text);
}
g_UnasmDefault = Addr;
g_UnasmDefault.off -=
(g_X86BiosBaseAddress + (Addr.seg << 4));
g_UnasmDefault.flat = g_UnasmDefault.off;
}
else
{
MachineInfo* Machine;
if (Ch == 'r')
{
// Force V86-mode address to force 16-bit disassembly.
// We leave the flat address so that the actual
// address used is not changed and we tweak
// the seg:off pair to represent a count from the
// start address.
g_UnasmDefault.seg = 0;
g_UnasmDefault.off = Flat(g_UnasmDefault) & 0xffff;
g_UnasmDefault.type = ADDR_V86 | FLAT_COMPUTED |
FLAT_BASIS;
Machine = g_Target->m_Machines[MACHIDX_I386];
}
else
{
Machine = g_Machine;
}
BOOL Status;
ADDR EndAddr;
ULONG SymAddrFlags = SYMADDR_FORCE | SYMADDR_LABEL | SYMADDR_SOURCE;
ADDRFLAT(&EndAddr, Length);
while ((HasLength && Length--) ||
(!HasLength && AddrLt(g_UnasmDefault, EndAddr)))
{
OutputSymAddr(Flat(g_UnasmDefault), SymAddrFlags, NULL);
Status = Machine->
Disassemble(g_Process, &g_UnasmDefault, Text, FALSE);
dprintf("%s", Text);
if (!Status)
{
error(MEMORY);
}
SymAddrFlags &= ~SYMADDR_FORCE;
if (CheckUserInterrupt())
{
return;
}
}
}
}