summaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authordaney <daney@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-15 17:25:24 +0000
committerdaney <daney@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-15 17:25:24 +0000
commit53973c81d70dccdd1e1ca48555ddf8620c652bcd (patch)
treeecd80f4d6cba05c29ed9420459814c84387b36bf /libjava
parent1e5e88e66f071071c698ff0f323f11220e2050da (diff)
downloadgcc-53973c81d70dccdd1e1ca48555ddf8620c652bcd.tar.gz
gcc/java:
2007-02-15 David Daney <ddaney@avtrex.com> * Make-lang.in (JAVA_MANFILES): Add doc/gc-analyze.1. (java.maintainer-clean):Add gc-analyze.1. (.INTERMEDIATE): Add gc-analyze.pod. (gc-analyze.pod): New rule. (java.install-man): Install gc-analyze.1 * gcj.texi: Add new section for the gc-analyze program. libjava: 2007-02-15 Johannes Schmidt <jschmidt@avtrex.com> David Daney <ddaney@avtrex.com> * configure.ac: Create vm-tools-packages file. Add gnu/gcj/tools/gc_analyze to standard.omit and vm-tools-packages. Check for /proc/self/maps. * Makefile.am (bin_PROGRAMS): Added gc-analyze. (gc_analyze_SOURCES): New. (gc_analyze_LDFLAGS): New. (gc_analyze_LINK): New. (gc_analyze_LDADD): New. (gc_analyze_DEPENDENCIES): New. (nat_source_files): Add gnu/gcj/util/natGCInfo.cc. * Makefile.in: Regenerated. * configure: Regenerated. * include/config.h.in: Regenerated. * sources.am: Regenerated. * scripts/makemake.tcl: Don't include gc-analyze classes in libgcj. * gnu/gcj/tools/gc_analyze/SymbolLookup.java: New. * gnu/gcj/tools/gc_analyze/ObjectMap.java: New. * gnu/gcj/tools/gc_analyze/MemoryMap.java: New. * gnu/gcj/tools/gc_analyze/SymbolTable.java: New. * gnu/gcj/tools/gc_analyze/BlockMap.java: New. * gnu/gcj/tools/gc_analyze/BytePtr.java: New. * gnu/gcj/tools/gc_analyze/ItemList.java: New. * gnu/gcj/tools/gc_analyze/ToolPrefix.java: New. * gnu/gcj/tools/gc_analyze/MemoryAnalyze.java: New. * gnu/gcj/util/GCInfo.java: New. * gnu/gcj/util/GCInfo.h: New. * gnu/gcj/util/natGCInfo.cc: New. * gnu/gcj/util/UtilPermission.java: New. * gnu/gcj/util/UtilPermission.h: New. * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolTable.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BytePtr.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ItemList.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ToolPrefix.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolLookup.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap.class: New. * classpath/lib/gnu/gcj/util/GCInfo.class: New. * classpath/lib/gnu/gcj/util/UtilPermission.class: New. libjava/classpath: 2007-02-15 David Daney <ddaney@avtrex.com> * tools/Makefile.am (TOOLS_ZIP): Add classes from vm-tools-packages. * tools/Makefile.in: Regenerated. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122007 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog56
-rw-r--r--libjava/Makefile.am17
-rw-r--r--libjava/Makefile.in54
-rw-r--r--libjava/classpath/ChangeLog.gcj5
-rw-r--r--libjava/classpath/lib/gnu/gcj/util/GCInfo.classbin0 -> 1043 bytes
-rw-r--r--libjava/classpath/lib/gnu/gcj/util/UtilPermission.classbin0 -> 367 bytes
-rwxr-xr-xlibjava/classpath/tools/Makefile.am11
-rw-r--r--libjava/classpath/tools/Makefile.in11
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.classbin0 -> 612 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.classbin0 -> 1004 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap.classbin0 -> 5408 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BytePtr.classbin0 -> 2466 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ItemList.classbin0 -> 3358 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.classbin0 -> 510 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.classbin0 -> 1109 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.classbin0 -> 1109 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.classbin0 -> 1073 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.classbin0 -> 1086 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.classbin0 -> 2636 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.classbin0 -> 1269 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze.classbin0 -> 10627 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$Range.classbin0 -> 714 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.classbin0 -> 1064 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap.classbin0 -> 7398 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.classbin0 -> 894 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap.classbin0 -> 4105 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolLookup.classbin0 -> 2485 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolTable.classbin0 -> 5725 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ToolPrefix.classbin0 -> 1051 bytes
-rwxr-xr-xlibjava/configure192
-rw-r--r--libjava/configure.ac10
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/BlockMap.java218
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/BytePtr.java115
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/ItemList.java72
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java458
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java359
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/ObjectMap.java140
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java112
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java198
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/ToolPrefix.java45
-rw-r--r--libjava/gnu/gcj/util/GCInfo.h45
-rw-r--r--libjava/gnu/gcj/util/GCInfo.java79
-rw-r--r--libjava/gnu/gcj/util/UtilPermission.h32
-rw-r--r--libjava/gnu/gcj/util/UtilPermission.java20
-rw-r--r--libjava/gnu/gcj/util/natGCInfo.cc454
-rw-r--r--libjava/include/config.h.in6
-rwxr-xr-xlibjava/scripts/makemake.tcl1
-rw-r--r--libjava/sources.am4
48 files changed, 2680 insertions, 34 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 6eeacf03ce4..9d4406f32fe 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,59 @@
+2007-02-15 Johannes Schmidt <jschmidt@avtrex.com>
+ David Daney <ddaney@avtrex.com>
+
+ * configure.ac: Create vm-tools-packages file. Add
+ gnu/gcj/tools/gc_analyze to standard.omit and vm-tools-packages.
+ Check for /proc/self/maps.
+ * Makefile.am (bin_PROGRAMS): Added gc-analyze.
+ (gc_analyze_SOURCES): New.
+ (gc_analyze_LDFLAGS): New.
+ (gc_analyze_LINK): New.
+ (gc_analyze_LDADD): New.
+ (gc_analyze_DEPENDENCIES): New.
+ (nat_source_files): Add gnu/gcj/util/natGCInfo.cc.
+ * Makefile.in: Regenerated.
+ * configure: Regenerated.
+ * include/config.h.in: Regenerated.
+ * sources.am: Regenerated.
+ * scripts/makemake.tcl: Don't include gc-analyze classes in libgcj.
+ * gnu/gcj/tools/gc_analyze/SymbolLookup.java: New.
+ * gnu/gcj/tools/gc_analyze/ObjectMap.java: New.
+ * gnu/gcj/tools/gc_analyze/MemoryMap.java: New.
+ * gnu/gcj/tools/gc_analyze/SymbolTable.java: New.
+ * gnu/gcj/tools/gc_analyze/BlockMap.java: New.
+ * gnu/gcj/tools/gc_analyze/BytePtr.java: New.
+ * gnu/gcj/tools/gc_analyze/ItemList.java: New.
+ * gnu/gcj/tools/gc_analyze/ToolPrefix.java: New.
+ * gnu/gcj/tools/gc_analyze/MemoryAnalyze.java: New.
+ * gnu/gcj/util/GCInfo.java: New.
+ * gnu/gcj/util/GCInfo.h: New.
+ * gnu/gcj/util/natGCInfo.cc: New.
+ * gnu/gcj/util/UtilPermission.java: New.
+ * gnu/gcj/util/UtilPermission.h: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolTable.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/BytePtr.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/ItemList.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/ToolPrefix.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolLookup.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap.class: New.
+ * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap.class: New.
+ * classpath/lib/gnu/gcj/util/GCInfo.class: New.
+ * classpath/lib/gnu/gcj/util/UtilPermission.class: New.
+
2007-02-15 David Daney <ddaney@avtrex.com>
* gnu/java/net/PlainSocketImpl.h: Regenerate.
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index 9841f60c4af..7c700e10929 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -73,7 +73,7 @@ db_pathtail = gcj-$(gcc_version)/$(db_name)
if NATIVE
bin_PROGRAMS = jv-convert gij grmic grmiregistry gcj-dbtool \
gappletviewer gjarsigner gkeytool gjar gjavah gnative2ascii \
- gorbd grmid gserialver gtnameserv
+ gorbd grmid gserialver gtnameserv gc-analyze
## It is convenient to actually build and install the default database
## when gcj-dbtool is available.
@@ -647,6 +647,20 @@ gcj_dbtool_LDADD = gnu/gcj/tools/gcj_dbtool.lo -L$(here)/.libs libgcj.la
## linking this program.
gcj_dbtool_DEPENDENCIES = gnu/gcj/tools/gcj_dbtool.lo libgcj.la libgcj.spec
+gc_analyze_SOURCES =
+
+## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'. We
+## need this because we are explicitly using libtool to link using the
+## `.la' file.
+gc_analyze_LDFLAGS = --main=gnu.gcj.tools.gc_analyze.MemoryAnalyze \
+ -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
+gc_analyze_LINK = $(GCJLINK)
+## See jv_convert_LDADD.
+gc_analyze_LDADD = -L$(here)/.libs libgcj-tools.la libgcj.la
+## Depend on the spec file to make sure it is up to date before
+## linking this program.
+gc_analyze_DEPENDENCIES = libgcj-tools.la libgcj.la libgcj.spec
+
gij_SOURCES =
## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'. We
## need this because we are explicitly using libtool to link using the
@@ -831,6 +845,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \
gnu/gcj/runtime/natSystemClassLoader.cc \
gnu/gcj/runtime/natStringBuffer.cc \
gnu/gcj/util/natDebug.cc \
+gnu/gcj/util/natGCInfo.cc \
gnu/java/lang/natMainThread.cc \
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.cc \
gnu/java/lang/management/natVMCompilationMXBeanImpl.cc \
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index 5411f07d6cc..b7cfb00aab7 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -51,7 +51,7 @@ target_triplet = @target@
@NATIVE_TRUE@ gjar$(EXEEXT) gjavah$(EXEEXT) \
@NATIVE_TRUE@ gnative2ascii$(EXEEXT) gorbd$(EXEEXT) \
@NATIVE_TRUE@ grmid$(EXEEXT) gserialver$(EXEEXT) \
-@NATIVE_TRUE@ gtnameserv$(EXEEXT)
+@NATIVE_TRUE@ gtnameserv$(EXEEXT) gc-analyze$(EXEEXT)
@BUILD_ECJ1_TRUE@libexecsub_PROGRAMS = ecjx$(EXEEXT)
@ANONVERSCRIPT_TRUE@am__append_5 = -Wl,--version-script=$(srcdir)/libgcj.ver
@USING_GCC_TRUE@am__append_6 = $(WARNINGS)
@@ -305,7 +305,7 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc jvmti.cc exception.cc \
gnu/gcj/runtime/natSharedLibLoader.cc \
gnu/gcj/runtime/natSystemClassLoader.cc \
gnu/gcj/runtime/natStringBuffer.cc gnu/gcj/util/natDebug.cc \
- gnu/java/lang/natMainThread.cc \
+ gnu/gcj/util/natGCInfo.cc gnu/java/lang/natMainThread.cc \
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.cc \
gnu/java/lang/management/natVMCompilationMXBeanImpl.cc \
gnu/java/lang/management/natVMGarbageCollectorMXBeanImpl.cc \
@@ -368,7 +368,7 @@ am__objects_2 = gnu/classpath/jdwp/natVMFrame.lo \
gnu/gcj/runtime/natSharedLibLoader.lo \
gnu/gcj/runtime/natSystemClassLoader.lo \
gnu/gcj/runtime/natStringBuffer.lo gnu/gcj/util/natDebug.lo \
- gnu/java/lang/natMainThread.lo \
+ gnu/gcj/util/natGCInfo.lo gnu/java/lang/natMainThread.lo \
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.lo \
gnu/java/lang/management/natVMCompilationMXBeanImpl.lo \
gnu/java/lang/management/natVMGarbageCollectorMXBeanImpl.lo \
@@ -438,6 +438,8 @@ am_ecjx_OBJECTS =
ecjx_OBJECTS = $(am_ecjx_OBJECTS)
am_gappletviewer_OBJECTS =
gappletviewer_OBJECTS = $(am_gappletviewer_OBJECTS)
+am_gc_analyze_OBJECTS =
+gc_analyze_OBJECTS = $(am_gc_analyze_OBJECTS)
am_gcj_dbtool_OBJECTS = gnu/gcj/tools/gcj_dbtool/natMain.$(OBJEXT)
gcj_dbtool_OBJECTS = $(am_gcj_dbtool_OBJECTS)
am__gen_from_JIS_SOURCES_DIST = gnu/gcj/convert/gen-from-JIS.c \
@@ -501,23 +503,23 @@ SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) $(libgcj_tools_la_SOURCES) \
$(libgcj_la_SOURCES) $(EXTRA_libgcj_la_SOURCES) \
$(libgcj_bc_la_SOURCES) $(libgij_la_SOURCES) \
$(libjvm_la_SOURCES) $(ecjx_SOURCES) $(gappletviewer_SOURCES) \
- $(gcj_dbtool_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) \
- $(gjar_SOURCES) $(gjarsigner_SOURCES) $(gjavah_SOURCES) \
- $(gkeytool_SOURCES) $(gnative2ascii_SOURCES) $(gorbd_SOURCES) \
- $(grmic_SOURCES) $(grmid_SOURCES) $(grmiregistry_SOURCES) \
- $(gserialver_SOURCES) $(gtnameserv_SOURCES) \
- $(jv_convert_SOURCES)
+ $(gc_analyze_SOURCES) $(gcj_dbtool_SOURCES) \
+ $(gen_from_JIS_SOURCES) $(gij_SOURCES) $(gjar_SOURCES) \
+ $(gjarsigner_SOURCES) $(gjavah_SOURCES) $(gkeytool_SOURCES) \
+ $(gnative2ascii_SOURCES) $(gorbd_SOURCES) $(grmic_SOURCES) \
+ $(grmid_SOURCES) $(grmiregistry_SOURCES) $(gserialver_SOURCES) \
+ $(gtnameserv_SOURCES) $(jv_convert_SOURCES)
DIST_SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) \
$(libgcj_tools_la_SOURCES) $(am__libgcj_la_SOURCES_DIST) \
$(EXTRA_libgcj_la_SOURCES) $(libgcj_bc_la_SOURCES) \
$(libgij_la_SOURCES) $(libjvm_la_SOURCES) $(ecjx_SOURCES) \
- $(gappletviewer_SOURCES) $(gcj_dbtool_SOURCES) \
- $(am__gen_from_JIS_SOURCES_DIST) $(gij_SOURCES) \
- $(gjar_SOURCES) $(gjarsigner_SOURCES) $(gjavah_SOURCES) \
- $(gkeytool_SOURCES) $(gnative2ascii_SOURCES) $(gorbd_SOURCES) \
- $(grmic_SOURCES) $(grmid_SOURCES) $(grmiregistry_SOURCES) \
- $(gserialver_SOURCES) $(gtnameserv_SOURCES) \
- $(jv_convert_SOURCES)
+ $(gappletviewer_SOURCES) $(gc_analyze_SOURCES) \
+ $(gcj_dbtool_SOURCES) $(am__gen_from_JIS_SOURCES_DIST) \
+ $(gij_SOURCES) $(gjar_SOURCES) $(gjarsigner_SOURCES) \
+ $(gjavah_SOURCES) $(gkeytool_SOURCES) $(gnative2ascii_SOURCES) \
+ $(gorbd_SOURCES) $(grmic_SOURCES) $(grmid_SOURCES) \
+ $(grmiregistry_SOURCES) $(gserialver_SOURCES) \
+ $(gtnameserv_SOURCES) $(jv_convert_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-exec-recursive install-info-recursive \
@@ -1344,7 +1346,9 @@ gnu/gcj/tools/gcj_dbtool/Main.java
gnu_gcj_tools_gcj_dbtool_header_files = $(patsubst %.java,%.h,$(gnu_gcj_tools_gcj_dbtool_source_files))
gnu_gcj_util_source_files = \
-gnu/gcj/util/Debug.java
+gnu/gcj/util/Debug.java \
+gnu/gcj/util/GCInfo.java \
+gnu/gcj/util/UtilPermission.java
gnu_gcj_util_header_files = $(patsubst %.java,%.h,$(gnu_gcj_util_source_files))
gnu_gcj_xlib_source_files = \
@@ -7818,6 +7822,13 @@ gcj_dbtool_LDFLAGS = --main=gnu.gcj.tools.gcj_dbtool.Main \
gcj_dbtool_LINK = $(GCJLINK)
gcj_dbtool_LDADD = gnu/gcj/tools/gcj_dbtool.lo -L$(here)/.libs libgcj.la
gcj_dbtool_DEPENDENCIES = gnu/gcj/tools/gcj_dbtool.lo libgcj.la libgcj.spec
+gc_analyze_SOURCES =
+gc_analyze_LDFLAGS = --main=gnu.gcj.tools.gc_analyze.MemoryAnalyze \
+ -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
+
+gc_analyze_LINK = $(GCJLINK)
+gc_analyze_LDADD = -L$(here)/.libs libgcj-tools.la libgcj.la
+gc_analyze_DEPENDENCIES = libgcj-tools.la libgcj.la libgcj.spec
gij_SOURCES =
gij_LDFLAGS = -rpath $(libdir)/gcj-$(gcc_version) -rpath $(toolexeclibdir) \
-shared-libgcc $(THREADLDFLAGS)
@@ -7947,6 +7958,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \
gnu/gcj/runtime/natSystemClassLoader.cc \
gnu/gcj/runtime/natStringBuffer.cc \
gnu/gcj/util/natDebug.cc \
+gnu/gcj/util/natGCInfo.cc \
gnu/java/lang/natMainThread.cc \
gnu/java/lang/management/natVMClassLoadingMXBeanImpl.cc \
gnu/java/lang/management/natVMCompilationMXBeanImpl.cc \
@@ -8360,6 +8372,8 @@ gnu/gcj/util/$(DEPDIR)/$(am__dirstamp):
@: > gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
gnu/gcj/util/natDebug.lo: gnu/gcj/util/$(am__dirstamp) \
gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
+gnu/gcj/util/natGCInfo.lo: gnu/gcj/util/$(am__dirstamp) \
+ gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
gnu/java/lang/$(am__dirstamp):
@$(mkdir_p) gnu/java/lang
@: > gnu/java/lang/$(am__dirstamp)
@@ -8694,6 +8708,9 @@ ecjx$(EXEEXT): $(ecjx_OBJECTS) $(ecjx_DEPENDENCIES)
gappletviewer$(EXEEXT): $(gappletviewer_OBJECTS) $(gappletviewer_DEPENDENCIES)
@rm -f gappletviewer$(EXEEXT)
$(gappletviewer_LINK) $(gappletviewer_LDFLAGS) $(gappletviewer_OBJECTS) $(gappletviewer_LDADD) $(LIBS)
+gc-analyze$(EXEEXT): $(gc_analyze_OBJECTS) $(gc_analyze_DEPENDENCIES)
+ @rm -f gc-analyze$(EXEEXT)
+ $(gc_analyze_LINK) $(gc_analyze_LDFLAGS) $(gc_analyze_OBJECTS) $(gc_analyze_LDADD) $(LIBS)
gnu/gcj/tools/gcj_dbtool/$(am__dirstamp):
@$(mkdir_p) gnu/gcj/tools/gcj_dbtool
@: > gnu/gcj/tools/gcj_dbtool/$(am__dirstamp)
@@ -8826,6 +8843,8 @@ mostlyclean-compile:
-rm -f gnu/gcj/tools/gcj_dbtool/natMain.$(OBJEXT)
-rm -f gnu/gcj/util/natDebug.$(OBJEXT)
-rm -f gnu/gcj/util/natDebug.lo
+ -rm -f gnu/gcj/util/natGCInfo.$(OBJEXT)
+ -rm -f gnu/gcj/util/natGCInfo.lo
-rm -f gnu/gcj/xlib/lib_gnu_awt_xlib_la-natClip.$(OBJEXT)
-rm -f gnu/gcj/xlib/lib_gnu_awt_xlib_la-natClip.lo
-rm -f gnu/gcj/xlib/lib_gnu_awt_xlib_la-natColormap.$(OBJEXT)
@@ -9035,6 +9054,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natSystemClassLoader.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/natMain.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/natDebug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/natGCInfo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/lib_gnu_awt_xlib_la-natClip.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/lib_gnu_awt_xlib_la-natColormap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/lib_gnu_awt_xlib_la-natDisplay.Plo@am__quote@
diff --git a/libjava/classpath/ChangeLog.gcj b/libjava/classpath/ChangeLog.gcj
index e4a71a829a5..c147ab6a7a8 100644
--- a/libjava/classpath/ChangeLog.gcj
+++ b/libjava/classpath/ChangeLog.gcj
@@ -1,3 +1,8 @@
+2007-02-15 David Daney <ddaney@avtrex.com>
+
+ * tools/Makefile.am (TOOLS_ZIP): Add classes from vm-tools-packages.
+ * tools/Makefile.in: Regenerated.
+
2007-02-15 Gary Benson <gbenson@redhat.com>
* javax/management/AttributeList.java: Updated.
diff --git a/libjava/classpath/lib/gnu/gcj/util/GCInfo.class b/libjava/classpath/lib/gnu/gcj/util/GCInfo.class
new file mode 100644
index 00000000000..e07bb933213
--- /dev/null
+++ b/libjava/classpath/lib/gnu/gcj/util/GCInfo.class
Binary files differ
diff --git a/libjava/classpath/lib/gnu/gcj/util/UtilPermission.class b/libjava/classpath/lib/gnu/gcj/util/UtilPermission.class
new file mode 100644
index 00000000000..f7d9dadb63e
--- /dev/null
+++ b/libjava/classpath/lib/gnu/gcj/util/UtilPermission.class
Binary files differ
diff --git a/libjava/classpath/tools/Makefile.am b/libjava/classpath/tools/Makefile.am
index f47191cfdbb..8ba984bb314 100755
--- a/libjava/classpath/tools/Makefile.am
+++ b/libjava/classpath/tools/Makefile.am
@@ -155,12 +155,19 @@ $(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
## mkdir classes asm
find $(srcdir)/external/asm -name '*.java' -print > asm.lst
find $(srcdir)/gnu/classpath/tools -name '*.java' -print > classes.lst
- cat classes.lst asm.lst > all-classes.lst
+ if [ -f $(top_builddir)/../vm-tools-packages ]; then \
+ for pkg in `cat $(top_builddir)/../vm-tools-packages`; do \
+ $(FIND) $(top_srcdir)/../$$pkg -follow -name '*.java' -print >> vm-tools.lst; \
+ done \
+ else \
+ echo -n > vm-tools.lst; \
+ fi
+ cat classes.lst asm.lst vm-tools.lst > all-classes.lst
if JAVA_MAINTAINER_MODE
## Compile ASM separately as it is latin-1 encoded.
AC=`echo $(JCOMPILER) | sed -e 's/UTF-8/ISO-8859-1/g'`; \
$$AC -g -w -d $(srcdir)/asm @asm.lst
- $(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst
+ $(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst @vm-tools.lst
## Copy over tools resource files.
@list=`cd $(top_srcdir)/resource && find gnu/classpath/tools -name \*.properties -print`; \
for p in $$list; do \
diff --git a/libjava/classpath/tools/Makefile.in b/libjava/classpath/tools/Makefile.in
index cb0525f49fd..960dc6e0035 100644
--- a/libjava/classpath/tools/Makefile.in
+++ b/libjava/classpath/tools/Makefile.in
@@ -1079,10 +1079,17 @@ dist-hook:
$(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
find $(srcdir)/external/asm -name '*.java' -print > asm.lst
find $(srcdir)/gnu/classpath/tools -name '*.java' -print > classes.lst
- cat classes.lst asm.lst > all-classes.lst
+ if [ -f $(top_builddir)/../vm-tools-packages ]; then \
+ for pkg in `cat $(top_builddir)/../vm-tools-packages`; do \
+ $(FIND) $(top_srcdir)/../$$pkg -follow -name '*.java' -print >> vm-tools.lst; \
+ done \
+ else \
+ echo -n > vm-tools.lst; \
+ fi
+ cat classes.lst asm.lst vm-tools.lst > all-classes.lst
@JAVA_MAINTAINER_MODE_TRUE@ AC=`echo $(JCOMPILER) | sed -e 's/UTF-8/ISO-8859-1/g'`; \
@JAVA_MAINTAINER_MODE_TRUE@ $$AC -g -w -d $(srcdir)/asm @asm.lst
-@JAVA_MAINTAINER_MODE_TRUE@ $(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst
+@JAVA_MAINTAINER_MODE_TRUE@ $(JCOMPILER) -g -w -d $(srcdir)/classes @classes.lst @vm-tools.lst
@JAVA_MAINTAINER_MODE_TRUE@ @list=`cd $(top_srcdir)/resource && find gnu/classpath/tools -name \*.properties -print`; \
@JAVA_MAINTAINER_MODE_TRUE@ for p in $$list; do \
@JAVA_MAINTAINER_MODE_TRUE@ dirname=classes/`dirname $$p`; \
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class
new file mode 100644
index 00000000000..59094b9c9b8
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class
new file mode 100644
index 00000000000..4a9c99a43ca
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap.class
new file mode 100644
index 00000000000..b29214c0290
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BlockMap.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BytePtr.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BytePtr.class
new file mode 100644
index 00000000000..c5a812e90bf
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/BytePtr.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ItemList.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ItemList.class
new file mode 100644
index 00000000000..c1098e5d87d
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ItemList.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class
new file mode 100644
index 00000000000..687e94d388c
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class
new file mode 100644
index 00000000000..9fbf1a59d74
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class
new file mode 100644
index 00000000000..5fa44be1b86
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class
new file mode 100644
index 00000000000..2c91530397e
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class
new file mode 100644
index 00000000000..125ac727990
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class
new file mode 100644
index 00000000000..9a12fb87991
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class
new file mode 100644
index 00000000000..238c2583b71
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class
new file mode 100644
index 00000000000..ce5c998e164
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class
new file mode 100644
index 00000000000..72d9ee0a437
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class
new file mode 100644
index 00000000000..4355000f58d
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap.class
new file mode 100644
index 00000000000..2646141081a
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/MemoryMap.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class
new file mode 100644
index 00000000000..4a27d3fd48f
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap.class
new file mode 100644
index 00000000000..f7fc0df7ae8
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ObjectMap.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolLookup.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolLookup.class
new file mode 100644
index 00000000000..7099959e27c
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolLookup.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolTable.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolTable.class
new file mode 100644
index 00000000000..49e0bbb8bfc
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/SymbolTable.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ToolPrefix.class b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ToolPrefix.class
new file mode 100644
index 00000000000..2224a23bb5d
--- /dev/null
+++ b/libjava/classpath/tools/classes/gnu/gcj/tools/gc_analyze/ToolPrefix.class
Binary files differ
diff --git a/libjava/configure b/libjava/configure
index da281d1b5aa..04449d535e1 100755
--- a/libjava/configure
+++ b/libjava/configure
@@ -5087,6 +5087,12 @@ if test "$use_x_awt" != yes; then
echo gnu/java/awt/peer/x >> standard.omit
fi
+# Tools that need to be compiled against classpath's tools classes
+for package in gnu/gcj/tools/gc_analyze ; do
+ echo $package >> standard.omit
+ echo $package >> vm-tools-packages
+done
+
if test -z "${with_multisubdir}"; then
builddotdot=.
else
@@ -6024,7 +6030,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
case $host in
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 6027 "configure"' > conftest.$ac_ext
+ echo '#line 6033 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7066,7 +7072,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then
:
else
cat > conftest.$ac_ext << EOF
-#line 7069 "configure"
+#line 7075 "configure"
struct S { ~S(); };
void bar();
void foo()
@@ -7819,7 +7825,7 @@ ac_x_header_dirs='
/usr/openwin/share/include'
if test "$ac_x_includes" = no; then
- # Guess where to find include files, by looking for Intrinsic.h.
+ # Guess where to find include files, by looking for Xlib.h.
# First, try using that file with no special directory specified.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
@@ -7827,7 +7833,7 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <X11/Intrinsic.h>
+#include <X11/Xlib.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
@@ -7854,7 +7860,7 @@ else
sed 's/^/| /' conftest.$ac_ext >&5
for ac_dir in $ac_x_header_dirs; do
- if test -r "$ac_dir/X11/Intrinsic.h"; then
+ if test -r "$ac_dir/X11/Xlib.h"; then
ac_x_includes=$ac_dir
break
fi
@@ -7868,7 +7874,7 @@ if test "$ac_x_libraries" = no; then
# See if we find them without any special options.
# Don't add to $LIBS permanently.
ac_save_LIBS=$LIBS
- LIBS="-lXt $LIBS"
+ LIBS="-lX11 $LIBS"
if test x$gcc_no_link = xyes; then
{ { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
@@ -7880,11 +7886,11 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <X11/Intrinsic.h>
+#include <X11/Xlib.h>
int
main ()
{
-XtMalloc (0)
+XrmInitialize ()
;
return 0;
}
@@ -10397,6 +10403,37 @@ _ACEOF
fi
+ echo "$as_me:$LINENO: checking for /proc/self/maps" >&5
+echo $ECHO_N "checking for /proc/self/maps... $ECHO_C" >&6
+if test "${ac_cv_file__proc_self_maps+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ test "$cross_compiling" = yes &&
+ { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+ { (exit 1); exit 1; }; }
+if test -r "/proc/self/maps"; then
+ ac_cv_file__proc_self_maps=yes
+else
+ ac_cv_file__proc_self_maps=no
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_file__proc_self_maps" >&5
+echo "${ECHO_T}$ac_cv_file__proc_self_maps" >&6
+if test $ac_cv_file__proc_self_maps = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__PROC_SELF_MAPS 1
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PROC_SELF_MAPS 1
+_ACEOF
+
+fi
+
else
case $host in
*-linux*)
@@ -10405,6 +10442,11 @@ cat >>confdefs.h <<\_ACEOF
#define HAVE_PROC_SELF_EXE 1
_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PROC_SELF_MAPS 1
+_ACEOF
+
;;
esac
fi
@@ -16815,7 +16857,7 @@ if test "${have_tls+set}" = set; then
else
if test "$cross_compiling" = yes; then
- if test x$gcc_no_link = xyes; then
+ if test x$gcc_no_link = xyes; then
{ { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
{ (exit 1); exit 1; }; }
@@ -16855,6 +16897,7 @@ fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
+
else
cat >conftest.$ac_ext <<_ACEOF
__thread int a; int b; int main() { return a = b; }
@@ -16870,7 +16913,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- save_LDFLAGS="$LDFLAGS"
+ chktls_save_LDFLAGS="$LDFLAGS"
LDFLAGS="-static $LDFLAGS"
if test x$gcc_no_link = xyes; then
{ { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
@@ -16942,7 +16985,134 @@ have_tls=yes
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
- LDFLAGS="$save_LDFLAGS"
+ LDFLAGS="$chktls_save_LDFLAGS"
+ if test $have_tls = yes; then
+ chktls_save_CFLAGS="$CFLAGS"
+ thread_CFLAGS=failed
+ for flag in '' '-pthread' '-lpthread'; do
+ CFLAGS="$flag $chktls_save_CFLAGS"
+ if test x$gcc_no_link = xyes; then
+ { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
+echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <pthread.h>
+ void *g(void *d) { return NULL; }
+int
+main ()
+{
+pthread_t t; pthread_create(&t,NULL,g,NULL);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ thread_CFLAGS="$flag"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ if test "X$thread_CFLAGS" != Xfailed; then
+ break
+ fi
+ done
+ CFLAGS="$chktls_save_CFLAGS"
+ if test "X$thread_CFLAGS" != Xfailed; then
+ CFLAGS="$thread_CFLAGS $chktls_save_CFLAGS"
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <pthread.h>
+ __thread int a;
+ static int *a_in_other_thread;
+ static void *
+ thread_func (void *arg)
+ {
+ a_in_other_thread = &a;
+ return (void *)0;
+ }
+int
+main ()
+{
+pthread_t thread;
+ void *thread_retval;
+ int *a_in_main_thread;
+ if (pthread_create (&thread, (pthread_attr_t *)0,
+ thread_func, (void *)0))
+ return 0;
+ a_in_main_thread = &a;
+ if (pthread_join (thread, &thread_retval))
+ return 0;
+ return (a_in_other_thread == a_in_main_thread);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ have_tls=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+have_tls=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+ CFLAGS="$chktls_save_CFLAGS"
+ fi
+ fi
else
echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
diff --git a/libjava/configure.ac b/libjava/configure.ac
index 0ee1ee00c77..a8e536f15d3 100644
--- a/libjava/configure.ac
+++ b/libjava/configure.ac
@@ -295,6 +295,12 @@ if test "$use_x_awt" != yes; then
echo gnu/java/awt/peer/x >> standard.omit
fi
+# Tools that need to be compiled against classpath's tools classes
+for package in gnu/gcj/tools/gc_analyze ; do
+ echo $package >> standard.omit
+ echo $package >> vm-tools-packages
+done
+
if test -z "${with_multisubdir}"; then
builddotdot=.
else
@@ -1012,10 +1018,14 @@ else
if test x"$cross_compiling" = x"no"; then
AC_CHECK_FILES(/proc/self/exe, [
AC_DEFINE(HAVE_PROC_SELF_EXE, 1, [Define if you have /proc/self/exe])])
+ AC_CHECK_FILES(/proc/self/maps, [
+ AC_DEFINE(HAVE_PROC_SELF_MAPS, 1,
+ [Define if you have /proc/self/maps])])
else
case $host in
*-linux*)
AC_DEFINE(HAVE_PROC_SELF_EXE, 1, [Define if you have /proc/self/exe])
+ AC_DEFINE(HAVE_PROC_SELF_MAPS, 1, [Define if you have /proc/self/maps])
;;
esac
fi
diff --git a/libjava/gnu/gcj/tools/gc_analyze/BlockMap.java b/libjava/gnu/gcj/tools/gc_analyze/BlockMap.java
new file mode 100644
index 00000000000..6e7adae20dd
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/BlockMap.java
@@ -0,0 +1,218 @@
+/* BlockMap.java -- Container for information on GC maintained memory blocks.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.TreeMap;
+
+class BlockMap
+{
+ static final int HBLKSIZE = 4096;
+
+ class SizeKind implements Comparable<SizeKind>
+ {
+ int size;
+ int kind;
+
+ public SizeKind(int size, int kind)
+ {
+ this.size = size;
+ this.kind = kind;
+ }
+
+ public int compareTo(SizeKind b)
+ {
+ if (this.size != b.size)
+ return this.size - b.size;
+ return this.kind - b.kind;
+ }
+ }
+
+ class PtrMarks
+ {
+ long ptr;
+ int marks;
+
+ public PtrMarks(long ptr, int marks)
+ {
+ this.ptr = ptr;
+ this.marks = marks;
+ }
+ }
+
+ private TreeMap<SizeKind, ArrayList<PtrMarks>> map =
+ new TreeMap<SizeKind, ArrayList<PtrMarks>>();
+
+ public BlockMap(BufferedReader reader) throws IOException
+ {
+ for (;;)
+ {
+ String s = reader.readLine();
+ if (s == null)
+ break;
+ if (s.charAt(0) == '#')
+ continue;
+ if (s.indexOf("Begin block map") >= 0)
+ {
+ for (;;)
+ {
+ s = reader.readLine();
+ if (s.charAt(0) == '#')
+ continue;
+ if (s.indexOf("End block map") >= 0)
+ return;
+ String[] items = s.split(",");
+ long ptr = 0;
+ int kind = 0, size = 0, marks = 0;
+ for (int i=0; i<items.length; i++)
+ {
+ String[] x = items[i].split(" ");
+ String last = x[x.length - 1];
+ switch (i)
+ {
+ case 0:
+ ptr = MemoryMap.parseHexLong(last.substring(2));
+ break;
+ case 1:
+ kind = Integer.parseInt(last);
+ break;
+ case 2:
+ size = Integer.parseInt(last);
+ break;
+ case 3:
+ marks = Integer.parseInt(last);
+ break;
+ }
+ }
+ SizeKind sk = new SizeKind(size, kind);
+ ArrayList<PtrMarks> m = map.get(sk);
+ if (m == null)
+ {
+ m = new ArrayList<PtrMarks>();
+ map.put(sk, m);
+ }
+ PtrMarks pm = new PtrMarks(ptr, marks);
+ m.add(pm);
+ } // inner loop
+ } // started inner loop
+ } // outer loop - finding begin
+ } // memoryMap
+
+ public void dump()
+ {
+ System.out.println();
+ System.out.println();
+ System.out.println("*** Used Blocks ***\n");
+ System.out.println();
+ System.out.println(" Size Kind Blocks Used Free Wasted");
+ System.out.println("------- ------------- ------- ---------- ---------- -------");
+
+ int total_blocks = 0, total_used = 0, total_free = 0, total_wasted = 0;
+
+ for (Map.Entry<SizeKind, ArrayList<PtrMarks>> me : map.entrySet())
+ {
+ SizeKind sk = me.getKey();
+
+ System.out.println(MemoryAnalyze.format(sk.size, 7) + " "
+ + MemoryAnalyze.kindToName(sk.kind));
+
+ int sub_blocks = 0, sub_used = 0, sub_free = 0, sub_wasted = 0;
+ int sub_count = 0;
+
+ ArrayList<PtrMarks> v = me.getValue();
+
+ for (PtrMarks pm : v)
+ {
+ int bytes = sk.size;
+ int blocks = (sk.size + HBLKSIZE - 1) / HBLKSIZE;
+ int used;
+ int free;
+ int wasted;
+
+ if (bytes < HBLKSIZE)
+ {
+ used = bytes * pm.marks;
+ free = bytes * (HBLKSIZE / bytes - pm.marks);
+ wasted = HBLKSIZE - HBLKSIZE / bytes * bytes;
+ }
+ else
+ {
+ if (pm.marks != 0)
+ {
+ used = bytes;
+ free = 0;
+ wasted = (bytes + HBLKSIZE - 1)
+ / HBLKSIZE * HBLKSIZE - used;
+ }
+ else
+ {
+ used = 0;
+ free = bytes;
+ wasted = 0;
+ }
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(blocks, 5));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(used, 9));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(free, 9));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(wasted, 9));
+ System.out.println(sb);
+
+ sub_blocks += blocks;
+ sub_used += used;
+ sub_free += free;
+ sub_wasted += wasted;
+ sub_count++;
+
+ total_blocks += blocks;
+ total_used += used;
+ total_free += free;
+ total_wasted += wasted;
+ } // blocks with size/kind
+ if (sub_count > 1)
+ {
+ System.out.println(
+ " ------- ---------- ---------- -------");
+ StringBuilder sb = new StringBuilder();
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(sub_blocks, 5));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(sub_used, 9));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(sub_free, 9));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(sub_wasted, 9));
+ System.out.println(sb);
+ }
+ } // size/kind
+
+ System.out.println("------- ------------- ------- ---------- ---------- -------");
+ StringBuilder sb = new StringBuilder();
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(total_blocks, 5));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(total_used, 9));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(total_free, 9));
+ sb.append(" ");
+ sb.append(MemoryAnalyze.format(total_wasted, 9));
+ System.out.println(sb);
+ System.out.println("Total bytes = "
+ + MemoryAnalyze.format(total_blocks * HBLKSIZE, 10));
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/BytePtr.java b/libjava/gnu/gcj/tools/gc_analyze/BytePtr.java
new file mode 100644
index 00000000000..4afceeeec8a
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/BytePtr.java
@@ -0,0 +1,115 @@
+/* BytePtr.java -- Container for bytes from a memory image.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.nio.ByteBuffer;
+
+public class BytePtr
+{
+ ByteBuffer content;
+ int wordSize;
+
+ BytePtr(ByteBuffer b, int ws)
+ {
+ content = b;
+ wordSize = ws;
+ }
+
+ public int getsize()
+ {
+ return content.limit();
+ }
+
+ public int getByte(int offset)
+ {
+ return content.get(offset);
+ }
+
+ public int getInt(int n)
+ {
+ return content.getInt(n * 4);
+ }
+
+ public int getShort(int n)
+ {
+ return content.getShort(n * 2);
+ }
+
+ public long getWord(int n)
+ {
+ if (4 == wordSize)
+ return 0xffffffffL & content.getInt(n * 4);
+ else
+ return content.getLong(n * 8);
+ }
+
+ public int intsPerWord()
+ {
+ return (4 == wordSize) ? 1 : 2;
+ }
+
+ public BytePtr getRegion(int offset, int size)
+ {
+ int oldLimit = content.limit();
+ content.position(offset);
+ content.limit(offset + size);
+ ByteBuffer n = content.slice();
+ content.position(0);
+ content.limit(oldLimit);
+
+ return new BytePtr(n, wordSize);
+ }
+
+ public void setInt(int a, int n)
+ {
+ content.putInt(a * 4, n);
+ }
+
+ public void dump()
+ {
+ // 38 5a f4 2a 50 bd 04 10 10 00 00 00 0e 00 00 00 8Z.*P...........
+ int i;
+ StringBuilder b = new StringBuilder(67);
+ for (i = 0; i < 66; i++)
+ b.append(' ');
+ b.append('\n');
+
+ i = 0;
+ do
+ {
+ for (int j = 0; j < 16; j++)
+ {
+ int k = i + j;
+
+ if (k < content.limit())
+ {
+ int v = 0xff & getByte(k);
+ // hex
+ int v1 = v/16;
+ b.setCharAt(j * 3 + 0,
+ (char)(v1 >= 10 ? 'a' - 10 + v1 : v1 + '0'));
+ v1 = v % 16;
+ b.setCharAt(j * 3 + 1,
+ (char)(v1 >= 10 ? 'a' - 10 + v1 : v1 + '0'));
+ // ascii
+ b.setCharAt(j + 50, (char)((v >= 32 && v <= 127) ? v: '.'));
+ }
+ else
+ {
+ b.setCharAt(j * 3 + 0, ' ');
+ b.setCharAt(j * 3 + 1, ' ');
+ b.setCharAt(j + 50, ' ');
+ }
+ }
+ i += 16;
+ System.out.print(b);
+ } while (i < content.limit());
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/ItemList.java b/libjava/gnu/gcj/tools/gc_analyze/ItemList.java
new file mode 100644
index 00000000000..7912bebca57
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/ItemList.java
@@ -0,0 +1,72 @@
+/* ItemList.java -- Maps all objects keyed by their addresses.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+class ItemList
+{
+ public ItemList()
+ {
+ }
+
+ private TreeMap<Long, HashMap<ObjectMap.ObjectItem, Integer>> map;
+
+ public void add(ObjectMap.ObjectItem item)
+ {
+ if (map == null)
+ map = new TreeMap<Long, HashMap<ObjectMap.ObjectItem, Integer>>();
+ Long x = new Long(item.klass);
+ HashMap<ObjectMap.ObjectItem, Integer> list = map.get(x);
+ if (list == null)
+ {
+ list = new HashMap<ObjectMap.ObjectItem, Integer>();
+ map.put(x, list);
+ }
+ Integer count = list.get(item);
+ if (count == null)
+ list.put(item, new Integer(1));
+ else
+ list.put(item, new Integer(count.intValue() + 1));
+ }
+
+ void dump(String title, SymbolLookup lookup) throws IOException
+ {
+ if (map == null)
+ return;
+ System.out.println(title);
+ for (Map.Entry<Long, HashMap<ObjectMap.ObjectItem, Integer>> me :
+ map.entrySet())
+ {
+ HashMap<ObjectMap.ObjectItem, Integer> list = me.getValue();
+ boolean first = true;
+
+ for (Map.Entry<ObjectMap.ObjectItem, Integer> me2 : list.entrySet())
+ {
+ ObjectMap.ObjectItem item = me2.getKey();
+ Integer count = me2.getValue();
+ if (first)
+ {
+ String name =
+ MemoryAnalyze.getSymbolPretty(lookup, item, false);
+ System.out.println(" " + name + ":");
+ first = false;
+ }
+ System.out.print(" 0x" + Long.toHexString(item.ptr));
+ if (count.intValue() != 1)
+ System.out.print(" * " + count);
+ System.out.println();
+ }
+ }
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java b/libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java
new file mode 100644
index 00000000000..d56a71da311
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/MemoryAnalyze.java
@@ -0,0 +1,458 @@
+/* MemoryAnalyze.java -- Analyzes a libgcj heap dump.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import gnu.classpath.tools.getopt.FileArgumentCallback;
+import gnu.classpath.tools.getopt.Option;
+import gnu.classpath.tools.getopt.OptionException;
+import gnu.classpath.tools.getopt.Parser;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+class MemoryAnalyze
+{
+ public MemoryAnalyze()
+ {
+ }
+
+ private static NumberFormat numberFormat;
+ private static boolean verbose;
+ static String format(long number, int digits)
+ {
+ if (numberFormat == null)
+ {
+ numberFormat = NumberFormat.getNumberInstance();
+ numberFormat.setGroupingUsed(true);
+ }
+ String temp = numberFormat.format(number);
+ int spaces = digits - temp.length();
+ if (spaces < 0)
+ spaces = 0;
+ return " ".substring(0,spaces) + temp;
+ }
+
+ static void sorted_report(String description,
+ int total_space,
+ ArrayList<String> list,
+ Comparator<String> comparator)
+ {
+ System.out.println("*** " + description + " ***");
+ System.out.println();
+ System.out.println(" Total Size Count Size Description");
+ System.out.println("-------------- ----- -------- -----------------------------------");
+ Collections.sort(list, comparator);
+ for (Iterator it = list.iterator(); it.hasNext(); )
+ {
+ String v = (String)it.next();
+ System.out.println(stripend(v));
+ }
+ System.out.println("-------------- ----- -------- -----------------------------------");
+ System.out.println(format(total_space, 14));
+ System.out.println();
+ System.out.println();
+ }
+
+ private static String stripend(String s)
+ {
+ int n = s.lastIndexOf(" /");
+ if (n > 0)
+ return s.substring(0,n);
+ return s;
+ }
+
+ static class SubstringComparator implements Comparator<String>
+ {
+ private int begin, end;
+ private boolean reverse;
+
+ SubstringComparator(int begin, int end, boolean reverse)
+ {
+ this.begin = begin;
+ this.end = end;
+ this.reverse = reverse;
+ }
+
+ public int compare(String s1, String s2)
+ {
+ if (end == 0)
+ s1 = s1.substring(begin);
+ else
+ s1 = s1.substring(begin, end);
+
+ if (end == 0)
+ s2 = s2.substring(begin);
+ else
+ s2 = s2.substring(begin, end);
+ int i = s1.compareTo(s2);
+ if (reverse)
+ return -i;
+ return i;
+ }
+ }
+
+ static class OptionParser extends Parser
+ {
+ int filesFound;
+
+ OptionParser()
+ {
+ super("gc-analyze",
+ "gc-analyze (" + System.getProperty("java.vm.version") + ")");
+
+ add(new Option('d',
+ "Directory containing runtime objects",
+ "directory")
+ {
+ public void parsed(String argument) throws OptionException
+ {
+ ToolPrefix.pathPrefix = argument;
+ }
+ });
+
+ add(new Option('p',
+ "Binary tool prefix, prepended to nm and readelf to "
+ + "obtain target specific versions of these commands",
+ "prefix")
+ {
+ public void parsed(String argument) throws OptionException
+ {
+ ToolPrefix.toolPrefix = argument;
+ }
+ });
+
+ add(new Option("verbose", 'v',
+ "Verbose output; requires filename.bytes")
+ {
+ public void parsed(String argument) throws OptionException
+ {
+ verbose = true;
+ }
+ });
+
+ setHeader("usage: gc-analyze [-v] [-p tool-prefix] [-d <directory>] "
+ + "filename");
+ }
+
+ protected void validate() throws OptionException
+ {
+ if (filesFound != 1)
+ throw new OptionException("Must specify exactly one filename");
+ }
+
+ public String[] parse(String[] inArgs)
+ {
+ final ArrayList<String> fileResult = new ArrayList<String>();
+ parse(inArgs, new FileArgumentCallback()
+ {
+ public void notifyFile(String fileArgument)
+ {
+ filesFound++;
+ fileResult.add(fileArgument);
+ }
+ });
+ return fileResult.toArray(new String[1]);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ class Info
+ {
+ int size;
+ int count;
+ }
+ int total_space = 0;
+
+ Parser optionParser = new OptionParser();
+
+ String rest[] = optionParser.parse(args);
+
+ String filename = rest[0];
+
+ try
+ {
+ BufferedReader reader =
+ new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+ SymbolLookup lookup = new SymbolLookup(reader, filename + ".bytes");
+ ObjectMap objectMap = new ObjectMap(reader);
+ BlockMap blockMap = new BlockMap(reader);
+ reader.close();
+
+ // add info to item(s)
+ // add item.klass
+ for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
+ {
+ ObjectMap.ObjectItem item = me.getValue();
+
+ // try to get a klass (happens with intern'ed strings...)
+ if (item.klass==0)
+ {
+ BytePtr p = lookup.getBytePtr(item.ptr, item.size);
+ if (p!=null)
+ {
+ long vtable = p.getWord(0);
+ String sym =
+ lookup.getSymbolViaVtable(vtable - 2 * lookup.memoryMap.wordSize);
+ if (sym != null)
+ {
+ item.typeName = SymbolTable.demangleVTName(sym);
+ }
+ else if (vtable != 0)
+ {
+ // get klass from vtable
+ p = lookup.getBytePtr(vtable,
+ lookup.memoryMap.wordSize);
+ if (p != null)
+ {
+ long klass = p.getWord(0);
+ item.klass = klass;
+ }
+ }
+ }
+ }
+
+ // figure out strings
+ String class_name;
+ if (null == item.typeName)
+ {
+ class_name =
+ MemoryAnalyze.getSymbolPretty(lookup, item, false);
+ item.typeName = class_name;
+ }
+ else
+ {
+ class_name = item.typeName;
+ }
+ System.out.print("class_name=[" + class_name + "]");
+
+ if (class_name.compareTo("_ZTVN4java4lang6StringE")==0
+ || class_name.compareTo("java.lang.String")==0)
+ {
+ BytePtr p = lookup.getBytePtr(item.ptr, item.size);
+ long data = p.getWord(1);
+ int boffset = p.getInt(2 * p.intsPerWord());
+ int count = p.getInt(1 + 2 * p.intsPerWord());
+ int hash = p.getInt(2 + 2 * p.intsPerWord());
+ BytePtr chars = lookup.getBytePtr(data+boffset, count * 2);
+ StringBuffer sb = new StringBuffer(count);
+ for (int qq = 0; qq<count; qq++)
+ sb.append((char)chars.getShort(qq));
+ int newhash = sb.toString().hashCode();
+ if (newhash!=hash)
+ {
+ p.setInt(4, newhash);
+ }
+
+ item.string = sb.toString();
+ System.out.println(" value = \"" + item.string + "\"");
+ if (data != item.ptr)
+ {
+ ObjectMap.ObjectItem next = objectMap.get(data);
+ if (next != null)
+ next.stringData = true;
+ else
+ System.out.println("String [" + item.string + "] at "
+ + Long.toHexString(item.ptr)
+ + " can't find array at "
+ + Long.toHexString(data));
+ }
+ }
+ else if (null != item.string)
+ System.out.println(" value = \"" + item.string + "\"");
+ else
+ System.out.println();
+ }
+
+
+ HashMap<String, Info> map = new HashMap<String, Info>();
+ for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
+ {
+ ObjectMap.ObjectItem item = me.getValue();
+ String name = getSymbolPretty(lookup, item, true);
+ Info info = map.get(name);
+ if (info == null)
+ {
+ info = new Info();
+ info.count = 0;
+ info.size = item.size;
+ map.put(name, info);
+ }
+ info.count++;
+ total_space += item.size;
+ }
+
+ ArrayList<String> list = new ArrayList<String>();
+ for (Iterator it = map.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry me = (Map.Entry)it.next();
+ String name = (String)me.getKey();
+ Info info = (Info)me.getValue();
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(format(info.count * info.size * 100 / total_space,
+ 3));
+ sb.append("%");
+ sb.append(format(info.count * info.size, 10));
+ sb.append(" = ");
+ sb.append(format(info.count, 7));
+ sb.append(" * ");
+ sb.append(format(info.size, 9));
+ sb.append(" - ");
+ sb.append(name);
+ list.add(sb.toString());
+ }
+
+ sorted_report("Memory Usage Sorted by Total Size",
+ total_space, list, new SubstringComparator(5,14,true));
+ sorted_report("Memory Usage Sorted by Description",
+ total_space, list, new SubstringComparator(39,0,false));
+ sorted_report("Memory Usage Sorted by Count",
+ total_space, list, new SubstringComparator(17,25,true));
+ sorted_report("Memory Usage Sorted by Size",
+ total_space, list, new SubstringComparator(28,37,true));
+
+ blockMap.dump();
+
+ // dump raw memory
+ if (verbose)
+ {
+ // analyze references
+ for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
+ {
+ long ptr = me.getKey();
+ ObjectMap.ObjectItem item = me.getValue();
+ BytePtr p = lookup.getBytePtr(ptr, item.size);
+ if (p == null)
+ System.out.println("can't find ptr 0x"
+ + Long.toHexString(ptr));
+ else if (item.kind != 0) // not GC_PTRFREE
+ for (int i = 1;
+ i < item.size / lookup.memoryMap.wordSize; i++)
+ {
+ long maybe_ptr = p.getWord(i);
+ ObjectMap.ObjectItem item2 = objectMap.get(maybe_ptr);
+ if (item2 != null)
+ {
+ item2.pointed_by.add(item);
+ item.points_to.add(item2);
+ }
+ }
+ }
+ System.out.println();
+ System.out.println("*** All Objects ***");
+ System.out.println();
+
+ for (Map.Entry<Long, ObjectMap.ObjectItem> me : objectMap)
+ {
+ long ptr = me.getKey();
+ ObjectMap.ObjectItem item = me.getValue();
+ String name = getSymbolPretty(lookup, item, false);
+ System.out.print("0x" + Long.toHexString(ptr) + " - " + name
+ + " (" + item.size + ")");
+ if (item.string != null)
+ System.out.println(" \"" + item.string + "\"");
+ else
+ System.out.println();
+
+ BytePtr p = lookup.getBytePtr(ptr, item.size);
+
+ if (p == null)
+ System.out.println(
+ "can't find memory; recently allocated from free list?");
+ else
+ p.dump();
+
+ item.points_to.dump(" points to:", lookup);
+ item.pointed_by.dump(" pointed to by:", lookup);
+ System.out.println();
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public static String kindToName(int kind)
+ {
+ String name;
+ switch (kind)
+ {
+ case 0:
+ name = "GC_PTRFREE";
+ break;
+ case 1:
+ name = "GC_NORMAL";
+ break;
+ case 2:
+ name = "GC_UNCOLLECTABLE";
+ break;
+ case 3:
+ name = "GC_AUUNCOLLCTABLE";
+ break;
+ case 4:
+ name = "(Java)";
+ break;
+ case 5:
+ name = "(Java Debug)";
+ break;
+ case 6:
+ name = "(Java Array)";
+ break;
+ default:
+ name = "(Kind " + kind + ")";
+ break;
+ }
+ return name;
+ }
+
+ public static String getSymbolPretty(SymbolLookup lookup,
+ ObjectMap.ObjectItem item,
+ boolean bsize)
+ throws IOException
+ {
+
+ String name = item.typeName;
+
+ if (name == null)
+ name = lookup.getSymbol(item.klass);
+
+ if (name == null)
+ {
+ String v = lookup.decodeUTF8(item.ptr, item.size);
+ if (null != v)
+ {
+ name = "UTF8Const";
+ item.string = v;
+ }
+ }
+
+ if (name == null)
+ {
+ name = kindToName(item.kind);
+ }
+ if (item.kind==6)
+ name += "[" + format(item.data, 0) + "]";
+ if (bsize)
+ name = name + " / " + format(item.size, 7);
+ return name;
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java b/libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java
new file mode 100644
index 00000000000..1bc06d58422
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java
@@ -0,0 +1,359 @@
+/* MemoryMap.java -- Maps address ranges to their data.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Reads /proc/self/maps output from dump file.
+ * Creates map of <filename> to Range.
+ *
+ * Returns filename given address.
+ * Returns offset given address.
+ * Returns BytePtr given address.
+ *
+ */
+class MemoryMap
+{
+ static class RangeComparator implements Comparator<Range>
+ {
+ public int compare(Range r1, Range r2)
+ {
+ if (r2.end == 0 && r1.end != 0)
+ return -compare(r2, r1);
+
+ if (r1.begin < r2.begin)
+ return -1;
+ else if (r1.begin >= r2.end)
+ return 1;
+ else
+ return 0;
+ }
+ }
+
+ static class Range
+ {
+ long begin;
+ long end;
+
+ long offset;
+ String filename;
+ Range()
+ {
+ }
+
+ Range(long b, long e, String s, long o)
+ {
+ begin = b;
+ end = e;
+ filename = s;
+ offset = o;
+ }
+ }
+
+ /**
+ * Parse the string as an unsigned hexadecimal number. This is
+ * similar to Long.parseInt(s,16), but without the restriction that
+ * values that have the sign bit set not being allowed.
+ *
+ * @param s the number as a String.
+ * @return the number.
+ */
+ static long parseHexLong(String s)
+ {
+ if (s.length() > 16)
+ throw new NumberFormatException();
+ long r = 0;
+ for (int i = 0; i < s.length(); i++)
+ {
+ int digit = 0;
+ char c = s.charAt(i);
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ digit = c - '0';
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ digit = 10 + c - 'a';
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ digit = 10 + c - 'A';
+ break;
+ default:
+ throw new NumberFormatException();
+ }
+ r = (r << 4) + digit;
+ }
+ return r;
+ }
+
+ // String filename -> Range
+ TreeSet<Range> map = new TreeSet<Range>(new RangeComparator());
+ HashMap<String, SymbolTable> symbolTables =
+ new HashMap<String, SymbolTable>();
+ ByteOrder byteOrder;
+ int wordSize;
+
+ public MemoryMap(BufferedReader reader,
+ String rawFileName) throws IOException
+ {
+ FileChannel raw = (new RandomAccessFile(rawFileName, "r")).getChannel();
+ ByteBuffer buf = ByteBuffer.allocate(8);
+ raw.read(buf);
+ if (buf.hasRemaining())
+ {
+ raw.close();
+ throw new EOFException();
+ }
+ buf.flip();
+ wordSize = buf.get();
+
+ if (wordSize == 8 || wordSize == 4)
+ byteOrder = ByteOrder.LITTLE_ENDIAN;
+ else
+ {
+ byteOrder = ByteOrder.BIG_ENDIAN;
+ buf.rewind();
+ wordSize = buf.getInt();
+ if (0 == wordSize)
+ wordSize = buf.getInt();
+ }
+ switch (wordSize)
+ {
+ case 4:
+ case 8:
+ break;
+ default:
+ throw new IOException("Bad .bytes file header");
+ }
+ buf = ByteBuffer.allocate(3 * wordSize);
+ buf.order(byteOrder);
+ raw.position(0L);
+
+ for(;;)
+ {
+ // Read the block header.
+ buf.clear();
+ if (-1 == raw.read(buf))
+ {
+ //EOF
+ raw.close();
+ break;
+ }
+ if (buf.hasRemaining())
+ {
+ raw.close();
+ throw new EOFException();
+ }
+ buf.flip();
+ long dummy
+ = (wordSize == 4) ? (buf.getInt() & 0xffffffffL) : buf.getLong();
+ if (dummy != wordSize)
+ throw new IOException("Bad .bytes file header");
+ long start
+ = wordSize == 4 ? (buf.getInt() & 0xffffffffL) : buf.getLong();
+ long length
+ = wordSize == 4 ? (buf.getInt() & 0xffffffffL) : buf.getLong();
+ if (length < 0L)
+ throw new IOException("Bad .bytes file header");
+
+ long currentPos = raw.position();
+ raw.position(currentPos + length);
+
+ Range range = new Range(start, start + length,
+ rawFileName, currentPos);
+ map.add(range);
+ }
+
+ for (;;)
+ {
+ String s = reader.readLine();
+ if (s == null)
+ break;
+ if (s.indexOf("Begin address map") >= 0)
+ {
+ for (;;)
+ {
+ s = reader.readLine();
+ if (s.indexOf("End address map") >= 0)
+ {
+ dump();
+ return;
+ }
+ int endOfAddress = s.indexOf('-');
+ long address = parseHexLong(s.substring(0, endOfAddress));
+ int endOfAddress2 = s.indexOf(' ', endOfAddress + 1);
+ long address2 = parseHexLong(s.substring(endOfAddress + 1,
+ endOfAddress2));
+ int endOfOffset = s.indexOf(' ', endOfAddress2 + 6);
+ long offset;
+ try
+ {
+ offset = parseHexLong(s.substring(endOfAddress2 + 6,
+ endOfOffset));
+ }
+ catch (Exception e)
+ {
+ offset = 0;
+ }
+ int end = s.indexOf('/');
+
+ if (end > 0)
+ {
+ String file = s.substring(end);
+ if (file.startsWith("/dev/"))
+ continue;
+
+ Range r = new Range(address, address2, file, offset);
+ if (offset == 0)
+ {
+ // Read the file's symbol table
+ try
+ {
+ File f = ToolPrefix.fileForName(file);
+ if (f != null)
+ {
+ SymbolTable st = new SymbolTable(f.getPath());
+ if (st.loadAddr != address)
+ st.relocation = address - st.loadAddr;
+ symbolTables.put(file, st);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ map.add(r);
+ }
+ } // inner loop
+ } // started inner loop
+ } // outer loop - finding begin
+ } // memoryMap
+
+
+ public void dump()
+ {
+ System.out.println("MemoryMap:");
+ for (Range r : map)
+ {
+ System.out.println(Long.toHexString(r.begin) + "-"
+ + Long.toHexString(r.end) + " -> "
+ + r.filename + " offset "
+ + Long.toHexString(r.offset));
+ }
+ }
+
+ Range getRange(long addr)
+ {
+ Range r = new Range();
+ r.begin = addr;
+ SortedSet<Range> t = map.tailSet(r);
+ if (t.isEmpty())
+ return null;
+ Range c = t.first();
+ if (c.begin <= addr && addr < c.end)
+ return c;
+ return null;
+ }
+
+ String getFile(long addr)
+ {
+ Range r = getRange(addr);
+ if (null != r)
+ return r.filename;
+ return null;
+ }
+
+ long getOffset(long addr)
+ {
+ Range r = getRange(addr);
+ if (null != r)
+ return r.offset;
+ return 0L;
+ }
+
+ /**
+ * @return BytePtr which includes given address.
+ */
+ BytePtr getBytePtr(long addr, int length) throws IOException
+ {
+ Range r = getRange(addr);
+
+ if (null == r)
+ return null;
+
+ File f = ToolPrefix.fileForName(r.filename);
+ if (null == f)
+ return null;
+
+ if (addr + length > r.end)
+ length = (int)(r.end - addr);
+
+ ByteBuffer b = ByteBuffer.allocate(length);
+ b.order(byteOrder);
+
+ FileChannel fc = (new RandomAccessFile(f, "r")).getChannel();
+ fc.position(r.offset + addr - r.begin);
+ int nr = fc.read(b);
+ fc.close();
+ if (nr != length)
+ return null;
+ b.flip();
+ return new BytePtr(b, wordSize);
+ }
+
+ public String getSymbol(long addr)
+ {
+ Range r = getRange(addr);
+
+ if (r == null)
+ return null;
+
+ SymbolTable st = symbolTables.get(r.filename);
+ if (st == null)
+ return null;
+
+ // Apply relocation
+ addr -= st.relocation;
+
+ return st.getSymbol(addr);
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/ObjectMap.java b/libjava/gnu/gcj/tools/gc_analyze/ObjectMap.java
new file mode 100644
index 00000000000..b55034be137
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/ObjectMap.java
@@ -0,0 +1,140 @@
+/* ObjectMap.java -- Contains a map of all objects keyed by their addresses.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+class ObjectMap implements Iterable<Map.Entry<Long, ObjectMap.ObjectItem>>
+{
+
+ class ObjectItem
+ {
+ int used;
+ int size;
+ int kind;
+ long klass;
+ long data;
+ long ptr;
+ String typeName;
+ String string; // only for string objects
+ boolean stringData; // character array pointed to by a string
+ ObjectItem reference; // object at reference points to this
+
+ ItemList points_to = new ItemList();
+ ItemList pointed_by = new ItemList();
+ }
+
+ private TreeMap<Long, ObjectItem> map = new TreeMap<Long, ObjectItem>();
+
+ public Iterator<Map.Entry<Long, ObjectItem>> iterator()
+ {
+ return map.entrySet().iterator();
+ }
+
+ public ObjectItem get(long ptr)
+ {
+ ObjectItem item = map.get(ptr);
+ return item;
+ }
+
+ public ObjectMap(BufferedReader reader) throws IOException
+ {
+ outer_loop:
+ for (;;)
+ {
+ String s = reader.readLine();
+ if (s == null)
+ break;
+ if (s.indexOf("Begin object map") >= 0)
+ {
+ for (;;)
+ {
+ s = reader.readLine();
+ if (s.indexOf("End object map") >= 0)
+ break outer_loop;
+ String[] items = s.split(",");
+ ObjectItem item = new ObjectItem();
+ long ptr = 0;
+ for (int i=0; i<items.length; i++)
+ {
+ String[] x = items[i].split(" ");
+ String last = x[x.length-1];
+ switch (i)
+ {
+ case 0:
+ item.used = Integer.parseInt(last);
+ break;
+ case 1:
+ ptr = MemoryMap.parseHexLong(last.substring(2));
+ break;
+ case 2:
+ item.size = Integer.parseInt(last);
+ break;
+ case 3:
+ item.kind = Integer.parseInt(last);
+ break;
+ case 4:
+ if (last.length() > 1)
+ item.klass =
+ MemoryMap.parseHexLong(last.substring(2));
+ else
+ item.klass = Integer.parseInt(last,16);
+ break;
+ case 5:
+ try
+ {
+ item.data =
+ Integer.parseInt(last.substring(2), 16);
+ }
+ catch (Exception e)
+ {
+ item.data = 0;
+ }
+ break;
+ }
+ }
+ item.ptr = ptr;
+ map.put(ptr, item);
+ } // inner loop
+ } // started inner loop
+ } // outer loop - finding begin
+ for (Map.Entry<Long, ObjectItem> me : this)
+ {
+ ObjectItem item = me.getValue();
+ if (item.data != 0)
+ {
+ // see if data is a pointer to a block
+ ObjectItem referenced = map.get(item.data);
+ if (referenced != null)
+ {
+ referenced.reference = item;
+ }
+ }
+ }
+ } // memoryMap
+
+ public void dump()
+ {
+ for (Map.Entry<Long, ObjectItem> me : this)
+ {
+ long ptr = me.getKey();
+ ObjectItem item = me.getValue();
+ System.out.println("ptr = " + Long.toHexString(ptr)
+ + ", size = " + item.size
+ + ", klass = " + Long.toHexString(item.klass)
+ + ", kind = " + item.kind
+ + ", data = " + item.data);
+ }
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java b/libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java
new file mode 100644
index 00000000000..b3963d8cfd8
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java
@@ -0,0 +1,112 @@
+/* SymbolLookup.java -- Finds class names by analyzing memory.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+class SymbolLookup
+{
+ MemoryMap memoryMap;
+
+ public SymbolLookup(BufferedReader reader,
+ String rawFileName)
+ throws IOException
+ {
+ memoryMap = new MemoryMap(reader, rawFileName);
+ }
+
+ public String decodeUTF8(long address) throws IOException
+ {
+ return decodeUTF8(address, -1);
+ }
+
+ public String decodeUTF8(long address, int limit) throws IOException
+ {
+ if (address == 0)
+ return null;
+
+ BytePtr utf8 = memoryMap.getBytePtr(address, 64);
+
+ if (utf8 == null)
+ return null;
+
+ int len = utf8.getShort(1);
+ int hash16 = utf8.getShort(0) & 0xffff;
+
+ if (len <= 0 || (limit > 0 && len > (limit - 4)))
+ return null;
+
+ if (len > utf8.getsize() + 4)
+ utf8 = memoryMap.getBytePtr(address, len + 4);
+
+ if (utf8 == null)
+ return null;
+
+ StringBuilder sb = new StringBuilder(len);
+ int pos = 4;
+ len += 4;
+
+ while (pos < len)
+ {
+ int f = utf8.getByte(pos++);
+ if ((f & 0x80) == 0)
+ {
+ sb.append((char)f);
+ }
+ else if ((f & 0xe0) == 0xc0)
+ {
+ int s = utf8.getByte(pos++);
+ char c = (char)(((f & 0x1f) << 6) | (s & 0x80));
+ sb.append(c);
+ }
+ else if ((f & 0xe0) == 0xe0)
+ {
+ int s = utf8.getByte(pos++);
+ int t = utf8.getByte(pos++);
+ char c = (char)(((f & 0x0f) << 12)
+ | ((s & 0x80) << 6) | (t & 0x80));
+ sb.append(c);
+ }
+ else
+ break; // Bad utf8
+ }
+ String rv = sb.toString();
+ if (hash16 == (rv.hashCode() & 0xffff))
+ return rv;
+ else
+ return null;
+ }
+
+ public String getSymbolViaVtable(long address) throws IOException
+ {
+ return memoryMap.getSymbol(address);
+ }
+
+ public String getSymbol(long address) throws IOException
+ {
+ String symbol = memoryMap.getSymbol(address);
+ if (null != symbol)
+ return symbol;
+
+ BytePtr klass = memoryMap.getBytePtr(address, 3 * memoryMap.wordSize);
+ if (klass == null)
+ return null;
+
+ long nameUTF8p = klass.getWord(2);
+
+ return decodeUTF8(nameUTF8p);
+ }
+
+ BytePtr getBytePtr(long addr, int length) throws IOException
+ {
+ return memoryMap.getBytePtr(addr, length);
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java b/libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java
new file mode 100644
index 00000000000..eb5df7641b7
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java
@@ -0,0 +1,198 @@
+/* SymbolTable.java -- Maintains a mapping of addresses to names.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+class SymbolTable
+{
+ // Long address->String name
+ private HashMap<Long, String> map = new HashMap<Long, String>();
+
+ // Reverse
+ // String name -> Long address
+ // used for RelocateImage
+ private HashMap<String, Long> reverse = new HashMap<String, Long>();
+
+ long loadAddr;
+ long relocation;
+
+ static Matcher interestingSymbol =
+ Pattern.compile("^([0-9a-fA-F]+)\\s+\\S+\\s+(_Z\\S+)").matcher("");
+ static Matcher readelfLoadMatcher =
+ Pattern.compile("^\\s+LOAD\\s+(\\S+)\\s+(\\S+)\\s.*").matcher("");
+
+ public SymbolTable(String filename) throws IOException
+ {
+ Process p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix
+ + "nm " + filename);
+ InputStream es = p.getErrorStream();
+ InputStream is = p.getInputStream();
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ int count = 0;
+
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ interestingSymbol.reset(line);
+ if (interestingSymbol.matches())
+ {
+ try
+ {
+ String name = interestingSymbol.group(2);
+ String addr = interestingSymbol.group(1);
+ if (name.startsWith("_ZTVN") || name.endsWith("6class$E"))
+ {
+ long address = MemoryMap.parseHexLong(addr);
+ Long l = new Long(address);
+ map.put(l, name);
+ count++;
+ reverse.put(name, l);
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ // ignore it
+ }
+ }
+ }
+ es.close();
+ is.close();
+ p.destroy();
+
+ if (count > 0)
+ {
+ // Assume nm read some symbols from it and that
+ // readelf can tell us something about how it is loaded.
+ p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix
+ + "readelf -l " + filename);
+ es = p.getErrorStream();
+ is = p.getInputStream();
+
+ reader = new BufferedReader(new InputStreamReader(is));
+ while ((line = reader.readLine()) != null)
+ {
+ readelfLoadMatcher.reset(line);
+ if (readelfLoadMatcher.matches())
+ {
+ loadAddr
+ = Long.decode(readelfLoadMatcher.group(2)).longValue();
+ break;
+ }
+ }
+ es.close();
+ is.close();
+ p.destroy();
+ }
+
+ System.out.println(ToolPrefix.toolPrefix + "nm " + filename
+ + " -> " + count + " symbols");
+ }
+
+ public static void main(String args[])
+ {
+ try
+ {
+ SymbolTable st = new SymbolTable(args[0]);
+ st.dump();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ public static String demangleVTName(String n)
+ {
+ if (n.startsWith("_ZTVN") && n.endsWith("E"))
+ return demangle(n.substring(5, n.length() - 1));
+ else
+ return null;
+ }
+
+ public void dump()
+ {
+ for (Map.Entry<Long, String> me : map.entrySet())
+ {
+ long address = me.getKey();
+ String symbol = me.getValue();
+ System.out.println(Long.toHexString(address) + " -> " + symbol);
+ if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E"))
+ {
+ System.out.println(" Class: "
+ + demangle(symbol.substring(3, symbol.length()
+ - 8)));
+ }
+ else if (symbol.startsWith("_ZTVN") && symbol.endsWith("E"))
+ {
+ System.out.println(" VT: "
+ + demangle(symbol.substring(5, symbol.length()
+ - 1)));
+ }
+ }
+ }
+
+ private static String demangle(String symbol)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i=0; i<symbol.length(); )
+ {
+ int l = 0;
+ while (i < symbol.length())
+ {
+ int d = symbol.charAt(i);
+ if (d < '0' || d > '9')
+ break;
+ l = 10 * l + (d - '0');
+ i++;
+ }
+ if (l == 0)
+ break;
+ // copy
+ if (sb.length() > 0)
+ sb.append('.');
+ while (l > 0 && i < symbol.length())
+ {
+ sb.append(symbol.charAt(i));
+ l--;
+ i++;
+ }
+ }
+ return sb.toString();
+ }
+
+ public String getSymbol(long address)
+ {
+ String symbol = map.get(address);
+ if (symbol == null)
+ return null;
+
+ if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E"))
+ symbol = demangle(symbol.substring(3, symbol.length() - 8));
+ return symbol;
+ }
+
+ // will return -1 if not found
+ public long getAddress(String symbol)
+ {
+ Long address = reverse.get(symbol);
+ if (address == null)
+ return -1;
+ return address.longValue();
+ }
+}
diff --git a/libjava/gnu/gcj/tools/gc_analyze/ToolPrefix.java b/libjava/gnu/gcj/tools/gc_analyze/ToolPrefix.java
new file mode 100644
index 00000000000..e8d73ae92db
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/ToolPrefix.java
@@ -0,0 +1,45 @@
+/* ToolPrefix.java -- Container of the toolPrefix String.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.File;
+
+class ToolPrefix
+{
+ /**
+ * Private constructor. No creation allowed. This class has
+ * Static methods only.
+ */
+ private ToolPrefix()
+ {
+ }
+
+ static String toolPrefix = "";
+
+ static String pathPrefix = "";
+
+ static File fileForName(String filename)
+ {
+ File f = new File(pathPrefix + filename);
+ if (!f.canRead())
+ {
+ // Try it without the prefix.
+ f = new File(filename);
+ if (!f.canRead())
+ {
+ // Try to find it in the current directory.
+ f = new File(f.getName());
+ if (!f.canRead())
+ return null;
+ }
+ }
+ return f;
+ }
+}
diff --git a/libjava/gnu/gcj/util/GCInfo.h b/libjava/gnu/gcj/util/GCInfo.h
new file mode 100644
index 00000000000..06e0dd0d06c
--- /dev/null
+++ b/libjava/gnu/gcj/util/GCInfo.h
@@ -0,0 +1,45 @@
+
+// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-
+
+#ifndef __gnu_gcj_util_GCInfo__
+#define __gnu_gcj_util_GCInfo__
+
+#pragma interface
+
+#include <java/lang/Object.h>
+extern "Java"
+{
+ namespace gnu
+ {
+ namespace gcj
+ {
+ namespace util
+ {
+ class GCInfo;
+ }
+ }
+ }
+}
+
+class gnu::gcj::util::GCInfo : public ::java::lang::Object
+{
+
+ GCInfo();
+ static void checkPermission();
+public:
+ static void dump(::java::lang::String *);
+private:
+ static void dump0(::java::lang::String *);
+public:
+ static void enumerate(::java::lang::String *);
+private:
+ static void enumerate0(::java::lang::String *);
+public:
+ static void setOOMDump(::java::lang::String *);
+private:
+ static void setOOMDump0(::java::lang::String *);
+public:
+ static ::java::lang::Class class$;
+};
+
+#endif // __gnu_gcj_util_GCInfo__
diff --git a/libjava/gnu/gcj/util/GCInfo.java b/libjava/gnu/gcj/util/GCInfo.java
new file mode 100644
index 00000000000..73f4718f9f2
--- /dev/null
+++ b/libjava/gnu/gcj/util/GCInfo.java
@@ -0,0 +1,79 @@
+/* GCInfo.java -- Support for creating heap dumps.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+package gnu.gcj.util;
+
+public class GCInfo
+{
+ private GCInfo()
+ {
+ }
+
+ /**
+ * @throws SecurityException if there is a SecurityManager installed
+ * and UtilPermission("dumpHeap") is not granted.
+ */
+ private static void checkPermission()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new UtilPermission("dumpHeap"));
+ }
+
+
+ /**
+ * Dump a description of the heap state.
+ *
+ * @param namePrefix The filename prefix for the dump files.
+ *
+ * @throws SecurityException if there is a SecurityManager installed
+ * and UtilPermission("dumpHeap") is not granted.
+ */
+ public static synchronized void dump(String name)
+ {
+ checkPermission();
+ dump0(name);
+ }
+
+ private static native void dump0(String name);
+
+
+ /**
+ * Create a heap dump.
+ *
+ * @param namePrefix The filename prefix for the dump files.
+ *
+ * @throws SecurityException if there is a SecurityManager installed
+ * and UtilPermission("dumpHeap") is not granted.
+ */
+ public static synchronized void enumerate(String namePrefix)
+ {
+ checkPermission();
+ enumerate0(namePrefix);
+ }
+
+ private static native void enumerate0(String namePrefix);
+
+ /**
+ * Cause a heap dump if out-of-memory condition occurs.
+ *
+ * @param namePrefix The filename prefix for the dump files. If
+ * null no dumps are created.
+ *
+ * @throws SecurityException if there is a SecurityManager installed
+ * and UtilPermission("dumpHeap") is not granted.
+ */
+ public static synchronized void setOOMDump(String namePrefix)
+ {
+ checkPermission();
+ setOOMDump0(namePrefix);
+ }
+
+ private static native void setOOMDump0(String namePrefix);
+}
diff --git a/libjava/gnu/gcj/util/UtilPermission.h b/libjava/gnu/gcj/util/UtilPermission.h
new file mode 100644
index 00000000000..4c7b2267154
--- /dev/null
+++ b/libjava/gnu/gcj/util/UtilPermission.h
@@ -0,0 +1,32 @@
+
+// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-
+
+#ifndef __gnu_gcj_util_UtilPermission__
+#define __gnu_gcj_util_UtilPermission__
+
+#pragma interface
+
+#include <java/security/BasicPermission.h>
+extern "Java"
+{
+ namespace gnu
+ {
+ namespace gcj
+ {
+ namespace util
+ {
+ class UtilPermission;
+ }
+ }
+ }
+}
+
+class gnu::gcj::util::UtilPermission : public ::java::security::BasicPermission
+{
+
+public:
+ UtilPermission(::java::lang::String *);
+ static ::java::lang::Class class$;
+};
+
+#endif // __gnu_gcj_util_UtilPermission__
diff --git a/libjava/gnu/gcj/util/UtilPermission.java b/libjava/gnu/gcj/util/UtilPermission.java
new file mode 100644
index 00000000000..1ea4cb71668
--- /dev/null
+++ b/libjava/gnu/gcj/util/UtilPermission.java
@@ -0,0 +1,20 @@
+/* GCInfo.java -- Support for creating heap dumps.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+package gnu.gcj.util;
+
+import java.security.BasicPermission;
+
+public class UtilPermission extends BasicPermission
+{
+ public UtilPermission(String name)
+ {
+ super(name);
+ }
+}
diff --git a/libjava/gnu/gcj/util/natGCInfo.cc b/libjava/gnu/gcj/util/natGCInfo.cc
new file mode 100644
index 00000000000..7e5c6fbb845
--- /dev/null
+++ b/libjava/gnu/gcj/util/natGCInfo.cc
@@ -0,0 +1,454 @@
+/* natGCInfo.cc -- Native portion of support for creating heap dumps.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+
+#include <config.h>
+
+#include <gcj/cni.h>
+
+#include <gnu/gcj/util/GCInfo.h>
+
+#ifdef HAVE_PROC_SELF_MAPS
+//
+// If /proc/self/maps does not exist we assume we are doomed and do nothing.
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+//
+// Boehm GC includes.
+//
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif
+
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif
+
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif
+
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+extern "C" {
+#include "private/dbg_mlc.h"
+ int GC_n_set_marks(hdr* hhdr);
+ ptr_t GC_clear_stack(ptr_t p);
+ extern int GC_gcj_kind;
+ extern int GC_gcj_debug_kind;
+}
+
+#endif
+
+#ifdef HAVE_PROC_SELF_MAPS
+
+static int gc_ok = 1;
+
+typedef struct gc_debug_info
+{
+ int used;
+ int free;
+ int wasted;
+ int blocks;
+ FILE* fp;
+};
+
+static void
+GC_print_debug_callback(hblk *h, word user_data)
+{
+ hdr *hhdr = HDR(h);
+ size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
+
+ gc_debug_info *pinfo = (gc_debug_info *)user_data;
+
+ fprintf(pinfo->fp, "ptr = %#lx, kind = %d, size = %zd, marks = %d\n",
+ (unsigned long)h, hhdr->hb_obj_kind, bytes, GC_n_set_marks(hhdr));
+}
+
+/*
+ this next section of definitions shouldn't really be here.
+ copied from boehmgc/allchblk.c
+*/
+
+# define UNIQUE_THRESHOLD 32
+# define HUGE_THRESHOLD 256
+# define FL_COMPRESSION 8
+# define N_HBLK_FLS (HUGE_THRESHOLD - UNIQUE_THRESHOLD)/FL_COMPRESSION \
+ + UNIQUE_THRESHOLD
+#ifndef USE_MUNMAP
+extern "C" {
+ extern word GC_free_bytes[N_HBLK_FLS+1];
+}
+#endif
+
+# ifdef USE_MUNMAP
+# define IS_MAPPED(hhdr) (((hhdr) -> hb_flags & WAS_UNMAPPED) == 0)
+# else /* !USE_MMAP */
+# define IS_MAPPED(hhdr) 1
+# endif /* USE_MUNMAP */
+
+static void
+GC_print_hblkfreelist_file(FILE *fp)
+{
+ struct hblk * h;
+ word total_free = 0;
+ hdr * hhdr;
+ word sz;
+ int i;
+
+ fprintf(fp, "---------- Begin free map ----------\n");
+ for (i = 0; i <= N_HBLK_FLS; ++i)
+ {
+ h = GC_hblkfreelist[i];
+#ifdef USE_MUNMAP
+ if (0 != h)
+ fprintf (fp, "Free list %ld:\n", (unsigned long)i);
+#else
+ if (0 != h)
+ fprintf (fp, "Free list %ld (Total size %ld):\n",
+ (unsigned long)i,
+ (unsigned long)GC_free_bytes[i]);
+#endif
+ while (h != 0)
+ {
+ hhdr = HDR(h);
+ sz = hhdr -> hb_sz;
+ fprintf (fp, "\t0x%lx size %lu ", (unsigned long)h,
+ (unsigned long)sz);
+ total_free += sz;
+
+ if (GC_is_black_listed (h, HBLKSIZE) != 0)
+ fprintf (fp, "start black listed\n");
+ else if (GC_is_black_listed(h, hhdr -> hb_sz) != 0)
+ fprintf (fp, "partially black listed\n");
+ else
+ fprintf (fp, "not black listed\n");
+
+ h = hhdr -> hb_next;
+ }
+ }
+#ifndef USE_MUNMAP
+ if (total_free != GC_large_free_bytes)
+ {
+ fprintf (fp, "GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
+ (unsigned long) GC_large_free_bytes);
+ }
+#endif
+ fprintf (fp, "Total of %lu bytes on free list\n", (unsigned long)total_free);
+ fprintf (fp, "---------- End free map ----------\n");
+}
+
+static int GC_dump_count = 1;
+
+static void
+GC_print_debug_info_file(FILE* fp)
+{
+ gc_debug_info info;
+
+ memset(&info, 0, sizeof info);
+ info.fp = fp;
+
+ if (gc_ok)
+ GC_gcollect();
+ fprintf(info.fp, "---------- Begin block map ----------\n");
+ GC_apply_to_all_blocks(GC_print_debug_callback, (word)(void*)(&info));
+ //fprintf(fp, "#Total used %d free %d wasted %d\n", info.used, info.free, info.wasted);
+ //fprintf(fp, "#Total blocks %d; %dK bytes\n", info.blocks, info.blocks*4);
+ fprintf(info.fp, "---------- End block map ----------\n");
+
+ //fprintf(fp, "\n***Free blocks:\n");
+ //GC_print_hblkfreelist();
+}
+
+namespace
+{
+ class __attribute__ ((visibility ("hidden"))) GC_enumerator
+ {
+ public:
+ GC_enumerator(const char *name);
+ void enumerate();
+ private:
+ FILE* fp;
+ int bytes_fd;
+
+ void print_address_map();
+ void enumerate_callback(struct hblk *h);
+ static void enumerate_callback_adaptor(struct hblk *h, word dummy);
+ };
+}
+
+GC_enumerator::GC_enumerator(const char *name)
+{
+ bytes_fd = -1;
+ fp = fopen (name, "w");
+ if (!fp)
+ {
+ printf ("GC_enumerator failed to open [%s]\n", name);
+ return;
+ }
+ printf ("GC_enumerator saving summary to [%s]\n", name);
+
+ // open heap file
+ char bytes_name[strlen(name) + 10];
+ sprintf (bytes_name, "%s.bytes", name);
+ bytes_fd = open (bytes_name, O_CREAT|O_TRUNC|O_WRONLY, 0666);
+ if (bytes_fd <= 0)
+ {
+ printf ("GC_enumerator failed to open [%s]\n", bytes_name);
+ return;
+ }
+ printf ("GC_enumerator saving heap contents to [%s]\n", bytes_name);
+}
+
+/*
+ sample format of /proc/self/maps
+
+ 0063b000-00686000 rw-p 001fb000 03:01 81993 /avtrex/bin/dumppropapp
+ 00686000-0072e000 rwxp 00000000 00:00 0
+
+ These are parsed below as:
+ start -end xxxx xxxxxxxx a:b xxxxxxxxxxxxxxx
+
+*/
+
+
+void
+GC_enumerator::print_address_map()
+{
+ FILE* fm;
+ char buffer[128];
+
+ fprintf(fp, "---------- Begin address map ----------\n");
+
+ fm = fopen("/proc/self/maps", "r");
+ if (fm == NULL)
+ {
+ if (0 == strerror_r (errno, buffer, sizeof buffer))
+ fputs (buffer, fp);
+ }
+ else
+ {
+ while (fgets (buffer, sizeof buffer, fm) != NULL)
+ {
+ fputs (buffer, fp);
+ char *dash = strchr(buffer, '-');
+ char *colon = strchr(buffer, ':');
+ if (dash && colon && ((ptrdiff_t)strlen(buffer) > (colon - buffer) + 2))
+ {
+ char *endp;
+ unsigned long start = strtoul(buffer, NULL, 16);
+ unsigned long end = strtoul(dash + 1, &endp, 16);
+ unsigned long a = strtoul(colon - 2, NULL, 16);
+ unsigned long b = strtoul(colon + 1, NULL, 16);
+ // If it is an anonymous mapping 00:00 and both readable
+ // and writeable then dump the contents of the mapping
+ // to the bytes file. Each block has a header of three
+ // unsigned longs:
+ // 0 - The number sizeof(unsigned long) to detect endianness and
+ // structure layout.
+ // 1 - The offset in VM.
+ // 2 - The Length in bytes.
+ // Followed by the bytes.
+ if (!a && !b && endp < colon && 'r' == endp[1] && 'w' == endp[2])
+ {
+ unsigned long t = sizeof(unsigned long);
+ write(bytes_fd, (void*)&t, sizeof(t));
+ write(bytes_fd, (void*)&start, sizeof(start));
+ t = end - start;
+ write(bytes_fd, (void*)&t, sizeof(t));
+ write(bytes_fd, (void*)start, (end - start));
+ }
+ }
+ }
+ fclose(fm);
+ }
+ fprintf(fp, "---------- End address map ----------\n");
+ fflush(fp);
+}
+
+void
+GC_enumerator::enumerate()
+{
+ print_address_map();
+ fprintf(fp, "---------- Begin object map ----------\n");
+ if (gc_ok)
+ GC_gcollect();
+ GC_apply_to_all_blocks(enumerate_callback_adaptor,
+ (word)(void*)(this));
+ fprintf(fp, "---------- End object map ----------\n");
+ fflush(fp);
+
+ GC_print_debug_info_file(fp);
+ fflush(fp);
+ GC_print_hblkfreelist_file(fp);
+ fflush(fp);
+
+ close(bytes_fd);
+ fclose(fp);
+
+ GC_clear_stack(0);
+}
+
+void
+GC_enumerator::enumerate_callback_adaptor(struct hblk *h,
+ word dummy)
+{
+ GC_enumerator* pinfo = (GC_enumerator*)dummy;
+ pinfo->enumerate_callback(h);
+}
+
+void
+GC_enumerator::enumerate_callback(struct hblk *h)
+{
+ hdr * hhdr = HDR(h);
+ size_t bytes = WORDS_TO_BYTES(hhdr->hb_sz);
+ int i;
+
+ for (i = 0; i == 0 || (i + bytes <= HBLKSIZE); i += bytes)
+ {
+ int inUse = mark_bit_from_hdr(hhdr,BYTES_TO_WORDS(i)); // in use
+ char *ptr = (char*)h+i; // address
+ int kind = hhdr->hb_obj_kind; // kind
+ void *klass = 0;
+ void *data = 0;
+ if (kind == GC_gcj_kind
+ || kind == GC_gcj_debug_kind
+ || kind == GC_gcj_debug_kind+1)
+ {
+ void* v = *(void **)ptr;
+ if (v)
+ {
+ klass = *(void **)v;
+ data = *(void **)(ptr + sizeof(void*));
+ }
+ }
+ if (inUse)
+ fprintf (fp, "used = %d, ptr = %#lx, size = %zd, kind = %d, "
+ "klass = %#lx, data = %#lx\n",
+ inUse, (unsigned long)ptr, bytes, kind,
+ (unsigned long)klass, (unsigned long)data);
+ }
+}
+
+/*
+ * Fill in a char[] with low bytes of the string characters. These
+ * methods may be called while an OutOfMemoryError is being thrown, so
+ * we cannot call nice java methods to get the encoding of the string.
+ */
+static void
+J2A(::java::lang::String* str, char *dst)
+{
+ jchar * pchars = JvGetStringChars(str);
+ jint len = str->length();
+ int i;
+ for (i=0; i<len; i++)
+ dst[i] = (char)pchars[i];
+ dst[i] = 0;
+}
+
+void
+::gnu::gcj::util::GCInfo::dump0 (::java::lang::String * name)
+{
+ char n[name->length() + 1];
+ J2A(name, n);
+
+ char temp[name->length() + 20];
+ sprintf(temp, "%s%03d", n, GC_dump_count++);
+ FILE* fp = fopen(temp, "w");
+
+ GC_print_debug_info_file(fp);
+
+ fclose(fp);
+}
+
+void
+::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String * name)
+{
+ char n[name->length() + 1];
+ J2A(name, n);
+ char temp[name->length() + 20];
+ sprintf(temp, "%s%03d", n, GC_dump_count++);
+
+ GC_enumerator x(temp);
+ x.enumerate();
+}
+
+static char *oomDumpName = NULL;
+
+static void *
+nomem_handler(size_t size)
+{
+ if (oomDumpName)
+ {
+ char temp[strlen(oomDumpName) + 20];
+ sprintf(temp, "%s%03d", temp, GC_dump_count++);
+ printf("nomem_handler(%zd) called\n", size);
+ gc_ok--;
+ GC_enumerator x(temp);
+ x.enumerate();
+ gc_ok++;
+ }
+ return (void*)0;
+}
+
+void
+::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String * name)
+{
+ char *oldName = oomDumpName;
+ oomDumpName = NULL;
+ free (oldName);
+
+ if (NULL == name)
+ return;
+
+ char *n = (char *)malloc(name->length() + 1);
+
+ J2A(name, n);
+ oomDumpName = n;
+ GC_oom_fn = nomem_handler;
+}
+
+#else // HAVE_PROC_SELF_MAPS
+
+void
+::gnu::gcj::util::GCInfo::dump0 (::java::lang::String * name)
+{
+ // Do nothing if dumping not supported.
+}
+
+void
+::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String * name)
+{
+ // Do nothing if dumping not supported.
+}
+
+void
+::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String * name)
+{
+ // Do nothing if dumping not supported.
+}
+
+#endif // HAVE_PROC_SELF_MAPS
+
diff --git a/libjava/include/config.h.in b/libjava/include/config.h.in
index a4e013d735f..2c025a27af5 100644
--- a/libjava/include/config.h.in
+++ b/libjava/include/config.h.in
@@ -232,6 +232,9 @@
/* Define if you have /proc/self/exe */
#undef HAVE_PROC_SELF_EXE
+/* Define if you have /proc/self/maps */
+#undef HAVE_PROC_SELF_MAPS
+
/* Define if using POSIX threads that have the mutexattr functions. */
#undef HAVE_PTHREAD_MUTEXATTR_INIT
@@ -375,6 +378,9 @@
/* Define to 1 if you have the file `AC_File'. */
#undef HAVE__PROC_SELF_EXE
+/* Define to 1 if you have the file `AC_File'. */
+#undef HAVE__PROC_SELF_MAPS
+
/* Define as const if the declaration of iconv() needs const. */
#undef ICONV_CONST
diff --git a/libjava/scripts/makemake.tcl b/libjava/scripts/makemake.tcl
index 78259a32af2..5a60097d698 100755
--- a/libjava/scripts/makemake.tcl
+++ b/libjava/scripts/makemake.tcl
@@ -42,6 +42,7 @@ set package_map(.) package
# These are ignored in Classpath.
set package_map(gnu/test) ignore
set package_map(gnu/javax/swing/plaf/gtk) ignore
+set package_map(gnu/gcj/tools/gc_analyze) ignore
set package_map(gnu/java/awt/peer/swing) bc
diff --git a/libjava/sources.am b/libjava/sources.am
index 0c9953f33b9..79b8832bb43 100644
--- a/libjava/sources.am
+++ b/libjava/sources.am
@@ -555,7 +555,9 @@ gnu/gcj/tools/gcj_dbtool.list: $(gnu_gcj_tools_gcj_dbtool_source_files)
gnu_gcj_util_source_files = \
-gnu/gcj/util/Debug.java
+gnu/gcj/util/Debug.java \
+gnu/gcj/util/GCInfo.java \
+gnu/gcj/util/UtilPermission.java
gnu_gcj_util_header_files = $(patsubst %.java,%.h,$(gnu_gcj_util_source_files))