gecko-dev/ef/Tools/Monitor/Commands.cpp

312 строки
5.7 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):
*/
// Commands.cpp
//
// Scott M. Silver
//
#include <stdio.h>
#include "Commands.h"
#include "Debugee.h"
#include "DataOutput.h"
#include "Symbols.h"
#include "MonitorExpression.h"
#include "Breakpoints.h"
#include "DebuggerChannel.h"
#include "Win32Util.h"
#include "XDisAsm.h"
extern DebugeeThread* gCurThread;
extern DebugeeProcess* gProcess;
extern bool gEndCommandLine;
#define CHECK_HAVE_PROCESS(inProcess) \
if (!inProcess) \
{ \
printf("No process started\n"); \
return; \
}
void
quit(char*)
{
if (gProcess)
gProcess->kill();
gEndCommandLine = true;
}
void
kill(char*)
{
CHECK_HAVE_PROCESS(gProcess);
gProcess->kill();
gProcess = NULL;
}
void
stepIn(char*)
{
CHECK_HAVE_PROCESS(gProcess);
gCurThread->singleStep();
}
void
stepOver(char*)
{
CHECK_HAVE_PROCESS(gProcess);
// set thread breakpoint on instruction after call
unsigned char data[32];
unsigned char* ip;
ip = (unsigned char*) gCurThread->getIP();
if (!gProcess->readMemory(ip, &data, 32, NULL))
showLastError();
if (data[0] == 0xe8 || data[0] == 0xff || data[0] == 0x9a)
{
unsigned char* tempStart;
unsigned char* nextInstruction;
tempStart = data;
nextInstruction = ip + x86InstructionLength(0, (char**)&tempStart, (char*) data + 32, kDisAsmFlag32BitSegments);
BreakpointManager::newBreakpoint(*gCurThread, nextInstruction).set();
gCurThread->resume();
}
else
gCurThread->singleStep();
}
void
go(char *)
{
CHECK_HAVE_PROCESS(gProcess);
if (gCurThread != NULL)
gCurThread->resume();
else
printf("no thread, use swt\n");
}
void
disassemble(char *inExpression)
{
CHECK_HAVE_PROCESS(gProcess);
void *address;
static void* sLastAddress = NULL;
if (*inExpression != '\0')
address = evaluateExpression(*gCurThread, inExpression);
else if (sLastAddress)
address = sLastAddress;
else
address = gCurThread->getIP();
sLastAddress = disassembleN(*gProcess, (char*) address, 10);
}
void
unhandledCommandLine(char *inLine)
{
CHECK_HAVE_PROCESS(gProcess);
PrintableValue value;
if (lookupSymbol(*gCurThread, inLine, value))
{
printf("'%s' = ", inLine);
printf(value.fmtString, value.value);
putchar('\n');
}
}
void* gArg;
void
breakpointCompileLoadAction(const char* inMethodName, void* inAddress, void* inArgument)
{
DebugeeThread* thread = (DebugeeThread*) inArgument;
BreakpointManager::newBreakpoint(*thread, inAddress).set();
}
void
deferredCompileLoadHandler(const char* inMethodName, void* inAddress)
{
printf("deferred notification at %p: %s\n", inAddress, inMethodName);
if (gArg)
breakpointCompileLoadAction(inMethodName, inAddress, gArg);
}
void
addDeferredCompileLoadAction(const char* inMethodName, void* inArgument)
{
DebuggerClientChannel* channel = gProcess->getChannel();
if (channel)
{
gArg = inArgument;
channel->setCompileOrLoadMethodHandler(deferredCompileLoadHandler);
channel->requestNotifyOnMethodCompileLoad(inMethodName);
}
}
// expressions limited now
void
breakExecution(char *inExpression)
{
CHECK_HAVE_PROCESS(gProcess);
void* address = evaluateExpression(*gCurThread, inExpression);
if (address)
BreakpointManager::newBreakpoint(*gCurThread, address).set();
else
{
const char* methodName;
if ((methodName = extractMethodFromExpression(inExpression)))
addDeferredCompileLoadAction(methodName, gCurThread);
else
printf("error %s unknown\n", methodName);
}
}
void
runClass(char* inClassName)
{
CHECK_HAVE_PROCESS(gProcess);
if (gProcess->getChannel())
gProcess->getChannel()->requestRunClass("javasoft/sqe/tests/api/java/lang/System/SystemTests10");
}
void
run(char*)
{
HANDLE debugThreadH;
const char* testApp = "e:\\trees\\ef1\\ns\\electricalfire\\Driver\\StandAloneJava\\winbuild\\electric\\sajava.exe";
if (gProcess)
printf("already running process\n");
else
gProcess = DebugeeProcess::createDebugeeProcess(testApp, ::GetCurrentThreadId(), debugThreadH);
}
void
switchThread(char *inExpression)
{
CHECK_HAVE_PROCESS(gProcess);
DebugeeThread* thread = gProcess->idToThread((DWORD) evaluateExpression(*gCurThread, inExpression));
if (thread)
gCurThread = thread;
}
extern "C" void
stack(DWORD id)
{
DebugeeThread* thread = gProcess->idToThread(id);
if (thread)
printThreadStack(*thread);
}
void
printThreads(char*)
{
CHECK_HAVE_PROCESS(gProcess);
printThreads(*gProcess);
}
void
printThisThread(char*)
{
CHECK_HAVE_PROCESS(gProcess);
if (gCurThread)
{
gCurThread->print();
printf("\n");
}
}
void
printThreadStack(char*)
{
CHECK_HAVE_PROCESS(gProcess);
if (gCurThread)
printThreadStack(*gCurThread);
}
void
connectToVM(char*)
{
CHECK_HAVE_PROCESS(gProcess);
if (!gProcess->getChannel(true))
printf("couldn't connect to VM\n");
}
void printFPRegs(char*)
{
CHECK_HAVE_PROCESS(gProcess);
}
void printIntegerRegs(char*)
{
CHECK_HAVE_PROCESS(gProcess);
printIntegerRegs(*gCurThread);
}
void printAllRegs(char*)
{
CHECK_HAVE_PROCESS(gProcess);
}
void dumpMemory(char*)
{
}