7088955: add C2 IR support to the SA

Reviewed-by: kvn
This commit is contained in:
Tom Rodriguez 2011-09-11 14:48:24 -07:00
parent e39ba1a5fe
commit e3afdf10ad
200 changed files with 7232 additions and 13674 deletions

View file

@ -48,6 +48,7 @@ sun.jvm.hotspot.asm.x86 \
sun.jvm.hotspot.bugspot \
sun.jvm.hotspot.bugspot.tree \
sun.jvm.hotspot.c1 \
sun.jvm.hotspot.ci \
sun.jvm.hotspot.code \
sun.jvm.hotspot.compiler \
sun.jvm.hotspot.debugger \
@ -56,9 +57,6 @@ sun.jvm.hotspot.debugger.cdbg \
sun.jvm.hotspot.debugger.cdbg.basic \
sun.jvm.hotspot.debugger.cdbg.basic.amd64 \
sun.jvm.hotspot.debugger.cdbg.basic.x86 \
sun.jvm.hotspot.debugger.dbx \
sun.jvm.hotspot.debugger.dbx.sparc \
sun.jvm.hotspot.debugger.dbx.x86 \
sun.jvm.hotspot.debugger.dummy \
sun.jvm.hotspot.debugger.ia64 \
sun.jvm.hotspot.debugger.linux \
@ -76,7 +74,6 @@ sun.jvm.hotspot.debugger.remote.amd64 \
sun.jvm.hotspot.debugger.remote.sparc \
sun.jvm.hotspot.debugger.remote.x86 \
sun.jvm.hotspot.debugger.sparc \
sun.jvm.hotspot.debugger.win32 \
sun.jvm.hotspot.debugger.win32.coff \
sun.jvm.hotspot.debugger.windbg \
sun.jvm.hotspot.debugger.windbg.amd64 \
@ -91,7 +88,9 @@ sun.jvm.hotspot.interpreter \
sun.jvm.hotspot.jdi \
sun.jvm.hotspot.livejvm \
sun.jvm.hotspot.memory \
sun.jvm.hotspot.opto \
sun.jvm.hotspot.oops \
sun.jvm.hotspot.prims \
sun.jvm.hotspot.runtime \
sun.jvm.hotspot.runtime.amd64 \
sun.jvm.hotspot.runtime.ia64 \
@ -139,6 +138,7 @@ sun/jvm/hotspot/asm/x86/*.java \
sun/jvm/hotspot/bugspot/*.java \
sun/jvm/hotspot/bugspot/tree/*.java \
sun/jvm/hotspot/c1/*.java \
sun/jvm/hotspot/ci/*.java \
sun/jvm/hotspot/code/*.java \
sun/jvm/hotspot/compiler/*.java \
sun/jvm/hotspot/debugger/*.java \
@ -147,9 +147,6 @@ sun/jvm/hotspot/debugger/cdbg/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \
sun/jvm/hotspot/debugger/dbx/*.java \
sun/jvm/hotspot/debugger/dbx/sparc/*.java \
sun/jvm/hotspot/debugger/dbx/x86/*.java \
sun/jvm/hotspot/debugger/dummy/*.java \
sun/jvm/hotspot/debugger/ia64/*.java \
sun/jvm/hotspot/debugger/linux/*.java \
@ -165,7 +162,6 @@ sun/jvm/hotspot/debugger/remote/amd64/*.java \
sun/jvm/hotspot/debugger/remote/sparc/*.java \
sun/jvm/hotspot/debugger/remote/x86/*.java \
sun/jvm/hotspot/debugger/sparc/*.java \
sun/jvm/hotspot/debugger/win32/*.java \
sun/jvm/hotspot/debugger/win32/coff/*.java \
sun/jvm/hotspot/debugger/windbg/*.java \
sun/jvm/hotspot/debugger/windbg/ia64/*.java \
@ -176,6 +172,8 @@ sun/jvm/hotspot/jdi/*.java \
sun/jvm/hotspot/livejvm/*.java \
sun/jvm/hotspot/memory/*.java \
sun/jvm/hotspot/oops/*.java \
sun/jvm/hotspot/opto/*.java \
sun/jvm/hotspot/prims/*.java \
sun/jvm/hotspot/runtime/*.java \
sun/jvm/hotspot/runtime/amd64/*.java \
sun/jvm/hotspot/runtime/ia64/*.java \

View file

@ -70,6 +70,14 @@ fi
SA_CLASSPATH=$STARTDIR/../build/classes:$STARTDIR/../src/share/lib/js.jar:$STARTDIR/sa.jar:$STARTDIR/lib/js.jar
if [ ! -z "$SA_TYPEDB" ]; then
if [ ! -f $SA_TYPEDB ]; then
echo "$SA_TYPEDB is unreadable"
exit 1
fi
OPTIONS="-Dsun.jvm.hotspot.typedb=$SA_TYPEDB ${OPTIONS}"
fi
OPTIONS="-Djava.system.class.loader=sun.jvm.hotspot.SALauncherLoader ${OPTIONS}"
SA_JAVA_CMD="$SA_PREFIX_CMD $SA_JAVA -showversion ${OPTIONS} -cp $SA_CLASSPATH $SA_OPTIONS"

View file

@ -67,6 +67,14 @@ fi
SA_CLASSPATH=$STARTDIR/../build/classes:$STARTDIR/../src/share/lib/js.jar:$STARTDIR/sa.jar::$STARTDIR/lib/js.jar
if [ ! -z "$SA_TYPEDB" ]; then
if [ ! -f $SA_TYPEDB ]; then
echo "$SA_TYPEDB is unreadable"
exit 1
fi
OPTIONS="-Dsun.jvm.hotspot.typedb=$SA_TYPEDB ${OPTIONS}"
fi
OPTIONS="-Djava.system.class.loader=sun.jvm.hotspot.SALauncherLoader ${OPTIONS}"
SA_JAVA_CMD="$SA_PREFIX_CMD $SA_JAVA -d64 -showversion ${OPTIONS} -cp $SA_CLASSPATH $SA_OPTIONS"

View file

@ -24,9 +24,7 @@
all:
cd dbx; $(MAKE) all
cd proc; $(MAKE) all
clean:
cd dbx; $(MAKE) clean
cd proc; $(MAKE) clean

View file

@ -1,91 +0,0 @@
#
# Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# Targets are:
# 32bit: Build the 32 bit version in ./32bit
# 64bit: Build the 64 bit version in ./64bit
# helloWorld: Build the helloWorld test program
# all: Build all of the above. This is the default.
#
# NOTE: This makefile uses IOBuf.cpp, IOBuf.hpp, Buffer.cpp, and
# Buffer.hpp from the src/os/win32/agent directory.
.PHONY: 32bit 64bit
ARCH_ORIG = $(shell uname -p)
# C++ := /java/devtools/$(ARCH_ORIG)/SUNWspro/SC6.1/bin/CC
C++ := CC
RM := /usr/bin/rm
MKDIRS := /usr/bin/mkdir -p
WIN32_DIR := ../../win32
ARCH := $(subst i386,i486,$(ARCH_ORIG))
# INCLUDES := -I/net/sparcworks.eng/export/set/sparcworks5/dbx_62_intg/dev/src/dbx -I$(WIN32_DIR)
INCLUDES := -I. -I$(WIN32_DIR)
CFLAGS_32bit := -xarch=v8
CFLAGS_64bit := -xarch=v9
CFLAGS := -PIC -xO3 $(INCLUDES)
LIBS := -lsocket -lnsl -lrtld_db
LDFLAGS := -G
ifneq "$(ARCH)" "i486"
CFLAGS += $(CFLAGS_$(VERSION))
LDFLAGS += $(CFLAGS_$(VERSION))
endif
# We use IOBuf.hpp, IOBuf.cpp, Buffer.hpp, and Buffer.cpp from the win32 dir.
vpath %.cpp .:$(WIN32_DIR)
vpath %.hpp .:$(WIN32_DIR)
OBJS = $(VERSION)/svc_agent_dbx.o $(VERSION)/IOBuf.o $(VERSION)/Buffer.o
# The default is to make both 32 bit and 64 bit versions.
all:: 32bit 64bit
32bit 64bit::
$(MKDIRS) $@
$(MAKE) $@/libsvc_agent_dbx.so helloWorld VERSION=$@
$(VERSION)/IOBuf.o: IOBuf.hpp
$(VERSION)/Buffer.o: Buffer.hpp
$(VERSION)/svc_agent_dbx.o: svc_agent_dbx.hpp
$(VERSION)/%.o: %.cpp
$(C++) $(CFLAGS) -c $< -o $@
$(VERSION)/libsvc_agent_dbx.so:: $(OBJS)
$(C++) $(LDFLAGS) -o $(VERSION)/libsvc_agent_dbx.so $(OBJS) $(LIBS)
# Would be nice to move this into a shared directory
helloWorld:: helloWorld.cpp
$(C++) -g $< -o $@
clean::
$(RM) -rf 32bit 64bit *.o helloWorld

View file

@ -1,9 +0,0 @@
shell_impl.h
proc_service_2.h
The above files are captured from the dbx build environment.
Rather then use a -I that points to stuff in .eng domain that
may not be accessible in other domains these files are just
copied here so local builds in other domains will work.
These files rarely change so the fact that we might have to
strobe in new ones on rare occasions is no big deal.

View file

@ -1,82 +0,0 @@
This import module uses a largely text-based protocol, except for
certain bulk data transfer operations. All text is in single-byte
US-ASCII.
Commands understood:
address_size ::= <int result>
Returns 32 if attached to 32-bit process, 64 if 64-bit.
peek_fail_fast <bool arg> ::=
Indicates whether "peek" requests should "fail fast"; that is, if
any of the addresses in the requested range are unmapped, report
the entire range as unmapped. This is substantially faster than
the alternative, which is to read the entire range byte-by-byte.
However, it should only be used when it is guaranteed by the
client application that peeks come from at most one page. The
default is that peek_fast_fail is not enabled.
peek <address addr> <unsigned int numBytes> ::=
B<binary char success>
[<binary unsigned int len> <binary char isMapped> [<binary char data>]...]...
NOTE that the binary portion of this message is prefixed by the
uppercase US-ASCII letter 'B', allowing easier synchronization by
clients. There is no data between the 'B' and the rest of the
message.
May only be called once attached. Reads the address space of the
target process starting at the given address (see below for format
specifications) and extending the given number of bytes. Whether
the read succeeded is indicated by a single byte containing a 1 or
0 (success or failure). If successful, the return result is given
in a sequence of ranges. _len_, the length of each range, is
indicated by a 32-bit unsigned integer transmitted with big-endian
byte ordering (i.e., most significant byte first). _isMapped_
indicates whether the range is mapped or unmapped in the target
process's address space, and will contain the value 1 or 0 for
mapped or unmapped, respectively. If the range is mapped,
_isMapped_ is followed by _data_, containing the raw binary data
for the range. The sum of all ranges' lengths is guaranteed to be
equivalent to the number of bytes requested.
poke <address addr> <int numBytes> B[<binary char data>]... ::= <bool result>
NOTE that the binary portion of this message is prefixed by the
uppercase US-ASCII letter 'B', allowing easier synchronization by
clients. There is no data between the 'B' and the rest of the
message.
Writes the given data to the target process starting at the given
address. Returns 1 on success, 0 on failure (i.e., one or more of
target addresses were unmapped).
mapped <address addr> <int numBytes> ::= <bool result>
Returns 1 if entire address range [address...address + int arg) is
mapped in target process's address space, 0 if not
lookup <symbol objName> <symbol sym> ::= <address addr>
First symbol is object name; second is symbol to be looked up.
Looks up symbol in target process's symbol table and returns
address. Returns NULL (0x0) if symbol is not found.
thr_gregs <int tid> ::= <int numAddresses> <address...>
Fetch the "general" (integer) register set for the given thread.
Returned as a series of hexidecimal values. NOTE: the meaning of
the return value is architecture-dependent. In general it is the
contents of the prgregset_t.
exit ::=
Exits the serviceability agent dbx module, returning control to
the dbx prompt.
// Data formats and example values:
<address> ::= 0x12345678[9ABCDEF0] /* up to 64-bit hex value */
<unsigned int> ::= 5 /* up to 32-bit integer number; no leading sign */
<bool> ::= 1 /* ASCII '0' or '1' */

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdio.h>
#include <inttypes.h>
extern "C" {
const char* helloWorldString = "Hello, world!";
// Do not change these values without changing TestDebugger.java as well
// FIXME: should make these jbyte, jshort, etc...
volatile int8_t testByte = 132;
volatile int16_t testShort = 27890;
volatile int32_t testInt = 1020304050;
volatile int64_t testLong = 102030405060708090LL;
volatile float testFloat = 35.4F;
volatile double testDouble = 1.23456789;
volatile int helloWorldTrigger = 0;
}
int
main(int, char**) {
while (1) {
while (helloWorldTrigger == 0) {
}
fprintf(stderr, "%s\n", helloWorldString);
fprintf(stderr, "testByte=%d\n", testByte);
fprintf(stderr, "testShort=%d\n", testShort);
fprintf(stderr, "testInt=%d\n", testInt);
fprintf(stderr, "testLong=%d\n", testLong);
fprintf(stderr, "testFloat=%d\n", testFloat);
fprintf(stderr, "testDouble=%d\n", testDouble);
while (helloWorldTrigger != 0) {
}
}
}

View file

@ -1,172 +0,0 @@
/*
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _PROC_SERVICE_2_H
#define _PROC_SERVICE_2_H
/*
* Types, function definitions for the provider of services beyond
* proc_service. This interface will be used by import modules like
* BAT/prex, NEO debugger etc.
*/
/*
CCR info
Version history:
1.0 - Initial CCR release
1.1 - Changes for GLUE/neo.
New entry points ps_svnt_generic() and ps_svc_generic()
- New entry point ps_getpid()
Release information for automatic CCR updates:
BEGIN RELEASE NOTES: (signifies what gets put into CCR release notes)
1.2 - Changes to support Solaris 2.7
END RELEASE NOTES: (signifies what gets put into CCR release notes)
Following is used for CCR version number:
#define CCR_PROC_SERVICE_2_VERSION 1.2
*/
#include <proc_service.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
struct ps_loadobj {
int objfd; /* fd of the load object or executable
* -1 implies its not available.
* This file decriptor is live only during the
* particular call to ps_iter_f(). If you
* need it beyond that you need to dup() it.
*/
psaddr_t
text_base; /* address where text of loadobj was mapped */
psaddr_t
data_base; /* address where data of loadobj was mapped */
const char *objname; /* loadobj name */
};
typedef int ps_iter_f(const struct ps_prochandle *, const struct ps_loadobj *,
void *cd);
/*
* Returns the ps_prochandle for the current process under focus. Returns
* NULL if there is none.
*/
const struct ps_prochandle *
ps_get_prochandle(void);
/*
* Returns the ps_prochandle for the current process(allows core files to
* be specified) under focus. Returns NULL if there is none.
*/
const struct ps_prochandle *
ps_get_prochandle2(int cores_too);
/*
* Returns the pid of the process referred to by the ps_prochandle.
*
* 0 is returned in case the ps_prochandle is not valid or refers to dead
* process.
*
*/
pid_t
ps_getpid(const struct ps_prochandle *);
/*
* Iteration function that iterates over all load objects *and the
* executable*
*
* If the callback routine returns:
* 0 - continue processing link objects
* non zero - stop calling the callback function
*
*/
ps_err_e
ps_loadobj_iter(const struct ps_prochandle *, ps_iter_f *, void *clnt_data);
/*
* Address => function name mapping
*
* Given an address, returns a pointer to the function's
* linker name (null terminated).
*/
ps_err_e
ps_find_fun_name(const struct ps_prochandle *, psaddr_t addr,
const char **name);
/*
* Interface to LD_PRELOAD. LD_PRELOAD given library across the
* program 'exec'.
*
*/
/*
* Append/Prepend the 'lib' (has to be library name as understood by LD_PRELOAD)
* to the LD_PRELOAD variable setting to be used by the debugee
* Returns a cookie (in id).
*/
ps_err_e
ps_ld_preload_append(const char *lib, int *id);
ps_err_e
ps_ld_preload_prepend(const char *lib, int *id);
/*
* Remove the library associated with 'id' from the LD_PRELOAD setting.
*
*/
ps_err_e
ps_ld_preload_remove(int id);
#ifdef __cplusplus
}
#endif
/*
* The following are C++ only interfaces
*/
#ifdef __cplusplus
/*
* classes ServiceDbx and ServantDbx and defined in "gp_dbx_svc.h" which is
* accessed via CCR
*/
extern class ServantDbx *ps_svnt_generic();
extern class ServiceDbx *ps_svc_generic();
#endif
#endif /* _PROC_SERVICE_2_H */

View file

@ -1,164 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHELL_IMP_H
#define SHELL_IMP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
/*
CCR info
Vesrion history:
1.0 - Initial CCR release
Release information for automatic CCR updates:
BEGIN RELEASE NOTES: (signifies what gets put into CCR release notes)
1.1
- Entry points for va_list style msgs; new shell_imp_vmsg()
and shell_imp_verrmsg()
- shell_imp_env_checker() is now shell_imp_var_checker().
Also the var_checker callback gets passed interp.
1.2 - interposition framework (used by jdbx)
- access to input FILE pointer.
END RELEASE NOTES: (signifies what gets put into CCR release notes)
Following is used as a CCR version number:
#define CCR_SHELL_IMP_VERSION 1.1
*/
#include <stdarg.h>
#define SHELL_IMP_MAJOR 1
#define SHELL_IMP_MINOR 2
#define SHELL_IMP_FLAG_GLOB 0x1
#define SHELL_IMP_FLAG_ARGQ 0x2
typedef void *shell_imp_interp_t;
typedef void *shell_imp_command_t;
typedef int shell_imp_fun_t(shell_imp_interp_t, int, char **, void *);
int
shell_imp_init(
int, /* major version number */
int, /* minor version number */
shell_imp_interp_t, /* interpreter */
int, /* argc */
char *[] /* argv */
);
int
shell_imp_fini(shell_imp_interp_t);
shell_imp_command_t
shell_imp_define_command(char *, /* command name e.g. "tnf" */
shell_imp_fun_t *, /* callback function */
int, /* SHELL_IMP_FLAG_* bit vector */
void *, /* client_data Passed as last arg to
/* callback function */
char * /* help message, e.g. */
/* "enable the specified tnf probes" */
);
int
shell_imp_undefine_command(shell_imp_command_t);
int
shell_imp_var_checker(shell_imp_interp_t,
const char *, /* var name */
int (*)(shell_imp_interp_t, const char*) /* env checker */
);
int
shell_imp_execute(shell_imp_interp_t, const char *);
const char *
shell_imp_get_var(shell_imp_interp_t, const char *);
void
shell_imp_msg(shell_imp_interp_t, const char *, ...);
void
shell_imp_errmsg(shell_imp_interp_t, const char *, ...);
void
shell_imp_vmsg(shell_imp_interp_t, const char *, va_list);
void
shell_imp_verrmsg(shell_imp_interp_t, const char *, va_list);
/*
* Stuff added for 1.2
*/
struct shell_imp_interposition_info_t {
shell_imp_fun_t *
new_func;
void * new_client_data;
shell_imp_fun_t *
original_func;
void * original_client_data;
int original_flags;
};
typedef int shell_imp_dispatcher_t(shell_imp_interp_t, int, char **,
shell_imp_interposition_info_t *);
shell_imp_command_t
shell_imp_interpose(char *name,
shell_imp_fun_t *new_func,
int flags,
void *client_data,
char * description,
shell_imp_dispatcher_t *);
int shell_imp_uninterpose(shell_imp_command_t);
int
shell_imp_dispatch_interposition(shell_imp_interp_t,
shell_imp_interposition_info_t *,
int argc, char *argv[]);
int
shell_imp_dispatch_original(shell_imp_interp_t,
shell_imp_interposition_info_t *,
int argc, char *argv[]);
FILE *
shell_imp_cur_input(shell_imp_interp_t);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,188 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "shell_imp.h"
#include "IOBuf.hpp"
#include <sys/time.h>
#include <thread_db.h>
typedef td_err_e td_init_fn_t();
typedef td_err_e td_ta_new_fn_t(struct ps_prochandle *, td_thragent_t **);
typedef td_err_e td_ta_delete_fn_t(td_thragent_t *);
typedef td_err_e td_ta_map_id2thr_fn_t(const td_thragent_t *, thread_t, td_thrhandle_t *);
typedef td_err_e td_thr_getgregs_fn_t(const td_thrhandle_t *, prgregset_t);
class ServiceabilityAgentDbxModule {
public:
ServiceabilityAgentDbxModule(int major, int minor,
shell_imp_interp_t interp, int argc, char *argv[]);
~ServiceabilityAgentDbxModule();
bool install();
bool uninstall();
/* This is invoked through the dbx command interpreter. It listens
on a socket for commands and does not return until it receives an
"exit" command. At that point control is returned to dbx's main
loop, at which point if the user sends an exit command to dbx's
shell the dbx process will exit. Returns true if completed
successfully, false if an error occurred while running (for
example, unable to bind listening socket). */
bool run();
private:
// This must be shared between the Java and C layers
static const int PORT = 21928;
// Command handlers
bool handleAddressSize(char* data);
bool handlePeekFailFast(char* data);
bool handlePeek(char* data);
bool handlePoke(char* data);
bool handleMapped(char* data);
bool handleLookup(char* data);
bool handleThrGRegs(char* data);
// Input routines
// May mutate addr argument even if result is false
bool scanAddress(char** data, psaddr_t* addr);
// May mutate num argument even if result is false
bool scanUnsignedInt(char** data, unsigned int* num);
// Returns NULL if error occurred while scanning. Otherwise, returns
// newly-allocated character array which must be freed with delete[].
char* scanSymbol(char** data);
// Helper routine: converts ASCII to 4-bit integer. Returns true if
// character is in range, false otherwise.
bool charToNibble(char ascii, int* value);
// Output routines
// Writes an int with no leading or trailing spaces
bool writeInt(int val, int fd);
// Writes an address in hex format with no leading or trailing
// spaces
bool writeAddress(psaddr_t addr, int fd);
// Writes a register in hex format with no leading or trailing
// spaces (addresses and registers might be of different size)
bool writeRegister(prgreg_t reg, int fd);
// Writes a space to given file descriptor
bool writeSpace(int fd);
// Writes carriage return to given file descriptor
bool writeCR(int fd);
// Writes a bool as [0|1]
bool writeBoolAsInt(bool val, int fd);
// Helper routine: converts low 4 bits to ASCII [0..9][A..F]
char nibbleToChar(unsigned char nibble);
// Base routine called by most of the above
bool writeString(const char* str, int fd);
// Writes a binary character
bool writeBinChar(char val, int fd);
// Writes a binary unsigned int in network (big-endian) byte order
bool writeBinUnsignedInt(unsigned int val, int fd);
// Writes a binary buffer
bool writeBinBuf(char* buf, int size, int fd);
// Routine to flush the socket
bool flush(int client_socket);
void cleanup(int client_socket);
// The shell interpreter on which we can invoke commands (?)
shell_imp_interp_t _interp;
// The "command line" arguments passed to us by dbx (?)
int _argc;
char **_argv;
// The installed command in the dbx shell
shell_imp_command_t _command;
// Access to libthread_db (dlsym'ed to be able to pick up the
// version loaded by dbx)
td_init_fn_t* td_init_fn;
td_ta_new_fn_t* td_ta_new_fn;
td_ta_delete_fn_t* td_ta_delete_fn;
td_ta_map_id2thr_fn_t* td_ta_map_id2thr_fn;
td_thr_getgregs_fn_t* td_thr_getgregs_fn;
// Our "thread agent" -- access to libthread_db
td_thragent_t* _tdb_agent;
// Path to libthread.so in target process; free with delete[]
char* libThreadName;
// Handle to dlopen'ed libthread_db.so
void* libThreadDB;
// Helper callback for finding libthread_db.so
friend int findLibThreadCB(const rd_loadobj_t* lo, void* data);
// Support for reading C strings out of the target process (so we
// can find the correct libthread_db). Returns newly-allocated char*
// which must be freed with delete[], or null if the read failed.
char* readCStringFromProcess(psaddr_t addr);
IOBuf myComm;
// Output buffer support (used by writeString, writeChar, flush)
char* output_buffer;
int output_buffer_size;
int output_buffer_pos;
// "Fail fast" flag
bool peek_fail_fast;
// Commands
static const char* CMD_ADDRESS_SIZE;
static const char* CMD_PEEK_FAIL_FAST;
static const char* CMD_PEEK;
static const char* CMD_POKE;
static const char* CMD_MAPPED;
static const char* CMD_LOOKUP;
static const char* CMD_THR_GREGS;
static const char* CMD_EXIT;
};
// For profiling. Times reported are in milliseconds.
class Timer {
public:
Timer();
~Timer();
void start();
void stop();
long total();
long average();
void reset();
private:
struct timeval startTime;
long long totalMicroseconds; // stored internally in microseconds
int counter;
long long timevalDiff(struct timeval* startTime, struct timeval* endTime);
};

View file

@ -1,66 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _BASIC_LIST_
#define _BASIC_LIST_
#include <vector>
template<class T>
class BasicList {
protected:
typedef std::vector<T> InternalListType;
InternalListType internalList;
public:
BasicList() {
}
virtual ~BasicList() {
}
void add(T arg) {
internalList.push_back(arg);
}
bool remove(T arg) {
for (InternalListType::iterator iter = internalList.begin();
iter != internalList.end(); iter++) {
if (*iter == arg) {
internalList.erase(iter);
return true;
}
}
return false;
}
int size() {
return internalList.size();
}
T get(int index) {
return internalList[index];
}
};
#endif // #defined _BASIC_LIST_

View file

@ -1,110 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "Buffer.hpp"
#include <string.h>
Buffer::Buffer(int bufSize) {
buf = new char[bufSize];
sz = bufSize;
fill = 0;
drain = 0;
}
Buffer::~Buffer() {
delete[] buf;
}
char*
Buffer::fillPos() {
return buf + fill;
}
int
Buffer::remaining() {
return sz - fill;
}
int
Buffer::size() {
return sz;
}
bool
Buffer::incrFillPos(int amt) {
if (fill + amt >= sz) {
return false;
}
fill += amt;
return true;
}
int
Buffer::readByte() {
if (drain < fill) {
return buf[drain++] & 0xFF;
} else {
return -1;
}
}
int
Buffer::readBytes(char* data, int len) {
int numRead = 0;
while (numRead < len) {
int c = readByte();
if (c < 0) break;
data[numRead++] = (char) c;
}
return numRead;
}
char*
Buffer::drainPos() {
return buf + drain;
}
int
Buffer::drainRemaining() {
return fill - drain;
}
bool
Buffer::incrDrainPos(int amt) {
if (drainRemaining() < amt) {
return false;
}
drain += amt;
return true;
}
void
Buffer::compact() {
// Copy down data
memmove(buf, buf + drain, fill - drain);
// Adjust positions
fill -= drain;
drain = 0;
}

View file

@ -1,68 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _BUFFER_
#define _BUFFER_
// A Buffer is the backing store for the IOBuf abstraction and
// supports producer-consumer filling and draining.
class Buffer {
public:
Buffer(int bufSize);
~Buffer();
char* fillPos(); // Position of the place where buffer should be filled
int remaining(); // Number of bytes that can be placed starting at fillPos
int size(); // Size of the buffer
// Move up fill position by amount (decreases remaining()); returns
// false if not enough space
bool incrFillPos(int amt);
// Read single byte (0..255); returns -1 if no data available.
int readByte();
// Read multiple bytes, non-blocking (this buffer does not define a
// fill mechanism), into provided buffer. Returns number of bytes read.
int readBytes(char* buf, int len);
// Access to drain position. Be very careful using this.
char* drainPos();
int drainRemaining();
bool incrDrainPos(int amt);
// Compact buffer, removing already-consumed input. This must be
// called periodically to yield the illusion of an infinite buffer.
void compact();
private:
Buffer(const Buffer&);
Buffer& operator=(const Buffer&);
char* buf;
int sz;
int fill;
int drain;
};
#endif // #defined _BUFFER_

View file

@ -1,115 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdio.h>
#include <string.h>
#include "dispatcher.hpp"
const char* CMD_ASCII = "ascii";
const char* CMD_UNICODE = "unicode";
const char* CMD_PROCLIST = "proclist";
const char* CMD_ATTACH = "attach";
const char* CMD_DETACH = "detach";
const char* CMD_LIBINFO = "libinfo";
const char* CMD_PEEK = "peek";
const char* CMD_POKE = "poke";
const char* CMD_THREADLIST = "threadlist";
const char* CMD_DUPHANDLE = "duphandle";
const char* CMD_CLOSEHANDLE = "closehandle";
const char* CMD_GETCONTEXT = "getcontext";
const char* CMD_SETCONTEXT = "setcontext";
const char* CMD_SELECTORENTRY = "selectorentry";
const char* CMD_SUSPEND = "suspend";
const char* CMD_RESUME = "resume";
const char* CMD_POLLEVENT = "pollevent";
const char* CMD_CONTINUEEVENT = "continueevent";
const char* CMD_EXIT = "exit";
// Uncomment the #define below to get messages on stderr
// #define DEBUGGING
void
Dispatcher::dispatch(char* cmd, Handler* handler) {
if (!strncmp(cmd, CMD_ASCII, strlen(CMD_ASCII))) {
handler->ascii(cmd + strlen(CMD_ASCII));
} else if (!strncmp(cmd, CMD_UNICODE, strlen(CMD_UNICODE))) {
handler->unicode(cmd + strlen(CMD_UNICODE));
} else if (!strncmp(cmd, CMD_PROCLIST, strlen(CMD_PROCLIST))) {
handler->procList(cmd + strlen(CMD_PROCLIST));
} else if (!strncmp(cmd, CMD_ATTACH, strlen(CMD_ATTACH))) {
handler->attach(cmd + strlen(CMD_ATTACH));
} else if (!strncmp(cmd, CMD_DETACH, strlen(CMD_DETACH))) {
handler->detach(cmd + strlen(CMD_DETACH));
} else if (!strncmp(cmd, CMD_LIBINFO, strlen(CMD_LIBINFO))) {
handler->libInfo(cmd + strlen(CMD_LIBINFO));
} else if (!strncmp(cmd, CMD_PEEK, strlen(CMD_PEEK))) {
handler->peek(cmd + strlen(CMD_PEEK));
} else if (!strncmp(cmd, CMD_POKE, strlen(CMD_POKE))) {
handler->poke(cmd + strlen(CMD_POKE));
} else if (!strncmp(cmd, CMD_THREADLIST, strlen(CMD_THREADLIST))) {
handler->threadList(cmd + strlen(CMD_THREADLIST));
} else if (!strncmp(cmd, CMD_DUPHANDLE, strlen(CMD_DUPHANDLE))) {
handler->dupHandle(cmd + strlen(CMD_DUPHANDLE));
} else if (!strncmp(cmd, CMD_CLOSEHANDLE, strlen(CMD_CLOSEHANDLE))) {
handler->closeHandle(cmd + strlen(CMD_CLOSEHANDLE));
} else if (!strncmp(cmd, CMD_GETCONTEXT, strlen(CMD_GETCONTEXT))) {
handler->getContext(cmd + strlen(CMD_GETCONTEXT));
} else if (!strncmp(cmd, CMD_SETCONTEXT, strlen(CMD_SETCONTEXT))) {
handler->setContext(cmd + strlen(CMD_SETCONTEXT));
} else if (!strncmp(cmd, CMD_SELECTORENTRY, strlen(CMD_SELECTORENTRY))) {
handler->selectorEntry(cmd + strlen(CMD_SELECTORENTRY));
} else if (!strncmp(cmd, CMD_SUSPEND, strlen(CMD_SUSPEND))) {
handler->suspend(cmd + strlen(CMD_SUSPEND));
} else if (!strncmp(cmd, CMD_RESUME, strlen(CMD_RESUME))) {
handler->resume(cmd + strlen(CMD_RESUME));
} else if (!strncmp(cmd, CMD_POLLEVENT, strlen(CMD_POLLEVENT))) {
handler->pollEvent(cmd + strlen(CMD_POLLEVENT));
} else if (!strncmp(cmd, CMD_CONTINUEEVENT, strlen(CMD_CONTINUEEVENT))) {
handler->continueEvent(cmd + strlen(CMD_CONTINUEEVENT));
} else if (!strcmp(cmd, CMD_EXIT)) {
handler->exit(cmd + strlen(CMD_EXIT));
}
#ifdef DEBUGGING
else fprintf(stderr, "Ignoring illegal command \"%s\"\n", cmd);
#endif
}

View file

