gecko-dev/ef/Tools/Monitor/DataOutput.cpp
1999-11-02 06:38:29 +00:00

288 lines
7.0 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
// DataOutput.cpp
//
// Scott M. Silver
#include <assert.h>
#include <stdio.h>
#include <Windows.h>
#include <ImageHlp.h>
#include "Debugee.h"
#include "XDisAsm.h"
#include "Win32Util.h"
#include "DataOutput.h"
#include "DebuggerChannel.h"
#include "Breakpoints.h"
void* disassembleToString(DebugeeProcess& inProcess, void* inStart, const char* inOutputBuffer);
void* printOneInstruction(DebugeeProcess& inProcess, void* inStart);
extern bool gCommandLineLoopActive;
extern "C" rl_clear_screen();
extern DebugeeThread* gCurThread;
void
disassembleBytes(DebugeeProcess& inProcess, const char* inStart, int /*length*/)
{
printOneInstruction(inProcess, (void*) inStart);
putchar('\n');
}
void*
disassembleToString(DebugeeProcess& inProcess, void* inStart, char* outOutputBuffer)
{
unsigned char data[32];
if (!inProcess.readMemory(inStart, &data, 32, NULL))
showLastError();
// if the current pc is the site of breakpoint
// we replace the breakpoint instruction with
// the replaced instruction
Breakpoint* bp = BreakpointManager::findBreakpoint(inStart);
if (bp)
data[0] = bp->getReplaced();
unsigned char* tempStart = data;
if (data[0] == 0xe8 || data[0] == 0xe9)
{
// call/jmp with 32 bit offset relative to pc from end of the instruction
char symbol[512];
DWORD offset;
void* address = (void*) ((Uint8*) inStart + *((Int32*) (data + 1)) + 5); // 5 is length of instruction
if (inProcess.getSymbol(address, symbol, sizeof(symbol), offset))
{
sprintf(outOutputBuffer, "%s\t %s + %d; %p", (data[0] == 0xe8) ? "call" : "jmp", symbol, offset, address);
goto FinishDisassembling;
}
// else false through and do the normal thing
}
// regular instruction
char* str;
str = disasmx86(0, (char**) &tempStart, (char*)data + 32, kDisAsmFlag32BitSegments);
strcpy(outOutputBuffer, str);
FinishDisassembling:
tempStart = data;
return ((void*) ((char*) inStart + x86InstructionLength(0, (char**)&tempStart, (char*) data + 32, kDisAsmFlag32BitSegments)));
}
DebugeeProcess::SymbolKind
printMethodName(DebugeeProcess& inProcess, const void* inMethodAddress)
{
char symbol[512];
DWORD offset;
DebugeeProcess::SymbolKind kind;
if ((kind = inProcess.getSymbol(inMethodAddress, symbol, sizeof(symbol), offset)) != DebugeeProcess::kNil)
printf("%s + %d", symbol, offset);
return (kind);
}
void*
printOneInstruction(DebugeeProcess& inProcess, void* inStart)
{
void* nextPC;
char buffer[1024];
nextPC = disassembleToString(inProcess, inStart, buffer);
printf("%.8x: %s", inStart, buffer);
return (nextPC);
}
void*
disassembleN(DebugeeProcess& inProcess, const char* inStart, int inInstructions)
{
int curInstruction;
void* curPC = (void*) inStart;
if (printMethodName(inProcess, inStart));
putchar('\n');
for (curInstruction = 0; curInstruction < inInstructions; curInstruction++)
{
curPC = printOneInstruction(inProcess, curPC);
printf("\n");
}
return (curPC);
}
void beginOutput()
{
if (gCommandLineLoopActive)
putchar('\n');
}
void endOutput()
{
if (gCommandLineLoopActive)
rl_clear_screen();
}
void
printThreads(DebugeeProcess& inProcess)
{
Vector<DebugeeThread*> threads = inProcess.getThreads();
printf(" %4s%5s%10s(%5s)%9s %s\n", "id", "hndl", "state", "cnt", "eip", "symbol");
DebugeeThread** curThread;
for(curThread = threads.begin(); curThread < threads.end(); curThread++)
{
if (gCurThread == *curThread)
printf("*");
else
printf(" ");
(*curThread)->print();
printf("\n");
}
}
void
printThreadStack(DebugeeThread& inThread)
{
STACKFRAME stackFrame;
CONTEXT context;
::ZeroMemory(&stackFrame, sizeof(stackFrame));
inThread.getContext(CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS, context);
stackFrame.AddrPC.Offset = context.Eip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = context.Esp;
stackFrame.AddrStack.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = context.Ebp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
DebugeeProcess::SymbolKind state;
for (;;)
{
if (stackFrame.AddrPC.Offset == 0)
break;
state = printMethodName(inThread.getProcess(), (void*) stackFrame.AddrPC.Offset);
if (state == DebugeeProcess::kJava)
{
printf("\n");
inThread.getProcess().readMemory(((DWORD*)stackFrame.AddrFrame.Offset + 1), &stackFrame.AddrPC.Offset, 4);
inThread.getProcess().readMemory((void*) stackFrame.AddrFrame.Offset, &stackFrame.AddrFrame.Offset, 4);
stackFrame.AddrStack.Offset = stackFrame.AddrFrame.Offset;
}
else if (state == DebugeeProcess::kNative)
{
printf("\n");
if (!::StackWalk(IMAGE_FILE_MACHINE_I386,
inThread.getProcess().getProcessHandle(),
inThread.getThreadHandle(),
&stackFrame,
NULL,
NULL,
SymFunctionTableAccess,
SymGetModuleBase,
NULL))
{
inThread.getProcess().readMemory(((DWORD*)stackFrame.AddrFrame.Offset + 1), &stackFrame.AddrPC.Offset, 4);
inThread.getProcess().readMemory((void*) stackFrame.AddrFrame.Offset, &stackFrame.AddrFrame.Offset, 4);
stackFrame.AddrStack.Offset = stackFrame.AddrFrame.Offset;
}
}
else
{
// try one more native frame
if (::StackWalk(IMAGE_FILE_MACHINE_I386,
inThread.getProcess().getProcessHandle(),
inThread.getThreadHandle(),
&stackFrame,
NULL,
NULL,
SymFunctionTableAccess,
SymGetModuleBase,
NULL))
state = printMethodName(inThread.getProcess(), (void*) stackFrame.AddrPC.Offset);
else
{
printf("<anonymous>\n");
break;
}
}
}
// showLastError();
}
void
printIntegerRegs(DebugeeThread& inThread)
{
CONTEXT context;
gCurThread->getContext(CONTEXT_INTEGER | CONTEXT_CONTROL, context);
printf( "EDI=%8p ESI=%8p EBX=%8p EDX=%8p\n"
"ECX=%8p EAX=%8p EBP=%8p ESP=%8p\n"
"EIP=%8p\n", context.Edi, context.Esi,
context.Ebx, context.Edx, context.Ecx,
context.Eax, context.Ebp, context.Esp,
context.Eip);
}
void
printFlags(DebugeeThread& inThread)
{
CONTEXT context;
gCurThread->getContext(CONTEXT_CONTROL, context);
const char* flagString = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
const char* cp = flagString;
while (context.EFlags)
{
if (context.EFlags & 1)
putchar(*cp);
else
putchar(*cp - 32);
cp++;
context.EFlags >>= 1;
}
}