提交 35fcee71 编写于 作者: I iveresov

Merge

......@@ -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 \
......
......@@ -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"
......@@ -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"
......@@ -24,9 +24,7 @@
all:
cd dbx; $(MAKE) all
cd proc; $(MAKE) all
clean:
cd dbx; $(MAKE) clean
cd proc; $(MAKE) clean
#
# 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
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.
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' */
/*
* 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) {
}
}
}
/*
* 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 */
/*
* 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
此差异已折叠。
/*
* 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);
};
/*
* 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_
/*
* 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_
/*
* 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
}
/*
* 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_
/*
* 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_
/*
* 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
}
/*
* 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_
/*
* 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_
/*
* 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_
/*
* 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());
}
/*
* 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_
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> ...
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.
/*
* 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;
}
/*
* 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_
此差异已折叠。
# 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
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>
{{{
}}}
###############################################################################
此差异已折叠。
# 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
/*
* 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_
/*
* 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;
}
/*
* 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_
/*
* 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));
}
/*
* 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_
/*
* 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);
}
/*
* 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_
/*
* 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;
}
}
此差异已折叠。
/*
* 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_
此差异已折叠。
/*
* 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_
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* 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;
}
}
......
/*
* 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.*;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册