@ -1,38 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _DISPATCHER_
#define _DISPATCHER_
#include "Handler.hpp"
/** This class understands the commands supported by the system and
calls the appropriate handler routines. */
class Dispatcher {
public:
static void dispatch(char* cmd, Handler* handler);
};
#endif // #defined _DISPATCHER_

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _HANDLER_
#define _HANDLER_
/** An abstract base class encapsulating the handlers for all commands
understood by the system. */
class Handler {
public:
virtual void ascii(char* arg) = 0;
virtual void unicode(char* arg) = 0;
virtual void procList(char* arg) = 0;
virtual void attach(char* arg) = 0;
virtual void detach(char* arg) = 0;
virtual void libInfo(char* arg) = 0;
virtual void peek(char* arg) = 0;
virtual void poke(char* arg) = 0;
virtual void threadList(char* arg) = 0;
virtual void dupHandle(char* arg) = 0;
virtual void closeHandle(char* arg) = 0;
virtual void getContext(char* arg) = 0;
virtual void setContext(char* arg) = 0;
virtual void selectorEntry(char* arg) = 0;
virtual void suspend(char* arg) = 0;
virtual void resume(char* arg) = 0;
virtual void pollEvent(char* arg) = 0;
virtual void continueEvent(char* arg) = 0;
virtual void exit(char* arg) = 0;
};
#endif // #defined _HANDLER_

View file

@ -1,490 +0,0 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdio.h>
// This file is currently used for os/solaris/agent too. At some point in time
// the source will be reorganized to avoid these ifdefs.
#ifdef __sun
#include <string.h>
#include <inttypes.h>
#include <sys/byteorder.h>
#endif
#include "IOBuf.hpp"
// Formats for printing pointers
#ifdef _LP64
# define INTPTR_FORMAT "0x%016lx"
#else /* ! _LP64 */
# define INTPTR_FORMAT "0x%08lx"
#endif /* _LP64 */
// Uncomment the #define below to get messages on stderr
// #define DEBUGGING
IOBuf::IOBuf(int inLen, int outLen) {
inBuf = new Buffer(inLen);
outBuf = new Buffer(outLen);
fd = INVALID_SOCKET;
outHandle = NULL;
usingSocket = true;
reset();
}
IOBuf::~IOBuf() {
delete inBuf;
delete outBuf;
}
void
IOBuf::setSocket(SOCKET sock) {
fd = sock;
usingSocket = true;
}
// Reading/writing files is only needed and used on windows.
#ifdef WIN32
void
IOBuf::setOutputFileHandle(HANDLE handle) {
outHandle = handle;
usingSocket = false;
}
#endif
void
IOBuf::reset() {
gotDataLastTime = false;
state = TEXT_STATE;
binPos = 0;
binLength = 0;
}
IOBuf::ReadLineResult
IOBuf::tryReadLine() {
return doReadLine(false);
}
char*
IOBuf::readLine() {
ReadLineResult rr = doReadLine(true);
if (rr != RL_GOT_DATA) {
return NULL;
}
return getLine();
}
IOBuf::ReadLineResult
IOBuf::doReadLine(bool shouldWait) {
if (!usingSocket) {
return IOBuf::RL_ERROR;
}
if (gotDataLastTime) {
curLine.clear();
}
int c;
do {
c = readChar(shouldWait);
if (c >= 0) {
Action act = processChar((char) c);
if (act == GOT_LINE) {
curLine.push_back('\0');
gotDataLastTime = true;
return IOBuf::RL_GOT_DATA;
} else if (act == SKIP_EOL_CHAR) {
// Do nothing
} else {
curLine.push_back((char) c);
}
}
} while (shouldWait || c >= 0);
gotDataLastTime = false;
return IOBuf::RL_NO_DATA;
}
bool
IOBuf::flushImpl(bool moreDataToCome) {
int numWritten = 0;
#ifdef WIN32
// When running on Windows and using IOBufs for inter-process
// communication, we need to write metadata into the stream
// indicating how many bytes are coming down. Five bytes are written
// per flush() call, four containing the integer number of bytes
// coming (not including the five-byte header) and one (a 0 or 1)
// indicating whether there is more data coming.
if (!usingSocket) {
int numToWrite = outBuf->drainRemaining();
char moreToCome = (moreDataToCome ? 1 : 0);
DWORD numBytesWritten;
if (!WriteFile(outHandle, &numToWrite, sizeof(int), &numBytesWritten, NULL)) {
return false;
}
if (numBytesWritten != sizeof(int)) {
return false;
}
if (!WriteFile(outHandle, &moreToCome, 1, &numBytesWritten, NULL)) {
return false;
}
if (numBytesWritten != 1) {
return false;
}
}
#endif
while (outBuf->drainRemaining() != 0) {
#ifdef DEBUGGING
fprintf(stderr, "Flushing %d bytes\n", outBuf->drainRemaining());
#endif
if (usingSocket) {
numWritten = send(fd, outBuf->drainPos(), outBuf->drainRemaining(), 0);
} else {
#ifdef WIN32
DWORD numBytesWritten;
if (!WriteFile(outHandle, outBuf->drainPos(), outBuf->drainRemaining(), &numBytesWritten, NULL)) {
numWritten = -1;
} else {
numWritten = numBytesWritten;
}
#endif
}
if (numWritten != -1) {
#ifdef DEBUGGING
fprintf(stderr, "Flushed %d bytes\n", numWritten);
#endif
outBuf->incrDrainPos(numWritten);
} else {
return false;
}
}
outBuf->compact();
return true;
}
int
IOBuf::readChar(bool block) {
do {
int c = inBuf->readByte();
if (c >= 0) {
return c;
}
// See whether we need to compact the input buffer
if (inBuf->remaining() < inBuf->size() / 2) {
inBuf->compact();
}
// See whether socket is ready
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (block || select(1 + fd, &fds, NULL, NULL, &timeout) > 0) {
if (block || FD_ISSET(fd, &fds)) {
#ifdef DEBUGGING
int b = (block ? 1 : 0);
fprintf(stderr, "calling recv: block = %d\n", b);
#endif
// Read data from socket
int numRead = recv(fd, inBuf->fillPos(), inBuf->remaining(), 0);
if (numRead < 0) {
#ifdef DEBUGGING
fprintf(stderr, "recv failed\n");
#endif
return -1;
}
inBuf->incrFillPos(numRead);
}
}
} while (block);
return inBuf->readByte();
}
char*
IOBuf::getLine() {
#ifdef DEBUGGING
fprintf(stderr, "Returning (first 10 chars) \"%.10s\"\n", curLine.begin());
#endif
return curLine.begin();
}
bool
IOBuf::flush() {
return flushImpl(false);
}
bool
IOBuf::writeString(const char* str) {
int len = strlen(str);
if (len > outBuf->size()) {
return false;
}
if (len > outBuf->remaining()) {
if (!flushImpl(true)) {
return false;
}
}
// NOTE we do not copy the null terminator of the string.
strncpy(outBuf->fillPos(), str, len);
outBuf->incrFillPos(len);
return true;
}
bool
IOBuf::writeInt(int val) {
char buf[128];
sprintf(buf, "%d", val);
return writeString(buf);
}
bool
IOBuf::writeUnsignedInt(unsigned int val) {
char buf[128];
sprintf(buf, "%u", val);
return writeString(buf);
}
bool
IOBuf::writeBoolAsInt(bool val) {
if (val) {
return writeString("1");
} else {
return writeString("0");
}
}
bool
IOBuf::writeAddress(void* val) {
char buf[128];
sprintf(buf, INTPTR_FORMAT, val);
return writeString(buf);
}
bool
IOBuf::writeSpace() {
return writeString(" ");
}
bool
IOBuf::writeEOL() {
return writeString("\n\r");
}
bool
IOBuf::writeBinChar(char c) {
return writeBinBuf((char*) &c, sizeof(c));
}
bool
IOBuf::writeBinUnsignedShort(unsigned short i) {
i = htons(i);
return writeBinBuf((char*) &i, sizeof(i));
}
bool
IOBuf::writeBinUnsignedInt(unsigned int i) {
i = htonl(i);
return writeBinBuf((char*) &i, sizeof(i));
}
bool
IOBuf::writeBinBuf(char* buf, int size) {
while (size > 0) {
int spaceRemaining = outBuf->remaining();
if (spaceRemaining == 0) {
if (!flushImpl(true)) {
return false;
}
spaceRemaining = outBuf->remaining();
}
int toCopy = (size > spaceRemaining) ? spaceRemaining : size;
memcpy(outBuf->fillPos(), buf, toCopy);
outBuf->incrFillPos(toCopy);
buf += toCopy;
size -= toCopy;
if (size > 0) {
if (!flushImpl(true)) {
return false;
}
}
}
return true;
}
#ifdef WIN32
IOBuf::FillState
IOBuf::fillFromFileHandle(HANDLE fh, DWORD* numBytesRead) {
int totalToRead;
char moreToCome;
outBuf->compact();
DWORD numRead;
if (!ReadFile(fh, &totalToRead, sizeof(int), &numRead, NULL)) {
return FAILED;
}
if (numRead != sizeof(int)) {
return FAILED;
}
if (!ReadFile(fh, &moreToCome, 1, &numRead, NULL)) {
return FAILED;
}
if (numRead != 1) {
return FAILED;
}
if (outBuf->remaining() < totalToRead) {
return FAILED;
}
int tmp = totalToRead;
while (totalToRead > 0) {
if (!ReadFile(fh, outBuf->fillPos(), totalToRead, &numRead, NULL)) {
return FAILED;
}
outBuf->incrFillPos((int) numRead);
totalToRead -= numRead;
}
*numBytesRead = tmp;
return ((moreToCome == 0) ? DONE : MORE_DATA_PENDING);
}
#endif
bool
IOBuf::isBinEscapeChar(char c) {
return (c == '|');
}
IOBuf::Action
IOBuf::processChar(char c) {
Action action = NO_ACTION;
switch (state) {
case TEXT_STATE: {
// Looking for text char, bin escape char, or EOL
if (isBinEscapeChar(c)) {
#ifdef DEBUGGING
fprintf(stderr, "[a: '%c'] ", inBuf[0]);
#endif
binPos = 0;
#ifdef DEBUGGING
fprintf(stderr, "[b: '%c'] ", inBuf[0]);
#endif
binLength = 0;
#ifdef DEBUGGING
fprintf(stderr, "[c: '%c'] ", inBuf[0]);
#endif
state = BIN_STATE;
#ifdef DEBUGGING
fprintf(stderr, "[d: '%c'] ", inBuf[0]);
#endif
#ifdef DEBUGGING
fprintf(stderr, "\nSwitching to BIN_STATE\n");
#endif
} else if (isEOL(c)) {
state = EOL_STATE;
action = GOT_LINE;
#ifdef DEBUGGING
fprintf(stderr, "\nSwitching to EOL_STATE (GOT_LINE)\n");
#endif
}
#ifdef DEBUGGING
else {
fprintf(stderr, "'%c' ", c);
fflush(stderr);
}
#endif
break;
}
case BIN_STATE: {
// Seeking to finish read of input
if (binPos < 4) {
int cur = c & 0xFF;
binLength <<= 8;
binLength |= cur;
++binPos;
} else {
#ifdef DEBUGGING
fprintf(stderr, "Reading binary byte %d of %d\n",
binPos - 4, binLength);
#endif
++binPos;
if (binPos == 4 + binLength) {
state = TEXT_STATE;
#ifdef DEBUGGING
fprintf(stderr, "Switching to TEXT_STATE\n");
#endif
}
}
break;
}
case EOL_STATE: {
// More EOL characters just cause us to re-enter this state
if (isEOL(c)) {
action = SKIP_EOL_CHAR;
} else if (isBinEscapeChar(c)) {
binPos = 0;
binLength = 0;
state = BIN_STATE;
} else {
state = TEXT_STATE;
#ifdef DEBUGGING
fprintf(stderr, "'%c' ", c);
fflush(stderr);
#endif
}
break;
}
} // switch
return action;
}
bool
IOBuf::isEOL(char c) {
#ifdef WIN32
return ((c == '\n') || (c == '\r'));
#elif defined(__sun)
return c == '\n';
#else
#error Please port isEOL() to your platform
return false;
#endif
}

View file

@ -1,222 +0,0 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _IO_BUF_
#define _IO_BUF_
// This file is currently used for os/solaris/agent/ too. At some point in time
// the source will be reorganized to avoid these ifdefs.
// Note that this class can read/write from a file as well as a socket. This
// file capability is only implemented on win32.
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
// These are from win32 winsock2.h
typedef unsigned int SOCKET;
typedef void * HANDLE;
typedef unsigned long DWORD;
#define INVALID_SOCKET (SOCKET)(~0)
#endif
#include <vector>
#include "Buffer.hpp"
/** Manages an input/output buffer pair for a socket or file handle. */
class IOBuf {
public:
IOBuf(int inBufLen, int outBufLen);
~IOBuf();
enum ReadLineResult {
RL_GOT_DATA,
RL_NO_DATA,
RL_ERROR
};
/** Change the socket with which this buffer is associated */
void setSocket(SOCKET sock);
// Reading/writing files is only supported on windows.
#ifdef WIN32
/** Change the output file handle with which this buffer is
associated. Currently IOBufs can not be used to read from a file
handle. */
void setOutputFileHandle(HANDLE handle);
#endif
/** Reset the input and output buffers, without flushing the output
data to the socket */
void reset();
/** Try to read a line of data from the given socket without
blocking. If was able to read a complete line of data, returns a
character pointer to the beginning of the (null-terminated)
string. If not, returns NULL, but maintains enough state that
subsequent calls to tryReadLine() will not ignore the data
already read. NOTE: this skips end-of-line characters (typically
CR/LF) as defined by "isEOL()". When switching back and forth
between binary and text modes, to be sure no data is lost, pad
the beginning and end of the binary transmission with bytes
which can not be confused with these characters. */
ReadLineResult tryReadLine();
/** Read a line of data from the given socket, blocking until a
line, including EOL, appears. Return the line, or NULL if
something goes wrong. */
char *readLine();
/** Get the pointer to the beginning of the (null-terminated) line.
This should only be called if tryReadLine() has returned
RL_GOT_DATA. This sets the "parsing cursor" to the beginning of
the line. */
char* getLine();
// NOTE: any further data-acquisition routines must ALWAYS call
// fixupData() at the beginning!
//----------------------------------------------------------------------
// Output routines
//
/** Flush the output buffer to the socket. Returns true if
succeeded, false if write error occurred. */
bool flush();
/** Write the given string to the output buffer. May flush if output
buffer becomes too full to store the data. Not guaranteed to
work if string is longer than the size of the output buffer.
Does not include the null terminator of the string. Returns true
if succeeded, false if write error occurred. */
bool writeString(const char* str);
/** Write the given int to the output buffer. May flush if output
buffer becomes too full to store the data. Returns true if
succeeded, false if write error occurred. */
bool writeInt(int val);
/** Write the given unsigned int to the output buffer. May flush if
output buffer becomes too full to store the data. Returns true
if succeeded, false if write error occurred. */
bool writeUnsignedInt(unsigned int val);
/** Write the given boolean to the output buffer. May flush if
output buffer becomes too full to store the data. Returns true
if succeeded, false if write error occurred. */
bool writeBoolAsInt(bool val);
/** Write the given address to the output buffer. May flush if
output buffer becomes too full to store the data. Returns true
if succeeded, false if write error occurred. */
bool writeAddress(void* val);
/** Writes a space to the output buffer. May flush if output buffer
becomes too full to store the data. Returns true if succeeded,
false if write error occurred. */
bool writeSpace();
/** Writes an end-of-line sequence to the output buffer. May flush
if output buffer becomes too full to store the data. Returns
true if succeeded, false if write error occurred. */
bool writeEOL();
/** Writes a binary character to the output buffer. */
bool writeBinChar(char c);
/** Writes a binary unsigned short in network (big-endian) byte
order to the output buffer. */
bool writeBinUnsignedShort(unsigned short i);
/** Writes a binary unsigned int in network (big-endian) byte order
to the output buffer. */
bool writeBinUnsignedInt(unsigned int i);
/** Writes a binary buffer to the output buffer. */
bool writeBinBuf(char* buf, int size);
#ifdef WIN32
enum FillState {
DONE = 1,
MORE_DATA_PENDING = 2,
FAILED = 3
};
/** Very specialized routine; fill the output buffer from the given
file handle. Caller is responsible for ensuring that there is
data to be read on the file handle. */
FillState fillFromFileHandle(HANDLE fh, DWORD* numRead);
#endif
/** Binary utility routine (for poke) */
static bool isBinEscapeChar(char c);
private:
IOBuf(const IOBuf&);
IOBuf& operator=(const IOBuf&);
// Returns -1 if non-blocking and no data available
int readChar(bool block);
// Line-oriented reading
std::vector<char> curLine;
bool gotDataLastTime;
ReadLineResult doReadLine(bool);
bool flushImpl(bool moreDataToCome);
SOCKET fd;
HANDLE outHandle;
bool usingSocket;
// Buffers
Buffer* inBuf;
Buffer* outBuf;
// Simple finite-state machine to handle binary data
enum State {
TEXT_STATE,
BIN_STATE,
EOL_STATE
};
enum Action {
NO_ACTION,
GOT_LINE, // TEXT_STATE -> EOL_STATE transition
SKIP_EOL_CHAR // EOL_STATE -> EOL_STATE transition
};
State state;
Action processChar(char c);
// Handling incoming binary buffers (poke command)
int binPos; // Number of binary characters read so far;
// total number to read is binLength + 4
int binLength; // Number of binary characters in message;
// not valid until binPos >= 4
bool isEOL(char c);
};
#endif // #defined _IO_BUF_

View file

@ -1,54 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _LOCKABLE_LIST_
#define _LOCKABLE_LIST_
#include <windows.h>
#include "BasicList.hpp"
template<class T>
class LockableList : public BasicList<T> {
private:
CRITICAL_SECTION crit;
public:
LockableList() {
InitializeCriticalSection(&crit);
}
~LockableList() {
DeleteCriticalSection(&crit);
}
void lock() {
EnterCriticalSection(&crit);
}
void unlock() {
LeaveCriticalSection(&crit);
}
};
#endif // #defined _LOCKABLE_LIST_

View file

@ -1,80 +0,0 @@
#
# Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
SERVER=SwDbgSrv.exe
SUBPROCESS=SwDbgSub.exe
SERVER_SOURCES = \
Buffer.cpp \
Dispatcher.cpp \
initWinsock.cpp \
IOBuf.cpp \
ioUtils.cpp \
isNT4.cpp \
nt4internals.cpp \
procList.cpp \
Reaper.cpp \
SwDbgSrv.cpp \
serverLists.cpp \
toolHelp.cpp
SUBPROCESS_SOURCES = \
SwDbgSub.cpp \
Buffer.cpp \
IOBuf.cpp \
isNT4.cpp \
libInfo.cpp \
Monitor.cpp \
nt4internals.cpp \
toolHelp.cpp
SERVER_OBJS = $(SERVER_SOURCES:.cpp=.obj)
SUBPROCESS_OBJS = $(SUBPROCESS_SOURCES:.cpp=.obj)
CPP=cl.exe
LINK32=link.exe
# These do not need to be optimized (don't run a lot of code) and it
# will be useful to have the assertion checks in place
CFLAGS=/nologo /MD /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
LIBS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib \
ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib \
winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib \
odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386
default: $(SERVER) $(SUBPROCESS)
$(SERVER): $(SERVER_OBJS)
$(LINK32) /out:$@ $(SERVER_OBJS) $(LIBS)
$(SUBPROCESS): $(SUBPROCESS_OBJS)
$(LINK32) /out:$@ $(SUBPROCESS_OBJS) $(LIBS)
clean:
rm -f *.obj *.idb *.pch *.pdb *.ncb *.opt *.plg *.exe *.ilk
.cpp.obj:
@ $(CPP) $(CFLAGS) /o $@ $<

View file

@ -1,123 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _MESSAGE_
#define _MESSAGE_
// These are the commands sent from the server to the child processes
// over the child processes' stdin pipes. A subset of the commands
// understood by the overall system, these require responses from the
// child process. Having a data structure rather than sending text
// simplifies parsing on the child side. The child replies by sending
// back fully-formatted replies which are copied by the server process
// to the clients' sockets.
struct PeekArg {
DWORD address;
DWORD numBytes;
};
// NOTE: when sending a PokeArg to the child process, we handle the
// buffer specially
struct PokeArg {
DWORD address;
DWORD numBytes;
void* data;
};
// Used for continueevent
struct BoolArg {
bool val;
};
// Used for duphandle, closehandle, and getcontext
struct HandleArg {
HANDLE handle;
};
// Used for setcontext
const int NUM_REGS_IN_CONTEXT = 22;
struct SetContextArg {
HANDLE handle;
DWORD Eax;
DWORD Ebx;
DWORD Ecx;
DWORD Edx;
DWORD Esi;
DWORD Edi;
DWORD Ebp;
DWORD Esp;
DWORD Eip;
DWORD Ds;
DWORD Es;
DWORD Fs;
DWORD Gs;
DWORD Cs;
DWORD Ss;
DWORD EFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
};
// Used for selectorentry
struct SelectorEntryArg {
HANDLE handle;
DWORD selector;
};
struct Message {
typedef enum {
ATTACH,
DETACH,
LIBINFO,
PEEK,
POKE,
THREADLIST,
DUPHANDLE,
CLOSEHANDLE,
GETCONTEXT,
SETCONTEXT,
SELECTORENTRY,
SUSPEND,
RESUME,
POLLEVENT,
CONTINUEEVENT
} Type;
Type type;
union {
PeekArg peekArg;
PokeArg pokeArg;
BoolArg boolArg;
HandleArg handleArg;
SetContextArg setContextArg;
SelectorEntryArg selectorArg;
};
};
#endif // #defined _MESSAGE_

View file

@ -1,176 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdio.h>
#include <assert.h>
#include "Monitor.hpp"
Monitor::Monitor() {
_lock_count = -1; // No threads have entered the critical section
_owner = NULL;
_lock_event = CreateEvent(NULL, false, false, NULL);
_wait_event = CreateEvent(NULL, true, false, NULL);
_counter = 0;
_tickets = 0;
_waiters = 0;
}
Monitor::~Monitor() {
assert(_owner == NULL); // Otherwise, owned monitor being deleted
assert(_lock_count == -1); // Otherwise, monitor being deleted with non -1 lock count
CloseHandle(_lock_event);
CloseHandle(_wait_event);
}
void
Monitor::lock() {
if (InterlockedIncrement(&_lock_count) == 0) {
// Success, we now own the lock
} else {
DWORD dwRet = WaitForSingleObject((HANDLE)_lock_event, INFINITE);
assert(dwRet == WAIT_OBJECT_0); // Unexpected return value from WaitForSingleObject
}
assert(owner() == NULL); // Otherwise, lock count and owner are inconsistent
setOwner(GetCurrentThread());
}
void
Monitor::unlock() {
setOwner(NULL);
if (InterlockedDecrement(&_lock_count) >= 0) {
// Wake a waiting thread up
DWORD dwRet = SetEvent(_lock_event);
assert(dwRet != 0); // Unexpected return value from SetEvent
}
}
bool
Monitor::wait(long timeout) {
assert(owner() != NULL);
assert(owner() == GetCurrentThread());
// 0 means forever. Convert to Windows specific code.
DWORD timeout_value = (timeout == 0) ? INFINITE : timeout;
DWORD which;
long c = _counter;
bool retry = false;
_waiters++;
// Loop until condition variable is signaled. The event object is
// set whenever the condition variable is signaled, and tickets will
// reflect the number of threads which have been notified. The counter
// field is used to make sure we don't respond to notifications that
// have occurred *before* we started waiting, and is incremented each
// time the condition variable is signaled.
while (true) {
// Leave critical region
unlock();
// If this is a retry, let other low-priority threads have a chance
// to run. Make sure that we sleep outside of the critical section.
if (retry) {
Sleep(1);
} else {
retry = true;
}
which = WaitForSingleObject(_wait_event, timeout_value);
// Enter critical section
lock();
if (_tickets != 0 && _counter != c) break;
if (which == WAIT_TIMEOUT) {
--_waiters;
return true;
}
}
_waiters--;
// If this was the last thread to be notified, then we need to reset
// the event object.
if (--_tickets == 0) {
ResetEvent(_wait_event);
}
return false;
}
// Notify a single thread waiting on this monitor
bool
Monitor::notify() {
assert(ownedBySelf()); // Otherwise, notify on unknown thread
if (_waiters > _tickets) {
if (!SetEvent(_wait_event)) {
return false;
}
_tickets++;
_counter++;
}
return true;
}
// Notify all threads waiting on this monitor
bool
Monitor::notifyAll() {
assert(ownedBySelf()); // Otherwise, notifyAll on unknown thread
if (_waiters > 0) {
if (!SetEvent(_wait_event)) {
return false;
}
_tickets = _waiters;
_counter++;
}
return true;
}
HANDLE
Monitor::owner() {
return _owner;
}
void
Monitor::setOwner(HANDLE owner) {
if (owner != NULL) {
assert(_owner == NULL); // Setting owner thread of already owned monitor
assert(owner == GetCurrentThread()); // Else should not be doing this
} else {
HANDLE oldOwner = _owner;
assert(oldOwner != NULL); // Removing the owner thread of an unowned mutex
assert(oldOwner == GetCurrentThread());
}
_owner = owner;
}
bool
Monitor::ownedBySelf() {
return (_owner == GetCurrentThread());
}

View file

@ -1,58 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _MONITOR_
#define _MONITOR_
#include <windows.h>
class Monitor {
public:
Monitor();
~Monitor();
void lock();
void unlock();
// Default time is forever (i.e, zero). Returns true if it times-out, otherwise
// false.
bool wait(long timeout = 0);
bool notify();
bool notifyAll();
private:
HANDLE owner();
void setOwner(HANDLE owner);
bool ownedBySelf();
HANDLE _owner;
long _lock_count;
HANDLE _lock_event; // Auto-reset event for blocking in lock()
HANDLE _wait_event; // Manual-reset event for notifications
long _counter; // Current number of notifications
long _waiters; // Number of threads waiting for notification
long _tickets; // Number of waiters to be notified
};
#endif // #defined _MONITOR_

View file

@ -1,246 +0,0 @@
This debug server uses a largely text-based protocol, except for
certain bulk data transfer operations. All text is in single-byte
US-ASCII except for the strings returned in "proclist".
NOTE that the character '|' (vertical bar) is used as an escape
character to switch the incoming data stream to the debug server into
binary mode, so no text command may contain that character.
Commands understood:
ascii <EOL> ::=
Changes to ASCII mode. This affects all outgoing strings. At
startup the system is in unicode mode.
unicode <EOL> ::=
Changes to UNICODE mode. This affects all outgoing strings. This
is the default mode upon startup.
proclist <EOL> ::=
<int num> [<unsigned int pid> <int charSize> <int numChars> [<binary char_t name>]...]... <EOL>
Returns integer indicating number of processes to follow, followed
by (pid, name) pairs. Names are given by (charSize, numChars,
[char_t]...) tuples; charSize indicates the size of each character
in bytes, numChars the number of characters in the string, and
name the raw data for the string. Each individual character of the
string, if multi-byte, is transmitted in network byte order.
numChars and name are guaranteed to be separated by precisely one
US-ASCII space. If process list is not available because of
limitations of the underlying operating system, number of
processes returned is 0.
attach <int pid> <EOL> ::= <bool result> <EOL>
Attempts to attach to the specified process. Returns 1 if
successful, 0 if not. Will fail if already attached or if the
process ID does not exist. Attaching to a process causes the
process to be suspended.
detach <EOL> ::= <bool result> <EOL>
Detaches from the given process. Attaching and detaching multiple
times during a debugging session is allowed. Detaching causes the
process to resume execution.
libinfo <EOL> ::=
<int numLibs> [<int charSize> <int numChars> [<binary char_t name>]... <address baseAddr>]... <EOL>
May only be called once attached and the target process must be
suspended; otherwise, returns 0. Returns list of the full path
names of all of the loaded modules (including the executable
image) in the target process, as well as the base address at which
each module was relocated. See proclist for format of strings, but
NOTE that charSize is ALWAYS 1 for this particular routine,
regardless of the setting of ASCII/UNICODE.
peek <address addr> <unsigned int numBytes> <EOL> ::=
B<binary char success>
[<binary unsigned int len> <binary char isMapped> [<binary char data>]...]...
NOTE that the binary portion of this message is prefixed by the
uppercase US-ASCII letter 'B', allowing easier synchronization by
clients. There is no data between the 'B' and the rest of the
message.
May only be called once attached. Reads the address space of the
target process starting at the given address (see below for format
specifications) and extending the given number of bytes. Whether
the read succeeded is indicated by a single byte containing a 1 or
0 (success or failure). If successful, the return result is given
in a sequence of ranges. _len_, the length of each range, is
indicated by a 32-bit unsigned integer transmitted with big-endian
byte ordering (i.e., most significant byte first). _isMapped_
indicates whether the range is mapped or unmapped in the target
process's address space, and will contain the value 1 or 0 for
mapped or unmapped, respectively. If the range is mapped,
_isMapped_ is followed by _data_, containing the raw binary data
for the range. The sum of all ranges' lengths is guaranteed to be
equivalent to the number of bytes requested.
poke <address addr> |[<binary unsigned int len> [<binary char data>]] <EOL> ::=
<bool result> <EOL>
NOTE that the binary portion of this message is prefixed by the
uppercase US-ASCII character '|' (vertical bar), allowing easier
synchronization by the server. There is no data between the '|'
and the rest of the message. ('B' is not used here because
addresses can contain that letter; no alphanumeric characters are
used because some of the parsing routines are used by the Solaris
SA port, and in that port any alphanumeric character can show up
as a part of a symbol being looked up.)
May only be called once attached. Writes the address space of the
target process starting at the given address (see below for format
specifications), extending the given number of bytes, and
containing the given data. The number of bytes is a 32-bit
unsigned integer transmitted with big-endian byte ordering (i.e.,
most significant byte first). This is followed by the raw binary
data to be placed at that address. The number of bytes of data
must match the number of bytes specified in the message.
Returns true if the write succeeded; false if it failed, for
example because a portion of the region was not mapped in the
target address space.
threadlist <EOL> ::= <int numThreads> [<address threadHandle>...] <EOL>
May only be called once attached and the target process must be
suspended; otherwise, returns 0. If available, returns handles for
all of the threads in the target process. These handles may be
used as arguments to the getcontext and selectorentry
commands. They do not need to be (and should not be) duplicated
via the duphandle command and must not be closed via the
closehandle command.
duphandle <address handle> <EOL> ::=
<bool success> [<address duplicate>] <EOL>
Duplicates a HANDLE read from the target process's address space.
HANDLE is a Windows construct (typically typedef'd to void *).
The returned handle should ultimately be closed via the
closehandle command; failing to do so can cause resource leaks.
The purpose of this command is to allow the debugger to read the
value of a thread handle from the target process and query its
register set and thread selector entries via the getcontext and
selectorentry commands, below; such use implies that the target
program has its own notion of the thread list, and further, that
the debugger has a way of locating that thread list.
closehandle <address handle> <EOL> ::=
Closes a handle retrieved via the duphandle command, above.
getcontext <address threadHandle> <EOL> ::= <bool success> [<context>] <EOL>
Returns the context for the given thread. The handle must either
be one of the handles returned from the threadlist command or the
result of duplicating a thread handle out of the target process
via the duphandle command. The target process must be suspended.
The context is returned as a series of hex values which represent
the following x86 registers in the following order:
EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP, DS, ES, FS, GS,
CS, SS, EFLAGS, DR0, DR1, DR2, DR3, DR6, DR7
FIXME: needs to be generalized and/or specified for other
architectures.
setcontext <address threadHandle> <context> ::= <bool success> <EOL>
Sets the context of the given thread. The target process must be
suspended. See the getcontext command for the ordering of the
registers in the context.
Even if the setcontext command succeeds, some of the bits in some
of the registers (like the global enable bits in the debug
registers) may be overridden by the operating system. To ensure
the debugger's notion of the register set is up to date, it is
recommended to follow up a setcontext with a getcontext.
selectorentry <address threadHandle> <int selector> <EOL> ::=
<bool success>
[<address limitLow> <address baseLow>
<address baseMid> <address flags1>
<address flags2> <address baseHi>] <EOL>
Retrieves a descriptor table entry for the given thread and
selector. This data structure allows conversion of a
segment-relative address to a linear virtual address. It is most
useful for locating the Thread Information Block for a given
thread handle to be able to find that thread's ID, to be able to
understand whether two different thread handles in fact refer to
the same underlying thread.
This command will only work on the X86 architecture and will
return false for the success flag (with no additional information
sent) on other architectures.
suspend ::=
Suspends the target process. Must be attached to a target process.
A process is suspended when attached to via the attach command. If
the target process is already suspended then this command has no
effect.
resume ::=
Resumes the target process without detaching from it. Must be
attached to a target process. After resuming a target process, the
debugger client must be prepared to poll for events from the
target process fairly frequently in order for execution in the
target process to proceed normally. If the target process is
already resumed then this command has no effect.
pollevent ::=
<bool eventPresent> [<address threadHandle> <unsigned int eventCode>]
Additional entries in result for given eventCode:
LOAD/UNLOAD_DLL_DEBUG_EVENT: <address baseOfDLL>
EXCEPTION_DEBUG_EVENT: <unsigned int exceptionCode> <address faultingPC>
Additional entries for given exceptionCode:
EXCEPTION_ACCESS_VIOLATION: <bool wasWrite> <address faultingAddress>
<EOL>
Polls once to see whether a debug event has been generated by the
target process. If none is present, returns 0 immediately.
Otherwise, returns 1 along with a series of textual information
about the event. The event is not cleared, and the thread resumed,
until the continueevent command is sent, or the debugger client
detaches from the target process.
Typically a debugger client will suspend the target process upon
reception of a debug event. Otherwise, it is not guaranteed that
all threads will be suspended upon reception of a debug event, and
any operations requiring that threads be suspended (including
fetching the context for the thread which generated the event)
will fail.
continueevent <bool passEventToClient> ::= <bool success> <EOL>
Indicates that the current debug event has been used by the
debugger client and that the target process should be resumed. The
passEventToClient flag indicates whether the event should be
propagated to the target process. Breakpoint and single-step
events should not be propagated to the target. Returns false if
there was no pending event, true otherwise.
exit <EOL>
Exits this debugger session.
Format specifications:
// Data formats and example values:
<EOL> ::= end of line (typically \n on Unix platforms, or \n\r on Windows)
<address> ::= 0x12345678[9ABCDEF0] /* up to 64-bit hex value */
<unsigned int> ::= 5 /* up to 32-bit integer number; no leading sign */
<bool> ::= 1 /* ASCII '0' or '1' */
<context> ::= <address> ...

View file

@ -1,64 +0,0 @@
This is a "Simple Windows Debug Server" written for the purpose of
enabling the Serviceability Agent on Win32. It has backends both for
Windows NT 4.0 (using internal Windows APIs for a few routines) as
well as for 95/98/ME/2000 via the Tool Help APIs.
The reason this debug server is necessary is that the Win32 debug APIs
by design tear down the target process when the debugger exits (see
knowledge base article Q164205 on msdn.microsoft.com). On Solaris, one
can attach to and detach from a process with no effect; this is key to
allowing dbx and gcore to work.
The Simple Windows Debug Server effectively implements attach/detach
functionality for arbitrary debug clients. This allows the SA to
attach non-destructively to a process, and will enable gcore for Win32
to be written shortly. While the debugger (the "client" in all of the
source code) is attached, the target process is suspended. (Note that
the debug server could be extended to support resumption of the target
process and transmission of debug events over to the debugger, but
this has been left for the future.)
The makefile (type "nmake") builds two executables: SwDbgSrv.exe,
which is the server process, and SwDbgSub.exe, which is forked by the
server and should not be directly invoked by the user.
The intent is that these two executables can be installed into
C:\WINNT\SYSTEM32 and SwDbgSrv installed to run as a service (on NT),
for example using ServiceInstaller (http://www.kcmultimedia.com/smaster/).
However, SwDbgSrv can also be run from the command line. It generates
no text output unless the source code is changed to enable debugging
printouts. As long as any processes which have been attached to by the
SA are alive, the SwDbgSrv and any forked SwDbgSub processes must be
left running. Terminating them will cause termination of the target
processes.
The debug server opens port 27000 and accepts incoming connections
from localhost only. The security model assumes that if one can run a
process on the given machine then one basically has access to most or
all of the machine's facilities; this seems to be in line with the
standard Windows security model. The protocol used is text-based, so
one can debug the debug server using telnet. See README-commands.txt
for documentation on the supported commands.
Testing indicates that the performance impact of attaching to a
process (and therefore permanently attaching a debugger) is minimal.
Some serious performance problems had been seen which ultimately
appeared to be a lack of physical memory on the machine running the
system.
Bugs:
This debug server is fundamentally incompatible with the Visual C++
debugger. Once the debug server is used to attach to a process, the
Visual C++ IDE will not be able to attach to the same process (even if
the debug server is "detached" from that process). Note that this
system is designed to work with the same primitives that C and C++
debuggers use (like "symbol lookup" and "read from process memory")
and exposes these primitives to Java, so in the long term we could
solve this problem by implementing platform-specific debug symbol
parsing and a platform-independent C++ debugger in Java.
Note:
The files IOBuf.cpp and IOBuf.hpp are also used in
building src/os/solaris/agent.

View file

@ -1,159 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <iostream>
#include "Reaper.hpp"
using namespace std;
Reaper::Reaper(ReaperCB* cb) {
InitializeCriticalSection(&crit);
event = CreateEvent(NULL, TRUE, FALSE, NULL);
this->cb = cb;
active = false;
shouldShutDown = false;
}
bool
Reaper::start() {
bool result = false;
EnterCriticalSection(&crit);
if (!active) {
DWORD id;
HANDLE reaper = CreateThread(NULL, 0, &Reaper::reaperThreadEntry,
this, 0, &id);
if (reaper != NULL) {
result = true;
}
}
LeaveCriticalSection(&crit);
return result;
}
bool
Reaper::stop() {
bool result = false;
EnterCriticalSection(&crit);
if (active) {
shouldShutDown = true;
SetEvent(event);
while (active) {
Sleep(1);
}
shouldShutDown = false;
result = true;
}
LeaveCriticalSection(&crit);
return result;
}
void
Reaper::registerProcess(HANDLE processHandle, void* userData) {
ProcessInfo info;
info.handle = processHandle;
info.userData = userData;
EnterCriticalSection(&crit);
procInfo.push_back(info);
SetEvent(event);
LeaveCriticalSection(&crit);
}
void
Reaper::reaperThread() {
while (!shouldShutDown) {
// Take atomic snapshot of the current process list and user data
EnterCriticalSection(&crit);
int num = procInfo.size();
HANDLE* handleList = new HANDLE[1 + num];
void** dataList = new void*[num];
for (int i = 0; i < num; i++) {
handleList[i] = procInfo[i].handle;
dataList[i] = procInfo[i].userData;
}
LeaveCriticalSection(&crit);
// Topmost handle becomes the event object, so other threads can
// signal this one to notice differences in the above list (or
// shut down)
handleList[num] = event;
// Wait for these objects
DWORD idx = WaitForMultipleObjects(1 + num, handleList,
FALSE, INFINITE);
if ((idx >= WAIT_OBJECT_0) && (idx <= WAIT_OBJECT_0 + num)) {
idx -= WAIT_OBJECT_0;
if (idx < num) {
// A process exited (i.e., it wasn't that we were woken up
// just because the event went off)
(*cb)(dataList[idx]);
// Remove this process from the list (NOTE: requires that
// ordering does not change, i.e., that all additions are to
// the back of the process list)
EnterCriticalSection(&crit);
std::vector<ProcessInfo>::iterator iter = procInfo.begin();
iter += idx;
procInfo.erase(iter);
LeaveCriticalSection(&crit);
} else {
// Notification from other thread
ResetEvent(event);
}
} else {
// Unexpected return value. For now, warn.
cerr << "Reaper::reaperThread(): unexpected return value "
<< idx << " from WaitForMultipleObjects" << endl;
}
// Clean up these lists
delete[] handleList;
delete[] dataList;
}
// Time to shut down
active = false;
}
DWORD WINAPI
Reaper::reaperThreadEntry(LPVOID data) {
Reaper* reaper = (Reaper*) data;
reaper->reaperThread();
return 0;
}

View file

@ -1,90 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _REAPER_
#define _REAPER_
#include <vector>
#include <windows.h>
typedef void ReaperCB(void* userData);
/** A Reaper maintains a thread which waits for child processes to
terminate; upon termination it calls a user-specified ReaperCB to
clean up resources associated with those child processes. */
class Reaper {
private:
Reaper& operator=(const Reaper&);
Reaper(const Reaper&);
public:
Reaper(ReaperCB*);
~Reaper();
// Start the reaper thread.
bool start();
// Stop the reaper thread. This is called automatically in the
// reaper's destructor. It is not thread safe and should be called
// by at most one thread at a time.
bool stop();
// Register a given child process with the reaper. This should be
// called by the application's main thread. When that process
// terminates, the cleanup callback will be called with the
// specified userData in the context of the reaper thread. Callbacks
// are guaranteed to be called serially, so they can safely refer to
// static data as well as the given user data.
void registerProcess(HANDLE processHandle, void* userData);
private:
// For thread safety of register()
CRITICAL_SECTION crit;
ReaperCB* cb;
// State variables
volatile bool active;
volatile bool shouldShutDown;
struct ProcessInfo {
HANDLE handle;
void* userData;
};
// Bookkeeping
std::vector<ProcessInfo> procInfo;
// Synchronization between application thread and reaper thread
HANDLE event;
// Entry point for reaper thread
void reaperThread();
// Static function which is actual thread entry point
static DWORD WINAPI reaperThreadEntry(LPVOID data);
};
#endif // #defined _REAPER_

File diff suppressed because it is too large Load diff

View file

@ -1,146 +0,0 @@
# Microsoft Developer Studio Project File - Name="SwDbgSrv" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=SwDbgSrv - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "SwDbgSrv.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "SwDbgSrv.mak" CFG="SwDbgSrv - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "SwDbgSrv - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "SwDbgSrv - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "SwDbgSrv - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "SwDbgSrv - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "SwDbgSrv___Win32_Debug"
# PROP BASE Intermediate_Dir "SwDbgSrv___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "SwDbgSrv - Win32 Release"
# Name "SwDbgSrv - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\Buffer.cpp
# End Source File
# Begin Source File
SOURCE=.\Dispatcher.cpp
# End Source File
# Begin Source File
SOURCE=.\initWinsock.cpp
# End Source File
# Begin Source File
SOURCE=.\IOBuf.cpp
# End Source File
# Begin Source File
SOURCE=.\ioUtils.cpp
# End Source File
# Begin Source File
SOURCE=.\isNT4.cpp
# End Source File
# Begin Source File
SOURCE=.\nt4internals.cpp
# End Source File
# Begin Source File
SOURCE=.\procList.cpp
# End Source File
# Begin Source File
SOURCE=.\Reaper.cpp
# End Source File
# Begin Source File
SOURCE=.\serverLists.cpp
# End Source File
# Begin Source File
SOURCE=.\SwDbgSrv.cpp
# End Source File
# Begin Source File
SOURCE=.\toolHelp.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View file

@ -1,41 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "SwDbgSrv"=.\SwDbgSrv.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "SwDbgSub"=.\SwDbgSub.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View file

@ -1,883 +0,0 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
// This is the source code for the subprocess forked by the Simple
// Windows Debug Server. It assumes most of the responsibility for the
// debug session, and processes all of the commands sent by clients.
// Disable too-long symbol warnings
#pragma warning ( disable : 4786 )
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <assert.h>
// Must come before windows.h
#include <winsock2.h>
#include <windows.h>
#include "IOBuf.hpp"
#include "libInfo.hpp"
#include "LockableList.hpp"
#include "Message.hpp"
#include "Monitor.hpp"
#include "nt4internals.hpp"
// Uncomment the #define below to get messages on stderr
// #define DEBUGGING
using namespace std;
DWORD pid;
HANDLE procHandle;
IOBuf* ioBuf;
// State flags indicating whether the attach to the remote process
// definitively succeeded or failed
volatile bool attachFailed = false;
volatile bool attachSucceeded = false;
// State flag indicating whether the target process is suspended.
// Modified by suspend()/resume(), viewed by debug thread, but only
// under cover of the threads lock.
volatile bool suspended = false;
// State flags indicating whether we are considered to be attached to
// the target process and are therefore queuing up events to be sent
// back to the debug server. These flags are only accessed and
// modified under the cover of the eventLock.
Monitor* eventLock;
// The following is set to true when a client is attached to this process
volatile bool generateDebugEvents = false;
// Pointer to current debug event; non-NULL indicates a debug event is
// waiting to be sent to the client. Main thread sets this to NULL to
// indicate that the event has been consumed; also sets
// passEventToClient, below.
volatile DEBUG_EVENT* curDebugEvent = NULL;
// Set by main thread to indicate whether the most recently posted
// debug event should be passed on to the target process.
volatile bool passEventToClient = true;
void conditionalPostDebugEvent(DEBUG_EVENT* ev, DWORD* continueOrNotHandledFlag) {
// FIXME: make it possible for the client to enable and disable
// certain types of events (have to do so in a platform-independent
// manner)
switch (ev->dwDebugEventCode) {
case EXCEPTION_DEBUG_EVENT:
switch (ev->u.Exception.ExceptionRecord.ExceptionCode) {
case EXCEPTION_BREAKPOINT: break;
case EXCEPTION_SINGLE_STEP: break;
case EXCEPTION_ACCESS_VIOLATION: break;
default: return;
}
}
eventLock->lock();
if (generateDebugEvents) {
curDebugEvent = ev;
while (curDebugEvent != NULL) {
eventLock->wait();
}
if (passEventToClient) {
*continueOrNotHandledFlag = DBG_EXCEPTION_NOT_HANDLED;
} else {
*continueOrNotHandledFlag = DBG_CONTINUE;
}
}
eventLock->unlock();
}
//----------------------------------------------------------------------
// Module list
//
vector<LibInfo> libs;
//----------------------------------------------------------------------
// Thread list
//
struct ThreadInfo {
DWORD tid;
HANDLE thread;
ThreadInfo(DWORD tid, HANDLE thread) {
this->tid = tid;
this->thread = thread;
}
};
class ThreadList : public LockableList<ThreadInfo> {
public:
bool removeByThreadID(DWORD tid) {
for (InternalListType::iterator iter = internalList.begin();
iter != internalList.end(); iter++) {
if ((*iter).tid == tid) {
internalList.erase(iter);
return true;
}
}
return false;
}
HANDLE threadIDToHandle(DWORD tid) {
for (InternalListType::iterator iter = internalList.begin();
iter != internalList.end(); iter++) {
if ((*iter).tid == tid) {
return (*iter).thread;
}
}
return NULL;
}
};
ThreadList threads;
//----------------------------------------------------------------------
// INITIALIZATION AND TERMINATION
//
void
printError(const char* prefix) {
DWORD detail = GetLastError();
LPTSTR message;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
0,
detail,
0,
(LPTSTR) &message,
1,
NULL);
// FIXME: This is signaling an error: "The handle is invalid." ?
// Do I have to do all of my WaitForDebugEvent calls from the same thread?
cerr << prefix << ": " << message << endl;
LocalFree(message);
}
void
endProcess(bool waitForProcess = true) {
NT4::unloadNTDLL();
if (waitForProcess) {
// Though we're exiting because of an error, do not tear down the
// target process.
WaitForSingleObject(procHandle, INFINITE);
}
CloseHandle(procHandle);
exit(0);
}
DWORD WINAPI
debugThreadEntry(void*) {
#ifdef DEBUGGING
DWORD lastMsgId = 0;
int count = 0;
#endif
if (!DebugActiveProcess(pid)) {
attachFailed = true;
return 0;
}
// Wait for debug events. We keep the information from some of these
// on the side in anticipation of later queries by the client. NOTE
// that we leave the process running. The main thread is responsible
// for suspending and resuming all currently-active threads upon
// client attach and detach.
while (true) {
DEBUG_EVENT ev;
if (!WaitForDebugEvent(&ev, INFINITE)) {
#ifdef DEBUGGING
if (++count < 10) {
// FIXME: This is signaling an error: "The handle is invalid." ?
// Do I have to do all of my WaitForDebugEvent calls from the same thread?
printError("WaitForDebugEvent failed");
}
#endif
} else {
#ifdef DEBUGGING
if (ev.dwDebugEventCode != lastMsgId) {
lastMsgId = ev.dwDebugEventCode;
count = 0;
cerr << "Debug thread received event " << ev.dwDebugEventCode << endl;
} else {
if (++count < 10) {
cerr << "Debug thread received event " << ev.dwDebugEventCode << endl;
}
}
#endif
DWORD dbgContinueMode = DBG_CONTINUE;
switch (ev.dwDebugEventCode) {
case LOAD_DLL_DEBUG_EVENT:
conditionalPostDebugEvent(&ev, &dbgContinueMode);
break;
case UNLOAD_DLL_DEBUG_EVENT:
conditionalPostDebugEvent(&ev, &dbgContinueMode);
break;
case CREATE_PROCESS_DEBUG_EVENT:
threads.lock();
// FIXME: will this deal properly with child processes? If
// not, is it possible to make it do so?
#ifdef DEBUGGING
cerr << "CREATE_PROCESS_DEBUG_EVENT " << ev.dwThreadId
<< " " << ev.u.CreateProcessInfo.hThread << endl;
#endif
if (ev.u.CreateProcessInfo.hThread != NULL) {
threads.add(ThreadInfo(ev.dwThreadId, ev.u.CreateProcessInfo.hThread));
}
threads.unlock();
break;
case CREATE_THREAD_DEBUG_EVENT:
threads.lock();
#ifdef DEBUGGING
cerr << "CREATE_THREAD_DEBUG_EVENT " << ev.dwThreadId
<< " " << ev.u.CreateThread.hThread << endl;
#endif
if (suspended) {
// Suspend this thread before adding it to the thread list
SuspendThread(ev.u.CreateThread.hThread);
}
threads.add(ThreadInfo(ev.dwThreadId, ev.u.CreateThread.hThread));
threads.unlock();
break;
case EXIT_THREAD_DEBUG_EVENT:
threads.lock();
#ifdef DEBUGGING
cerr << "EXIT_THREAD_DEBUG_EVENT " << ev.dwThreadId << endl;
#endif
threads.removeByThreadID(ev.dwThreadId);
threads.unlock();
break;
case EXCEPTION_DEBUG_EVENT:
// cerr << "EXCEPTION_DEBUG_EVENT" << endl;
switch (ev.u.Exception.ExceptionRecord.ExceptionCode) {
case EXCEPTION_BREAKPOINT:
// cerr << "EXCEPTION_BREAKPOINT" << endl;
if (!attachSucceeded && !attachFailed) {
attachSucceeded = true;
}
break;
default:
dbgContinueMode = DBG_EXCEPTION_NOT_HANDLED;
break;
}
conditionalPostDebugEvent(&ev, &dbgContinueMode);
break;
case EXIT_PROCESS_DEBUG_EVENT:
endProcess(false);
// NOT REACHED
break;
default:
#ifdef DEBUGGING
cerr << "Received debug event " << ev.dwDebugEventCode << endl;
#endif
break;
}
ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, dbgContinueMode);
}
}
}
bool
attachToProcess() {
// Create event lock
eventLock = new Monitor();
// Get a process handle for later
procHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (procHandle == NULL) {
return false;
}
// Start up the debug thread
DWORD debugThreadId;
if (CreateThread(NULL, 0, &debugThreadEntry, NULL, 0, &debugThreadId) == NULL) {
// Failed to make background debug thread. Fail.
return false;
}
while ((!attachSucceeded) && (!attachFailed)) {
Sleep(1);
}
if (attachFailed) {
return false;
}
assert(attachSucceeded);
return true;
}
bool
readMessage(Message* msg) {
DWORD numRead;
if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE),
msg,
sizeof(Message),
&numRead,
NULL)) {
return false;
}
if (numRead != sizeof(Message)) {
return false;
}
// For "poke" messages, must follow up by reading raw data
if (msg->type == Message::POKE) {
char* dataBuf = new char[msg->pokeArg.numBytes];
if (dataBuf == NULL) {
return false;
}
if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE),
dataBuf,
msg->pokeArg.numBytes,
&numRead,
NULL)) {
delete[] dataBuf;
return false;
}
if (numRead != msg->pokeArg.numBytes) {
delete[] dataBuf;
return false;
}
msg->pokeArg.data = (void *) dataBuf;
}
return true;
}
void
handlePeek(Message* msg) {
#ifdef DEBUGGING
cerr << "Entering handlePeek()" << endl;
#endif
char* memBuf = new char[msg->peekArg.numBytes];
if (memBuf == NULL) {
ioBuf->writeString("B");
ioBuf->writeBinChar(0);
ioBuf->flush();
delete[] memBuf;
return;
}
// Try fast case first
DWORD numRead;
BOOL res = ReadProcessMemory(procHandle,
(LPCVOID) msg->peekArg.address,
memBuf,
msg->peekArg.numBytes,
&numRead);
if (res && (numRead == msg->peekArg.numBytes)) {
// OK, complete success. Phew.
#ifdef DEBUGGING
cerr << "Peek success case" << endl;
#endif
ioBuf->writeString("B");
ioBuf->writeBinChar(1);
ioBuf->writeBinUnsignedInt(numRead);
ioBuf->writeBinChar(1);
ioBuf->writeBinBuf(memBuf, numRead);
} else {
#ifdef DEBUGGING
cerr << "*** Peek slow case ***" << endl;
#endif
ioBuf->writeString("B");
ioBuf->writeBinChar(1);
// Use VirtualQuery to speed things up a bit
DWORD numLeft = msg->peekArg.numBytes;
char* curAddr = (char*) msg->peekArg.address;
while (numLeft > 0) {
MEMORY_BASIC_INFORMATION memInfo;
VirtualQueryEx(procHandle, curAddr, &memInfo, sizeof(memInfo));
DWORD numToRead = memInfo.RegionSize;
if (numToRead > numLeft) {
numToRead = numLeft;
}
DWORD numRead;
if (memInfo.State == MEM_COMMIT) {
// Read the process memory at this address for this length
// FIXME: should check the result of this read
ReadProcessMemory(procHandle, curAddr, memBuf,
numToRead, &numRead);
// Write this out
#ifdef DEBUGGING
cerr << "*** Writing " << numToRead << " bytes as mapped ***" << endl;
#endif
ioBuf->writeBinUnsignedInt(numToRead);
ioBuf->writeBinChar(1);
ioBuf->writeBinBuf(memBuf, numToRead);
} else {
// Indicate region is free
#ifdef DEBUGGING
cerr << "*** Writing " << numToRead << " bytes as unmapped ***" << endl;
#endif
ioBuf->writeBinUnsignedInt(numToRead);
ioBuf->writeBinChar(0);
}
curAddr += numToRead;
numLeft -= numToRead;
}
}
ioBuf->flush();
delete[] memBuf;
#ifdef DEBUGGING
cerr << "Exiting handlePeek()" << endl;
#endif
}
void
handlePoke(Message* msg) {
#ifdef DEBUGGING
cerr << "Entering handlePoke()" << endl;
#endif
DWORD numWritten;
BOOL res = WriteProcessMemory(procHandle,
(LPVOID) msg->pokeArg.address,
msg->pokeArg.data,
msg->pokeArg.numBytes,
&numWritten);
if (res && (numWritten == msg->pokeArg.numBytes)) {
// Success
ioBuf->writeBoolAsInt(true);
#ifdef DEBUGGING
cerr << " (Succeeded)" << endl;
#endif
} else {
// Failure
ioBuf->writeBoolAsInt(false);
#ifdef DEBUGGING
cerr << " (Failed)" << endl;
#endif
}
ioBuf->writeEOL();
ioBuf->flush();
// We clean up the data
char* dataBuf = (char*) msg->pokeArg.data;
delete[] dataBuf;
#ifdef DEBUGGING
cerr << "Exiting handlePoke()" << endl;
#endif
}
bool
suspend() {
if (suspended) {
return false;
}
// Before we suspend, we must take a snapshot of the loaded module
// names and base addresses, since acquiring this snapshot requires
// starting and exiting a thread in the remote process (at least on
// NT 4).
libs.clear();
#ifdef DEBUGGING
cerr << "Starting suspension" << endl;
#endif
libInfo(pid, libs);
#ifdef DEBUGGING
cerr << " Got lib info" << endl;
#endif
threads.lock();
#ifdef DEBUGGING
cerr << " Got thread lock" << endl;
#endif
suspended = true;
int j = 0;
for (int i = 0; i < threads.size(); i++) {
j++;
SuspendThread(threads.get(i).thread);
}
#ifdef DEBUGGING
cerr << "Suspended " << j << " threads" << endl;
#endif
threads.unlock();
return true;
}
bool
resume() {
if (!suspended) {
return false;
}
threads.lock();
suspended = false;
for (int i = 0; i < threads.size(); i++) {
ResumeThread(threads.get(i).thread);
}
threads.unlock();
#ifdef DEBUGGING
cerr << "Resumed process" << endl;
#endif
return true;
}
int
main(int argc, char **argv)
{
if (argc != 2) {
// Should only be used by performing CreateProcess within SwDbgSrv
exit(1);
}
if (sscanf(argv[1], "%u", &pid) != 1) {
exit(1);
}
// Try to attach to process
if (!attachToProcess()) {
// Attach failed. Notify parent by writing result to stdout file
// handle.
char res = 0;
DWORD numBytes;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &res, sizeof(res),
&numBytes, NULL);
exit(1);
}
// Server is expecting success result back.
char res = 1;
DWORD numBytes;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &res, sizeof(res),
&numBytes, NULL);
// Initialize our I/O buffer
ioBuf = new IOBuf(32768, 131072);
ioBuf->setOutputFileHandle(GetStdHandle(STD_OUTPUT_HANDLE));
// At this point we are attached. Enter our main loop which services
// requests from the server. Note that in order to handle attach/
// detach properly (i.e., resumption of process upon "detach") we
// will need another thread which handles debug events.
while (true) {
// Read a message from the server
Message msg;
if (!readMessage(&msg)) {
endProcess();
}
#ifdef DEBUGGING
cerr << "Main thread read message: " << msg.type << endl;
#endif
switch (msg.type) {
// ATTACH and DETACH messages MUST come in pairs
case Message::ATTACH:
suspend();
eventLock->lock();
generateDebugEvents = true;
eventLock->unlock();
break;
case Message::DETACH:
eventLock->lock();
generateDebugEvents = false;
// Flush remaining event if any
if (curDebugEvent != NULL) {
curDebugEvent = NULL;
eventLock->notifyAll();
}
eventLock->unlock();
resume();
break;
case Message::LIBINFO:
{
if (!suspended) {
ioBuf->writeInt(0);
} else {
// Send back formatted text
ioBuf->writeInt(libs.size());
for (int i = 0; i < libs.size(); i++) {
ioBuf->writeSpace();
ioBuf->writeInt(1);
ioBuf->writeSpace();
ioBuf->writeInt(libs[i].name.size());
ioBuf->writeSpace();
ioBuf->writeString(libs[i].name.c_str());
ioBuf->writeSpace();
ioBuf->writeAddress(libs[i].base);
}
}
ioBuf->writeEOL();
ioBuf->flush();
break;
}
case Message::PEEK:
handlePeek(&msg);
break;
case Message::POKE:
handlePoke(&msg);
break;
case Message::THREADLIST:
{
if (!suspended) {
ioBuf->writeInt(0);
} else {
threads.lock();
ioBuf->writeInt(threads.size());
for (int i = 0; i < threads.size(); i++) {
ioBuf->writeSpace();
ioBuf->writeAddress((void*) threads.get(i).thread);
}
threads.unlock();
}
ioBuf->writeEOL();
ioBuf->flush();
break;
}
case Message::DUPHANDLE:
{
HANDLE dup;
if (DuplicateHandle(procHandle,
msg.handleArg.handle,
GetCurrentProcess(),
&dup,
0,
FALSE,
DUPLICATE_SAME_ACCESS)) {
ioBuf->writeBoolAsInt(true);
ioBuf->writeSpace();
ioBuf->writeAddress((void*) dup);
} else {
ioBuf->writeBoolAsInt(false);
}
ioBuf->writeEOL();
ioBuf->flush();
break;
}
case Message::CLOSEHANDLE:
{
CloseHandle(msg.handleArg.handle);
break;
}
case Message::GETCONTEXT:
{
if (!suspended) {
ioBuf->writeBoolAsInt(false);
} else {
CONTEXT context;
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
if (GetThreadContext(msg.handleArg.handle, &context)) {
ioBuf->writeBoolAsInt(true);
// EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP, DS, ES, FS, GS,
// CS, SS, EFLAGS, DR0, DR1, DR2, DR3, DR6, DR7
// See README-commands.txt
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Eax);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Ebx);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Ecx);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Edx);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Esi);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Edi);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Ebp);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Esp);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Eip);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegDs);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegEs);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegFs);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegGs);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegCs);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegSs);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.EFlags);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr0);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr1);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr2);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr3);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr6);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr7);
} else {
ioBuf->writeBoolAsInt(false);
}
}
ioBuf->writeEOL();
ioBuf->flush();
break;
}
case Message::SETCONTEXT:
{
if (!suspended) {
ioBuf->writeBoolAsInt(false);
} else {
CONTEXT context;
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
context.Eax = msg.setContextArg.Eax;
context.Ebx = msg.setContextArg.Ebx;
context.Ecx = msg.setContextArg.Ecx;
context.Edx = msg.setContextArg.Edx;
context.Esi = msg.setContextArg.Esi;
context.Edi = msg.setContextArg.Edi;
context.Ebp = msg.setContextArg.Ebp;
context.Esp = msg.setContextArg.Esp;
context.Eip = msg.setContextArg.Eip;
context.SegDs = msg.setContextArg.Ds;
context.SegEs = msg.setContextArg.Es;
context.SegFs = msg.setContextArg.Fs;
context.SegGs = msg.setContextArg.Gs;
context.SegCs = msg.setContextArg.Cs;
context.SegSs = msg.setContextArg.Ss;
context.EFlags = msg.setContextArg.EFlags;
context.Dr0 = msg.setContextArg.Dr0;
context.Dr1 = msg.setContextArg.Dr1;
context.Dr2 = msg.setContextArg.Dr2;
context.Dr3 = msg.setContextArg.Dr3;
context.Dr6 = msg.setContextArg.Dr6;
context.Dr7 = msg.setContextArg.Dr7;
if (SetThreadContext(msg.setContextArg.handle, &context)) {
ioBuf->writeBoolAsInt(true);
} else {
ioBuf->writeBoolAsInt(false);
}
}
ioBuf->writeEOL();
ioBuf->flush();
break;
}
case Message::SELECTORENTRY:
{
LDT_ENTRY entry;
if (GetThreadSelectorEntry(msg.selectorArg.handle,
msg.selectorArg.selector,
&entry)) {
ioBuf->writeBoolAsInt(true);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.LimitLow);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.BaseLow);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.BaseMid);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.Flags1);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.Flags2);
ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.BaseHi);
} else {
ioBuf->writeBoolAsInt(false);
}
ioBuf->writeEOL();
ioBuf->flush();
break;
}
case Message::SUSPEND:
suspend();
break;
case Message::RESUME:
resume();
break;
case Message::POLLEVENT:
eventLock->lock();
if (curDebugEvent == NULL) {
ioBuf->writeBoolAsInt(false);
} else {
ioBuf->writeBoolAsInt(true);
ioBuf->writeSpace();
threads.lock();
ioBuf->writeAddress((void*) threads.threadIDToHandle(curDebugEvent->dwThreadId));
threads.unlock();
ioBuf->writeSpace();
ioBuf->writeUnsignedInt(curDebugEvent->dwDebugEventCode);
// Figure out what else to write
switch (curDebugEvent->dwDebugEventCode) {
case LOAD_DLL_DEBUG_EVENT:
ioBuf->writeSpace();
ioBuf->writeAddress(curDebugEvent->u.LoadDll.lpBaseOfDll);
break;
case UNLOAD_DLL_DEBUG_EVENT:
ioBuf->writeSpace();
ioBuf->writeAddress(curDebugEvent->u.UnloadDll.lpBaseOfDll);
break;
case EXCEPTION_DEBUG_EVENT:
{
DWORD code = curDebugEvent->u.Exception.ExceptionRecord.ExceptionCode;
ioBuf->writeSpace();
ioBuf->writeUnsignedInt(code);
ioBuf->writeSpace();
ioBuf->writeAddress(curDebugEvent->u.Exception.ExceptionRecord.ExceptionAddress);
switch (curDebugEvent->u.Exception.ExceptionRecord.ExceptionCode) {
case EXCEPTION_ACCESS_VIOLATION:
ioBuf->writeSpace();
ioBuf->writeBoolAsInt(curDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[0] != 0);
ioBuf->writeSpace();
ioBuf->writeAddress((void*) curDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[1]);
break;
default:
break;
}
break;
}
default:
break;
}
}
eventLock->unlock();
ioBuf->writeEOL();
ioBuf->flush();
break;
case Message::CONTINUEEVENT:
eventLock->lock();
if (curDebugEvent == NULL) {
ioBuf->writeBoolAsInt(false);
} else {
curDebugEvent = NULL;
passEventToClient = msg.boolArg.val;
ioBuf->writeBoolAsInt(true);
eventLock->notify();
}
eventLock->unlock();
ioBuf->writeEOL();
ioBuf->flush();
break;
}
}
endProcess();
// NOT REACHED
return 0;
}

View file

@ -1,130 +0,0 @@
# Microsoft Developer Studio Project File - Name="SwDbgSub" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=SwDbgSub - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "SwDbgSub.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "SwDbgSub.mak" CFG="SwDbgSub - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "SwDbgSub - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "SwDbgSub - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "SwDbgSub - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "SwDbgSub - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "SwDbgSub___Win32_Debug"
# PROP BASE Intermediate_Dir "SwDbgSub___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "SwDbgSub - Win32 Release"
# Name "SwDbgSub - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\Buffer.cpp
# End Source File
# Begin Source File
SOURCE=.\IOBuf.cpp
# End Source File
# Begin Source File
SOURCE=.\isNT4.cpp
# End Source File
# Begin Source File
SOURCE=.\libInfo.cpp
# End Source File
# Begin Source File
SOURCE=.\Monitor.cpp
# End Source File
# Begin Source File
SOURCE=.\nt4internals.cpp
# End Source File
# Begin Source File
SOURCE=.\SwDbgSub.cpp
# End Source File
# Begin Source File
SOURCE=.\toolHelp.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View file

@ -1,71 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <iostream>
#include <winsock2.h>
using namespace std;
void
initWinsock()
{
static int initted = 0;
WORD wVersionRequested;
WSADATA wsaData;
int err;
if (!initted) {
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
{
/* Tell the user that we couldn't find a usable */
/* WinSock DLL. */
cerr << "SocketBase::SocketBase: unable to find usable "
<< "WinSock DLL" << endl;
exit(1);
}
}
/* Confirm that the WinSock DLL supports 2.0.*/
/* Note that if the DLL supports versions greater */
/* than 2.0 in addition to 2.0, it will still return */
/* 2.0 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 ) {
/* Tell the user that we couldn't find a usable */
/* WinSock DLL. */
{
cerr << "Unable to find suitable version of WinSock DLL" << endl;
WSACleanup( );
exit(1);
}
}
initted = 1;
}
}

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _INIT_WINSOCK_
#define _INIT_WINSOCK_
void initWinsock();
#endif // #defined _INIT_WINSOCK_

View file

@ -1,156 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <ctype.h>
#include <string.h>
#include "ioUtils.hpp"
#include "IOBuf.hpp"
bool
scanInt(char** data, int* num) {
*num = 0;
// Skip whitespace
while ((**data != 0) && (isspace(**data))) {
++*data;
}
if (**data == 0) {
return false;
}
while ((**data != 0) && (!isspace(**data))) {
char cur = **data;
if ((cur < '0') || (cur > '9')) {
return false;
}
*num *= 10;
*num += cur - '0';
++*data;
}
return true;
}
bool
scanUnsignedLong(char** data, unsigned long* num) {
*num = 0;
// Skip whitespace
while ((**data != 0) && (isspace(**data))) {
++*data;
}
if (**data == 0) {
return false;
}
while ((**data != 0) && (!isspace(**data))) {
char cur = **data;
if ((cur < '0') || (cur > '9')) {
return false;
}
*num *= 10;
*num += cur - '0';
++*data;
}
return true;
}
bool
charToNibble(char ascii, int* value) {
if (ascii >= '0' && ascii <= '9') {
*value = ascii - '0';
return true;
} else if (ascii >= 'A' && ascii <= 'F') {
*value = 10 + ascii - 'A';
return true;
} else if (ascii >= 'a' && ascii <= 'f') {
*value = 10 + ascii - 'a';
return true;
}
return false;
}
bool
scanAddress(char** data, unsigned long* addr) {
*addr = 0;
// Skip whitespace
while ((**data != 0) && (isspace(**data))) {
++*data;
}
if (**data == 0) {
return false;
}
if (strncmp(*data, "0x", 2) != 0) {
return false;
}
*data += 2;
while ((**data != 0) && (!isspace(**data))) {
int val;
bool res = charToNibble(**data, &val);
if (!res) {
return false;
}
*addr <<= 4;
*addr |= val;
++*data;
}
return true;
}
bool
scanAndSkipBinEscapeChar(char** data) {
// Skip whitespace
while ((**data != 0) && (isspace(**data))) {
++*data;
}
if (!IOBuf::isBinEscapeChar(**data)) {
return false;
}
++*data;
return true;
}
bool
scanBinUnsignedLong(char** data, unsigned long* num) {
*num = 0;
for (int i = 0; i < 4; i++) {
unsigned char val = (unsigned char) **data;
*num = (*num << 8) | val;
++*data;
}
return true;
}

View file

@ -1,36 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _IO_UTILS_
#define _IO_UTILS_
bool scanInt(char** data, int* num);
bool scanUnsignedLong(char** data, unsigned long* num);
bool scanAddress(char** data, unsigned long* addr);
// Binary utils (for poke)
bool scanAndSkipBinEscapeChar(char** data);
bool scanBinUnsignedLong(char** data, unsigned long* num);
#endif // #defined _IO_UTILS_

View file

@ -1,39 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "isNT4.hpp"
#include <windows.h>
bool
isNT4() {
OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof(info);
if (!GetVersionEx(&info)) {
return false;
}
return ((info.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(info.dwMajorVersion == 4));
}

View file

@ -1,34 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _ISNT4_H_
#define _ISNT4_H_
// We need to special-case the Windows NT 4.0 implementations of some
// of the debugging routines because the Tool Help API is not
// available on this platform.
bool isNT4();
#endif // #defined _ISNT4_H_

View file

@ -1,186 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
// Disable too-long symbol warnings
#pragma warning ( disable : 4786 )
#include "libInfo.hpp"
#include "nt4internals.hpp"
#include "isNT4.hpp"
#include "toolHelp.hpp"
#include <assert.h>
using namespace std;
typedef void LibInfoImplFunc(DWORD pid, vector<LibInfo>& info);
static void libInfoImplNT4(DWORD pid, vector<LibInfo>& info);
static void libInfoImplToolHelp(DWORD pid, vector<LibInfo>& info);
void
libInfo(DWORD pid, vector<LibInfo>& info) {
static LibInfoImplFunc* impl = NULL;
if (impl == NULL) {
// See which operating system we're on
impl = (isNT4() ? &libInfoImplNT4 : &libInfoImplToolHelp);
}
assert(impl != NULL);
(*impl)(pid, info);
}
static ULONG
ModuleCount(NT4::PDEBUG_BUFFER db) {
return db->ModuleInformation ? *PULONG(db->ModuleInformation) : 0;
}
#define MAX2(a, b) (((a) < (b)) ? (b) : (a))
static void
libInfoImplNT4(DWORD pid, vector<LibInfo>& info) {
static EnumProcessModulesFunc* enumFunc = NULL;
static GetModuleFileNameExFunc* fnFunc = NULL;
static GetModuleInformationFunc* infoFunc = NULL;
if (enumFunc == NULL) {
HMODULE dll = loadPSAPIDLL();
enumFunc = (EnumProcessModulesFunc*) GetProcAddress(dll, "EnumProcessModules");
fnFunc = (GetModuleFileNameExFunc*) GetProcAddress(dll, "GetModuleFileNameExA");
infoFunc = (GetModuleInformationFunc*) GetProcAddress(dll, "GetModuleInformation");
assert(enumFunc != NULL);
assert(fnFunc != NULL);
assert(infoFunc != NULL);
}
static HMODULE* mods = new HMODULE[256];
static int numMods = 256;
if (mods == NULL) {
mods = new HMODULE[numMods];
if (mods == NULL) {
return;
}
}
bool done = false;
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (proc == NULL) {
return;
}
do {
DWORD bufSize = numMods * sizeof(HMODULE);
DWORD neededSize;
if (!(*enumFunc)(proc, mods, bufSize, &neededSize)) {
// Enum failed
CloseHandle(proc);
return;
}
int numFetched = neededSize / sizeof(HMODULE);
if (numMods < numFetched) {
// Grow buffer
numMods = MAX2(numFetched, 2 * numMods);
delete[] mods;
mods = new HMODULE[numMods];
if (mods == NULL) {
CloseHandle(proc);
return;
}
} else {
char filename[MAX_PATH];
MODULEINFO modInfo;
// Iterate through and fetch each one's info
for (int i = 0; i < numFetched; i++) {
if (!(*fnFunc)(proc, mods[i], filename, MAX_PATH)) {
CloseHandle(proc);
return;
}
if (!(*infoFunc)(proc, mods[i], &modInfo, sizeof(MODULEINFO))) {
CloseHandle(proc);
return;
}
info.push_back(LibInfo(string(filename), (void*) modInfo.lpBaseOfDll));
}
done = true;
}
} while (!done);
CloseHandle(proc);
return;
}
void
libInfoImplToolHelp(DWORD pid, vector<LibInfo>& info) {
using namespace ToolHelp;
static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL;
static Module32FirstFunc* firstFunc = NULL;
static Module32NextFunc* nextFunc = NULL;
if (snapshotFunc == NULL) {
HMODULE dll = loadDLL();
snapshotFunc =
(CreateToolhelp32SnapshotFunc*) GetProcAddress(dll,
"CreateToolhelp32Snapshot");
firstFunc = (Module32FirstFunc*) GetProcAddress(dll,
"Module32First");
nextFunc = (Module32NextFunc*) GetProcAddress(dll,
"Module32Next");
assert(snapshotFunc != NULL);
assert(firstFunc != NULL);
assert(nextFunc != NULL);
}
HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPMODULE, pid);
if (snapshot == (HANDLE) -1) {
// Error occurred during snapshot
return;
}
// Iterate
MODULEENTRY32 module;
if ((*firstFunc)(snapshot, &module)) {
do {
info.push_back(LibInfo(string(module.szExePath), (void*) module.modBaseAddr));
} while ((*nextFunc)(snapshot, &module));
}
CloseHandle(snapshot);
}

View file

@ -1,44 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _LIBINFO_
#define _LIBINFO_
#include <vector>
#include <string>
#include <windows.h>
struct LibInfo {
std::string name;
void* base;
LibInfo(const std::string& name, void* base) {
this->name = name;
this->base = base;
}
};
void libInfo(DWORD pid, std::vector<LibInfo>& info);
#endif // #defined _LIBINFO_

View file

@ -1,75 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "nt4internals.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
namespace NT4 {
static HMODULE ntDLL = NULL;
HMODULE loadNTDLL() {
if (ntDLL == NULL) {
ntDLL = LoadLibrary("NTDLL.DLL");
}
assert(ntDLL != NULL);
return ntDLL;
}
void unloadNTDLL() {
if (ntDLL != NULL) {
FreeLibrary(ntDLL);
ntDLL = NULL;
}
}
} // namespace NT4
static HMODULE psapiDLL = NULL;
HMODULE
loadPSAPIDLL() {
if (psapiDLL == NULL) {
psapiDLL = LoadLibrary("PSAPI.DLL");
}
if (psapiDLL == NULL) {
fprintf(stderr, "Simple Windows Debug Server requires PSAPI.DLL on Windows NT 4.0.\n");
fprintf(stderr, "Please install this DLL from the SDK and restart the server.\n");
exit(1);
}
return psapiDLL;
}
void
unloadPSAPIDLL() {
if (psapiDLL != NULL) {
FreeLibrary(psapiDLL);
psapiDLL = NULL;
}
}

View file

@ -1,273 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _NT4INTERNALS_H_
#define _NT4INTERNALS_H_
#include <windows.h>
namespace NT4 {
extern "C" {
// Data structures and constants required to be able to get necessary
// debugging-related information on Windows NT 4.0 through internal
// (i.e., non-public) APIs. These are adapted from those in the
// _Windows NT/2000 Native API Reference_ by Gary Nebbett, Macmillan
// Technical Publishing, 201 West 103rd Street, Indianapolis, IN
// 46290, 2000.
typedef LONG NTSTATUS;
typedef LONG KPRIORITY;
#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define NTAPI __stdcall
#else
#define _cdecl
#define NTAPI
#endif
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemProcessesAndThreadsInformation = 5
} SYSTEM_INFORMATION_CLASS;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef struct _VM_COUNTERS {
ULONG PeakVirtualSize;
ULONG VirtualSize;
ULONG PageFaultCount;
ULONG PeakWorkingSetSize;
ULONG WorkingSetSize;
ULONG QuotaPeakPagedPoolUsage;
ULONG QuotaPagedPoolUsage;
ULONG QuotaPeakNonPagedPoolUsage;
ULONG QuotaNonPagedPoolUsage;
ULONG PagefileUsage;
ULONG PeakPagefileUsage;
} VM_COUNTERS, *PVM_COUNTERS;
typedef struct _IO_COUNTERS {
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
} IO_COUNTERS, *PIO_COUNTERS;
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef enum {
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
} THREAD_STATE;
typedef enum {
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVirtualMemory,
WrPageOut,
WrRendezvous,
Spare2,
Spare3,
Spare4,
Spare5,
Spare6,
WrKernel
} KWAIT_REASON;
typedef struct _SYSTEM_THREADS {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
KWAIT_REASON WaitReason;
} SYSTEM_THREADS, *PSYSTEM_THREADS;
typedef struct _SYSTEM_PROCESSES { // Information class 5
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
ULONG PrivatePageCount;
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters; // Windows 2000 only
SYSTEM_THREADS Threads[1];
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
typedef NTSTATUS NTAPI
ZwQuerySystemInformationFunc(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
typedef struct _DEBUG_BUFFER {
HANDLE SectionHandle;
PVOID SectionBase;
PVOID RemoteSectionBase;
ULONG SectionBaseDelta;
HANDLE EventPairHandle;
ULONG Unknown[2];
HANDLE RemoteThreadHandle;
ULONG InfoClassMask;
ULONG SizeOfInfo;
ULONG AllocatedSize;
ULONG SectionSize;
PVOID ModuleInformation;
PVOID BackTraceInformation;
PVOID HeapInformation;
PVOID LockInformation;
PVOID Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;
typedef PDEBUG_BUFFER NTAPI
RtlCreateQueryDebugBufferFunc(IN ULONG Size,
IN BOOLEAN EventPair);
#define PDI_MODULES 0x01 // The loaded modules of the process
#define PDI_BACKTRACE 0x02 // The heap stack back traces
#define PDI_HEAPS 0x04 // The heaps of the process
#define PDI_HEAP_TAGS 0x08 // The heap tags
#define PDI_HEAP_BLOCKS 0x10 // The heap blocks
#define PDI_LOCKS 0x20 // The locks created by the process
typedef struct _DEBUG_MODULE_INFORMATION { // c.f. SYSTEM_MODULE_INFORMATION
ULONG Reserved[2];
ULONG Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} DEBUG_MODULE_INFORMATION, *PDEBUG_MODULE_INFORMATION;
// Flags
#define LDRP_STATIC_LINK 0x00000002
#define LDRP_IMAGE_DLL 0x00000004
#define LDRP_LOAD_IN_PROGRESS 0x00001000
#define LDRP_UNLOAD_IN_PROGRESS 0x00002000
#define LDRP_ENTRY_PROCESSED 0x00004000
#define LDRP_ENTRY_INSERTED 0x00008000
#define LDRP_CURRENT_LOAD 0x00010000
#define LDRP_FAILED_BUILTIN_LOAD 0x00020000
#define LDRP_DONT_CALL_FOR_THREADS 0x00040000
#define LDRP_PROCESS_ATTACH_CALLED 0x00080000
#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000
#define LDRP_IMAGE_NOT_AT_BASE 0x00200000
#define LDRP_WX86_IGNORE_MACHINETYPE 0x00400000
// NOTE that this will require creating a thread in the target
// process, implying that we can not call this while the process is
// suspended. May have to run this command in the child processes
// rather than the server.
typedef NTSTATUS NTAPI
RtlQueryProcessDebugInformationFunc(IN ULONG ProcessId,
IN ULONG DebugInfoClassMask,
IN OUT PDEBUG_BUFFER DebugBuffer);
typedef NTSTATUS NTAPI
RtlDestroyQueryDebugBufferFunc(IN PDEBUG_BUFFER DebugBuffer);
// Routines to load and unload NTDLL.DLL.
HMODULE loadNTDLL();
// Safe to call even if has not been loaded
void unloadNTDLL();
} // extern "C"
} // namespace NT4
//----------------------------------------------------------------------
// On NT 4 only, we now use PSAPI to enumerate the loaded modules in
// the target processes. RtlQueryProcessDebugInformation creates a
// thread in the target process, which causes problems when we are
// handling events like breakpoints in the debugger. The dependence on
// an external DLL which might not be present is unfortunate, but we
// can either redistribute this DLL (if allowed) or refuse to start on
// NT 4 if it is not present.
typedef struct _MODULEINFO {
LPVOID lpBaseOfDll;
DWORD SizeOfImage;
LPVOID EntryPoint;
} MODULEINFO, *LPMODULEINFO;
typedef BOOL (WINAPI EnumProcessModulesFunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
typedef DWORD (WINAPI GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
typedef BOOL (WINAPI GetModuleInformationFunc)(HANDLE, HMODULE, LPMODULEINFO, DWORD);
// Routines to load and unload PSAPI.DLL.
HMODULE loadPSAPIDLL();
// Safe to call even if has not been loaded
void unloadPSAPIDLL();
#endif // #defined _NT4INTERNALS_H_

View file

@ -1,32 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _PORTS_H_
#define _PORTS_H_
// This is the "public" port which end-user clients can connect to
// with an arbitrary application, including telnet.
const short CLIENT_PORT = 27000;
#endif // #defined _PORTS_H_

View file

@ -1,190 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "procList.hpp"
#include "nt4internals.hpp"
#include "isNT4.hpp"
#include "toolHelp.hpp"
#include <assert.h>
using namespace std;
using namespace NT4;
typedef void ProcListImplFunc(ProcEntryList& processes);
void procListImplNT4(ProcEntryList& processes);
void procListImplToolHelp(ProcEntryList& processes);
ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, WCHAR* name) {
this->pid = pid;
this->nameLength = nameLength;
this->name = new WCHAR[nameLength];
memcpy(this->name, name, nameLength * sizeof(WCHAR));
}
ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, char* name) {
this->pid = pid;
this->nameLength = nameLength;
this->name = new WCHAR[nameLength];
int j = 0;
for (int i = 0; i < nameLength; i++) {
// FIXME: what is the proper promotion from ASCII to UNICODE?
this->name[i] = name[i] & 0xFF;
}
}
ProcEntry::ProcEntry(const ProcEntry& arg) {
name = NULL;
copyFrom(arg);
}
ProcEntry&
ProcEntry::operator=(const ProcEntry& arg) {
copyFrom(arg);
return *this;
}
ProcEntry::~ProcEntry() {
delete[] name;
}
void
ProcEntry::copyFrom(const ProcEntry& arg) {
if (name != NULL) {
delete[] name;
}
pid = arg.pid;
nameLength = arg.nameLength;
name = new WCHAR[nameLength];
memcpy(name, arg.name, nameLength * sizeof(WCHAR));
}
ULONG
ProcEntry::getPid() {
return pid;
}
USHORT
ProcEntry::getNameLength() {
return nameLength;
}
WCHAR*
ProcEntry::getName() {
return name;
}
void
procList(ProcEntryList& processes) {
static ProcListImplFunc* impl = NULL;
if (impl == NULL) {
// See which operating system we're on
impl = (isNT4() ? &procListImplNT4 : &procListImplToolHelp);
}
assert(impl != NULL);
(*impl)(processes);
}
void
procListImplNT4(ProcEntryList& processes) {
using namespace NT4;
static ZwQuerySystemInformationFunc* query = NULL;
if (query == NULL) {
HMODULE ntDLL = loadNTDLL();
query =
(ZwQuerySystemInformationFunc*) GetProcAddress(ntDLL,
"ZwQuerySystemInformation");
assert(query != NULL);
}
ULONG n = 0x100;
PSYSTEM_PROCESSES sp = new SYSTEM_PROCESSES[n];
while ((*query)(SystemProcessesAndThreadsInformation,
sp, n * sizeof(SYSTEM_PROCESSES), 0) == STATUS_INFO_LENGTH_MISMATCH) {
delete[] sp;
n *= 2;
sp = new SYSTEM_PROCESSES[n];
}
bool done = false;
for (PSYSTEM_PROCESSES p = sp; !done;
p = PSYSTEM_PROCESSES(PCHAR(p) + p->NextEntryDelta)) {
processes.push_back(ProcEntry(p->ProcessId,
p->ProcessName.Length / 2,
p->ProcessName.Buffer));
done = p->NextEntryDelta == 0;
}
}
void
procListImplToolHelp(ProcEntryList& processes) {
using namespace ToolHelp;
static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL;
static Process32FirstFunc* firstFunc = NULL;
static Process32NextFunc* nextFunc = NULL;
if (snapshotFunc == NULL) {
HMODULE dll = loadDLL();
snapshotFunc =
(CreateToolhelp32SnapshotFunc*) GetProcAddress(dll,
"CreateToolhelp32Snapshot");
firstFunc = (Process32FirstFunc*) GetProcAddress(dll,
"Process32First");
nextFunc = (Process32NextFunc*) GetProcAddress(dll,
"Process32Next");
assert(snapshotFunc != NULL);
assert(firstFunc != NULL);
assert(nextFunc != NULL);
}
HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPPROCESS, 0 /* ignored */);
if (snapshot == (HANDLE) -1) {
// Error occurred during snapshot
return;
}
// Iterate
PROCESSENTRY32 proc;
if ((*firstFunc)(snapshot, &proc)) {
do {
// FIXME: could make this uniform to the NT version by cutting
// off the path name just before the executable name
processes.push_back(ProcEntry(proc.th32ProcessID,
strlen(proc.szExeFile),
proc.szExeFile));
} while ((*nextFunc)(snapshot, &proc));
}
CloseHandle(snapshot);
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _PROCLIST_
#define _PROCLIST_
#include <windows.h>
#include <vector>
class ProcEntry {
public:
/** name may not be NULL */
ProcEntry(ULONG pid, USHORT nameLength, wchar_t* name);
ProcEntry(ULONG pid, USHORT nameLength, char* name);
~ProcEntry();
ProcEntry(const ProcEntry& arg);
ProcEntry& operator=(const ProcEntry& arg);
ULONG getPid();
/** Returns number of WCHAR characters in getName() */
USHORT getNameLength();
WCHAR* getName();
private:
ULONG pid;
USHORT nameLength;
WCHAR* name;
void copyFrom(const ProcEntry& arg);
};
typedef std::vector<ProcEntry> ProcEntryList;
void procList(ProcEntryList& processes);
#endif // #defined _PROCLIST_

View file

@ -1,270 +0,0 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <assert.h>
#include "serverLists.hpp"
//----------------------------------------------------------------------
// Lists
//
CRITICAL_SECTION Lists::crit;
void
Lists::init() {
InitializeCriticalSection(&crit);
}
void
Lists::lock() {
EnterCriticalSection(&crit);
}
void
Lists::unlock() {
LeaveCriticalSection(&crit);
}
//----------------------------------------------------------------------
// ListsLocker
//
ListsLocker::ListsLocker() {
Lists::lock();
}
ListsLocker::~ListsLocker() {
Lists::unlock();
}
//----------------------------------------------------------------------
// ChildInfo
//
ChildInfo::ChildInfo(DWORD pid, HANDLE childProcessHandle,
HANDLE writeToStdinHandle, HANDLE readFromStdoutHandle,
HANDLE auxHandle1, HANDLE auxHandle2) {
this->pid = pid;
this->childProcessHandle = childProcessHandle;
this->writeToStdinHandle = writeToStdinHandle;
this->readFromStdoutHandle = readFromStdoutHandle;
this->auxHandle1 = auxHandle1;
this->auxHandle2 = auxHandle2;
client = NULL;
}
DWORD
ChildInfo::getPid() {
return pid;
}
HANDLE
ChildInfo::getChildProcessHandle() {
return childProcessHandle;
}
HANDLE
ChildInfo::getWriteToStdinHandle() {
return writeToStdinHandle;
}
HANDLE
ChildInfo::getReadFromStdoutHandle() {
return readFromStdoutHandle;
}
void
ChildInfo::setClient(ClientInfo* clientInfo) {
client = clientInfo;
}
ClientInfo*
ChildInfo::getClient() {
return client;
}
void
ChildInfo::closeAll() {
CloseHandle(childProcessHandle);
CloseHandle(writeToStdinHandle);
CloseHandle(readFromStdoutHandle);
CloseHandle(auxHandle1);
CloseHandle(auxHandle2);
}
//----------------------------------------------------------------------
// ChildList
//
ChildList::ChildList() {
}
ChildList::~ChildList() {
}
void
ChildList::addChild(ChildInfo* info) {
// Could store these in binary sorted order by pid for efficiency
childList.push_back(info);
}
ChildInfo*
ChildList::removeChild(HANDLE childProcessHandle) {
for (ChildInfoList::iterator iter = childList.begin(); iter != childList.end();
iter++) {
ChildInfo* info = *iter;
if (info->getChildProcessHandle() == childProcessHandle) {
childList.erase(iter);
return info;
}
}
assert(false);
return NULL;
}
void
ChildList::removeChild(ChildInfo* info) {
for (ChildInfoList::iterator iter = childList.begin(); iter != childList.end();
iter++) {
if (*iter == info) {
childList.erase(iter);
return;
}
}
assert(false);
}
ChildInfo*
ChildList::getChildByPid(DWORD pid) {
for (ChildInfoList::iterator iter = childList.begin(); iter != childList.end();
iter++) {
ChildInfo* info = *iter;
if (info->getPid() == pid) {
return info;
}
}
return NULL;
}
int
ChildList::size() {
return childList.size();
}
ChildInfo*
ChildList::getChildByIndex(int index) {
return childList[index];
}
//----------------------------------------------------------------------
// ClientInfo
//
ClientInfo::ClientInfo(SOCKET dataSocket) {
this->dataSocket = dataSocket;
buf = new IOBuf(32768, 131072);
buf->setSocket(dataSocket);
target = NULL;
}
ClientInfo::~ClientInfo() {
delete buf;
}
SOCKET
ClientInfo::getDataSocket() {
return dataSocket;
}
IOBuf*
ClientInfo::getIOBuf() {
return buf;
}
void
ClientInfo::setTarget(ChildInfo* childInfo) {
target = childInfo;
}
ChildInfo*
ClientInfo::getTarget() {
return target;
}
void
ClientInfo::closeAll() {
shutdown(dataSocket, SD_BOTH);
closesocket(dataSocket);
dataSocket = INVALID_SOCKET;
}
//----------------------------------------------------------------------
// ClientList
//
ClientList::ClientList() {
}
ClientList::~ClientList() {
}
void
ClientList::addClient(ClientInfo* info) {
clientList.push_back(info);
}
bool
ClientList::isAnyDataSocketSet(fd_set* fds, ClientInfo** out) {
for (ClientInfoList::iterator iter = clientList.begin(); iter != clientList.end();
iter++) {
ClientInfo* info = *iter;
if (FD_ISSET(info->getDataSocket(), fds)) {
*out = info;
return true;
}
}
return false;
}
void
ClientList::removeClient(ClientInfo* client) {
for (ClientInfoList::iterator iter = clientList.begin(); iter != clientList.end();
iter++) {
if (*iter == client) {
clientList.erase(iter);
return;
}
}
assert(false);
}
int
ClientList::size() {
return clientList.size();
}
ClientInfo*
ClientList::get(int num) {
return clientList[num];
}

View file

@ -1,204 +0,0 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _SERVER_LISTS_
#define _SERVER_LISTS_
#include <vector>
#include <winsock2.h>
#include "IOBuf.hpp"
//
// NOTE:
//
// All of these lists are guarded by the global lock managed by the
// Lists class. Lists::init() must be called at the start of the
// program.
//
class Lists {
friend class ListsLocker;
public:
static void init();
private:
static void lock();
static void unlock();
static CRITICAL_SECTION crit;
};
// Should be allocated on stack. Ensures proper locking/unlocking
// pairing.
class ListsLocker {
public:
ListsLocker();
~ListsLocker();
};
// We must keep track of all of the child processes we have forked to
// handle attaching to a target process. This is necessary because we
// allow clients to detach from processes, but the child processes we
// fork must necessarily stay alive for the duration of the target
// application. A subsequent attach operation to the target process
// results in the same child process being reused. For this reason,
// child processes are known to be in one of two states: attached and
// detached.
class ClientInfo;
class ChildInfo {
public:
/** The pid of the ChildInfo indicates the process ID of the target
process which the subprocess was created to debug, not the pid
of the subprocess itself. */
ChildInfo(DWORD pid, HANDLE childProcessHandle,
HANDLE writeToStdinHandle, HANDLE readFromStdoutHandle,
HANDLE auxHandle1, HANDLE auxHandle2);
DWORD getPid();
HANDLE getChildProcessHandle();
HANDLE getWriteToStdinHandle();
HANDLE getReadFromStdoutHandle();
/** Set the client which is currently attached to the target process
via this child process. Set this to NULL to indicate that the
child process is ready to accept another attachment. */
void setClient(ClientInfo* clientInfo);
ClientInfo* getClient();
/** This is NOT automatically called in the destructor */
void closeAll();
private:
DWORD pid;
HANDLE childProcessHandle;
HANDLE writeToStdinHandle;
HANDLE readFromStdoutHandle;
HANDLE auxHandle1;
HANDLE auxHandle2;
ClientInfo* client;
};
// We keep track of a list of child debugger processes, each of which
// is responsible for debugging a certain target process. These
// debugger processes can serve multiple clients during their
// lifetime. When a client detaches from a given process or tells the
// debugger to "exit", the debug server is notified that the child
// process is once again available to accept connections from clients.
class ChildList {
private:
typedef std::vector<ChildInfo*> ChildInfoList;
public:
ChildList();
~ChildList();
void addChild(ChildInfo*);
/** Removes and returns the ChildInfo* associated with the given
child process handle. */
ChildInfo* removeChild(HANDLE childProcessHandle);
/** Removes the given ChildInfo. */
void removeChild(ChildInfo* info);
/** Return the ChildInfo* associated with a given process ID without
removing it from the list. */
ChildInfo* getChildByPid(DWORD pid);
/** Iteration support */
int size();
/** Iteration support */
ChildInfo* getChildByIndex(int index);
private:
ChildInfoList childList;
};
// We also keep a list of clients whose requests we are responsible
// for serving. Clients can attach and detach from child processes.
class ClientInfo {
public:
ClientInfo(SOCKET dataSocket);
~ClientInfo();
SOCKET getDataSocket();
/** Gets an IOBuf configured for the data socket, which should be
used for all communication with the client. */
IOBuf* getIOBuf();
/** Set the information for the process to which this client is
attached. Set this to NULL to indicate that the client is not
currently attached to any target process. */
void setTarget(ChildInfo* childInfo);
/** Get the information for the process to which this client is
currently attached, or NULL if none. */
ChildInfo* getTarget();
/** Close down the socket connection to this client. This is NOT
automatically called by the destructor. */
void closeAll();
private:
SOCKET dataSocket;
IOBuf* buf;
ChildInfo* target;
};
class ClientList {
private:
typedef std::vector<ClientInfo*> ClientInfoList;
public:
ClientList();
~ClientList();
/** Adds a client to the list. */
void addClient(ClientInfo* info);
/** Check to see whether the parent socket of any of the ClientInfo
objects is readable in the given fd_set. If so, returns TRUE and
sets the given ClientInfo* (a non-NULL pointer to which must be
given) appropriately. */
bool isAnyDataSocketSet(fd_set* fds, ClientInfo** info);
/** Removes a client from the list. User is responsible for deleting
the ClientInfo* using operator delete. */
void removeClient(ClientInfo* client);
/** Iteration support. */
int size();
/** Iteration support. */
ClientInfo* get(int num);
private:
ClientInfoList clientList;
};
#endif // #defined _SERVER_LISTS_

View file

@ -1,48 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "toolHelp.hpp"
#include <assert.h>
namespace ToolHelp {
static HMODULE kernelDLL = NULL;
HMODULE loadDLL() {
if (kernelDLL == NULL) {
kernelDLL = LoadLibrary("KERNEL32.DLL");
}
assert(kernelDLL != NULL);
return kernelDLL;
}
void unloadDLL() {
if (kernelDLL != NULL) {
FreeLibrary(kernelDLL);
kernelDLL = NULL;
}
}
} // namespace ToolHelp

View file

@ -1,75 +0,0 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _TOOLHELP_H_
#define _TOOLHELP_H_
#include <windows.h>
#include <tlhelp32.h>
namespace ToolHelp {
extern "C" {
///////////////
// Snapshots //
///////////////
typedef HANDLE WINAPI
CreateToolhelp32SnapshotFunc(DWORD dwFlags, DWORD th32ProcessID);
//////////////////
// Process List //
//////////////////
typedef BOOL WINAPI Process32FirstFunc(HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
typedef BOOL WINAPI Process32NextFunc(HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
// NOTE: although these routines are defined in TLHELP32.H, they
// seem to always return false (maybe only under US locales)
typedef BOOL WINAPI Process32FirstWFunc(HANDLE hSnapshot,
LPPROCESSENTRY32W lppe);
typedef BOOL WINAPI Process32NextWFunc(HANDLE hSnapshot,
LPPROCESSENTRY32W lppe);
/////////////////
// Module List //
/////////////////
typedef BOOL WINAPI
Module32FirstFunc(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
typedef BOOL WINAPI
Module32NextFunc (HANDLE hSnapshot, LPMODULEENTRY32 lpme);
// Routines to load and unload KERNEL32.DLL.
HMODULE loadDLL();
// Safe to call even if has not been loaded
void unloadDLL();
} // extern "C"
} // namespace "ToolHelp"
#endif // #defined _TOOLHELP_H_

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -170,6 +170,7 @@ public class CLHSDB {
final String errMsg = formatMessage(e.getMessage(), 80);
System.err.println("Unable to connect to process ID " + pid + ":\n\n" + errMsg);
agent.detach();
e.printStackTrace();
return;
}
}
@ -191,6 +192,7 @@ public class CLHSDB {
final String errMsg = formatMessage(e.getMessage(), 80);
System.err.println("Unable to open core file\n" + corePath + ":\n\n" + errMsg);
agent.detach();
e.printStackTrace();
return;
}
}
@ -209,6 +211,7 @@ public class CLHSDB {
final String errMsg = formatMessage(e.getMessage(), 80);
System.err.println("Unable to connect to machine \"" + remoteMachineName + "\":\n\n" + errMsg);
agent.detach();
e.printStackTrace();
return;
}
}

View file

@ -40,6 +40,8 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.opto.*;
import sun.jvm.hotspot.ci.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.utilities.soql.*;
@ -48,6 +50,8 @@ import sun.jvm.hotspot.ui.tree.*;
import sun.jvm.hotspot.tools.*;
import sun.jvm.hotspot.tools.ObjectHistogram;
import sun.jvm.hotspot.tools.StackTrace;
import sun.jvm.hotspot.tools.jcore.ClassDump;
import sun.jvm.hotspot.tools.jcore.ClassFilter;
public class CommandProcessor {
public abstract static class DebuggerInterface {
@ -59,6 +63,27 @@ public class CommandProcessor {
public abstract void reattach();
}
public static class BootFilter implements ClassFilter {
public boolean canInclude(InstanceKlass kls) {
return kls.getClassLoader() == null;
}
}
public static class NonBootFilter implements ClassFilter {
private HashMap emitted = new HashMap();
public boolean canInclude(InstanceKlass kls) {
if (kls.getClassLoader() == null) return false;
if (emitted.get(kls.getName()) != null) {
// Since multiple class loaders are being shoved
// together duplicate classes are a possibilty. For
// now just ignore them.
return false;
}
emitted.put(kls.getName(), kls);
return true;
}
}
static class Tokens {
final String input;
int i;
@ -258,9 +283,14 @@ public class CommandProcessor {
}
void dumpFields(Type type) {
dumpFields(type, true);
}
void dumpFields(Type type, boolean allowStatic) {
Iterator i = type.getFields();
while (i.hasNext()) {
Field f = (Field) i.next();
if (!allowStatic && f.isStatic()) continue;
out.print("field ");
quote(type.getName());
out.print(" ");
@ -458,13 +488,18 @@ public class CommandProcessor {
});
}
},
new Command("flags", "flags [ flag ]", false) {
new Command("flags", "flags [ flag | -nd ]", false) {
public void doit(Tokens t) {
int tokens = t.countTokens();
if (tokens != 0 && tokens != 1) {
usage();
} else {
String name = tokens > 0 ? t.nextToken() : null;
boolean nonDefault = false;
if (name != null && name.equals("-nd")) {
name = null;
nonDefault = true;
}
VM.Flag[] flags = VM.getVM().getCommandLineFlags();
if (flags == null) {
@ -474,7 +509,12 @@ public class CommandProcessor {
for (int f = 0; f < flags.length; f++) {
VM.Flag flag = flags[f];
if (name == null || flag.getName().equals(name)) {
out.println(flag.getName() + " = " + flag.getValue());
if (nonDefault && flag.getOrigin() == 0) {
// only print flags which aren't their defaults
continue;
}
out.println(flag.getName() + " = " + flag.getValue() + " " + flag.getOrigin());
printed = true;
}
}
@ -586,6 +626,158 @@ public class CommandProcessor {
}
}
},
new Command("printmdo", "printmdo [ -a | expression ]", false) {
// Print every MDO in the heap or the one referenced by expression.
public void doit(Tokens t) {
if (t.countTokens() != 1) {
usage();
} else {
String s = t.nextToken();
if (s.equals("-a")) {
HeapVisitor iterator = new DefaultHeapVisitor() {
public boolean doObj(Oop obj) {
if (obj instanceof MethodData) {
Method m = ((MethodData)obj).getMethod();
out.println("MethodData " + obj.getHandle() + " for " +
"method " + m.getMethodHolder().getName().asString() + "." +
m.getName().asString() +
m.getSignature().asString() + "@" + m.getHandle());
((MethodData)obj).printDataOn(out);
}
return false;
}
};
VM.getVM().getObjectHeap().iteratePerm(iterator);
} else {
Address a = VM.getVM().getDebugger().parseAddress(s);
OopHandle handle = a.addOffsetToAsOopHandle(0);
MethodData mdo = (MethodData)VM.getVM().getObjectHeap().newOop(handle);
mdo.printDataOn(out);
}
}
}
},
new Command("dumpideal", "dumpideal { -a | id }", false) {
// Do a full dump of the nodes reachabile from root in each compiler thread.
public void doit(Tokens t) {
if (t.countTokens() != 1) {
usage();
} else {
String name = t.nextToken();
boolean all = name.equals("-a");
Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) {
if (thread instanceof CompilerThread) {
CompilerThread ct = (CompilerThread)thread;
out.println(ct);
ciEnv env = ct.env();
if (env != null) {
Compile c = env.compilerData();
c.root().dump(9999, out);
} else {
out.println(" not compiling");
}
}
}
}
}
}
},
new Command("dumpcfg", "dumpcfg { -a | id }", false) {
// Dump the PhaseCFG for every compiler thread that has one live.
public void doit(Tokens t) {
if (t.countTokens() != 1) {
usage();
} else {
String name = t.nextToken();
boolean all = name.equals("-a");
Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) {
if (thread instanceof CompilerThread) {
CompilerThread ct = (CompilerThread)thread;
out.println(ct);
ciEnv env = ct.env();
if (env != null) {
Compile c = env.compilerData();
c.cfg().dump(out);
}
}
}
}
}
}
},
new Command("dumpilt", "dumpilt { -a | id }", false) {
// dumps the InlineTree of a C2 compile
public void doit(Tokens t) {
if (t.countTokens() != 1) {
usage();
} else {
String name = t.nextToken();
boolean all = name.equals("-a");
Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) {
if (thread instanceof CompilerThread) {
CompilerThread ct = (CompilerThread)thread;
ciEnv env = ct.env();
if (env != null) {
Compile c = env.compilerData();
InlineTree ilt = c.ilt();
if (ilt != null) {
ilt.print(out);
}
}
}
}
}
}
}
},
new Command("vmstructsdump", "vmstructsdump", false) {
public void doit(Tokens t) {
if (t.countTokens() != 0) {
usage();
return;
}
// Dump a copy of the type database in a form that can
// be read back.
Iterator i = agent.getTypeDataBase().getTypes();
// Make sure the types are emitted in an order than can be read back in
HashSet emitted = new HashSet();
Stack pending = new Stack();
while (i.hasNext()) {
Type n = (Type)i.next();
if (emitted.contains(n.getName())) {
continue;
}
while (n != null && !emitted.contains(n.getName())) {
pending.push(n);
n = n.getSuperclass();
}
while (!pending.empty()) {
n = (Type)pending.pop();
dumpType(n);
emitted.add(n.getName());
}
}
i = agent.getTypeDataBase().getTypes();
while (i.hasNext()) {
dumpFields((Type)i.next(), false);
}
}
},
new Command("inspect", "inspect expression", false) {
public void doit(Tokens t) {
if (t.countTokens() != 1) {
@ -760,6 +952,50 @@ public class CommandProcessor {
}
}
},
new Command("intConstant", "intConstant [ name [ value ] ]", true) {
public void doit(Tokens t) {
if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {
usage();
return;
}
HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
if (t.countTokens() == 1) {
out.println("intConstant " + name + " " + db.lookupIntConstant(name));
} else if (t.countTokens() == 0) {
Iterator i = db.getIntConstants();
while (i.hasNext()) {
String name = (String)i.next();
out.println("intConstant " + name + " " + db.lookupIntConstant(name));
}
} else if (t.countTokens() == 2) {
String name = t.nextToken();
Integer value = Integer.valueOf(t.nextToken());
db.addIntConstant(name, value);
}
}
},
new Command("longConstant", "longConstant [ name [ value ] ]", true) {
public void doit(Tokens t) {
if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {
usage();
return;
}
HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
if (t.countTokens() == 1) {
out.println("longConstant " + name + " " + db.lookupLongConstant(name));
} else if (t.countTokens() == 0) {
Iterator i = db.getLongConstants();
while (i.hasNext()) {
String name = (String)i.next();
out.println("longConstant " + name + " " + db.lookupLongConstant(name));
}
} else if (t.countTokens() == 2) {
String name = t.nextToken();
Long value = Long.valueOf(t.nextToken());
db.addLongConstant(name, value);
}
}
},
new Command("field", "field [ type [ name fieldtype isStatic offset address ] ]", true) {
public void doit(Tokens t) {
if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {
@ -1311,13 +1547,13 @@ public class CommandProcessor {
return;
}
executeCommand(ln);
executeCommand(ln, prompt);
}
}
static Pattern historyPattern = Pattern.compile("((!\\*)|(!\\$)|(!!-?)|(!-?[0-9][0-9]*)|(![a-zA-Z][^ ]*))");
public void executeCommand(String ln) {
public void executeCommand(String ln, boolean putInHistory) {
if (ln.indexOf('!') != -1) {
int size = history.size();
if (size == 0) {
@ -1406,7 +1642,7 @@ public class CommandProcessor {
Tokens t = new Tokens(ln);
if (t.hasMoreTokens()) {
boolean error = false;
history.add(ln);
if (putInHistory) history.add(ln);
int len = t.countTokens();
if (len > 2) {
String r = t.at(len - 2);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,6 @@
package sun.jvm.hotspot;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,10 +28,8 @@ import java.io.PrintStream;
import java.net.*;
import java.rmi.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.debugger.remote.*;
import sun.jvm.hotspot.debugger.win32.*;
import sun.jvm.hotspot.debugger.windbg.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.memory.*;
@ -436,7 +434,6 @@ public class HotSpotAgent {
private void setupDebuggerSolaris() {
setupJVMLibNamesSolaris();
if(System.getProperty("sun.jvm.hotspot.debugger.useProcDebugger") != null) {
ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
debugger = dbg;
attachDebugger();
@ -466,83 +463,6 @@ public class HotSpotAgent {
dbg.setMachineDescription(machDesc);
return;
} else {
String dbxPathName;
String dbxPathPrefix;
String dbxSvcAgentDSOPathName;
String dbxSvcAgentDSOPathPrefix;
String[] dbxSvcAgentDSOPathNames = null;
// use path names/prefixes specified on command
dbxPathName = System.getProperty("dbxPathName");
if (dbxPathName == null) {
dbxPathPrefix = System.getProperty("dbxPathPrefix");
if (dbxPathPrefix == null) {
dbxPathPrefix = defaultDbxPathPrefix;
}
dbxPathName = dbxPathPrefix + fileSep + os + fileSep + cpu + fileSep + "bin" + fileSep + "dbx";
}
dbxSvcAgentDSOPathName = System.getProperty("dbxSvcAgentDSOPathName");
if (dbxSvcAgentDSOPathName != null) {
dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathName } ;
} else {
dbxSvcAgentDSOPathPrefix = System.getProperty("dbxSvcAgentDSOPathPrefix");
if (dbxSvcAgentDSOPathPrefix == null) {
dbxSvcAgentDSOPathPrefix = defaultDbxSvcAgentDSOPathPrefix;
}
if (cpu.equals("sparc")) {
dbxSvcAgentDSOPathNames = new String[] {
// FIXME: bad hack for SPARC v9. This is necessary because
// there are two dbx executables on SPARC, one for v8 and one
// for v9, and it isn't obvious how to tell the two apart
// using the dbx command line. See
// DbxDebuggerLocal.importDbxModule().
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + "v9" + fileSep + "lib" +
fileSep + "libsvc_agent_dbx.so",
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" +
fileSep + "libsvc_agent_dbx.so",
};
} else {
dbxSvcAgentDSOPathNames = new String[] {
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" +
fileSep + "libsvc_agent_dbx.so"
};
}
}
// Note we do not use a cache for the local debugger in server
// mode; it's taken care of on the client side
DbxDebuggerLocal dbg = new DbxDebuggerLocal(null, dbxPathName, dbxSvcAgentDSOPathNames, !isServer);
debugger = dbg;
attachDebugger();
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's " +
"address size. It's possible that the Serviceability Agent's dbx module failed to " +
"initialize. Examine the standard output and standard error streams from the dbx " +
"process for more information.");
}
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
}
dbg.setMachineDescription(machDesc);
}
}
private void connectRemoteDebugger() throws DebuggerException {
@ -589,11 +509,7 @@ public class HotSpotAgent {
// mode; it will be taken care of on the client side (once remote
// debugging is implemented).
if (System.getProperty("sun.jvm.hotspot.debugger.useWindbgDebugger") != null) {
debugger = new WindbgDebuggerLocal(machDesc, !isServer);
} else {
debugger = new Win32DebuggerLocal(machDesc, !isServer);
}
attachDebugger();

View file

@ -87,6 +87,7 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
readVMStructs();
readVMIntConstants();
readVMLongConstants();
readExternalDefinitions();
}
public Type lookupType(String cTypeName, boolean throwException) {
@ -98,9 +99,9 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
fieldType = (BasicType)lookupType(cTypeName.substring(0, cTypeName.length() - 6), false);
}
if (fieldType == null) {
if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">*")) {
if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">")) {
String ttype = cTypeName.substring("GrowableArray<".length(),
cTypeName.length() - 2);
cTypeName.length() - 1);
Type templateType = lookupType(ttype, false);
if (templateType == null && typeNameIsPointerType(ttype)) {
templateType = recursiveCreateBasicPointerType(ttype);
@ -108,7 +109,21 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
if (templateType == null) {
lookupOrFail(ttype);
}
fieldType = recursiveCreateBasicPointerType(cTypeName);
BasicType basicTargetType = createBasicType(cTypeName, false, false, false);
// transfer fields from GenericGrowableArray to template instance
BasicType generic = lookupOrFail("GenericGrowableArray");
BasicType specific = lookupOrFail("GrowableArray<int>");
basicTargetType.setSize(specific.getSize());
Iterator fields = generic.getFields();
while (fields.hasNext()) {
Field f = (Field)fields.next();
basicTargetType.addField(internalCreateField(basicTargetType, f.getName(),
f.getType(), f.isStatic(),
f.getOffset(), null));
}
fieldType = basicTargetType;
}
}
if (fieldType == null && typeNameIsPointerType(cTypeName)) {
@ -208,6 +223,156 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
return type;
}
private void readExternalDefinitions() {
String file = System.getProperty("sun.jvm.hotspot.typedb");
if (file != null) {
System.out.println("Reading " + file);
BufferedReader in = null;
try {
StreamTokenizer t = new StreamTokenizer(in = new BufferedReader(new InputStreamReader(new FileInputStream(file))));
t.resetSyntax();
t.wordChars('\u0000','\uFFFF');
t.whitespaceChars(' ', ' ');
t.whitespaceChars('\n', '\n');
t.whitespaceChars('\r', '\r');
t.quoteChar('\"');
t.eolIsSignificant(true);
while (t.nextToken() != StreamTokenizer.TT_EOF) {
if (t.ttype == StreamTokenizer.TT_EOL) {
continue;
}
if (t.sval.equals("field")) {
t.nextToken();
BasicType containingType = (BasicType)lookupType(t.sval);
t.nextToken();
String fieldName = t.sval;
// The field's Type must already be in the database -- no exceptions
t.nextToken();
Type fieldType = lookupType(t.sval);
t.nextToken();
boolean isStatic = Boolean.valueOf(t.sval).booleanValue();
t.nextToken();
long offset = Long.parseLong(t.sval);
t.nextToken();
Address staticAddress = null;
if (isStatic) {
throw new InternalError("static fields not supported");
}
// check to see if the field already exists
Iterator i = containingType.getFields();
boolean defined = false;
while (i.hasNext()) {
Field f = (Field) i.next();
if (f.getName().equals(fieldName)) {
if (f.isStatic() != isStatic) {
throw new RuntimeException("static/nonstatic mismatch: " + fieldName);
}
if (!isStatic) {
if (f.getOffset() != offset) {
throw new RuntimeException("bad redefinition of field offset: " + fieldName);
}
} else {
if (!f.getStaticFieldAddress().equals(staticAddress)) {
throw new RuntimeException("bad redefinition of field location: " + fieldName);
}
}
if (f.getType() != fieldType) {
System.out.println(fieldType);
System.out.println(f.getType());
throw new RuntimeException("bad redefinition of field type: " + fieldName);
}
defined = true;
break;
}
}
if (!defined) {
// Create field by type
createField(containingType,
fieldName, fieldType,
isStatic,
offset,
staticAddress);
}
} else if (t.sval.equals("type")) {
t.nextToken();
String typeName = t.sval;
t.nextToken();
String superclassName = t.sval;
if (superclassName.equals("null")) {
superclassName = null;
}
t.nextToken();
boolean isOop = Boolean.valueOf(t.sval).booleanValue();
t.nextToken();
boolean isInteger = Boolean.valueOf(t.sval).booleanValue();
t.nextToken();
boolean isUnsigned = Boolean.valueOf(t.sval).booleanValue();
t.nextToken();
long size = Long.parseLong(t.sval);
BasicType type = null;
try {
type = (BasicType)lookupType(typeName);
} catch (RuntimeException e) {
}
if (type != null) {
if (type.isOopType() != isOop) {
throw new RuntimeException("oop mismatch in type definition: " + typeName);
}
if (type.isCIntegerType() != isInteger) {
throw new RuntimeException("integer type mismatch in type definition: " + typeName);
}
if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) {
throw new RuntimeException("unsigned mismatch in type definition: " + typeName);
}
if (type.getSuperclass() == null) {
if (superclassName != null) {
if (type.getSize() == -1) {
type.setSuperclass(lookupType(superclassName));
} else {
throw new RuntimeException("unexpected superclass in type definition: " + typeName);
}
}
} else {
if (superclassName == null) {
throw new RuntimeException("missing superclass in type definition: " + typeName);
}
if (!type.getSuperclass().getName().equals(superclassName)) {
throw new RuntimeException("incorrect superclass in type definition: " + typeName);
}
}
if (type.getSize() != size) {
if (type.getSize() == -1 || type.getSize() == 0) {
type.setSize(size);
} else {
throw new RuntimeException("size mismatch in type definition: " + typeName + ": " + type.getSize() + " != " + size);
}
}
}
if (lookupType(typeName, false) == null) {
// Create type
createType(typeName, superclassName, isOop, isInteger, isUnsigned, size);
}
} else {
throw new InternalError("\"" + t.sval + "\"");
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
in.close();
} catch (Exception e) {
}
}
}
}
private void readVMStructs() {
// Get the variables we need in order to traverse the VMStructEntry[]
long structEntryTypeNameOffset;
@ -504,20 +669,6 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
BasicType basicTargetType = createBasicType(targetTypeName, false, true, true);
basicTargetType.setSize(1);
targetType = basicTargetType;
} else if (targetTypeName.startsWith("GrowableArray<")) {
BasicType basicTargetType = createBasicType(targetTypeName, false, false, false);
// transfer fields from GenericGrowableArray to template instance
BasicType generic = lookupOrFail("GenericGrowableArray");
basicTargetType.setSize(generic.getSize());
Iterator fields = generic.getFields();
while (fields.hasNext()) {
Field f = (Field)fields.next();
basicTargetType.addField(internalCreateField(basicTargetType, f.getName(),
f.getType(), f.isStatic(),
f.getOffset(), null));
}
targetType = basicTargetType;
} else {
if (DEBUG) {
System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\"");
@ -572,7 +723,7 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
// Classes are created with a size of UNINITIALIZED_SIZE.
// Set size if necessary.
if (curType.getSize() == UNINITIALIZED_SIZE) {
if (curType.getSize() == UNINITIALIZED_SIZE || curType.getSize() == 0) {
curType.setSize(size);
} else {
if (curType.getSize() != size) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,18 +25,12 @@
package sun.jvm.hotspot;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.debugger.proc.*;
// A test of the debugger backend. This should be used to connect to
// the helloWorld.cpp program.
public class TestDebugger {
// FIXME: make these configurable, i.e., via a dotfile
private static final String dbxPathName = "/export/home/kbr/ws/dbx_61/dev/Derived-sparcv9-S2./src/dbx/dbx";
private static final String[] dbxSvcAgentDSOPathNames =
new String[] {
"/export/home/kbr/main/sa_baseline/src/os/solaris/agent/libsvc_agent_dbx.so"
};
private static void usage() {
System.out.println("usage: java TestDebugger [pid]");
@ -58,8 +52,7 @@ public class TestDebugger {
usage();
}
JVMDebugger debugger = new DbxDebuggerLocal(new MachineDescriptionSPARC64Bit(),
dbxPathName, dbxSvcAgentDSOPathNames, true);
JVMDebugger debugger = new ProcDebuggerLocal(null, true);
try {
debugger.attach(pid);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,7 +34,7 @@ import javax.swing.filechooser.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.posix.*;
import sun.jvm.hotspot.debugger.win32.*;
import sun.jvm.hotspot.debugger.windbg.*;
import sun.jvm.hotspot.livejvm.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
@ -604,7 +604,7 @@ public class BugSpot extends JPanel {
throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Windows");
}
localDebugger = new Win32DebuggerLocal(new MachineDescriptionIntelX86(), true);
localDebugger = new WindbgDebuggerLocal(new MachineDescriptionIntelX86(), true);
} else if (os.equals("linux")) {
if (!cpu.equals("x86")) {
throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Linux");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,10 +29,8 @@ import java.net.*;
import java.rmi.*;
import sun.jvm.hotspot.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.win32.*;
import sun.jvm.hotspot.debugger.windbg.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.debugger.sparc.*;
@ -627,8 +625,6 @@ public class BugSpotAgent {
private void setupDebuggerSolaris() {
setupJVMLibNamesSolaris();
String prop = System.getProperty("sun.jvm.hotspot.debugger.useProcDebugger");
if (prop != null && !prop.equals("false")) {
ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
debugger = dbg;
attachDebugger();
@ -656,75 +652,6 @@ public class BugSpotAgent {
}
dbg.setMachineDescription(machDesc);
return;
} else {
String dbxPathName;
String dbxPathPrefix;
String dbxSvcAgentDSOPathName;
String dbxSvcAgentDSOPathPrefix;
String[] dbxSvcAgentDSOPathNames = null;
// use path names/prefixes specified on command
dbxPathName = System.getProperty("dbxPathName");
if (dbxPathName == null) {
dbxPathPrefix = System.getProperty("dbxPathPrefix");
if (dbxPathPrefix == null) {
dbxPathPrefix = defaultDbxPathPrefix;
}
dbxPathName = dbxPathPrefix + fileSep + os + fileSep + cpu + fileSep + "bin" + fileSep + "dbx";
}
dbxSvcAgentDSOPathName = System.getProperty("dbxSvcAgentDSOPathName");
if (dbxSvcAgentDSOPathName != null) {
dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathName } ;
} else {
dbxSvcAgentDSOPathPrefix = System.getProperty("dbxSvcAgentDSOPathPrefix");
if (dbxSvcAgentDSOPathPrefix == null) {
dbxSvcAgentDSOPathPrefix = defaultDbxSvcAgentDSOPathPrefix;
}
if (cpu.equals("sparc")) {
dbxSvcAgentDSOPathNames = new String[] {
// FIXME: bad hack for SPARC v9. This is necessary because
// there are two dbx executables on SPARC, one for v8 and one
// for v9, and it isn't obvious how to tell the two apart
// using the dbx command line. See
// DbxDebuggerLocal.importDbxModule().
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + "v9" + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so",
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so",
};
} else {
dbxSvcAgentDSOPathNames = new String[] {
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so"
};
}
}
// Note we do not use a cache for the local debugger in server
// mode; it's taken care of on the client side
DbxDebuggerLocal dbg = new DbxDebuggerLocal(null, dbxPathName, dbxSvcAgentDSOPathNames, !isServer);
debugger = dbg;
attachDebugger();
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's address size. It's possible that the Serviceability Agent's dbx module failed to initialize. Examine the standard output and standard error streams from the dbx process for more information.");
}
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
}
dbg.setMachineDescription(machDesc);
}
}
private void connectRemoteDebugger() throws DebuggerException {
@ -772,11 +699,7 @@ public class BugSpotAgent {
// mode; it will be taken care of on the client side (once remote
// debugging is implemented).
if (System.getProperty("sun.jvm.hotspot.debugger.useWindbgDebugger") != null) {
debugger = new WindbgDebuggerLocal(machDesc, !isServer);
} else {
debugger = new Win32DebuggerLocal(machDesc, !isServer);
}
attachDebugger();
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciArrayKlass extends ciKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciArrayKlass");
dimensionField = new IntField(type.getJIntField("_dimension"), 0);
}
private static IntField dimensionField;
public ciArrayKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciArrayKlassKlass extends ciKlassKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciArrayKlassKlass");
}
public ciArrayKlassKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciConstant extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciConstant");
valueObjectField = type.getAddressField("_value._object");
valueDoubleField = type.getJDoubleField("_value._double");
valueFloatField = type.getJFloatField("_value._float");
valueLongField = type.getJLongField("_value._long");
valueIntField = type.getJIntField("_value._int");
typeField = new CIntField(type.getCIntegerField("_type"), 0);
}
private static AddressField valueObjectField;
private static JDoubleField valueDoubleField;
private static JFloatField valueFloatField;
private static JLongField valueLongField;
private static JIntField valueIntField;
private static CIntField typeField;
public ciConstant(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.opto.*;
import sun.jvm.hotspot.compiler.CompileTask;
import sun.jvm.hotspot.prims.JvmtiExport;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.GrowableArray;
public class ciEnv extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciEnv");
dependenciesField = type.getAddressField("_dependencies");
factoryField = type.getAddressField("_factory");
compilerDataField = type.getAddressField("_compiler_data");
taskField = type.getAddressField("_task");
systemDictionaryModificationCounterField = new CIntField(type.getCIntegerField("_system_dictionary_modification_counter"), 0);
}
private static AddressField dependenciesField;
private static AddressField factoryField;
private static AddressField compilerDataField;
private static AddressField taskField;
private static CIntField systemDictionaryModificationCounterField;
public ciEnv(Address addr) {
super(addr);
}
public Compile compilerData() {
return new Compile(compilerDataField.getValue(this.getAddress()));
}
public ciObjectFactory factory() {
return new ciObjectFactory(factoryField.getValue(this.getAddress()));
}
public CompileTask task() {
return new CompileTask(taskField.getValue(this.getAddress()));
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciField extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciField");
constantValueField = type.getAddressField("_constant_value");
isConstantField = type.getAddressField("_is_constant");
offsetField = new CIntField(type.getCIntegerField("_offset"), 0);
signatureField = type.getAddressField("_signature");
nameField = type.getAddressField("_name");
holderField = type.getAddressField("_holder");
}
private static AddressField constantValueField;
private static AddressField isConstantField;
private static CIntField offsetField;
private static AddressField signatureField;
private static AddressField nameField;
private static AddressField holderField;
public ciField(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciInstance extends ciObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciInstance");
}
public ciInstance(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.memory.SystemDictionary;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
import sun.jvm.hotspot.types.WrongTypeException;
public class ciInstanceKlass extends ciKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciInstanceKlass");
initStateField = new CIntField(type.getCIntegerField("_init_state"), 0);
isSharedField = new CIntField(type.getCIntegerField("_is_shared"), 0);
CLASS_STATE_LINKED = db.lookupIntConstant("instanceKlass::linked").intValue();
CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("instanceKlass::fully_initialized").intValue();
}
private static CIntField initStateField;
private static CIntField isSharedField;
private static int CLASS_STATE_LINKED;
private static int CLASS_STATE_FULLY_INITIALIZED;
public ciInstanceKlass(Address addr) {
super(addr);
}
public int initState() {
int initState = (int)initStateField.getValue(getAddress());
if (isShared() && initState < CLASS_STATE_LINKED) {
InstanceKlass ik = (InstanceKlass)getOop();
initState = ik.getInitStateAsInt();
}
return initState;
}
public boolean isShared() {
return isSharedField.getValue(getAddress()) != 0;
}
public boolean isLinked() {
return initState() >= CLASS_STATE_LINKED;
}
public boolean isInitialized() {
return initState() == CLASS_STATE_FULLY_INITIALIZED;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -16,29 +16,35 @@
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.debugger.dbx.sparc;
package sun.jvm.hotspot.ci;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class DbxSPARCThreadFactory implements DbxThreadFactory {
private DbxDebugger debugger;
public DbxSPARCThreadFactory(DbxDebugger debugger) {
this.debugger = debugger;
public class ciInstanceKlassKlass extends ciKlassKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
return new DbxSPARCThread(debugger, threadIdentifierAddr);
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciInstanceKlassKlass");
}
public ThreadProxy createThreadWrapper(long id) {
return new DbxSPARCThread(debugger, id);
public ciInstanceKlassKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciKlass extends ciType {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciKlass");
nameField = type.getAddressField("_name");
}
private static AddressField nameField;
public String name() {
ciSymbol sym = new ciSymbol(nameField.getValue(getAddress()));
return sym.asUtf88();
}
public ciKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciKlassKlass extends ciKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciKlassKlass");
}
public ciKlassKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciMethod extends ciObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciMethod");
interpreterThrowoutCountField = new CIntField(type.getCIntegerField("_interpreter_throwout_count"), 0);
interpreterInvocationCountField = new CIntField(type.getCIntegerField("_interpreter_invocation_count"), 0);
try {
// XXX
instructionsSizeField = new CIntField(type.getCIntegerField("_instructions_size"), 0);
} catch (Exception e) {
}
}
private static CIntField interpreterThrowoutCountField;
private static CIntField interpreterInvocationCountField;
private static CIntField instructionsSizeField;
public ciMethod(Address addr) {
super(addr);
}
public Method method() {
return (Method)getOop();
}
public int interpreterThrowoutCount() {
return (int) interpreterThrowoutCountField.getValue(getAddress());
}
public int interpreterInvocationCount() {
return (int) interpreterInvocationCountField.getValue(getAddress());
}
public int instructionsSize() {
if (instructionsSizeField == null) {
// XXX
Method method = (Method)getOop();
NMethod nm = method.getNativeMethod();
if (nm != null) return (int)nm.codeEnd().minus(nm.getVerifiedEntryPoint());
return 0;
}
return (int) instructionsSizeField.getValue(getAddress());
}
public void printShortName(PrintStream st) {
Method method = (Method)getOop();
st.printf(" %s::%s", method.getMethodHolder().getName().asString().replace('/', '.'),
method.getName().asString());
}
}

View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciMethodData extends ciObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciMethodData");
origField = type.getAddressField("_orig");
currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0);
argReturnedField = new CIntField(type.getCIntegerField("_arg_returned"), 0);
argStackField = new CIntField(type.getCIntegerField("_arg_stack"), 0);
argLocalField = new CIntField(type.getCIntegerField("_arg_local"), 0);
eflagsField = new CIntField(type.getCIntegerField("_eflags"), 0);
hintDiField = new CIntField(type.getCIntegerField("_hint_di"), 0);
currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0);
dataField = type.getAddressField("_data");
extraDataSizeField = new CIntField(type.getCIntegerField("_extra_data_size"), 0);
dataSizeField = new CIntField(type.getCIntegerField("_data_size"), 0);
stateField = new CIntField(type.getCIntegerField("_state"), 0);
sizeofMethodDataOopDesc = (int)db.lookupType("methodDataOopDesc").getSize();;
}
private static AddressField origField;
private static CIntField currentMileageField;
private static CIntField argReturnedField;
private static CIntField argStackField;
private static CIntField argLocalField;
private static CIntField eflagsField;
private static CIntField hintDiField;
private static AddressField dataField;
private static CIntField extraDataSizeField;
private static CIntField dataSizeField;
private static CIntField stateField;
private static int sizeofMethodDataOopDesc;
public ciMethodData(Address addr) {
super(addr);
}
private byte[] fetchDataAt(Address base, long size) {
byte[] result = new byte[(int)size];
for (int i = 0; i < size; i++) {
result[i] = base.getJByteAt(i);
}
return result;
}
public byte[] orig() {
// fetch the orig methodDataOopDesc data between header and dataSize
Address base = getAddress().addOffsetTo(origField.getOffset());
byte[] result = new byte[MethodData.sizeofMethodDataOopDesc];
for (int i = 0; i < MethodData.sizeofMethodDataOopDesc; i++) {
result[i] = base.getJByteAt(i);
}
return result;
}
public long[] data() {
// Read the data as an array of intptr_t elements
Address base = dataField.getValue(getAddress());
int elements = dataSize() / MethodData.cellSize;
long[] result = new long[elements];
for (int i = 0; i < elements; i++) {
Address value = base.getAddressAt(i * MethodData.cellSize);
if (value != null) {
result[i] = value.minus(null);
}
}
return result;
}
int dataSize() {
return (int)dataSizeField.getValue(getAddress());
}
int state() {
return (int)stateField.getValue(getAddress());
}
int currentMileage() {
return (int)currentMileageField.getValue(getAddress());
}
boolean outOfBounds(int dataIndex) {
return dataIndex >= dataSize();
}
ProfileData dataAt(int dataIndex) {
if (outOfBounds(dataIndex)) {
return null;
}
DataLayout dataLayout = new DataLayout(dataField.getValue(getAddress()), dataIndex);
switch (dataLayout.tag()) {
case DataLayout.noTag:
default:
throw new InternalError();
case DataLayout.bitDataTag:
return new BitData(dataLayout);
case DataLayout.counterDataTag:
return new CounterData(dataLayout);
case DataLayout.jumpDataTag:
return new JumpData(dataLayout);
case DataLayout.receiverTypeDataTag:
return new ciReceiverTypeData(dataLayout);
case DataLayout.virtualCallDataTag:
return new ciVirtualCallData(dataLayout);
case DataLayout.retDataTag:
return new RetData(dataLayout);
case DataLayout.branchDataTag:
return new BranchData(dataLayout);
case DataLayout.multiBranchDataTag:
return new MultiBranchData(dataLayout);
}
}
int dpToDi(int dp) {
return dp;
}
int firstDi() { return 0; }
ProfileData firstData() { return dataAt(firstDi()); }
ProfileData nextData(ProfileData current) {
int currentIndex = dpToDi(current.dp());
int nextIndex = currentIndex + current.sizeInBytes();
return dataAt(nextIndex);
}
boolean isValid(ProfileData current) { return current != null; }
public void printDataOn(PrintStream st) {
ProfileData data = firstData();
for ( ; isValid(data); data = nextData(data)) {
st.print(dpToDi(data.dp()));
st.print(" ");
// st->fillTo(6);
data.printDataOn(st);
}
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciMethodKlass extends ciKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciMethodKlass");
}
public ciMethodKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciObjArrayKlass extends ciArrayKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciObjArrayKlass");
elementKlassField = type.getAddressField("_element_klass");
baseElementKlassField = type.getAddressField("_base_element_klass");
}
private static AddressField elementKlassField;
private static AddressField baseElementKlassField;
public ciObjArrayKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciObjArrayKlassKlass extends ciArrayKlassKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciObjArrayKlassKlass");
}
public ciObjArrayKlassKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciObject extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciObject");
identField = new CIntField(type.getCIntegerField("_ident"), 0);
klassField = type.getAddressField("_klass");
handleField = type.getAddressField("_handle");
}
private static CIntField identField;
private static AddressField klassField;
private static AddressField handleField;
public Oop getOop() {
OopHandle oh = handleField.getValue(getAddress()).getOopHandleAt(0);
return VM.getVM().getObjectHeap().newOop(oh);
}
public ciObject(Address addr) {
super(addr);
}
public void printOn(PrintStream out) {
getOop().printValueOn(out);
out.println();
}
public String toString() {
return getOop().toString();
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.lang.reflect.Constructor;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciObjectFactory extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciObjectFactory");
unloadedMethodsField = type.getAddressField("_unloaded_methods");
ciObjectsField = type.getAddressField("_ci_objects");
symbolsField = type.getAddressField("_symbols");
ciObjectConstructor = new VirtualBaseConstructor<ciObject>(db, db.lookupType("ciObject"), "sun.jvm.hotspot.ci", ciObject.class);
ciSymbolConstructor = new VirtualBaseConstructor<ciSymbol>(db, db.lookupType("ciSymbol"), "sun.jvm.hotspot.ci", ciSymbol.class);
}
private static AddressField unloadedMethodsField;
private static AddressField ciObjectsField;
private static AddressField symbolsField;
private static VirtualBaseConstructor<ciObject> ciObjectConstructor;
private static VirtualBaseConstructor<ciSymbol> ciSymbolConstructor;
public static ciObject get(Address addr) {
if (addr == null) return null;
return (ciObject)ciObjectConstructor.instantiateWrapperFor(addr);
}
public GrowableArray<ciObject> objects() {
return GrowableArray.create(ciObjectsField.getValue(getAddress()), ciObjectConstructor);
}
public GrowableArray<ciSymbol> symbols() {
return GrowableArray.create(symbolsField.getValue(getAddress()), ciSymbolConstructor);
}
public ciObjectFactory(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciReceiverTypeData extends ReceiverTypeData {
public ciReceiverTypeData(DataLayout data) {
super(data);
}
public Klass receiver(int row) {
throw new InternalError("should not call");
}
public ciKlass receiverAt(int row) {
//assert((uint)row < rowLimit(), "oob");
ciObject recv = ciObjectFactory.get(addressAt(receiverCellIndex(row)));
if (recv != null && !(recv instanceof ciKlass)) {
System.err.println(recv);
}
//assert(recv == NULL || recv->isKlass(), "wrong type");
return (ciKlass)recv;
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciSymbol extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciSymbol");
identField = type.getCIntegerField("_ident");
symbolField = type.getAddressField("_symbol");
}
private static AddressField symbolField;
private static CIntegerField identField;
public String asUtf88() {
Symbol sym = Symbol.create(symbolField.getValue(getAddress()));
return sym.asString();
}
public ciSymbol(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciType extends ciObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciType");
basicTypeField = new CIntField(type.getCIntegerField("_basic_type"), 0);
}
private static CIntField basicTypeField;
public ciType(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciTypeArrayKlass extends ciArrayKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciTypeArrayKlass");
}
public ciTypeArrayKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciTypeArrayKlassKlass extends ciArrayKlassKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciTypeArrayKlassKlass");
}
public ciTypeArrayKlassKlass(Address addr) {
super(addr);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package sun.jvm.hotspot.ci;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ciVirtualCallData extends VirtualCallData {
public ciVirtualCallData(DataLayout data) {
super(data);
}
public Klass receiver(int row) {
throw new InternalError("should not call");
}
public ciKlass receiverAt(int row) {
//assert((uint)row < rowLimit(), "oob");
ciObject recv = ciObjectFactory.get(addressAt(receiverCellIndex(row)));
if (recv != null && !(recv instanceof ciKlass)) {
System.err.println(recv);
}
//assert(recv == NULL || recv->isKlass(), "wrong type");
return (ciKlass)recv;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -190,6 +190,8 @@ public class NMethod extends CodeBlob {
public boolean handlerTableContains(Address addr) { return handlerTableBegin().lessThanOrEqual(addr) && handlerTableEnd().greaterThan(addr); }
public boolean nulChkTableContains (Address addr) { return nulChkTableBegin() .lessThanOrEqual(addr) && nulChkTableEnd() .greaterThan(addr); }
public int getOopsLength() { return (int) (oopsSize() / VM.getVM().getOopSize()); }
/** Entry points */
public Address getEntryPoint() { return entryPointField.getValue(addr); }
public Address getVerifiedEntryPoint() { return verifiedEntryPointField.getValue(addr); }
@ -198,7 +200,7 @@ public class NMethod extends CodeBlob {
public OopHandle getOopAt(int index) {
if (index == 0) return null;
if (Assert.ASSERTS_ENABLED) {
Assert.that(index > 0 && index <= oopsSize(), "must be a valid non-zero index");
Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index");
}
return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize());
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.compiler;
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.opto.*;
import sun.jvm.hotspot.prims.JvmtiExport;
import sun.jvm.hotspot.types.*;
public class CompileTask extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("CompileTask");
methodField = type.getAddressField("_method");
osrBciField = new CIntField(type.getCIntegerField("_osr_bci"), 0);
}
private static AddressField methodField;
private static CIntField osrBciField;
public CompileTask(Address addr) {
super(addr);
}
public Method method() {
OopHandle oh = methodField.getValue(getAddress()).getOopHandleAt(0);
return (Method)VM.getVM().getObjectHeap().newOop(oh);
}
public int osrBci() {
return (int)osrBciField.getValue(getAddress());
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,4 +39,8 @@ public class AddressException extends RuntimeException {
public long getAddress() {
return addr;
}
public String getMessage() {
return Long.toHexString(addr);
}
}

View file

@ -1,395 +0,0 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.dbx;
import sun.jvm.hotspot.debugger.*;
class DbxAddress implements Address {
protected DbxDebugger debugger;
protected long addr;
DbxAddress(DbxDebugger debugger, long addr) {
this.debugger = debugger;
this.addr = addr;
}
//
// Basic Java routines
//
public boolean equals(Object arg) {
if (arg == null) {
return false;
}
if (!(arg instanceof DbxAddress)) {
return false;
}
return (addr == ((DbxAddress) arg).addr);
}
public int hashCode() {
// FIXME: suggestions on a better hash code?
return (int) addr;
}
public String toString() {
return debugger.addressValueToString(addr);
}
//
// C/C++-related routines
//
public long getCIntegerAt(long offset, long numBytes, boolean isUnsigned) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCInteger(addr + offset, numBytes, isUnsigned);
}
public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
//
public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJBoolean(addr + offset);
}
public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJByte(addr + offset);
}
public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJChar(addr + offset);
}
public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJDouble(addr + offset);
}
public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJFloat(addr + offset);
}
public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJInt(addr + offset);
}
public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJLong(addr + offset);
}
public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJShort(addr + offset);
}
public OopHandle getOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
// Mutators -- not implemented for now (FIXME)
public void setCIntegerAt(long offset, long numBytes, long value) {
throw new DebuggerException("Unimplemented");
}
public void setAddressAt(long offset, Address value) {
throw new DebuggerException("Unimplemented");
}
public void setJBooleanAt (long offset, boolean value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setJByteAt (long offset, byte value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setJCharAt (long offset, char value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setJDoubleAt (long offset, double value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setJFloatAt (long offset, float value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setJIntAt (long offset, int value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setJLongAt (long offset, long value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setJShortAt (long offset, short value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
public void setOopHandleAt (long offset, OopHandle value)
throws UnmappedAddressException, UnalignedAddressException {
throw new DebuggerException("Unimplemented");
}
//
// Arithmetic operations -- necessary evil.
//
public Address addOffsetTo (long offset) throws UnsupportedOperationException {
long value = addr + offset;
if (value == 0) {
return null;
}
return new DbxAddress(debugger, value);
}
public OopHandle addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException {
long value = addr + offset;
if (value == 0) {
return null;
}
return new DbxOopHandle(debugger, value);
}
/** (FIXME: any signed/unsigned issues? Should this work for
OopHandles?) */
public long minus(Address arg) {
if (arg == null) {
return addr;
}
return addr - ((DbxAddress) arg).addr;
}
// Two's complement representation.
// All negative numbers are larger than positive numbers.
// Numbers with the same sign can be compared normally.
// Test harness is below in main().
public boolean lessThan (Address arg) {
if (arg == null) {
return false;
}
DbxAddress dbxArg = (DbxAddress) arg;
if ((addr >= 0) && (dbxArg.addr < 0)) {
return true;
}
if ((addr < 0) && (dbxArg.addr >= 0)) {
return false;
}
return (addr < dbxArg.addr);
}
public boolean lessThanOrEqual (Address arg) {
if (arg == null) {
return false;
}
DbxAddress dbxArg = (DbxAddress) arg;
if ((addr >= 0) && (dbxArg.addr < 0)) {
return true;
}
if ((addr < 0) && (dbxArg.addr >= 0)) {
return false;
}
return (addr <= dbxArg.addr);
}
public boolean greaterThan (Address arg) {
if (arg == null) {
return true;
}
DbxAddress dbxArg = (DbxAddress) arg;
if ((addr >= 0) && (dbxArg.addr < 0)) {
return false;
}
if ((addr < 0) && (dbxArg.addr >= 0)) {
return true;
}
return (addr > dbxArg.addr);
}
public boolean greaterThanOrEqual(Address arg) {
if (arg == null) {
return true;
}
DbxAddress dbxArg = (DbxAddress) arg;
if ((addr >= 0) && (dbxArg.addr < 0)) {
return false;
}
if ((addr < 0) && (dbxArg.addr >= 0)) {
return true;
}
return (addr >= dbxArg.addr);
}
public Address andWithMask(long mask) throws UnsupportedOperationException {
long value = addr & mask;
if (value == 0) {
return null;
}
return new DbxAddress(debugger, value);
}
public Address orWithMask(long mask) throws UnsupportedOperationException {
long value = addr | mask;
if (value == 0) {
return null;
}
return new DbxAddress(debugger, value);
}
public Address xorWithMask(long mask) throws UnsupportedOperationException {
long value = addr ^ mask;
if (value == 0) {
return null;
}
return new DbxAddress(debugger, value);
}
//--------------------------------------------------------------------------------
// Internals only below this point
//
long getValue() {
return addr;
}
private static void check(boolean arg, String failMessage) {
if (!arg) {
System.err.println(failMessage + ": FAILED");
System.exit(1);
}
}
// Test harness
public static void main(String[] args) {
// p/n indicates whether the interior address is really positive
// or negative. In unsigned terms, p1 < p2 < n1 < n2.
DbxAddress p1 = new DbxAddress(null, 0x7FFFFFFFFFFFFFF0L);
DbxAddress p2 = (DbxAddress) p1.addOffsetTo(10);
DbxAddress n1 = (DbxAddress) p2.addOffsetTo(10);
DbxAddress n2 = (DbxAddress) n1.addOffsetTo(10);
// lessThan positive tests
check(p1.lessThan(p2), "lessThan 1");
check(p1.lessThan(n1), "lessThan 2");
check(p1.lessThan(n2), "lessThan 3");
check(p2.lessThan(n1), "lessThan 4");
check(p2.lessThan(n2), "lessThan 5");
check(n1.lessThan(n2), "lessThan 6");
// lessThan negative tests
check(!p1.lessThan(p1), "lessThan 7");
check(!p2.lessThan(p2), "lessThan 8");
check(!n1.lessThan(n1), "lessThan 9");
check(!n2.lessThan(n2), "lessThan 10");
check(!p2.lessThan(p1), "lessThan 11");
check(!n1.lessThan(p1), "lessThan 12");
check(!n2.lessThan(p1), "lessThan 13");
check(!n1.lessThan(p2), "lessThan 14");
check(!n2.lessThan(p2), "lessThan 15");
check(!n2.lessThan(n1), "lessThan 16");
// lessThanOrEqual positive tests
check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1");
check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2");
check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3");
check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4");
check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5");
check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6");
check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7");
check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8");
check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9");
check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10");
// lessThanOrEqual negative tests
check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11");
check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12");
check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13");
check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14");
check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15");
check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16");
// greaterThan positive tests
check(n2.greaterThan(p1), "greaterThan 1");
check(n2.greaterThan(p2), "greaterThan 2");
check(n2.greaterThan(n1), "greaterThan 3");
check(n1.greaterThan(p1), "greaterThan 4");
check(n1.greaterThan(p2), "greaterThan 5");
check(p2.greaterThan(p1), "greaterThan 6");
// greaterThan negative tests
check(!p1.greaterThan(p1), "greaterThan 7");
check(!p2.greaterThan(p2), "greaterThan 8");
check(!n1.greaterThan(n1), "greaterThan 9");
check(!n2.greaterThan(n2), "greaterThan 10");
check(!p1.greaterThan(n2), "greaterThan 11");
check(!p2.greaterThan(n2), "greaterThan 12");
check(!n1.greaterThan(n2), "greaterThan 13");
check(!p1.greaterThan(n1), "greaterThan 14");
check(!p2.greaterThan(n1), "greaterThan 15");
check(!p1.greaterThan(p2), "greaterThan 16");
// greaterThanOrEqual positive tests
check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1");
check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2");
check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3");
check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4");
check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5");
check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6");
check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7");
check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8");
check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9");
check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10");
// greaterThanOrEqual negative tests
check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11");
check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12");
check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13");
check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14");
check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15");
check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16");
System.err.println("DbxAddress: all tests passed successfully.");
}
}

View file

@ -1,76 +0,0 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.dbx;
import sun.jvm.hotspot.debugger.*;
/** An extension of the JVMDebugger interface with a few additions to
support 32-bit vs. 64-bit debugging as well as features required
by the architecture-specific subpackages. */
public interface DbxDebugger extends JVMDebugger {
public String addressValueToString(long address) throws DebuggerException;
public boolean readJBoolean(long address) throws DebuggerException;
public byte readJByte(long address) throws DebuggerException;
public char readJChar(long address) throws DebuggerException;
public double readJDouble(long address) throws DebuggerException;
public float readJFloat(long address) throws DebuggerException;
public int readJInt(long address) throws DebuggerException;
public long readJLong(long address) throws DebuggerException;
public short readJShort(long address) throws DebuggerException;
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws DebuggerException;
public DbxAddress readAddress(long address) throws DebuggerException;
public DbxAddress readCompOopAddress(long address) throws DebuggerException;
public DbxOopHandle readOopHandle(long address) throws DebuggerException;
public DbxOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException;
public Address newAddress(long value) throws DebuggerException;
// NOTE: this interface implicitly contains the following methods:
// From the Debugger interface via JVMDebugger
// public void attach(int processID) throws DebuggerException;
// public void attach(String executableName, String coreFileName) throws DebuggerException;
// public boolean detach();
// public Address parseAddress(String addressString) throws NumberFormatException;
// public long getAddressValue(Address addr) throws DebuggerException;
// public String getOS();
// public String getCPU();
// From the SymbolLookup interface via Debugger and JVMDebugger
// public Address lookup(String objectName, String symbol);
// public OopHandle lookupOop(String objectName, String symbol);
// From the JVMDebugger interface
// public void configureJavaPrimitiveTypeSizes(long jbooleanSize,
// long jbyteSize,
// long jcharSize,
// long jdoubleSize,
// long jfloatSize,
// long jintSize,
// long jlongSize,
// long jshortSize);
// From the ThreadAccess interface via Debugger and JVMDebugger
// public ThreadProxy getThreadForIdentifierAddress(Address addr);
// public ThreadProxy getThreadForThreadId(long id);
}

View file

@ -1,744 +0,0 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.dbx;
import java.io.*;
import java.net.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.sparc.*;
import sun.jvm.hotspot.debugger.dbx.x86.*;
import sun.jvm.hotspot.debugger.cdbg.CDebugger;
import sun.jvm.hotspot.utilities.*;
/** <P> An implementation of the JVMDebugger interface which sits on
top of dbx and relies on the SA's dbx import module for
communication with the debugger. </P>
<P> <B>NOTE</B> that since we have the notion of fetching "Java
primitive types" from the remote process (which might have
different sizes than we expect) we have a bootstrapping
problem. We need to know the sizes of these types before we can
fetch them. The current implementation solves this problem by
requiring that it be configured with these type sizes before they
can be fetched. The readJ(Type) routines here will throw a
RuntimeException if they are called before the debugger is
configured with the Java primitive type sizes. </P>
*/
public class DbxDebuggerLocal extends DebuggerBase implements DbxDebugger {
// These may be set by DbxDebuggerRemote
protected boolean unalignedAccessesOkay;
protected DbxThreadFactory threadFactory;
private String dbxPathName;
private String[] dbxSvcAgentDSOPathNames;
private Process dbxProcess;
private StreamMonitor dbxOutStreamMonitor;
private StreamMonitor dbxErrStreamMonitor;
private PrintWriter dbxOstr;
private PrintWriter out;
private InputLexer in;
private Socket importModuleSocket;
private static final int PORT = 21928;
private static final int LONG_TIMEOUT = 60000;
private static final int DBX_MODULE_NOT_FOUND = 101;
private static final int DBX_MODULE_LOADED = 102;
//--------------------------------------------------------------------------------
// Implementation of Debugger interface
//
/** <P> machDesc may be null if it couldn't be determined yet; i.e.,
if we're on SPARC, we need to ask the remote process whether
we're in 32- or 64-bit mode. </P>
<P> useCache should be set to true if debugging is being done
locally, and to false if the debugger is being created for the
purpose of supporting remote debugging. </P> */
public DbxDebuggerLocal(MachineDescription machDesc,
String dbxPathName,
String[] dbxSvcAgentDSOPathNames,
boolean useCache) {
this.machDesc = machDesc;
this.dbxPathName = dbxPathName;
this.dbxSvcAgentDSOPathNames = dbxSvcAgentDSOPathNames;
int cacheNumPages;
int cachePageSize;
if (PlatformInfo.getCPU().equals("sparc")) {
cacheNumPages = parseCacheNumPagesProperty(2048);
cachePageSize = 8192;
threadFactory = new DbxSPARCThreadFactory(this);
} else if (PlatformInfo.getCPU().equals("x86")) {
cacheNumPages = 4096;
cachePageSize = 4096;
threadFactory = new DbxX86ThreadFactory(this);
unalignedAccessesOkay = true;
} else {
throw new RuntimeException("Thread access for CPU architecture " + PlatformInfo.getCPU() + " not yet supported");
}
if (useCache) {
// Cache portion of the remote process's address space.
// Fetching data over the socket connection to dbx is relatively
// slow. For now, this cache works best if it covers the entire
// heap of the remote process. FIXME: at least should make this
// tunable from the outside, i.e., via the UI. This is a 16 MB
// cache divided on SPARC into 2048 8K pages and on x86 into
// 4096 4K pages; the page size must be adjusted to be the OS's
// page size. (FIXME: should pick this up from the debugger.)
initCache(cachePageSize, cacheNumPages);
}
}
/** Only called by DbxDebuggerRemote */
protected DbxDebuggerLocal() {
}
/** FIXME: implement this with a Runtime.exec() of ps followed by
parsing of its output */
public boolean hasProcessList() throws DebuggerException {
return false;
}
public List getProcessList() throws DebuggerException {
throw new DebuggerException("Not yet supported");
}
/** From the Debugger interface via JVMDebugger */
public synchronized void attach(int processID) throws DebuggerException {
try {
launchProcess();
dbxErrStreamMonitor.addTrigger("dbx: no process", 1);
dbxErrStreamMonitor.addTrigger("dbx: Cannot open", 1);
dbxErrStreamMonitor.addTrigger("dbx: Cannot find", DBX_MODULE_NOT_FOUND);
dbxOstr = new PrintWriter(dbxProcess.getOutputStream(), true);
dbxOstr.println("debug - " + processID);
dbxOstr.println("kprint -u2 \\(ready\\)");
boolean seen = dbxErrStreamMonitor.waitFor("(ready)", LONG_TIMEOUT);
if (!seen) {
detach();
throw new DebuggerException("Timed out while connecting to process " + processID);
}
List retVals = dbxErrStreamMonitor.getTriggersSeen();
if (retVals.contains(new Integer(1))) {
detach();
throw new DebuggerException("No such process " + processID);
}
// Throws DebuggerException upon failure
importDbxModule();
dbxOstr.println("svc_agent_run");
connectToImportModule();
// Set "fail fast" mode on process memory reads
printlnToOutput("peek_fail_fast 1");
}
catch (IOException e) {
detach();
throw new DebuggerException("Error while connecting to dbx process", e);
}
}
/** From the Debugger interface via JVMDebugger */
public synchronized void attach(String executableName, String coreFileName) throws DebuggerException {
try {
launchProcess();
// Missing executable
dbxErrStreamMonitor.addTrigger("dbx: Cannot open", 1);
// Missing core file
dbxErrStreamMonitor.addTrigger("dbx: can't read", 2);
// Corrupt executable
dbxErrStreamMonitor.addTrigger("dbx: File", 3);
// Corrupt core file
dbxErrStreamMonitor.addTrigger("dbx: Unable to read", 4);
// Mismatched core and executable
dbxErrStreamMonitor.addTrigger("dbx: core object name", 5);
// Missing loadobject
dbxErrStreamMonitor.addTrigger("dbx: can't stat", 6);
// Successful load of svc module
dbxOstr = new PrintWriter(dbxProcess.getOutputStream(), true);
dbxOstr.println("debug " + executableName + " " + coreFileName);
dbxOstr.println("kprint -u2 \\(ready\\)");
boolean seen = dbxErrStreamMonitor.waitFor("(ready)", LONG_TIMEOUT);
if (!seen) {
detach();
throw new DebuggerException("Timed out while attaching to core file");
}
List retVals = dbxErrStreamMonitor.getTriggersSeen();
if (retVals.size() > 0) {
detach();
if (retVals.contains(new Integer(1))) {
throw new DebuggerException("Can not find executable \"" + executableName + "\"");
} else if (retVals.contains(new Integer(2))) {
throw new DebuggerException("Can not find core file \"" + coreFileName + "\"");
} else if (retVals.contains(new Integer(3))) {
throw new DebuggerException("Corrupt executable \"" + executableName + "\"");
} else if (retVals.contains(new Integer(4))) {
throw new DebuggerException("Corrupt core file \"" + coreFileName + "\"");
} else if (retVals.contains(new Integer(5))) {
throw new DebuggerException("Mismatched core file/executable \"" + coreFileName + "\"/\"" + executableName + "\"");
} else {
throw new DebuggerException("Couldn't find all loaded libraries for executable \"" + executableName + "\"");
}
}
// Throws DebuggerException upon failure
importDbxModule();
dbxOstr.println("svc_agent_run");
connectToImportModule();
// Set "fail fast" mode on process memory reads
printlnToOutput("peek_fail_fast 1");
}
catch (IOException e) {
detach();
throw new DebuggerException("Error while connecting to dbx process", e);
}
}
/** From the Debugger interface via JVMDebugger */
public synchronized boolean detach() {
try {
if (dbxProcess == null) {
return false;
}
if (out != null && dbxOstr != null) {
printlnToOutput("exit");
dbxOstr.println("exit");
// Wait briefly for the process to exit (FIXME: should make this
// nicer)
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
}
}
shutdown();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/** From the Debugger interface via JVMDebugger */
public Address parseAddress(String addressString) throws NumberFormatException {
long addr = utils.scanAddress(addressString);
if (addr == 0) {
return null;
}
return new DbxAddress(this, addr);
}
/** From the Debugger interface via JVMDebugger */
public String getOS() {
return PlatformInfo.getOS();
}
/** From the Debugger interface via JVMDebugger */
public String getCPU() {
return PlatformInfo.getCPU();
}
public boolean hasConsole() throws DebuggerException {
return true;
}
public synchronized String consoleExecuteCommand(String cmd) throws DebuggerException {
try {
// A little tricky. We need to cause the dbx import module to
// exit, then print our command on dbx's stdin along with a
// command which will allow our StreamMonitors to
// resynchronize. We need save the output from the StreamMonitors
// along the way.
printlnToOutput("exit");
importModuleSocket.close();
importModuleSocket = null;
out = null;
in = null;
dbxOstr.println("kprint \\(ready\\)");
dbxOstr.flush();
dbxOutStreamMonitor.waitFor("(ready)", LONG_TIMEOUT);
dbxOutStreamMonitor.startCapture();
dbxErrStreamMonitor.startCapture();
dbxOstr.println(cmd);
dbxOstr.println("kprint \\(ready\\)");
dbxOutStreamMonitor.waitFor("(ready)", LONG_TIMEOUT);
String result = dbxOutStreamMonitor.stopCapture();
String result2 = dbxErrStreamMonitor.stopCapture();
result = result + result2;
// Cut out the "(ready)" string
StringBuffer outBuf = new StringBuffer(result.length());
BufferedReader reader = new BufferedReader(new StringReader(result));
// FIXME: bug in BufferedReader? readLine returns null when
// ready() returns true.
String line = null;
do {
line = reader.readLine();
if ((line != null) && (!line.equals("(ready)"))) {
outBuf.append(line);
outBuf.append("\n");
}
} while (line != null);
dbxOstr.println("svc_agent_run");
dbxOstr.flush();
connectToImportModule();
return outBuf.toString();
}
catch (IOException e) {
detach();
throw new DebuggerException("Error while executing command on dbx console", e);
}
}
public String getConsolePrompt() throws DebuggerException {
return "(dbx) ";
}
public CDebugger getCDebugger() throws DebuggerException {
return null;
}
/** From the SymbolLookup interface via Debugger and JVMDebugger */
public synchronized Address lookup(String objectName, String symbol) {
long addr = lookupInProcess(objectName, symbol);
if (addr == 0) {
return null;
}
return new DbxAddress(this, addr);
}
/** From the SymbolLookup interface via Debugger and JVMDebugger */
public synchronized OopHandle lookupOop(String objectName, String symbol) {
long addr = lookupInProcess(objectName, symbol);
if (addr == 0) {
return null;
}
return new DbxOopHandle(this, addr);
}
/** From the Debugger interface */
public MachineDescription getMachineDescription() {
return machDesc;
}
/** Internal routine supporting lazy setting of MachineDescription,
since on SPARC we will need to query the remote process to ask
it what its data model is (32- or 64-bit). NOTE that this is NOT
present in the DbxDebugger interface because it should not be
called across the wire (until we support attaching to multiple
remote processes via RMI -- see the documentation for
DbxDebuggerRemoteIntf.) */
public void setMachineDescription(MachineDescription machDesc) {
this.machDesc = machDesc;
setBigEndian(machDesc.isBigEndian());
utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian());
}
/** Internal routine which queries the remote process about its data
model -- i.e., size of addresses. Returns -1 upon error.
Currently supported return values are 32 and 64. NOTE that this
is NOT present in the DbxDebugger interface because it should
not be called across the wire (until we support attaching to
multiple remote processes via RMI -- see the documentation for
DbxDebuggerRemoteIntf.) */
public int getRemoteProcessAddressSize() {
if (dbxProcess == null) {
throw new RuntimeException("Not attached to remote process");
}
try {
printlnToOutput("address_size");
int i = in.parseInt();
return i;
}
catch (IOException e) {
return -1;
}
}
//--------------------------------------------------------------------------------
// Implementation of ThreadAccess interface
//
/** From the ThreadAccess interface via Debugger and JVMDebugger */
public ThreadProxy getThreadForIdentifierAddress(Address addr) {
return threadFactory.createThreadWrapper(addr);
}
public ThreadProxy getThreadForThreadId(long id) {
return threadFactory.createThreadWrapper(id);
}
//----------------------------------------------------------------------
// Overridden from DebuggerBase because we need to relax alignment
// constraints on x86
public long readJLong(long address)
throws UnmappedAddressException, UnalignedAddressException {
checkJavaConfigured();
// FIXME: allow this to be configurable. Undesirable to add a
// dependency on the runtime package here, though, since this
// package should be strictly underneath it.
if (unalignedAccessesOkay) {
utils.checkAlignment(address, jintSize);
} else {
utils.checkAlignment(address, jlongSize);
}
byte[] data = readBytes(address, jlongSize);
return utils.dataToJLong(data, jlongSize);
}
//--------------------------------------------------------------------------------
// Internal routines (for implementation of DbxAddress).
// These must not be called until the MachineDescription has been set up.
//
/** From the DbxDebugger interface */
public String addressValueToString(long address) {
return utils.addressValueToString(address);
}
/** Need to override this to relax alignment checks on Solaris/x86. */
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws UnmappedAddressException, UnalignedAddressException {
checkConfigured();
if (!unalignedAccessesOkay) {
utils.checkAlignment(address, numBytes);
} else {
// Only slightly relaxed semantics -- this is a hack, but is
// necessary on Solaris/x86 where it seems the compiler is
// putting some global 64-bit data on 32-bit boundaries
if (numBytes == 8) {
utils.checkAlignment(address, 4);
} else {
utils.checkAlignment(address, numBytes);
}
}
byte[] data = readBytes(address, numBytes);
return utils.dataToCInteger(data, isUnsigned);
}
/** From the DbxDebugger interface */
public DbxAddress readAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readAddressValue(address);
return (value == 0 ? null : new DbxAddress(this, value));
}
public DbxAddress readCompOopAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new DbxAddress(this, value));
}
/** From the DbxDebugger interface */
public DbxOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readAddressValue(address);
return (value == 0 ? null : new DbxOopHandle(this, value));
}
public DbxOopHandle readCompOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new DbxOopHandle(this, value));
}
//--------------------------------------------------------------------------------
// Thread context access. Can not be package private, but should
// only be accessed by the architecture-specific subpackages.
/** From the DbxDebugger interface. May have to redefine this later. */
public synchronized long[] getThreadIntegerRegisterSet(int tid) {
try {
printlnToOutput("thr_gregs " + tid);
int num = in.parseInt();
long[] res = new long[num];
for (int i = 0; i < num; i++) {
res[i] = in.parseAddress();
}
return res;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
//--------------------------------------------------------------------------------
// Address access. Can not be package private, but should only be
// accessed by the architecture-specific subpackages.
/** From the Debugger interface */
public long getAddressValue(Address addr) {
if (addr == null) return 0;
return ((DbxAddress) addr).getValue();
}
/** From the DbxDebugger interface */
public Address newAddress(long value) {
if (value == 0) return null;
return new DbxAddress(this, value);
}
//--------------------------------------------------------------------------------
// Internals only below this point
//
private void launchProcess() throws IOException {
dbxProcess = Runtime.getRuntime().exec(dbxPathName);
// dbxOutStreamMonitor = new StreamMonitor(dbxProcess.getInputStream());
// dbxErrStreamMonitor = new StreamMonitor(dbxProcess.getErrorStream());
dbxOutStreamMonitor = new StreamMonitor(dbxProcess.getInputStream(), "dbx stdout", true);
dbxErrStreamMonitor = new StreamMonitor(dbxProcess.getErrorStream(), "dbx stderr", true);
}
/** Requires that dbxErrStreamMonitor has a trigger on "dbx: Cannot
find" with number DBX_MODULE_NOT_FOUND as well as one on "dbx:
warning:" (plus the serviceability agent's dbx module path name,
to avoid conflation with inability to load individual object
files) with number DBX_MODULE_FAILED_TO_LOAD. The former
indicates an absence of libsvc_agent_dbx.so, while the latter
indicates that the module failed to load, specifically because
the architecture was mismatched. (I don't see a way to detect
from the dbx command prompt whether it's running the v8 or v9
executbale, so we try to import both flavors of the import
module; the "v8" file name convention doesn't actually include
the v8 prefix, so this code should work for Intel as well.) */
private void importDbxModule() throws DebuggerException {
// Trigger for a successful load
dbxOutStreamMonitor.addTrigger("Defining svc_agent_run", DBX_MODULE_LOADED);
for (int i = 0; i < dbxSvcAgentDSOPathNames.length; i++) {
dbxOstr.println("import " + dbxSvcAgentDSOPathNames[i]);
dbxOstr.println("kprint -u2 \\(Ready\\)");
boolean seen = dbxErrStreamMonitor.waitFor("(Ready)", LONG_TIMEOUT);
if (!seen) {
detach();
throw new DebuggerException("Timed out while importing dbx module from file\n" + dbxSvcAgentDSOPathNames[i]);
}
List retVals = dbxErrStreamMonitor.getTriggersSeen();
if (retVals.contains(new Integer(DBX_MODULE_NOT_FOUND))) {
detach();
throw new DebuggerException("Unable to find the Serviceability Agent's dbx import module at pathname \"" +
dbxSvcAgentDSOPathNames[i] + "\"");
} else {
retVals = dbxOutStreamMonitor.getTriggersSeen();
if (retVals.contains(new Integer(DBX_MODULE_LOADED))) {
System.out.println("importDbxModule: imported " + dbxSvcAgentDSOPathNames[i]);
return;
}
}
}
// Failed to load all flavors
detach();
String errMsg = ("Unable to find a version of the Serviceability Agent's dbx import module\n" +
"matching the architecture of dbx at any of the following locations:");
for (int i = 0; i < dbxSvcAgentDSOPathNames.length; i++) {
errMsg = errMsg + "\n" + dbxSvcAgentDSOPathNames[i];
}
throw new DebuggerException(errMsg);
}
/** Terminate the debugger forcibly */
private void shutdown() {
if (dbxProcess != null) {
// See whether the process has exited and, if not, terminate it
// forcibly
try {
dbxProcess.exitValue();
}
catch (IllegalThreadStateException e) {
dbxProcess.destroy();
}
}
try {
if (importModuleSocket != null) {
importModuleSocket.close();
}
}
catch (IOException e) {
}
// Release references to all objects
clear();
clearCache();
}
/** Looks up an address in the remote process's address space.
Returns 0 if symbol not found or upon error. Package private to
allow DbxDebuggerRemoteIntfImpl access. */
synchronized long lookupInProcess(String objectName, String symbol) {
try {
printlnToOutput("lookup " + objectName + " " + symbol);
return in.parseAddress();
}
catch (Exception e) {
return 0;
}
}
/** This reads bytes from the remote process. */
public synchronized ReadResult readBytesFromProcess(long address, long numBytes)
throws DebuggerException {
if (numBytes < 0) {
throw new DebuggerException("Can not read negative number (" + numBytes + ") of bytes from process");
}
try {
String cmd = "peek " + utils.addressValueToString(address) + " " + numBytes;
printlnToOutput(cmd);
while (in.readByte() != 'B') {
}
byte res = in.readByte();
if (res == 0) {
System.err.println("Failing command: " + cmd);
throw new DebuggerException("Read of remote process address space failed");
}
// NOTE: must read ALL of the data regardless of whether we need
// to throw an UnmappedAddressException. Otherwise will corrupt
// the input stream each time we have a failure. Not good. Do
// not want to risk "flushing" the input stream in case a huge
// read has a hangup in the middle and we leave data on the
// stream.
byte[] buf = new byte[(int) numBytes];
boolean bailOut = false;
long failureAddress = 0;
int numReads = 0;
while (numBytes > 0) {
long len = in.readUnsignedInt();
boolean isMapped = ((in.readByte() == 0) ? false : true);
if (!isMapped) {
if (!bailOut) {
bailOut = true;
failureAddress = address;
}
} else {
// This won't work if we have unmapped regions, but if we do
// then we're going to throw an exception anyway
// NOTE: there is a factor of 20 speed difference between
// these two ways of doing this read.
in.readBytes(buf, 0, (int) len);
}
// Do NOT do this:
// for (int i = 0; i < (int) len; i++) {
// buf[i] = in.readByte();
// }
numBytes -= len;
address += len;
++numReads;
}
if (Assert.ASSERTS_ENABLED) {
Assert.that(numBytes == 0, "Bug in debug server's implementation of peek: numBytesLeft == " +
numBytes + ", should be 0 (did " + numReads + " reads)");
}
if (bailOut) {
return new ReadResult(failureAddress);
}
return new ReadResult(buf);
}
catch (IOException e) {
throw new DebuggerException(e);
}
}
public void writeBytesToProcess(long address, long numBytes, byte[] data)
throws UnmappedAddressException, DebuggerException {
// FIXME
throw new DebuggerException("Unimplemented");
}
/** This provides DbxDebuggerRemoteIntfImpl access to readBytesFromProcess */
ReadResult readBytesFromProcessInternal(long address, long numBytes)
throws DebuggerException {
return readBytesFromProcess(address, numBytes);
}
/** Convenience routine */
private void printlnToOutput(String s) throws IOException {
out.println(s);
if (out.checkError()) {
throw new IOException("Error occurred while writing to debug server");
}
}
private void clear() {
dbxProcess = null;
dbxOstr = null;
out = null;
in = null;
importModuleSocket = null;
}
/** Connects to the dbx import module, setting up out and in
streams. Factored out to allow access to the dbx console. */
private void connectToImportModule() throws IOException {
// Try for 20 seconds to connect to dbx import module; time out
// with failure if didn't succeed
importModuleSocket = null;
long endTime = System.currentTimeMillis() + LONG_TIMEOUT;
while ((importModuleSocket == null) && (System.currentTimeMillis() < endTime)) {
try {
importModuleSocket = new Socket(InetAddress.getLocalHost(), PORT);
importModuleSocket.setTcpNoDelay(true);
}
catch (IOException e) {
// Swallow IO exceptions while attempting connection
try {
// Don't swamp the CPU
Thread.sleep(1000);
}
catch (InterruptedException ex) {
}
}
}
if (importModuleSocket == null) {
// Failed to connect because of timeout
detach();
throw new DebuggerException("Timed out while attempting to connect to remote dbx process");
}
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(importModuleSocket.getOutputStream(), "US-ASCII")), true);
in = new InputLexer(new BufferedInputStream(importModuleSocket.getInputStream()));
}
}

View file

@ -1,49 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.dbx;
import sun.jvm.hotspot.debugger.*;
class DbxOopHandle extends DbxAddress implements OopHandle {
DbxOopHandle(DbxDebugger debugger, long addr) {
super(debugger, addr);
}
public Address addOffsetTo (long offset) throws UnsupportedOperationException {
throw new UnsupportedOperationException("addOffsetTo not applicable to OopHandles (interior object pointers not allowed)");
}
public Address andWithMask(long mask) throws UnsupportedOperationException {
throw new UnsupportedOperationException("andWithMask not applicable to OopHandles (i.e., anything but C addresses)");
}
public Address orWithMask(long mask) throws UnsupportedOperationException {
throw new UnsupportedOperationException("orWithMask not applicable to OopHandles (i.e., anything but C addresses)");
}
public Address xorWithMask(long mask) throws UnsupportedOperationException {
throw new UnsupportedOperationException("xorWithMask not applicable to OopHandles (i.e., anything but C addresses)");
}
}

View file

@ -1,35 +0,0 @@
/*
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.dbx;
import sun.jvm.hotspot.debugger.*;
/** An interface used only internally by the DbxDebugger to be able to
create platform-specific Thread objects */
public interface DbxThreadFactory {
public ThreadProxy createThreadWrapper(Address threadIdentifierAddr);
public ThreadProxy createThreadWrapper(long id);
}

View file

@ -1,86 +0,0 @@
/*
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.dbx.sparc;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.utilities.*;
public class DbxSPARCThread implements ThreadProxy {
private DbxDebugger debugger;
private int id;
public DbxSPARCThread(DbxDebugger debugger, Address addr) {
this.debugger = debugger;
// FIXME: the size here should be configurable. However, making it
// so would produce a dependency on the "types" package from the
// debugger package, which is not desired.
this.id = (int) addr.getCIntegerAt(0, 4, true);
}
public DbxSPARCThread(DbxDebugger debugger, long id) {
this.debugger = debugger;
this.id = (int) id;
}
public boolean equals(Object obj) {
if ((obj == null) || !(obj instanceof DbxSPARCThread)) {
return false;
}
return (((DbxSPARCThread) obj).id == id);
}
public int hashCode() {
return id;
}
public ThreadContext getContext() throws IllegalThreadStateException {
DbxSPARCThreadContext context = new DbxSPARCThreadContext(debugger);
long[] regs = debugger.getThreadIntegerRegisterSet(id);
if (Assert.ASSERTS_ENABLED) {
Assert.that(regs.length == SPARCThreadContext.NPRGREG, "size of register set must match");
}
for (int i = 0; i < regs.length; i++) {
context.setRegister(i, regs[i]);
}
return context;
}
public boolean canSetContext() throws DebuggerException {
return false;
}
public void setContext(ThreadContext context)
throws IllegalThreadStateException, DebuggerException {
throw new DebuggerException("Unimplemented");
}
public String toString() {
return "t@" + id;
}
}

View file

@ -1,86 +0,0 @@
/*
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.dbx.x86;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.utilities.*;
public class DbxX86Thread implements ThreadProxy {
private DbxDebugger debugger;
private int id;
public DbxX86Thread(DbxDebugger debugger, Address addr) {
this.debugger = debugger;
// FIXME: the size here should be configurable. However, making it
// so would produce a dependency on the "types" package from the
// debugger package, which is not desired.
this.id = (int) addr.getCIntegerAt(0, 4, true);
}
public DbxX86Thread(DbxDebugger debugger, long id) {
this.debugger = debugger;
this.id = (int) id;
}
public boolean equals(Object obj) {
if ((obj == null) || !(obj instanceof DbxX86Thread)) {
return false;
}
return (((DbxX86Thread) obj).id == id);
}
public int hashCode() {
return id;
}
public ThreadContext getContext() throws IllegalThreadStateException {
DbxX86ThreadContext context = new DbxX86ThreadContext(debugger);
long[] regs = debugger.getThreadIntegerRegisterSet(id);
if (Assert.ASSERTS_ENABLED) {
Assert.that(regs.length == 19, "unknown size of register set -- adjust this code");
}
for (int i = 0; i < regs.length; i++) {
context.setRegister(i, regs[i]);
}
return context;
}
public boolean canSetContext() throws DebuggerException {
return false;
}
public void setContext(ThreadContext context)
throws IllegalThreadStateException, DebuggerException {
throw new DebuggerException("Unimplemented");
}
public String toString() {
return "t@" + id;
}
}

View file

@ -1,99 +0,0 @@
/*
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import java.io.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.win32.coff.*;
class AddressDataSource implements DataSource {
AddressDataSource(Address addr) {
this.addr = addr;
offset = 0;
}
public byte readByte() throws IOException {
try {
byte res = (byte) addr.getCIntegerAt(offset, 1, false);
++offset;
return res;
} catch (UnmappedAddressException e) {
throw (IOException) new IOException("Unmapped address at 0x" + Long.toHexString(e.getAddress())).initCause(e);
} catch (DebuggerException e) {
throw (IOException) new IOException(e.toString()).initCause(e);
}
}
public short readShort() throws IOException {
// NOTE: byte swapping is taken care of at the COFFFileImpl level
int b1 = readByte() & 0xFF;
int b2 = readByte() & 0xFF;
return (short) ((b1 << 8) | b2);
}
public int readInt() throws IOException {
// NOTE: byte swapping is taken care of at the COFFFileImpl level
int b1 = ((int) readByte()) & 0xFF;
int b2 = ((int) readByte()) & 0xFF;
int b3 = ((int) readByte()) & 0xFF;
int b4 = ((int) readByte()) & 0xFF;
return ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
}
public long readLong() throws IOException {
// NOTE: byte swapping is taken care of at the COFFFileImpl level
long b1 = ((long) readByte()) & 0xFFL;
long b2 = ((long) readByte()) & 0xFFL;
long b3 = ((long) readByte()) & 0xFFL;
long b4 = ((long) readByte()) & 0xFFL;
long b5 = ((long) readByte()) & 0xFFL;
long b6 = ((long) readByte()) & 0xFFL;
long b7 = ((long) readByte()) & 0xFFL;
long b8 = ((long) readByte()) & 0xFFL;
return (((((b1 << 24) | (b2 << 16) | (b3 << 8) | b4)) << 32) |
((((b5 << 24) | (b6 << 16) | (b7 << 8) | b8))));
}
public int read(byte[] b) throws IOException {
for (int i = 0; i < b.length; i++) {
b[i] = readByte();
}
return b.length;
}
public void seek(long pos) throws IOException {
offset = pos;
}
public long getFilePointer() throws IOException {
return offset;
}
public void close() throws IOException {
}
private Address addr;
private long offset;
}

View file

@ -1,209 +0,0 @@
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.win32.coff.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.utilities.Assert;
import sun.jvm.hotspot.utilities.memo.*;
/** Provides a simple wrapper around the COFF library which handles
relocation. A DLL can represent either a DLL or an EXE file. */
class DLL implements LoadObject {
DLL(Win32Debugger dbg, String filename, long size, Address relocation) throws COFFException {
this.dbg = dbg;
fullPathName = filename;
this.size = size;
file = new MemoizedObject() {
public Object computeValue() {
return COFFFileParser.getParser().parse(fullPathName);
}
};
addr = relocation;
}
/** This constructor was originally used to fetch the DLL's name out
of the target process to match it up with the known DLL names,
before the fetching of the DLL names and bases was folded into
one command. It is no longer used. If it is used, getName() will
return null and getSize() will return 0. */
DLL(Address base) throws COFFException {
this.addr = base;
file = new MemoizedObject() {
public Object computeValue() {
return COFFFileParser.getParser().parse(new AddressDataSource(addr));
}
};
}
/** Indicates whether this is really a DLL or actually a .EXE
file. */
boolean isDLL() {
return getFile().getHeader().hasCharacteristic(Characteristics.IMAGE_FILE_DLL);
}
/** Look up a symbol; returns absolute address or null if symbol was
not found. */
Address lookupSymbol(String symbol) throws COFFException {
if (!isDLL()) {
return null;
}
ExportDirectoryTable exports = getExportDirectoryTable();
return lookupSymbol(symbol, exports,
0, exports.getNumberOfNamePointers() - 1);
}
public Address getBase() {
return addr;
}
/** Returns the full path name of this DLL/EXE, or null if this DLL
object was created by parsing the target process's address
space. */
public String getName() {
return fullPathName;
}
public long getSize() {
return size;
}
public CDebugInfoDataBase getDebugInfoDataBase() throws DebuggerException {
if (db != null) {
return db;
}
// Try to parse
if (dbg == null) {
return null; // Need Win32Debugger
}
if (Assert.ASSERTS_ENABLED) {
Assert.that(fullPathName != null, "Need full path name to build debug info database");
}
db = new Win32CDebugInfoBuilder(dbg).buildDataBase(fullPathName, addr);
return db;
}
public BlockSym debugInfoForPC(Address pc) throws DebuggerException {
CDebugInfoDataBase db = getDebugInfoDataBase();
if (db == null) {
return null;
}
return db.debugInfoForPC(pc);
}
public ClosestSymbol closestSymbolToPC(Address pcAsAddr) throws DebuggerException {
ExportDirectoryTable exports = getExportDirectoryTable();
if (exports == null) {
return null;
}
String name = null;
long pc = dbg.getAddressValue(pcAsAddr);
long diff = Long.MAX_VALUE;
long base = dbg.getAddressValue(addr);
for (int i = 0; i < exports.getNumberOfNamePointers(); i++) {
if (!exports.isExportAddressForwarder(exports.getExportOrdinal(i))) {
long tmp = base + (exports.getExportAddress(exports.getExportOrdinal(i)) & 0xFFFFFFFF);
if ((tmp <= pc) && ((pc - tmp) < diff)) {
diff = pc - tmp;
name = exports.getExportName(i);
}
}
}
if (name == null) {
return null;
}
return new ClosestSymbol(name, diff);
}
public LineNumberInfo lineNumberForPC(Address pc) throws DebuggerException {
CDebugInfoDataBase db = getDebugInfoDataBase();
if (db == null) {
return null;
}
return db.lineNumberForPC(pc);
}
void close() {
getFile().close();
file = null;
}
//----------------------------------------------------------------------
// Internals only below this point
//
private COFFFile getFile() {
return (COFFFile) file.getValue();
}
private Address lookupSymbol(String symbol, ExportDirectoryTable exports,
int loIdx, int hiIdx) {
do {
int curIdx = ((loIdx + hiIdx) >> 1);
String cur = exports.getExportName(curIdx);
if (symbol.equals(cur)) {
return addr.addOffsetTo(
((long) exports.getExportAddress(exports.getExportOrdinal(curIdx))) & 0xFFFFFFFFL
);
}
if (symbol.compareTo(cur) < 0) {
if (hiIdx == curIdx) {
hiIdx = curIdx - 1;
} else {
hiIdx = curIdx;
}
} else {
if (loIdx == curIdx) {
loIdx = curIdx + 1;
} else {
loIdx = curIdx;
}
}
} while (loIdx <= hiIdx);
return null;
}
private ExportDirectoryTable getExportDirectoryTable() {
return
getFile().getHeader().getOptionalHeader().getDataDirectories().getExportDirectoryTable();
}
private Win32Debugger dbg;
private String fullPathName;
private long size;
// MemoizedObject contains a COFFFile
private MemoizedObject file;
// Base address of module in target process
private Address addr;
// Debug info database for this DLL
private CDebugInfoDataBase db;
}

View file

@ -1,70 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
public class TestDebugger {
private static void usage() {
System.out.println("usage: java TestDebugger [pid]");
System.exit(1);
}
public static void main(String[] args) {
try {
if (args.length != 1) {
usage();
}
int pid = 0;
try {
pid = Integer.parseInt(args[0]);
}
catch (NumberFormatException e) {
usage();
}
JVMDebugger debugger = new Win32DebuggerLocal(new MachineDescriptionIntelX86(), true);
System.err.println("Process list: ");
List processes = debugger.getProcessList();
for (Iterator iter = processes.iterator(); iter.hasNext(); ) {
ProcessInfo info = (ProcessInfo) iter.next();
System.err.println(info.getPid() + " " + info.getName());
}
System.err.println("Trying to attach...");
debugger.attach(pid);
System.err.println("Attach succeeded.");
System.err.println("Trying to detach...");
if (!debugger.detach()) {
System.err.println("ERROR: detach failed.");
System.exit(0);
}
System.err.println("Detach succeeded.");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -1,70 +0,0 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
/** Tests to see whether we can find the "Hello, World" string in a
target process */
public class TestHelloWorld {
private static void usage() {
System.out.println("usage: java TestHelloWorld [pid]");
System.out.println("pid must be the process ID of the HelloWorldDLL programs");
System.exit(1);
}
public static void main(String[] args) {
try {
if (args.length != 1) {
usage();
}
int pid = 0;
try {
pid = Integer.parseInt(args[0]);
}
catch (NumberFormatException e) {
usage();
}
JVMDebugger debugger = new Win32DebuggerLocal(new MachineDescriptionIntelX86(), true);
System.err.println("Trying to attach...");
debugger.attach(pid);
System.err.println("Attach succeeded.");
Address addr = debugger.lookup("helloworld.dll", "helloWorldString");
System.err.println("helloWorldString address = " + addr);
System.err.println("Trying to detach...");
if (!debugger.detach()) {
System.err.println("ERROR: detach failed.");
System.exit(0);
}
System.err.println("Detach succeeded.");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -1,403 +0,0 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import sun.jvm.hotspot.debugger.*;
class Win32Address implements Address {
protected Win32Debugger debugger;
protected long addr;
Win32Address(Win32Debugger debugger, long addr) {
this.debugger = debugger;
this.addr = addr;
}
//
// Basic Java routines
//
public boolean equals(Object arg) {
if (arg == null) {
return false;
}
if (!(arg instanceof Win32Address)) {
return false;
}
return (addr == ((Win32Address) arg).addr);
}
public int hashCode() {
// FIXME: suggestions on a better hash code?
return (int) addr;
}
public String toString() {
return debugger.addressValueToString(addr);
}
//
// C/C++-related routines
//
public long getCIntegerAt(long offset, long numBytes, boolean isUnsigned) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCInteger(addr + offset, numBytes, isUnsigned);
}
public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
//
public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJBoolean(addr + offset);
}
public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJByte(addr + offset);
}
public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJChar(addr + offset);
}
public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJDouble(addr + offset);
}
public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJFloat(addr + offset);
}
public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJInt(addr + offset);
}
public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJLong(addr + offset);
}
public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readJShort(addr + offset);
}
public OopHandle getOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
//
// C/C++-related mutators
//
public void setCIntegerAt(long offset, long numBytes, long value) {
debugger.writeCInteger(addr + offset, numBytes, value);
}
public void setAddressAt(long offset, Address value) {
debugger.writeAddress(addr + offset, (Win32Address) value);
}
//
// Java-related mutators
//
public void setJBooleanAt (long offset, boolean value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJBoolean(addr + offset, value);
}
public void setJByteAt (long offset, byte value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJByte(addr + offset, value);
}
public void setJCharAt (long offset, char value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJChar(addr + offset, value);
}
public void setJDoubleAt (long offset, double value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJDouble(addr + offset, value);
}
public void setJFloatAt (long offset, float value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJFloat(addr + offset, value);
}
public void setJIntAt (long offset, int value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJInt(addr + offset, value);
}
public void setJLongAt (long offset, long value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJLong(addr + offset, value);
}
public void setJShortAt (long offset, short value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeJShort(addr + offset, value);
}
public void setOopHandleAt (long offset, OopHandle value)
throws UnmappedAddressException, UnalignedAddressException {
debugger.writeOopHandle(addr + offset, (Win32OopHandle) value);
}
//
// Arithmetic operations -- necessary evil.
//
public Address addOffsetTo (long offset) throws UnsupportedOperationException {
long value = addr + offset;
if (value == 0) {
return null;
}
return new Win32Address(debugger, value);
}
public OopHandle addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException {
long value = addr + offset;
if (value == 0) {
return null;
}
return new Win32OopHandle(debugger, value);
}
/** (FIXME: any signed/unsigned issues? Should this work for
OopHandles?) */
public long minus(Address arg) {
if (arg == null) {
return addr;
}
return addr - ((Win32Address) arg).addr;
}
// Two's complement representation.
// All negative numbers are larger than positive numbers.
// Numbers with the same sign can be compared normally.
// Test harness is below in main().
public boolean lessThan (Address a) {
if (a == null) {
return false;
}
Win32Address arg = (Win32Address) a;
if ((addr >= 0) && (arg.addr < 0)) {
return true;
}
if ((addr < 0) && (arg.addr >= 0)) {
return false;
}
return (addr < arg.addr);
}
public boolean lessThanOrEqual (Address a) {
if (a == null) {
return false;
}
Win32Address arg = (Win32Address) a;
if ((addr >= 0) && (arg.addr < 0)) {
return true;
}
if ((addr < 0) && (arg.addr >= 0)) {
return false;
}
return (addr <= arg.addr);
}
public boolean greaterThan (Address a) {
if (a == null) {
return true;
}
Win32Address arg = (Win32Address) a;
if ((addr >= 0) && (arg.addr < 0)) {
return false;
}
if ((addr < 0) && (arg.addr >= 0)) {
return true;
}
return (addr > arg.addr);
}
public boolean greaterThanOrEqual(Address a) {
if (a == null) {
return true;
}
Win32Address arg = (Win32Address) a;
if ((addr >= 0) && (arg.addr < 0)) {
return false;
}
if ((addr < 0) && (arg.addr >= 0)) {
return true;
}
return (addr >= arg.addr);
}
public Address andWithMask(long mask) throws UnsupportedOperationException {
long value = addr & mask;
if (value == 0) {
return null;
}
return new Win32Address(debugger, value);
}
public Address orWithMask(long mask) throws UnsupportedOperationException {
long value = addr | mask;
if (value == 0) {
return null;
}
return new Win32Address(debugger, value);
}
public Address xorWithMask(long mask) throws UnsupportedOperationException {
long value = addr ^ mask;
if (value == 0) {
return null;
}
return new Win32Address(debugger, value);
}
//--------------------------------------------------------------------------------
// Internals only below this point
//
long getValue() {
return addr;
}
private static void check(boolean arg, String failMessage) {
if (!arg) {
System.err.println(failMessage + ": FAILED");
System.exit(1);
}
}
// Test harness
public static void main(String[] args) {
// p/n indicates whether the interior address is really positive
// or negative. In unsigned terms, p1 < p2 < n1 < n2.
Win32Address p1 = new Win32Address(null, 0x7FFFFFFFFFFFFFF0L);
Win32Address p2 = (Win32Address) p1.addOffsetTo(10);
Win32Address n1 = (Win32Address) p2.addOffsetTo(10);
Win32Address n2 = (Win32Address) n1.addOffsetTo(10);
// lessThan positive tests
check(p1.lessThan(p2), "lessThan 1");
check(p1.lessThan(n1), "lessThan 2");
check(p1.lessThan(n2), "lessThan 3");
check(p2.lessThan(n1), "lessThan 4");
check(p2.lessThan(n2), "lessThan 5");
check(n1.lessThan(n2), "lessThan 6");
// lessThan negative tests
check(!p1.lessThan(p1), "lessThan 7");
check(!p2.lessThan(p2), "lessThan 8");
check(!n1.lessThan(n1), "lessThan 9");
check(!n2.lessThan(n2), "lessThan 10");
check(!p2.lessThan(p1), "lessThan 11");
check(!n1.lessThan(p1), "lessThan 12");
check(!n2.lessThan(p1), "lessThan 13");
check(!n1.lessThan(p2), "lessThan 14");
check(!n2.lessThan(p2), "lessThan 15");
check(!n2.lessThan(n1), "lessThan 16");
// lessThanOrEqual positive tests
check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1");
check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2");
check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3");
check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4");
check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5");
check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6");
check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7");
check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8");
check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9");
check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10");
// lessThanOrEqual negative tests
check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11");
check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12");
check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13");
check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14");
check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15");
check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16");
// greaterThan positive tests
check(n2.greaterThan(p1), "greaterThan 1");
check(n2.greaterThan(p2), "greaterThan 2");
check(n2.greaterThan(n1), "greaterThan 3");
check(n1.greaterThan(p1), "greaterThan 4");
check(n1.greaterThan(p2), "greaterThan 5");
check(p2.greaterThan(p1), "greaterThan 6");
// greaterThan negative tests
check(!p1.greaterThan(p1), "greaterThan 7");
check(!p2.greaterThan(p2), "greaterThan 8");
check(!n1.greaterThan(n1), "greaterThan 9");
check(!n2.greaterThan(n2), "greaterThan 10");
check(!p1.greaterThan(n2), "greaterThan 11");
check(!p2.greaterThan(n2), "greaterThan 12");
check(!n1.greaterThan(n2), "greaterThan 13");
check(!p1.greaterThan(n1), "greaterThan 14");
check(!p2.greaterThan(n1), "greaterThan 15");
check(!p1.greaterThan(p2), "greaterThan 16");
// greaterThanOrEqual positive tests
check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1");
check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2");
check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3");
check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4");
check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5");
check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6");
check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7");
check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8");
check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9");
check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10");
// greaterThanOrEqual negative tests
check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11");
check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12");
check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13");
check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14");
check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15");
check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16");
System.err.println("Win32Address: all tests passed successfully.");
}
}

View file

@ -1,824 +0,0 @@
/*
* Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.win32.coff.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.*;
import sun.jvm.hotspot.utilities.Assert;
class Win32CDebugInfoBuilder
implements DebugVC50SubsectionTypes, DebugVC50TypeLeafIndices, DebugVC50TypeEnums, DebugVC50SymbolTypes, DebugVC50MemberAttributes, CVAttributes, AccessControl {
private Win32Debugger dbg;
private Address base;
private DebugVC50 vc50;
private BasicCDebugInfoDataBase db;
private DebugVC50TypeIterator iter;
private DebugVC50SymbolIterator symIter;
// Logical->physical segment mapping
private COFFFile file;
private DebugVC50SSSegMap segMap;
// Canonicalization of primitive types
private Map primIndexToTypeMap;
// Global unnamed enumeration
// (FIXME: must figure out how to handle nested type descriptions)
private BasicEnumType unnamedEnum;
private Stack blockStack;
private int endsToSkip;
private static final int POINTER_SIZE = 4;
Win32CDebugInfoBuilder(Win32Debugger dbg) {
this.dbg = dbg;
}
CDebugInfoDataBase buildDataBase(String dllName, Address base) {
this.base = base;
file = COFFFileParser.getParser().parse(dllName);
vc50 = getDebugVC50(file);
if (vc50 == null) return null;
segMap = getSegMap();
primIndexToTypeMap = new HashMap();
blockStack = new Stack();
endsToSkip = 0;
db = new BasicCDebugInfoDataBase();
db.beginConstruction();
// Get global types and add them to the database
DebugVC50SSGlobalTypes types = getGlobalTypes();
for (iter = types.getTypeIterator(); !iter.done(); iter.next()) {
while (!iter.typeStringDone()) {
switch (iter.typeStringLeaf()) {
case LF_MODIFIER: {
int idx = iter.getModifierIndex();
BasicType target = getTypeByIndex(idx);
short windowsMods = iter.getModifierAttribute();
short mods = 0;
if ((windowsMods & MODIFIER_CONST_MASK) != 0) mods |= CONST;
if ((windowsMods & MODIFIER_VOLATILE_MASK) != 0) mods |= VOLATILE;
putType(target.getCVVariant(mods));
break;
}
case LF_POINTER: {
int idx = iter.getPointerType();
BasicType target = getTypeByIndex(idx);
short windowsMods = iter.getModifierAttribute();
short mods = 0;
if ((windowsMods & POINTER_CONST_MASK) != 0) mods |= CONST;
if ((windowsMods & POINTER_VOLATILE_MASK) != 0) mods |= VOLATILE;
BasicPointerType ptrType = new BasicPointerType(POINTER_SIZE, target);
if (mods != 0) {
ptrType = (BasicPointerType) ptrType.getCVVariant(mods);
}
putType(ptrType);
break;
}
case LF_ARRAY: {
BasicType elemType = getTypeByIndex(iter.getArrayElementType());
putType(new BasicArrayType(iter.getArrayName(), elemType, iter.getArrayLength()));
break;
}
case LF_CLASS:
case LF_STRUCTURE: {
CompoundTypeKind kind = ((iter.typeStringLeaf() == LF_CLASS) ? CompoundTypeKind.CLASS
: CompoundTypeKind.STRUCT);
BasicCompoundType type = new BasicCompoundType(iter.getClassName(),
iter.getClassSize(),
kind);
// Skip parsing of forward references to types
// FIXME: do we have to resolve these later?
if ((iter.getClassProperty() & PROPERTY_FWDREF) == 0) {
DebugVC50TypeIterator fieldIter = iter.getClassFieldListIterator();
if (Assert.ASSERTS_ENABLED) {
Assert.that(fieldIter.typeStringLeaf() == LF_FIELDLIST, "Expected field list");
}
boolean advance = false;
while (!fieldIter.typeStringDone()) {
advance = true;
switch (fieldIter.typeStringLeaf()) {
case LF_FIELDLIST: break;
case LF_BCLASS: {
int accessControl = memberAttributeToAccessControl(fieldIter.getBClassAttribute());
Type baseType = getTypeByIndex(fieldIter.getBClassType());
// FIXME: take offset into account
type.addBaseClass(new BasicBaseClass(accessControl, false, baseType));
break;
}
case LF_VBCLASS: {
int accessControl = memberAttributeToAccessControl(fieldIter.getVBClassAttribute());
Type baseType = getTypeByIndex(fieldIter.getVBClassBaseClassType());
// FIXME: take offset and virtual base offset into account
type.addBaseClass(new BasicBaseClass(accessControl, true, baseType));
break;
}
// I don't think we need to handle indirect virtual base
// classes since they should be handled indirectly through
// the modeling of the type hierarchy
case LF_IVBCLASS: break;
case LF_INDEX: {
fieldIter = fieldIter.getIndexIterator();
advance = false;
break;
}
case LF_MEMBER: {
BasicField field = new BasicField(fieldIter.getMemberName(),
getTypeByIndex(fieldIter.getMemberType()),
memberAttributeToAccessControl(fieldIter.getMemberAttribute()),
false);
field.setOffset(fieldIter.getMemberOffset());
type.addField(field);
break;
}
case LF_STMEMBER: {
BasicField field = new BasicField(fieldIter.getStaticName(),
getTypeByIndex(fieldIter.getStaticType()),
memberAttributeToAccessControl(fieldIter.getStaticAttribute()),
true);
// The field's address will be found during resolution
// of the debug info database
type.addField(field);
break;
}
// FIXME: handle methods
case LF_METHOD: break;
case LF_ONEMETHOD: break;
// FIXME: handle nested types
case LF_NESTTYPE: break;
case LF_NESTTYPEEX: break;
// NOTE: virtual functions not needed/handled yet for
// this debugging system (because we are not planning to
// handle calling methods in the target process at
// runtime)
case LF_VFUNCTAB: break;
case LF_FRIENDCLS: break;
case LF_VFUNCOFF: break;
case LF_MEMBERMODIFY: break;
case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3:
case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7:
case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11:
case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break;
default: System.err.println("WARNING: unexpected leaf index " +
fieldIter.typeStringLeaf() +
" in field list for type " + iter.getTypeIndex());
}
if (advance) {
fieldIter.typeStringNext();
}
}
}
putType(type);
break;
}
case LF_UNION: {
BasicCompoundType type = new BasicCompoundType(iter.getUnionName(),
iter.getUnionSize(),
CompoundTypeKind.UNION);
// Skip parsing of forward references to types
// FIXME: do we have to resolve these later?
if ((iter.getClassProperty() & PROPERTY_FWDREF) == 0) {
DebugVC50TypeIterator fieldIter = iter.getUnionFieldListIterator();
if (Assert.ASSERTS_ENABLED) {
Assert.that(fieldIter.typeStringLeaf() == LF_FIELDLIST, "Expected field list");
}
boolean advance = false;
while (!fieldIter.typeStringDone()) {
advance = true;
switch (fieldIter.typeStringLeaf()) {
case LF_FIELDLIST: break;
case LF_BCLASS: break;
case LF_VBCLASS: break;
case LF_IVBCLASS: break;
case LF_INDEX: {
fieldIter = fieldIter.getIndexIterator();
advance = false;
break;
}
case LF_MEMBER: {
BasicField field = new BasicField(fieldIter.getMemberName(),
getTypeByIndex(fieldIter.getMemberType()),
memberAttributeToAccessControl(fieldIter.getMemberAttribute()),
false);
field.setOffset(fieldIter.getMemberOffset());
type.addField(field);
break;
}
case LF_STMEMBER: {
System.err.println("WARNING: I didn't think unions could contain static fields...");
BasicField field = new BasicField(fieldIter.getStaticName(),
getTypeByIndex(fieldIter.getStaticType()),
memberAttributeToAccessControl(fieldIter.getStaticAttribute()),
true);
// The field's address will be found during resolution
// of the debug info database
type.addField(field);
break;
}
case LF_METHOD: break;
case LF_ONEMETHOD: break;
// FIXME: handle nested types
case LF_NESTTYPE: break;
case LF_NESTTYPEEX: break;
case LF_VFUNCTAB: break;
case LF_FRIENDCLS: break;
case LF_VFUNCOFF: break;
case LF_MEMBERMODIFY: break;
case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3:
case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7:
case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11:
case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break;
default: System.err.println("WARNING: unexpected leaf index " +
fieldIter.typeStringLeaf() +
" in field list for union of type " + iter.getTypeIndex());
}
if (advance) {
fieldIter.typeStringNext();
}
}
}
putType(type);
break;
}
case LF_ENUM: {
String name = iter.getEnumName();
BasicEnumType enumType = null;
if ((name == null) || (name.equals(""))) {
if (unnamedEnum == null) {
unnamedEnum = new BasicEnumType(null, getTypeByIndex(iter.getEnumType()));
}
enumType = unnamedEnum;
} else {
enumType = new BasicEnumType(name, getTypeByIndex(iter.getEnumType()));
}
DebugVC50TypeIterator fieldIter = iter.getEnumFieldListIterator();
if (Assert.ASSERTS_ENABLED) {
Assert.that(fieldIter.typeStringLeaf() == LF_FIELDLIST, "Expected field list");
}
boolean advance = false;
while (!fieldIter.typeStringDone()) {
advance = true;
switch (fieldIter.typeStringLeaf()) {
case LF_FIELDLIST: break;
case LF_ENUMERATE: {
String enumName = fieldIter.getEnumerateName();
long enumVal = fieldIter.getEnumerateValue();
enumType.addEnum(enumName, enumVal);
break;
}
case LF_INDEX: {
fieldIter = fieldIter.getIndexIterator();
advance = false;
break;
}
case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3:
case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7:
case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11:
case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break;
default: System.err.println("WARNING: unexpected leaf index " +
fieldIter.typeStringLeaf() +
" in field list for enum of type " + iter.getTypeIndex());
}
if (advance) {
fieldIter.typeStringNext();
}
}
putType(enumType);
break;
}
case LF_PROCEDURE: {
Type retType = getTypeByIndex(iter.getProcedureReturnType());
BasicFunctionType func = new BasicFunctionType(null, POINTER_SIZE, retType);
DebugVC50TypeIterator argIter = iter.getProcedureArgumentListIterator();
if (Assert.ASSERTS_ENABLED) {
Assert.that(argIter.typeStringLeaf() == LF_ARGLIST, "Expected argument list");
}
for (int i = 0; i < argIter.getArgListCount(); i++) {
func.addArgumentType(getTypeByIndex(argIter.getArgListType(i)));
}
putType(func);
break;
}
case LF_MFUNCTION: {
Type retType = getTypeByIndex(iter.getMFunctionReturnType());
Type container = getTypeByIndex(iter.getMFunctionContainingClass());
Type thisType = getTypeByIndex(iter.getMFunctionThis());
long thisAdjust = iter.getMFunctionThisAdjust();
BasicMemberFunctionType func = new BasicMemberFunctionType(null,
POINTER_SIZE,
retType,
container,
thisType,
thisAdjust);
DebugVC50TypeIterator argIter = iter.getMFunctionArgumentListIterator();
for (int i = 0; i < argIter.getArgListCount(); i++) {
func.addArgumentType(getTypeByIndex(argIter.getArgListType(i)));
}
putType(func);
break;
}
// FIXME: handle virtual function table shape description
case LF_VTSHAPE: break;
case LF_BARRAY: System.err.println("FIXME: don't know what to do with LF_BARRAY leaves (convert to pointers?"); break;
case LF_LABEL: break;
case LF_NULL: break; // FIXME: do we need to handle this? With what?
case LF_DIMARRAY: System.err.println("FIXME: don't know what to do with LF_DIMARRAY leaves yet"); break;
case LF_VFTPATH: break;
case LF_PRECOMP: break;
case LF_ENDPRECOMP: break;
case LF_OEM: break;
case LF_TYPESERVER: break;
// Type records referenced from other type records
case LF_SKIP: break;
case LF_ARGLIST: skipTypeRecord(); break;
case LF_DEFARG: System.err.println("FIXME: handle default arguments (dereference the type)"); break;
case LF_FIELDLIST: skipTypeRecord(); break;
case LF_DERIVED: break;
case LF_BITFIELD: {
Type underlyingType = getTypeByIndex(iter.getBitfieldFieldType());
BasicBitType bit = new BasicBitType(underlyingType,
(iter.getBitfieldLength() & 0xFF),
(iter.getBitfieldPosition() & 0xFF));
putType(bit);
break;
}
case LF_METHODLIST: break;
case LF_DIMCONU:
case LF_DIMCONLU:
case LF_DIMVARU:
case LF_DIMVARLU: break;
case LF_REFSYM: break;
case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3:
case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7:
case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11:
case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break;
default: {
System.err.println("Unexpected leaf index " +
iter.typeStringLeaf() + " at offset 0x" +
Integer.toHexString(iter.typeStringOffset()));
break;
}
}
if (!iter.typeStringDone()) {
iter.typeStringNext();
}
}
}
// Add all symbol directories to debug info
// (FIXME: must figure out how to handle module-by-module
// arrangement of at least the static symbols to have proper
// lookup -- should probably also take advantage of the PROCREF
// and UDT references to understand how to build the global
// database vs. the module-by-module one)
DebugVC50SubsectionDirectory dir = vc50.getSubsectionDirectory();
int moduleNumber = 0; // Debugging
for (int i = 0; i < dir.getNumEntries(); i++) {
DebugVC50Subsection ss = dir.getSubsection(i);
int ssType = ss.getSubsectionType();
boolean process = false;
if ((ssType == SST_GLOBAL_SYM) ||
(ssType == SST_GLOBAL_PUB) ||
(ssType == SST_STATIC_SYM)) {
DebugVC50SSSymbolBase syms = (DebugVC50SSSymbolBase) ss;
symIter = syms.getSymbolIterator();
process = true;
}
if (ssType == SST_ALIGN_SYM) {
DebugVC50SSAlignSym syms = (DebugVC50SSAlignSym) ss;
symIter = syms.getSymbolIterator();
process = true;
}
if (process) {
for (; !symIter.done(); symIter.next()) {
switch (symIter.getType()) {
case S_COMPILE: break;
case S_SSEARCH: break; // FIXME: may need this later
case S_END: {
try {
// FIXME: workaround for warnings until we figure out
// what to do with THUNK32 symbols
if (endsToSkip == 0) {
blockStack.pop();
} else {
--endsToSkip;
}
} catch (EmptyStackException e) {
System.err.println("WARNING: mismatched block begins/ends in debug information");
}
break;
}
case S_SKIP: break;
case S_CVRESERVE: break;
case S_OBJNAME: break; // FIXME: may need this later
case S_ENDARG: break;
case S_COBOLUDT: break;
case S_MANYREG: break; // FIXME: may need to add support for this
case S_RETURN: break; // NOTE: would need this if adding support for calling functions
case S_ENTRYTHIS: break; // FIXME: may need to add support for this
case S_REGISTER: break; // FIXME: may need to add support for this
case S_CONSTANT: break; // FIXME: will need to add support for this
case S_UDT: break; // FIXME: need to see how these are used; are
// they redundant, or are they used to describe
// global variables as opposed to types?
case S_COBOLUDT2: break;
case S_MANYREG2: break;
case S_BPREL32: {
LocalSym sym = new BasicLocalSym(symIter.getBPRelName(),
getTypeByIndex(symIter.getBPRelType()),
symIter.getBPRelOffset());
addLocalToCurBlock(sym);
break;
}
case S_LDATA32:
case S_GDATA32: {
// FIXME: must handle these separately from global data (have
// module scoping and only add these at the module level)
boolean isModuleLocal = (symIter.getType() == S_LDATA32);
GlobalSym sym = new BasicGlobalSym(symIter.getLGDataName(),
getTypeByIndex(symIter.getLGDataType()),
newAddress(symIter.getLGDataOffset(), symIter.getLGDataSegment()),
isModuleLocal);
// FIXME: must handle module-local symbols differently
addGlobalSym(sym);
break;
}
case S_PUB32: break; // FIXME: figure out how these differ from
// above and how they are used
case S_LPROC32:
case S_GPROC32: {
BasicFunctionSym sym = new BasicFunctionSym(newLazyBlockSym(symIter.getLGProcParentOffset()),
symIter.getLGProcLength(),
newAddress(symIter.getLGProcOffset(), symIter.getLGProcSegment()),
symIter.getLGProcName(),
getTypeByIndex(symIter.getLGProcType()),
(symIter.getType() == S_LPROC32));
// FIXME: have to handle local procedures differently (have
// notion of modules and only add those procedures to the
// module they are defined in)
addBlock(sym);
break;
}
case S_THUNK32: {
// FIXME: see whether we need to handle these
skipEnd();
break;
}
case S_BLOCK32: {
BasicBlockSym sym = new BasicBlockSym(newLazyBlockSym(symIter.getBlockParentOffset()),
symIter.getBlockLength(),
newAddress(symIter.getBlockOffset(), symIter.getBlockSegment()),
symIter.getBlockName());
addBlock(sym);
break;
}
case S_WITH32: break;
case S_LABEL32: break;
case S_CEXMODEL32: break;
case S_VFTTABLE32: break; // FIXME: may need to handle this
// (most likely for run-time type determination)
case S_REGREL32: break; // FIXME: may need to add support for this
case S_LTHREAD32: break;
case S_GTHREAD32: break; // FIXME: may need to add support for these
case S_PROCREF: break;
case S_DATAREF: break;
case S_ALIGN: break;
default:
// These two unknown symbol types show up very frequently.
// Symbol type 0 appears to always be a no-op symbol of
// length 2 (i.e., length just covers the symbol type.)
// Symbol type 4115 appears to be a copyright notice for
// the Microsoft linker.
if ((symIter.getType() != 0) && (symIter.getType() != 4115)) {
System.err.println(" NOTE: Unexpected symbol of type " +
symIter.getType() + " at offset 0x" +
Integer.toHexString(symIter.getOffset()));
}
break;
}
}
}
}
// Add line number information for all modules
for (int i = 0; i < dir.getNumEntries(); i++) {
DebugVC50Subsection ss = dir.getSubsection(i);
if (ss.getSubsectionType() == SST_SRC_MODULE) {
DebugVC50SSSrcModule srcMod = (DebugVC50SSSrcModule) ss;
for (int sf = 0; sf < srcMod.getNumSourceFiles(); sf++) {
DebugVC50SrcModFileDesc desc = srcMod.getSourceFileDesc(sf);
// Uniquify these to save space
String name = desc.getSourceFileName().intern();
for (int cs = 0; cs < desc.getNumCodeSegments(); cs++) {
DebugVC50SrcModLineNumberMap map = desc.getLineNumberMap(cs);
SectionHeader seg = file.getHeader().getSectionHeader(map.getSegment());
for (int lp = 0; lp < map.getNumSourceLinePairs(); lp++) {
Address startPC = base.addOffsetTo(seg.getVirtualAddress() + map.getCodeOffset(lp));
// Fake address for endPC -- will be filled in by BasicLineNumberMapping
Address endPC = base.addOffsetTo(seg.getSize());
db.addLineNumberInfo(new BasicLineNumberInfo(name, map.getLineNumber(lp), startPC, endPC));
}
}
}
}
}
// Finish assembly of database
db.resolve(new ResolveListener() {
public void resolveFailed(Type containingType, LazyType failedResolve, String detail) {
System.err.println("WARNING: failed to resolve type of index " +
((Integer) failedResolve.getKey()).intValue() +
" in type " + containingType.getName() + " (class " +
containingType.getClass().getName() + ") while " + detail);
}
public void resolveFailed(Type containingType, String staticFieldName) {
System.err.println("WARNING: failed to resolve address of static field \"" +
staticFieldName + "\" in type " + containingType.getName());
}
public void resolveFailed(Sym containingSymbol, LazyType failedResolve, String detail) {
System.err.println("WARNING: failed to resolve type of index " +
((Integer) failedResolve.getKey()).intValue() +
" in symbol of type " + containingSymbol.getClass().getName() +
" while " + detail);
}
public void resolveFailed(Sym containingSymbol, LazyBlockSym failedResolve, String detail) {
System.err.println("WARNING: failed to resolve block at offset 0x" +
Integer.toHexString(((Integer) failedResolve.getKey()).intValue()) +
" in symbol of type " + containingSymbol.getClass().getName() +
" while " + detail);
}
});
db.endConstruction();
return db;
}
//----------------------------------------------------------------------
// Internals only below this point
//
private static DebugVC50 getDebugVC50(COFFFile file) {
COFFHeader header = file.getHeader();
OptionalHeader opt = header.getOptionalHeader();
if (opt == null) {
// Optional header not found
return null;
}
OptionalHeaderDataDirectories dd = opt.getDataDirectories();
if (dd == null) {
// Optional header data directories not found
return null;
}
DebugDirectory debug = dd.getDebugDirectory();
if (debug == null) {
// Debug directory not found
return null;
}
for (int i = 0; i < debug.getNumEntries(); i++) {
DebugDirectoryEntry entry = debug.getEntry(i);
if (entry.getType() == DebugTypes.IMAGE_DEBUG_TYPE_CODEVIEW) {
return entry.getDebugVC50();
}
}
// CodeView information not found in debug directory
return null;
}
private DebugVC50SSSegMap getSegMap() {
return (DebugVC50SSSegMap) findSubsection(SST_SEG_MAP);
}
private DebugVC50SSGlobalTypes getGlobalTypes() {
return (DebugVC50SSGlobalTypes) findSubsection(SST_GLOBAL_TYPES);
}
private DebugVC50SSGlobalSym getGlobalSymbols() {
return (DebugVC50SSGlobalSym) findSubsection(SST_GLOBAL_SYM);
}
private DebugVC50Subsection findSubsection(short ssType) {
DebugVC50SubsectionDirectory dir = vc50.getSubsectionDirectory();
for (int i = 0; i < dir.getNumEntries(); i++) {
DebugVC50Subsection ss = dir.getSubsection(i);
if (ss.getSubsectionType() == ssType) {
return ss;
}
}
throw new DebuggerException("Unable to find subsection of type " + ssType);
}
private void putType(Type t) {
db.addType(new Integer(iter.getTypeIndex()), t);
}
private Address newAddress(int offset, short segment) {
int seg = segment & 0xFFFF;
// NOTE: it isn't clear how to use the segMap to map from logical
// to physical segments. It seems it would make more sense if the
// SegDescs contained a physical segment number in addition to the
// offset within the physical segment of the logical one.
// Get the section header corresponding to this segment
SectionHeader section = file.getHeader().getSectionHeader(seg);
// Result is relative to image base
return base.addOffsetTo(section.getVirtualAddress() + offset);
}
private BasicType getTypeByIndex(int intIndex) {
Integer index = new Integer(intIndex);
// Handle primitive types here.
if (intIndex <= 0x0FFF) {
BasicType type = (BasicType) primIndexToTypeMap.get(index);
if (type != null) {
return type;
}
// Construct appropriate new primitive type
int primMode = intIndex & RESERVED_MODE_MASK;
if (primMode == RESERVED_MODE_DIRECT) {
int primType = intIndex & RESERVED_TYPE_MASK;
switch (primType) {
case RESERVED_TYPE_SIGNED_INT:
case RESERVED_TYPE_UNSIGNED_INT: {
boolean unsigned = (primType == RESERVED_TYPE_UNSIGNED_INT);
int size = 0;
String name = null;
switch (intIndex & RESERVED_SIZE_MASK) {
case RESERVED_SIZE_INT_1_BYTE: size = 1; name = "char"; break;
case RESERVED_SIZE_INT_2_BYTE: size = 2; name = "short"; break;
case RESERVED_SIZE_INT_4_BYTE: size = 4; name = "int"; break;
case RESERVED_SIZE_INT_8_BYTE: size = 8; name = "__int64"; break;
default: throw new DebuggerException("Illegal size of integer type " + intIndex);
}
type = new BasicIntType(name, size, unsigned);
break;
}
case RESERVED_TYPE_BOOLEAN: {
int size = 0;
switch (intIndex & RESERVED_SIZE_MASK) {
case RESERVED_SIZE_INT_1_BYTE: size = 1; break;
case RESERVED_SIZE_INT_2_BYTE: size = 2; break;
case RESERVED_SIZE_INT_4_BYTE: size = 4; break;
case RESERVED_SIZE_INT_8_BYTE: size = 8; break;
default: throw new DebuggerException("Illegal size of boolean type " + intIndex);
}
type = new BasicIntType("bool", size, false);
break;
}
case RESERVED_TYPE_REAL: {
switch (intIndex & RESERVED_SIZE_MASK) {
case RESERVED_SIZE_REAL_32_BIT:
type = new BasicFloatType("float", 4);
break;
case RESERVED_SIZE_REAL_64_BIT:
type = new BasicDoubleType("double", 8);
break;
default:
throw new DebuggerException("Unsupported floating-point size in type " + intIndex);
}
break;
}
case RESERVED_TYPE_REALLY_INT: {
switch (intIndex & RESERVED_SIZE_MASK) {
case RESERVED_SIZE_REALLY_INT_CHAR: type = new BasicIntType("char", 1, false); break;
case RESERVED_SIZE_REALLY_INT_WCHAR: type = new BasicIntType("wchar", 2, false); break;
case RESERVED_SIZE_REALLY_INT_2_BYTE: type = new BasicIntType("short", 2, false); break;
case RESERVED_SIZE_REALLY_INT_2_BYTE_U: type = new BasicIntType("short", 2, true); break;
case RESERVED_SIZE_REALLY_INT_4_BYTE: type = new BasicIntType("int", 4, false); break;
case RESERVED_SIZE_REALLY_INT_4_BYTE_U: type = new BasicIntType("int", 4, true); break;
case RESERVED_SIZE_REALLY_INT_8_BYTE: type = new BasicIntType("__int64", 8, false); break;
case RESERVED_SIZE_REALLY_INT_8_BYTE_U: type = new BasicIntType("__int64", 8, true); break;
default: throw new DebuggerException("Illegal REALLY_INT size in type " + intIndex);
}
break;
}
case RESERVED_TYPE_SPECIAL: {
switch (intIndex & RESERVED_SIZE_MASK) {
case RESERVED_SIZE_SPECIAL_NO_TYPE:
case RESERVED_SIZE_SPECIAL_VOID: type = new BasicVoidType(); break;
default: throw new DebuggerException("Don't know how to handle reserved special type " + intIndex);
}
break;
}
default:
throw new DebuggerException("Don't know how to handle reserved type " + intIndex);
}
} else {
// Fold all pointer types together since we only support
// flat-mode addressing anyway
Type targetType = getTypeByIndex(intIndex & (~RESERVED_MODE_MASK));
type = new BasicPointerType(POINTER_SIZE, targetType);
}
if (Assert.ASSERTS_ENABLED) {
Assert.that(type != null, "Got null Type for primitive type " + intIndex);
}
primIndexToTypeMap.put(index, type);
return type;
}
// Not primitive type. Construct lazy reference to target type.
// (Is it worth canonicalizing these as well to save space?)
return new LazyType(index);
}
private void addBlock(BlockSym block) {
db.addBlock(new Integer(symIter.getOffset()), block);
blockStack.push(block);
}
private void skipEnd() {
++endsToSkip;
}
private BlockSym newLazyBlockSym(int offset) {
if (offset == 0) {
return null;
}
return new LazyBlockSym(new Integer(offset));
}
private int memberAttributeToAccessControl(short memberAttribute) {
int acc = memberAttribute & MEMATTR_ACCESS_MASK;
switch (acc) {
case MEMATTR_ACCESS_NO_PROTECTION: return NO_PROTECTION;
case MEMATTR_ACCESS_PRIVATE: return PRIVATE;
case MEMATTR_ACCESS_PROTECTED: return PROTECTED;
case MEMATTR_ACCESS_PUBLIC: return PUBLIC;
default: throw new RuntimeException("Should not reach here");
}
}
private void addLocalToCurBlock(LocalSym local) {
((BasicBlockSym) blockStack.peek()).addLocal(local);
}
private void addGlobalSym(GlobalSym sym) {
db.addGlobalSym(sym);
}
private void skipTypeRecord() {
while (!iter.typeStringDone()) {
iter.typeStringNext();
}
}
}

View file

@ -1,123 +0,0 @@
/*
* Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.x86.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.utilities.AddressOps;
class Win32CDebugger implements CDebugger, ProcessControl {
// FIXME: think about how to make this work in a remote debugging
// scenario; who should keep open DLLs? Need local copies of these
// DLLs on the debugging machine?
private Win32Debugger dbg;
Win32CDebugger(Win32Debugger dbg) {
this.dbg = dbg;
}
public List getThreadList() throws DebuggerException {
return dbg.getThreadList();
}
public List/*<LoadObject>*/ getLoadObjectList() throws DebuggerException{
return dbg.getLoadObjectList();
}
public LoadObject loadObjectContainingPC(Address pc) throws DebuggerException {
// FIXME: could keep sorted list of these to be able to do binary
// searches, for better scalability
if (pc == null) {
return null;
}
List objs = getLoadObjectList();
for (Iterator iter = objs.iterator(); iter.hasNext(); ) {
LoadObject obj = (LoadObject) iter.next();
if (AddressOps.lte(obj.getBase(), pc) && (pc.minus(obj.getBase()) < obj.getSize())) {
return obj;
}
}
return null;
}
public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException {
X86ThreadContext context = (X86ThreadContext) thread.getContext();
Address ebp = context.getRegisterAsAddress(X86ThreadContext.EBP);
if (ebp == null) return null;
Address pc = context.getRegisterAsAddress(X86ThreadContext.EIP);
if (pc == null) return null;
return new X86CFrame(this, ebp, pc);
}
public String getNameOfFile(String fileName) {
return new File(fileName).getName();
}
public ProcessControl getProcessControl() throws DebuggerException {
return this;
}
// C++ name demangling
public boolean canDemangle() {
return false;
}
public String demangle(String sym) {
throw new UnsupportedOperationException();
}
//
// Support for ProcessControl interface
//
public void suspend() throws DebuggerException {
dbg.suspend();
}
public void resume() throws DebuggerException {
dbg.resume();
}
public boolean isSuspended() throws DebuggerException {
return dbg.isSuspended();
}
public void setBreakpoint(Address addr) throws DebuggerException {
dbg.setBreakpoint(addr);
}
public void clearBreakpoint(Address addr) throws DebuggerException {
dbg.clearBreakpoint(addr);
}
public boolean isBreakpointSet(Address addr) throws DebuggerException {
return dbg.isBreakpointSet(addr);
}
public DebugEvent debugEventPoll() throws DebuggerException {
return dbg.debugEventPoll();
}
public void debugEventContinue() throws DebuggerException {
dbg.debugEventContinue();
}
}

View file

@ -1,135 +0,0 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.win32;
import java.util.List;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
/** An extension of the JVMDebugger interface with a few additions to
support 32-bit vs. 64-bit debugging as well as features required
by the architecture-specific subpackages. */
public interface Win32Debugger extends JVMDebugger {
public String addressValueToString(long address) throws DebuggerException;
public boolean readJBoolean(long address) throws DebuggerException;
public byte readJByte(long address) throws DebuggerException;
public char readJChar(long address) throws DebuggerException;
public double readJDouble(long address) throws DebuggerException;
public float readJFloat(long address) throws DebuggerException;
public int readJInt(long address) throws DebuggerException;
public long readJLong(long address) throws DebuggerException;
public short readJShort(long address) throws DebuggerException;
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws DebuggerException;
public Win32Address readAddress(long address) throws DebuggerException;
public Win32Address readCompOopAddress(long address) throws DebuggerException;
public Win32OopHandle readOopHandle(long address) throws DebuggerException;
public Win32OopHandle readCompOopHandle(long address) throws DebuggerException;
public void writeJBoolean(long address, boolean value) throws DebuggerException;
public void writeJByte(long address, byte value) throws DebuggerException;
public void writeJChar(long address, char value) throws DebuggerException;
public void writeJDouble(long address, double value) throws DebuggerException;
public void writeJFloat(long address, float value) throws DebuggerException;
public void writeJInt(long address, int value) throws DebuggerException;
public void writeJLong(long address, long value) throws DebuggerException;
public void writeJShort(long address, short value) throws DebuggerException;
public void writeCInteger(long address, long numBytes, long value) throws DebuggerException;
public void writeAddress(long address, Win32Address value) throws DebuggerException;
public void writeOopHandle(long address, Win32OopHandle value) throws DebuggerException;
// On Windows the int is actually the value of a HANDLE which
// currently must be read from the target process; that is, the
// target process must maintain its own thread list, each element of
// which holds a HANDLE to its underlying OS thread. FIXME: should
// add access to the OS-level thread list, but there are too many
// limitations imposed by Windows to usefully do so; see
// src/os/win32/agent/README-commands.txt, command "duphandle".
//
// The returned array of register contents is guaranteed to be in
// the same order as in the DbxDebugger for Solaris/x86; that is,
// the indices match those in debugger/x86/X86ThreadContext.java.
public long[] getThreadIntegerRegisterSet(int threadHandleValue,
boolean mustDuplicateHandle) throws DebuggerException;
// Implmentation of setContext
public void setThreadIntegerRegisterSet(int threadHandleValue,
boolean mustDuplicateHandle,
long[] contents) throws DebuggerException;
public Address newAddress(long value) throws DebuggerException;
// Routine supporting the ThreadProxy implementation, in particular
// the ability to get a thread ID from a thread handle via
// examination of the Thread Information Block. Fetch the LDT entry
// for a given selector.
public Win32LDTEntry getThreadSelectorEntry(int threadHandleValue,
boolean mustDuplicateHandle,
int selector) throws DebuggerException;
// Support for the CDebugger interface. Retrieves the thread list of
// the target process as a List of ThreadProxy objects.
public List/*<ThreadProxy>*/ getThreadList() throws DebuggerException;
// Support for the CDebugger interface. Retrieves a List of the
// loadobjects in the target process.
public List/*<LoadObject>*/ getLoadObjectList() throws DebuggerException;
// Support for the ProcessControl interface
public void writeBytesToProcess(long startAddress, long numBytes, byte[] data) throws UnmappedAddressException, DebuggerException;
public void suspend() throws DebuggerException;
public void resume() throws DebuggerException;
public boolean isSuspended() throws DebuggerException;
public void setBreakpoint(Address addr) throws DebuggerException;
public void clearBreakpoint(Address addr) throws DebuggerException;
public boolean isBreakpointSet(Address addr) throws DebuggerException;
// FIXME: do not want to expose complicated data structures (like
// the DebugEvent) in this interface due to serialization issues
public DebugEvent debugEventPoll() throws DebuggerException;
public void debugEventContinue() throws DebuggerException;
// NOTE: this interface implicitly contains the following methods:
// From the Debugger interface via JVMDebugger
// public void attach(int processID) throws DebuggerException;
// public void attach(String executableName, String coreFileName) throws DebuggerException;
// public boolean detach();
// public Address parseAddress(String addressString) throws NumberFormatException;
// public long getAddressValue(Address addr) throws DebuggerException;
// public String getOS();
// public String getCPU();
// From the SymbolLookup interface via Debugger and JVMDebugger
// public Address lookup(String objectName, String symbol);
// public OopHandle lookupOop(String objectName, String symbol);
// From the JVMDebugger interface
// public void configureJavaPrimitiveTypeSizes(long jbooleanSize,
// long jbyteSize,
// long jcharSize,
// long jdoubleSize,
// long jfloatSize,
// long jintSize,
// long jlongSize,
// long jshortSize);
// From the ThreadAccess interface via Debugger and JVMDebugger
// public ThreadProxy getThreadForIdentifierAddress(Address addr);
}

Some files were not shown because too many files have changed in this diff Show more