Compare commits

...

260 Commits

Author SHA1 Message Date
J. Duke
e482d16c43 Merge 2017-07-05 17:53:21 +02:00
J. Duke
754d67857b Merge 2017-07-05 17:53:18 +02:00
J. Duke
f3b42bf53d Merge 2017-07-05 17:53:13 +02:00
J. Duke
e77ad65c04 Merge 2017-07-05 17:53:11 +02:00
J. Duke
111b74d777 Merge 2017-07-05 17:53:08 +02:00
J. Duke
7d9ec688e0 Merge 2017-07-05 17:53:04 +02:00
J. Duke
6540497350 Merge 2017-07-05 17:52:56 +02:00
J. Duke
0324f8cbc8 Added tag jdk8-b09 for changeset fbf3cabc9e3b 2017-07-05 17:52:45 +02:00
J. Duke
1cf5ba0b12 Merge 2017-07-05 17:52:45 +02:00
J. Duke
82145dd2fc Merge 2017-07-05 17:52:42 +02:00
J. Duke
395eada57d Merge 2017-07-05 17:52:39 +02:00
J. Duke
57d29c9d2b Merge 2017-07-05 17:52:37 +02:00
J. Duke
25f958342e Merge 2017-07-05 17:52:35 +02:00
J. Duke
d491a9540c Merge 2017-07-05 17:52:33 +02:00
J. Duke
8b9535d068 Merge 2017-07-05 17:52:30 +02:00
J. Duke
453101c15d Added tag jdk8-b08 for changeset 24ee504f8041 2017-07-05 17:52:22 +02:00
J. Duke
48ad07fd2c Merge 2017-07-05 17:52:21 +02:00
J. Duke
326bf79674 Merge 2017-07-05 17:52:18 +02:00
J. Duke
76edb04f74 Merge 2017-07-05 17:52:13 +02:00
J. Duke
c7e37d5eaf Merge 2017-07-05 17:52:09 +02:00
J. Duke
fa2aecf110 Merge 2017-07-05 17:52:05 +02:00
J. Duke
7945521d98 Merge 2017-07-05 17:52:01 +02:00
J. Duke
ca2669bd2f Merge 2017-07-05 17:51:48 +02:00
J. Duke
933fa3f5aa Added tag jdk8-b07 for changeset bc5710332b29 2017-07-05 17:51:26 +02:00
J. Duke
bb930ae01e Merge 2017-07-05 17:51:25 +02:00
J. Duke
9adbb9c684 Merge 2017-07-05 17:51:22 +02:00
J. Duke
c54e770c42 Merge 2017-07-05 17:51:20 +02:00
J. Duke
b204091ef8 Merge 2017-07-05 17:51:17 +02:00
J. Duke
a85e655e2d Merge 2017-07-05 17:51:14 +02:00
J. Duke
97679d059b Merge 2017-07-05 17:51:12 +02:00
J. Duke
1a597ce85b Merge 2017-07-05 17:51:09 +02:00
J. Duke
c67e801a7e Added tag jdk8-b06 for changeset 429da7734bf4 2017-07-05 17:50:59 +02:00
Lana Steuck
501fe865e8 Merge 2011-10-17 19:07:26 -07:00
Lana Steuck
2e49137b38 Merge 2011-10-17 19:06:53 -07:00
John Coomes
02c6e31091 Added tag hs23-b02 for changeset e597a451dc88 2011-10-14 18:21:47 -07:00
John Coomes
56eac0155c Merge 2011-10-14 18:17:01 -07:00
David Katleman
5839368eee Added tag jdk8-b09 for changeset 0169651a48bf 2011-10-13 10:35:50 -07:00
David Katleman
70a4d09791 Added tag jdk8-b09 for changeset 8b314218e3ab 2011-10-13 10:35:43 -07:00
David Katleman
f524534650 Added tag jdk8-b09 for changeset 8124579f60fd 2011-10-13 10:35:40 -07:00
David Katleman
7a7270c0bd Added tag jdk8-b09 for changeset 072884311758 2011-10-13 10:35:39 -07:00
David Katleman
5219fbb397 Added tag jdk8-b09 for changeset fad441085165 2011-10-13 10:35:32 -07:00
David Katleman
9acc701280 Added tag jdk8-b09 for changeset 44d496c3c830 2011-10-13 10:35:29 -07:00
David Katleman
1175eb8a27 Added tag jdk8-b09 for changeset 56ae1c1e8584 2011-10-13 10:35:24 -07:00
Lana Steuck
5cbdf8db6c Merge 2011-10-12 12:26:38 -07:00
Lana Steuck
8eac661507 Merge 2011-10-12 12:26:03 -07:00
Lana Steuck
9e05d4f813 Merge 2011-10-12 12:25:03 -07:00
Naoto Sato
f54e7ec9bc 7027061: Testcase failure: java/util/Locale/Bug6989440.java - java.util.ConcurrentModificationException
Reviewed-by: dholmes, chegar
2011-10-12 12:12:25 -07:00
John Cuthbertson
4738ed88a5 7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.

Reviewed-by: tonyp, brutisso, ysr
2011-10-12 10:25:51 -07:00
Alexandr Scherbatiy
6fb68448cc 7076791: closed/javax/swing/JColorChooser/Test6827032.java failed on windows
Reviewed-by: rupashka
2011-10-11 15:22:40 +04:00
Bengt Rutisson
7fa7f8a597 7099454: /bin/sh does not support syntax used in the src/os/posix/launcher/launcher.script shell script
Also reviewed by mikael.gerdin@oracle.com; Changed to the `` syntax instead. Also changed "source" to ".".

Reviewed-by: never, stefank, dsamersoff, rottenha
2011-10-11 10:21:36 +02:00
Y. Srinivas Ramakrishna
8fbb0e0f4a Merge 2011-10-10 08:40:34 -07:00
Y. Srinivas Ramakrishna
a7dc867057 7095236: G1: _markedRegions never contains NULL regions
Removed the code for skipping over NULL regions in _markedRegions, replacing it with an assertion that a NULL region is never encountered; removed dead methods, remove() and remove_region(), and inlined a simplified addRegion() directly into fillCache().

Reviewed-by: brutisso, tonyp
2011-10-06 18:56:47 -07:00
David Katleman
0b92e7c70b Added tag jdk8-b08 for changeset c9fb751a1f21 2011-10-06 14:01:45 -07:00
David Katleman
1d6d5772d7 Added tag jdk8-b08 for changeset 88f1603ed2de 2011-10-06 14:01:37 -07:00
David Katleman
a8ca4c2947 Added tag jdk8-b08 for changeset c074b109d708 2011-10-06 14:01:34 -07:00
David Katleman
6d08c900c4 Added tag jdk8-b08 for changeset c6ec1d396a6f 2011-10-06 14:01:33 -07:00
David Katleman
bc8656528c Added tag jdk8-b08 for changeset 410b29777a51 2011-10-06 14:01:26 -07:00
David Katleman
7e4cbf7ede Added tag jdk8-b08 for changeset 21c3dca02af5 2011-10-06 14:01:21 -07:00
David Katleman
e0ebf7426d Added tag jdk8-b08 for changeset 29f7779184ad 2011-10-06 14:01:13 -07:00
Maurizio Cimadamore
b6f671b41e 7090499: missing rawtypes warnings in anonymous inner class
Javac does not detect raw types inside anonymous inner classes

Reviewed-by: jjg
2011-10-06 18:39:31 +01:00
Antonios Printezis
78662d3b17 Merge 2011-10-06 13:28:09 -04:00
John Cuthbertson
6513930e7a 7095194: G1: HeapRegion::GrainBytes, GrainWords, and CardsPerRegion should be size_t
Declare GrainBytes, GrainWords, and CardsPerRegion as size_t.

Reviewed-by: jcoomes, tonyp, jmasa
2011-10-05 08:44:10 -07:00
Pavel Porvatov
72f4cfb2e7 7072167: The "root" field in BufferStrategyPaintManager leaks memory
Reviewed-by: alexp
2011-10-05 18:21:23 +04:00
John Coomes
92bbff7143 Merge 2011-10-04 12:39:42 -07:00
Lana Steuck
2346a1c754 Merge 2011-10-03 18:26:59 -07:00
Lana Steuck
8401a88197 Merge 2011-10-03 18:26:01 -07:00
Lana Steuck
4a7dc9240b Merge 2011-10-03 18:22:43 -07:00
Alejandro Murillo
91823a458f 7096124: Bump the hs23 build number to 02
Reviewed-by: johnc
2011-09-30 22:54:43 -07:00
John Coomes
b731247c38 Added tag hs23-b01 for changeset cca3c612bd14 2011-09-30 18:27:43 -07:00
John Coomes
ef5fc6d83d Merge 2011-09-30 18:27:39 -07:00
John Coomes
5bd84d92a1 Merge 2011-09-30 17:20:56 -07:00
Igor Veresov
7f01a4d4f5 Merge 2011-09-30 13:48:17 -07:00
Roland Westrelin
8ae50d45a4 7096010: c2: running with +PrintOptoAssembly crashes the VM when $constanttablebase is used
ADLC generates code to prepare the register string to be printed in a char array but then calls print without the char array as an argument.

Reviewed-by: never
2011-09-30 13:47:26 +02:00
Igor Veresov
0219cf5423 7096639: Tiered: Incorrect counter overflow handling for inlined methods
Enable invocation events for inlinees

Reviewed-by: kvn
2011-09-29 23:09:54 -07:00
David Katleman
4749de17ea Added tag jdk8-b07 for changeset 64ad92439924 2011-09-29 18:54:01 -07:00
David Katleman
723ea00e0c Added tag jdk8-b07 for changeset 3286cf6d9881 2011-09-29 18:53:53 -07:00
David Katleman
bede38196b Added tag jdk8-b07 for changeset 2b6c60642ad8 2011-09-29 18:53:49 -07:00
David Katleman
34db0587a4 Added tag jdk8-b07 for changeset dff0b2eda2a8 2011-09-29 18:53:48 -07:00
David Katleman
f5d9fec70d Added tag jdk8-b07 for changeset 3793fe38dc85 2011-09-29 18:53:42 -07:00
David Katleman
5be998e5ce Added tag jdk8-b07 for changeset 24e2df5cb0b0 2011-09-29 18:53:38 -07:00
David Katleman
261f588e13 Added tag jdk8-b07 for changeset 5b03d68a6a38 2011-09-29 18:53:33 -07:00
Volker Simonis
812f619214 7096016: SA build still produces "arg list too long" errors
Reviewed-by: kvn, never
2011-09-29 13:47:57 -07:00
Tom Rodriguez
f103a0e31f 7092278: "jmap -finalizerinfo" throws "sun.jvm.hotspot.utilities.AssertionFailure: invalid cp index 0 137"
Reviewed-by: kvn
2011-09-29 09:53:56 -07:00
Kurchi Subhra Hazra
e83fde21ff 7092375: Security Libraries don't build with javac -Werror
Changes to security related java and make files to remove warnings

Reviewed-by: xuelei
2011-09-28 15:10:02 -07:00
Chris Hegarty
08d82ca044 7099488: TwoStacksPlainSocketImpl should invoke super.create(stream), typo in fix for 7098719
Reviewed-by: coffeys
2011-10-11 12:06:46 +01:00
Neil Richards
bbcff1b792 Merge 2011-10-10 16:13:38 +01:00
Chris Hegarty
e92787f075 7098755: test/sun/misc/JarIndex/metaInfFilenames/Basic.java should use supported compiler interface
Reviewed-by: mcimadamore
2011-10-10 15:29:24 +01:00
Steve Poole
9a2fc5f236 7099119: Remove unused dlinfo local variable in launcher code
Reviewed-by: ohair, chegar, ngmr
2011-10-10 14:50:51 +01:00
Chris Hegarty
214254cac5 7098719: -Dsun.net.maxDatagramSockets and Socket constructor does not work correctly with System.gc()
Reviewed-by: michaelm
2011-10-10 10:38:35 +01:00
Vinnie Ryan
a3fcc12dc8 7094377: Com.sun.jndi.ldap.read.timeout doesn't work with ldaps
Reviewed-by: chegar
2011-10-07 14:09:53 +01:00
Naoto Sato
7af669ecc0 7098394: JDK8 TL repo build fails in src/solaris/native/java/util/TimeZone_md.c
Reviewed-by: chegar
2011-10-06 17:40:16 -07:00
Chris Hegarty
d5e5ad5996 7090499: missing rawtypes warnings in anonymous inner class
Fix anonymous inner classes with raw types currently being built in the jdk with -Werror

Reviewed-by: mcimadamore, alanb
2011-10-06 12:15:07 +01:00
Masayoshi Okutsu
a9ef11a8d4 7092679: (tz) Java getting wrong timezone/DST info on Solaris 11
6984762: Invalid close of file descriptor '-1' in findZoneinfoFile

Reviewed-by: coffeys, ohair, naoto, peytoia
2011-10-05 15:13:40 +09:00
Chris Hegarty
1d5bbbec86 7095949: java/net/URLConnection/RedirectLimit.java and Redirect307Test fail intermittently
Reviewed-by: alanb
2011-10-04 16:37:08 +01:00
Kurchi Subhra Hazra
ebd4f912d7 6953455: CookieStore.add() cannot handle null URI parameter, contrary to the API
Reviewed-by: chegar, mduigou
2011-10-04 13:48:41 +01:00
Bengt Rutisson
cfe349b1e0 7005808: G1: re-enable ReduceInitialCardMarks for G1
Remove the extra guard to allow G1 to use ReduceInitialCardMarks

Reviewed-by: jmasa, tonyp, johnc, ysr
2011-09-28 08:21:30 +02:00
Weijun Wang
650bd8320d 7077646: gssapi wrap for CFX per-message tokens always set FLAG_ACCEPTOR_SUBKEY
Reviewed-by: valeriep
2011-09-28 14:21:11 +08:00
Weijun Wang
a912e7557c 7077640: gss wrap for cfx doesn't handle rrc != 0
Reviewed-by: valeriep
2011-09-28 14:21:10 +08:00
Weijun Wang
a099202006 7089889: Krb5LoginModule.login() throws an exception if used without a keytab
Reviewed-by: xuelei, valeriep
2011-09-28 14:21:10 +08:00
Oleg Pekhovskiy
45df73bc12 7073337: Crash after playing Java game on Pogo
Reviewed-by: art, uta
2011-09-27 13:38:29 +04:00
Kurchi Subhra Hazra
09ff856431 7088502: Security libraries don't build with javac -Werror
Changes to files in src/share/classes/com/sun/org/apache/xml/internal/security and its subpackages to remove warnings

Reviewed-by: mullan
2011-09-26 17:20:45 -07:00
David Buck
daa2552a25 7029903: Splash screen is not shown in 64-bit Linux with 16-bit color depth
Added Xflush() call after splash screen is updated to ensure update is no stuck in client side buffer until JVM starts up. See JET review request 4154 for details.

Reviewed-by: kevinw, anthony
2011-09-26 15:40:05 -07:00
Lana Steuck
3ae6cc4f7e Merge 2011-09-26 14:33:34 -07:00
Lana Steuck
3d1e626d8f Merge 2011-09-26 14:32:38 -07:00
Lana Steuck
238736e33d Merge 2011-09-26 14:31:05 -07:00
Lana Steuck
9f70387b50 Merge 2011-09-26 14:30:38 -07:00
Lana Steuck
79c9b7b711 Merge 2011-09-26 14:29:34 -07:00
Kurchi Subhra Hazra
8987ea2bdf 7084030: DatagramSocket.getLocalAddress inconsistent on XP/2003 when IPv6 enabled and socket is connected
Use family of connected IP address to retrieve desired local address of the datagram socket

Reviewed-by: chegar
2011-09-26 11:48:37 -07:00
Vladimir Kozlov
47e357e16f 7081933: Use zeroing elimination optimization for large array
Don't zero new typeArray during runtime call if the allocation is followed by arraycopy into it.

Reviewed-by: twisti
2011-09-26 10:24:05 -07:00
Denis Fokin
89371ad57d 7080289: AWTKeystroke class registers a subclass factory during deserialization
Reviewed-by: serb
2011-09-26 18:18:29 +04:00
Chris Hegarty
2d492ea7e1 7094141: test/sun/misc/JarIndex/metaInfFilenames/Basic.java no longer compiles
Reviewed-by: alanb
2011-09-26 15:04:59 +01:00
Clemens Eisserer
20558b33b9 7081670: Disposing an AppContext can lead to a spinning EventDispatchThread
Reviewed-by: art, anthony, dholmes
2011-09-26 17:59:52 +04:00
Pavel Porvatov
3cfef23dff 7088744: SwingUtilities.isMiddleMouseButton does not work with ALT/Meta keys
Reviewed-by: alexp
2011-09-26 17:37:08 +04:00
Weijun Wang
0ac639e5b0 7094842: test/javax/security/auth/Subject/{Synch.java,Synch2.java,Synch3.java} loop forever in agentvm mode
Reviewed-by: alanb
2011-09-26 17:13:47 +08:00
Kurt Miller
95c56a472b 7089790: integrate bsd-port changes
Co-authored-by: Greg Lewis <glewis@eyesbeyond.com>
Co-authored-by: Jung-uk Kim <jkim@freebsd.org>
Co-authored-by: Christos Zoulas <christos@zoulas.com>
Co-authored-by: Landon Fuller <landonf@plausible.coop>
Co-authored-by: The FreeBSD Foundation <board@freebsdfoundation.org>
Co-authored-by: Michael Franz <mvfranz@gmail.com>
Co-authored-by: Roger Hoover <rhoover@apple.com>
Co-authored-by: Alexander Strange <astrange@apple.com>
Reviewed-by: kvn, twisti, jrose
2011-09-25 16:03:29 -07:00
Lana Steuck
d941d29b0c Merge 2011-09-23 23:30:31 -07:00
Lana Steuck
633ccfc791 Merge 2011-09-23 23:29:56 -07:00
Lana Steuck
1c1cfca47c Merge 2011-09-23 23:25:30 -07:00
Lana Steuck
f13c56e8aa Merge 2011-09-23 16:51:29 -07:00
Lana Steuck
f181b4c76d Merge 2011-09-23 16:50:37 -07:00
Doug Lea
2d19ea519b 7091003: ScheduledExecutorService never executes Runnable with corePoolSize of zero
Reviewed-by: dholmes, chegar
2011-09-23 14:24:04 +01:00
David Katleman
93cf5130d6 Added tag jdk8-b06 for changeset c579ee9c7624 2011-09-22 16:02:16 -07:00
David Katleman
7b62b4870c Added tag jdk8-b06 for changeset d91b32b59eda 2011-09-22 16:02:08 -07:00
David Katleman
2587f18d1c Added tag jdk8-b06 for changeset 3632c6a1c35c 2011-09-22 16:02:05 -07:00
David Katleman
0761734777 Added tag jdk8-b06 for changeset 301b3b8fc6aa 2011-09-22 16:02:05 -07:00
David Katleman
9ebcc8e000 Added tag jdk8-b06 for changeset d062411f33d7 2011-09-22 16:01:59 -07:00
David Katleman
c055987003 Added tag jdk8-b06 for changeset 553337da9f77 2011-09-22 16:01:56 -07:00
David Katleman
a4515c2fa3 Added tag jdk8-b06 for changeset f6b03ab4a2b6 2011-09-22 16:01:51 -07:00
Jonathan Gibbons
4a8efe66a5 7075721: javac should have public enum for exit codes
Reviewed-by: mcimadamore
2011-09-22 09:24:01 -07:00
Kevin Walls
f4e1298403 7051189: Need to suppress info message if -xcheck:jni used with libjsig.so
Reviewed-by: coleenp, minqi
2011-09-22 16:48:41 +01:00
Joe Darcy
82e488e3ae 7092404: Add Math.nextDown and Double.isFinite
Reviewed-by: mduigou
2011-09-21 23:22:11 -07:00
Jonathan Gibbons
ff7362918f 7092965: javac should not close processorClassLoader before end of compilation
Reviewed-by: darcy
2011-09-21 21:56:53 -07:00
Weijun Wang
035522bd7a 7092627: use agentvm mode instead of samevm in regtests
Reviewed-by: alanb, dsamersoff
2011-09-22 12:05:26 +08:00
Michael McMahon
9486648fdf Merge 2011-09-21 14:54:38 +01:00
Michael McMahon
98f96fac17 7079012: test/java/net/NetworkInterface/NetParamsTest.java fails with SocketException getting mac address
Reviewed-by: chegar, alanb
2011-09-21 14:51:01 +01:00
Charles Lee
daed5f0dd3 7032018: The file list in JFileChooser does not have an accessible name
Reviewed-by: rupashka
2011-09-21 17:08:02 +04:00
Tom Rodriguez
52f0eccb24 7092236: java/util/EnumSet/EnumSetBash.java fails
Reviewed-by: kvn, twisti, jrose
2011-09-20 23:50:16 -07:00
David Holmes
d9b7e6c18c 7012206: ~20 tools tests failing due to -XX:-UsePerfData default in Java SE Embedded
Explicitly enable UsePerfData for the tools that require it to be enabled

Reviewed-by: alanb, ohair
2011-09-20 22:20:05 -04:00
Daniel D. Daugherty
43b11a7dca 7085944: 3/3 FDS: gdb does not find debug symbols for libjsig link
Add support for importing .debuginfo files from HSX.

Reviewed-by: phh
2011-09-20 19:16:21 -07:00
Joe Darcy
17af9b241a 6268216: Boolean.getBoolean() throws SecurityException
Reviewed-by: mduigou
2011-09-20 18:33:25 -07:00
Mike Duigou
b9c11d661e 7074264: Switches to packages tree view and adds unit tests to sources
Reviewed-by: igor
2011-09-20 12:27:45 -07:00
Jonathan Gibbons
1577e0f073 7030473: Remove dead field JCCompilationUnit.flags
Reviewed-by: dlsmith
2011-09-20 12:08:48 -07:00
Vladimir Kozlov
a46128d0dd 7081842: assert(Compile::current()->unique() < (uint)MaxNodeLimit) failed: Node limit exceeded
Add missing node limit check in IGVN optimizer

Reviewed-by: iveresov, never
2011-09-20 08:39:40 -07:00
Weijun Wang
4d4a89de9b 7091290: fails to build jdk8 b05 Embedded build
Reviewed-by: xuelei, dholmes
2011-09-20 12:40:23 +08:00
Igor Veresov
9661feecbc 7091764: Tiered: enable aastore profiling
Turn on aastore profiling

Reviewed-by: jrose, twisti
2011-09-19 15:21:03 -07:00
Daniel D. Daugherty
55bfd400ca Merge 2011-09-19 12:18:46 -07:00
Michael McMahon
b88865d91f 7091369: DatagramSocket/Limit.java failing on 8 and 7u2
Reviewed-by: chegar, alanb
2011-09-19 15:14:17 +01:00
Andrew Brygin
b89d40e747 7088287: libpng need to be updated
Reviewed-by: jgodinez, prr
2011-09-19 05:56:44 -07:00
Joe Darcy
5b7643e258 7091682: Move sun.misc.FpUtils code into java.lang.Math
Reviewed-by: alanb
2011-09-18 18:14:07 -07:00
Alan Bateman
19f1338ae9 7091935: (fs) Polling based WatchService not used on Linux
Reviewed-by: forax
2011-09-18 12:33:56 +01:00
John Coomes
e3faa527bd 7091545: hs23 - set hotspot version & build number
Reviewed-by: tonyp, never, phh, jmasa
2011-09-16 21:35:06 -07:00
Daniel D. Daugherty
d381d4b0b4 7071904: 4/4 HotSpot: Full Debug Symbols
Add support for .debuginfo files for HSX libraries.

Reviewed-by: poonam, dholmes, never
2011-09-16 16:21:20 -07:00
Jonathan Gibbons
51763c43f7 7091528: javadoc attempts to parse .class files
Reviewed-by: darcy
2011-09-16 16:18:46 -07:00
Kurchi Subhra Hazra
3580661098 7090158: Networking Libraries don't build with javac -Werror
Minor changes to networking java files to remove warnings

Co-authored-by: Alexandre Boulgakov <sasha_bu@hotmail.com>
Reviewed-by: chegar, weijun, hawtin
2011-09-16 12:09:04 -07:00
Maurizio Cimadamore
bd420dc94e 7086586: Inference producing null type argument
Inference should fail in 15.12.2.7 when inference variables with 'nulltype' upper bounds are found

Reviewed-by: dlsmith
2011-09-16 14:16:11 +01:00
John Coomes
854ad24077 Added tag hs22-b06 for changeset 9de632dc424b 2011-09-15 20:56:24 -07:00
Alejandro Murillo
303c03e2ea 7091255: Bump the hs22 build number to 06
Reviewed-by: johnc
2011-09-15 20:56:24 -07:00
John Coomes
86b01d9960 7091294: disable quicksort tests
Reviewed-by: jmasa, ysr, kvn
2011-09-15 20:30:12 -07:00
John Coomes
db1c1037b5 Merge 2011-09-15 19:33:39 -07:00
Igor Veresov
0e0ba86cd8 Merge 2011-09-15 12:44:09 -07:00
Michael McMahon
49849e0dcf Merge 2011-09-15 14:10:30 +01:00
Michael McMahon
f9cd96b19b 7073491: -Dsun.net.maxDatagramSockets=1 does not work correctly with system.gc()
Reviewed-by: ngmr
2011-09-15 13:50:30 +01:00
Pavel Porvatov
782f6f887e 7090007: Missing style.css in nimbus/doc-files/properties.html
Reviewed-by: alexp
2011-09-15 16:43:25 +04:00
Yuka Kamiya
0594a39498 7090843: (tz) Support tzdata2011j
Reviewed-by: okutsu
2011-09-15 15:02:05 +09:00
Yuka Kamiya
3674ebe6e6 7090844: Support a timezone whose offset is changed more than once in the future
Reviewed-by: okutsu
2011-09-15 14:45:35 +09:00
Mala Bankal
6624a6c8d1 Merge 2011-09-14 22:36:02 -07:00
Mala Bankal
d9777d76bd 7049963: DISTINGUISHED NAMES FOR CERT ARE ESCAPED IN JROCKIT 1.6(NOT COMPATIBLE WITH JROC
Reviewed-by: mullan
2011-09-14 21:43:42 -07:00
Jonathan Gibbons
4589920917 7068437: Regression: Filer.getResource(SOURCE_OUTPUT, ...) no longer works in JDK 7 w/o -s
Reviewed-by: darcy
2011-09-14 18:26:57 -07:00
Jonathan Gibbons
afaeb37bb5 7090700: fix for 7080267 breaks two tests
Reviewed-by: ksrini
2011-09-14 15:49:54 -07:00
Tom Rodriguez
a300a41ea1 7090654: nightly failures after 7086585
Reviewed-by: kvn
2011-09-14 13:57:32 -07:00
Joe Darcy
2c3a780b41 7088500: there is no @since tag on SafeVarargs
Reviewed-by: mduigou
2011-09-14 13:09:15 -07:00
Jonathan Gibbons
2bbf651156 7090249: IllegalStateException from Trees.getScope when called from JSR 199
Reviewed-by: mcimadamore
2011-09-14 12:14:30 -07:00
Jonathan Gibbons
1ec8f70fdd 7080267: Call to toString() from an ExpressionStatementTree doesn't take in consideration the ";" at the end
Reviewed-by: mcimadamore
2011-09-14 12:07:50 -07:00
Joe Darcy
30d2b45bd8 6879143: java.math.BigInteger misses the xxxValueExact methods
Reviewed-by: alanb
2011-09-14 11:32:11 -07:00
Mandy Chung
16a24a909d 6915797: Remove sun.tools.jar.JarImageSource that is not used
7090178: Move java.util.XMLUtils to another package to avoid split package

Reviewed-by: alanb, sherman
2011-09-14 08:33:34 -07:00
Bertrand Delsart
bc855ff2e0 7077806: ARM: java.lang.InternalError: bound subword value does not fit into the subword type
Shared fix necessary for ARM/PPC

Reviewed-by: twisti, roland
2011-09-14 16:28:39 +02:00
Bertrand Delsart
fcc31d9741 7057978: improve robustness of c1 ARM back-end wrt non encodable constants
ARM only, avoid assertion failures for huge constants generated by C1 shared code

Reviewed-by: never, vladidan
2011-09-14 10:40:13 +02:00
Vladimir Kozlov
f99084037a 7090259: Fix hotspot sources to build with old compilers
Fixed warnings which prevent building VM with old compilers.

Reviewed-by: never
2011-09-13 20:28:00 -07:00
Igor Veresov
9b101c8ba6 7090069: Java launcher hangs in infinite loop on windows when UseNUMA[Interleaving] is specified
Fix _numa_used_node_list array size specification

Reviewed-by: kvn, johnc, jmasa, ysr
2011-09-13 16:58:35 -07:00
Mandy Chung
12a0dac949 7090297: Remove com.sun.tools.javac.Launcher from tools.jar
Reviewed-by: jjg
2011-09-13 16:37:09 -07:00
Vladimir Kozlov
e756c96259 7089632: assert(machtmp->outcnt() == 1) failed: expected for a MachTemp
Replace assert with check to delete MachTemp nodes only when they are really dead.

Reviewed-by: never
2011-09-13 11:46:51 -07:00
Antonios Printezis
7d850203b9 7089625: G1: policy for how many old regions to add to the CSet (when young gen is fixed) is broken
When refactoring the code for a previous fix, a condition was not correctly negated which prevents the G1 policy from adding the correct number of old regions to the CSet when the young gen size is fixed. The changeset also fixes a small syntactical issue in g1ErgoVerbose.hpp which is causing compiler warnings.

Reviewed-by: brutisso, ysr
2011-09-13 12:40:14 -04:00
Lana Steuck
c755492882 Merge 2011-09-13 08:37:34 -07:00
Maurizio Cimadamore
08619c2e9c 7086601: Error message bug: cause for method mismatch is 'null'
Inference error during lub() does not set 'cause' for method resolution diagnostic

Reviewed-by: jjg
2011-09-13 14:15:39 +01:00
Maurizio Cimadamore
0208d38b3c 7003595: IncompatibleClassChangeError with unreferenced local class with subclass
Compiler omits unreferenced local inner classes from the InnerClasses attribute

Reviewed-by: jjg
2011-09-13 14:15:22 +01:00
Maurizio Cimadamore
8db2f8de59 7086595: Error message bug: name of initializer is 'null'
Implementation of MethodSymbol.location() should take into account static/instance initializers

Reviewed-by: jjg
2011-09-13 14:14:57 +01:00
Sean Coffey
81d33c4727 7082769: FileInputStream/FileOutputStream/RandomAccessFile allow file descriptor be closed when still in use
Reviewed-by: alanb
2011-09-13 11:21:51 +01:00
Tom Rodriguez
1f8f1f79be 7089709: type "jushort" not found
Reviewed-by: kvn, twisti
2011-09-12 13:51:40 -07:00
Stefan Karlsson
a4523cfc7f 7021322: assert(object_end <= top()) failed: Object crosses promotion LAB boundary
Pass the same object size value to both allocate and unallocate_object

Reviewed-by: ysr, brutisso
2011-09-12 16:09:50 +02:00
Antonios Printezis
75685a273a 7097048: G1: extend the G1 SA changes to print per-heap space information
Reviewed-by: brutisso, johnc
2011-10-03 19:04:14 -04:00
John Cuthbertson
02e9894454 7097053: G1: assert(da ? referent->is_oop() : referent->is_oop_or_null()) failed: referenceProcessor.cpp:1054
During remembered set scanning, the reference processor could discover a reference object whose referent was in the process of being copied and so may not be completely initialized. Do not perform reference discovery during remembered set scanning.

Reviewed-by: tonyp, ysr
2011-10-03 12:49:53 -07:00
John Cuthbertson
bbfe9c6e25 7086533: G1: assert(!_g1->is_obj_dead(obj)): We should not be preserving dead objs: g1CollectedHeap.cpp:3835
Some objects may not be marked in the event of an evacuation failure in a partially young GC, during a marking cycle. Avoid this situation by not allowing partially young GCs during a marking cycle.

Reviewed-by: tonyp, ysr, brutisso
2011-09-28 10:36:31 -07:00
Bengt Rutisson
cc177fd515 7091366: re-enable quicksort tests
Added extern "C" to make it build with JDK6 compilers

Reviewed-by: jwilhelm, kvn
2011-09-26 10:14:30 +02:00
Antonios Printezis
55c503aea2 7075646: G1: fix inconsistencies in the monitoring data
Fixed a few inconsistencies in the monitoring data, in particular when reported from jstat.

Reviewed-by: jmasa, brutisso, johnc
2011-09-23 16:07:49 -04:00
John Cuthbertson
1b62d10b4b 6484982: G1: process references during evacuation pauses
G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.

Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
2011-09-22 10:57:37 -07:00
Antonios Printezis
70bb8e788e 7092238: G1: Uninitialized field gc_efficiency in G1PrintRegionLivenessInfo output
Reviewed-by: jcoomes, johnc
2011-09-22 07:18:51 -04:00
John Cuthbertson
08bdb35a29 7092245: G1: Wrong format specifier in G1PrintRegionLivenessInfo header output
Cast HeapRegion::GrainBytes to size_t in output statement.

Reviewed-by: ysr, brutisso, pbk, tonyp
2011-09-21 15:24:07 -07:00
Antonios Printezis
0f7ff53cce 7091032: G1: assert failure when NewRatio is used
The desired min / max heap sizes are miscalculated at initialization when NewRatio is used. The changeset also includes an additional small change to turn a print statement into a warning.

Reviewed-by: johnc, jmasa, ysr, brutisso
2011-09-21 13:36:37 -04:00
John Cuthbertson
2f83b52706 7068215: G1: Print reference processing time during remark
Displays the elapsed time taken to perform reference processing during remark as part of the PrintGCDetails output.

Reviewed-by: ysr
2011-09-21 10:04:45 -07:00
Antonios Printezis
c5b2025c02 7045232: G1: pool names are inconsistent with other collectors (don't have 'Space')
Make sure the eden and survivor pools have "Space" in their name.

Reviewed-by: jmasa, ysr
2011-09-21 01:27:20 -04:00
John Cuthbertson
3ae9021b59 7092412: G1: Some roots not marked during an initial mark that gets an evacuation failure
As a result of the changes for 7080389, an evacuation failure during an initial mark pause may result in some root objects not being marked. Pass whether the caller is a root scanning closure into the evacuation failure handling code so that the thread that successfully forwards an object to itself also marks the object.

Reviewed-by: ysr, brutisso, tonyp
2011-09-20 15:39:17 -07:00
Antonios Printezis
95832db2e5 7059019: G1: add G1 support to the SA
Extend the SA to recognize the G1CollectedHeap and implement any code that's needed by our serviceability tools (jmap, jinfo, jstack, etc.) that depend on the SA.

Reviewed-by: never, poonam, johnc
2011-09-20 09:59:59 -04:00
Tom Rodriguez
e3afdf10ad 7088955: add C2 IR support to the SA
Reviewed-by: kvn
2011-09-11 14:48:24 -07:00
Tom Rodriguez
e39ba1a5fe 7086585: make Java field injection more flexible
Reviewed-by: jrose, twisti, kvn, coleenp
2011-09-10 17:29:02 -07:00
Tom Rodriguez
1ebca30d26 7088020: SEGV in JNIHandleBlock::release_block
Reviewed-by: kvn, twisti
2011-09-10 00:11:04 -07:00
John Coomes
d6fd9c2339 Added tag hs22-b05 for changeset 2787676b53cf 2011-09-09 16:33:13 -07:00
Alejandro Murillo
8ad902f1ed 7088991: Bump ths hs22 build number to 05
Reviewed-by: johnc
2011-09-09 16:24:12 -07:00
John Coomes
8bc1babb6d Merge 2011-09-09 16:17:16 -07:00
Vladimir Kozlov
92b2b44b18 7035946: Up to 15% regression on JDK 7 b136 vs b135 on specjvm2008.crypto.rsa on x64
Revert changes which caused regression.

Reviewed-by: never
2011-09-09 13:47:11 -07:00
Igor Veresov
67ba51cae8 Merge 2011-09-09 12:44:37 -07:00
Stefan Karlsson
bfa7e324d9 Merge 2011-09-09 14:44:43 +02:00
Antonios Printezis
1a9d9b84f8 7087717: G1: make the G1PrintRegionLivenessInfo parameter diagnostic
Reviewed-by: brutisso, ysr
2011-09-09 05:20:58 -04:00
Bengt Rutisson
0be11c915c 6929868: G1: introduce min / max young gen size bounds
Make G1 handle young gen size command line flags more consistently

Reviewed-by: tonyp, jwilhelm
2011-09-08 16:29:41 +02:00
Robert Ottenhag
b62fb1de97 Merge 2011-09-08 06:36:31 -07:00
Antonios Printezis
d96de580b6 7084509: G1: fix inconsistencies and mistakes in the young list target length calculations
Fixed inconsistencies and mistakes in the young list target length calculations so that a) the calculated target length is optimal (before, it was not), b) other parameters like max survivor size and max gc locker eden expansion are always consistent with the calculated target length (before, they were not always), and c) the resulting target length was always bound by desired min and max values (before, it was not).

Reviewed-by: brutisso, johnc
2011-09-08 05:16:49 -04:00
Roland Westrelin
499732d316 7087453: PhaseChaitin::yank_if_dead() should handle MachTemp inputs
PhaseChaitin::yank_if_dead() should be able to handle MachTemp inputs as a special case and yank them.

Reviewed-by: never, kvn
2011-09-08 09:35:41 +02:00
Vladimir Kozlov
42c3c5cb7b 7087947: Add regression test for 7068051
Add regression test.

Reviewed-by: never
2011-09-08 12:44:04 -07:00
Christian Thalinger
439b75eb12 7085860: JSR 292: implement CallSite.setTargetNormal and setTargetVolatile as native methods
Reviewed-by: jrose, never
2011-09-08 05:11:31 -07:00
Bertrand Delsart
6141a568aa 7087445: Improve platform independence of JSR292 shared code
Changes necessary for some JSR292 ports

Reviewed-by: jrose, dholmes
2011-09-08 10:12:25 +02:00
Tom Rodriguez
50bc4343b3 7082631: JSR 292: need profiling support in GWTs
Add CountingMethodHandle

Reviewed-by: twisti, jrose
2011-09-07 21:05:24 -07:00
Igor Veresov
1940a13d31 7086226: UseNUMA fails on old versions of windows
Return correct answers from os::numa_*() for UMA machines or if NUMA API is not supported

Reviewed-by: johnc
2011-09-07 18:58:33 -07:00
Weijun Wang
83b6b7ace1 7087428: move client tests out of jdk_misc
Reviewed-by: ohair, alanb
2011-09-08 09:06:09 +08:00
Y. Srinivas Ramakrishna
ed72e31727 4965777: GC changes to support use of discovered field for pending references
If and when the reference handler thread is able to use the discovered field to link reference objects in its pending list, so will GC. In that case, GC will scan through this field once a reference object has been placed on the pending list, but not scan that field before that stage, as the field is used by the concurrent GC thread to link discovered objects. When ReferenceHandleR thread does not use the discovered field for the purpose of linking the elements in the pending list, as would be the case in older JDKs, the JVM will fall back to the old behaviour of using the next field for that purpose.

Reviewed-by: jcoomes, mchung, stefank
2011-09-07 13:55:42 -07:00
Y. Srinivas Ramakrishna
ec13301b32 Merge 2011-09-07 15:00:13 -07:00
Vladimir Kozlov
61068411fa 7054211: No loop unrolling done in jdk7b144 for a test update() while loop
Restore unrolling code for CaffeineMark.

Reviewed-by: never
2011-09-07 12:58:42 -07:00
Igor Veresov
315ec64dce Merge 2011-09-07 11:52:00 -07:00
Antonios Printezis
24eb07061e 7050392: G1: Introduce flag to generate a log of the G1 ergonomic decisions
It introduces ergonomic decision logging in G1 for the following heuristics: heap sizing, collection set construction, concurrent cycle initiation, and partially-young GC start/end. The code has a bit of refactoring in a few places to make the decision logging possible. It also replaces alternative ad-hoc logging that we have under different parameters and switches (G1_DEBUG, G1PolicyVerbose).

Reviewed-by: johnc, ysr
2011-09-07 12:21:23 -04:00
Roland Westrelin
90844ca5dc 7085012: ARM: com/sun/jdi/PopSynchronousTest.java still fails
InterpreterRuntime::popframe_move_outgoing_args() is required for the ARM interpreter.

Reviewed-by: kvn, twisti
2011-09-07 14:15:07 +02:00
Roland Westrelin
48ecf5dfe4 7086394: c2/arm: enable UseFPUForSpilling
ARM has instructions to move data directly between the fpu and integer registers.

Reviewed-by: kvn, never
2011-09-07 09:35:52 +02:00
Igor Veresov
a9cd50a1c8 7087583: Hotspot fails to allocate heap with mmap(MAP_HUGETLB)
Try using small pages when transparent huge pages allocation fails

Reviewed-by: ysr
2011-09-06 21:03:51 -07:00
Tom Rodriguez
edb7b9514a 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
Reviewed-by: kvn
2011-09-05 17:09:05 -07:00
Vladimir Kozlov
dece7fbfec 7086560: 7085404 changes broke VM with -XX:-EnableInvokeDynamic
Add check that ciEnv::_CallSite_klass is initialized.

Reviewed-by: jrose
2011-09-03 14:03:54 -07:00
Tom Rodriguez
b13890a199 Merge 2011-09-03 09:56:57 -07:00
Tom Rodriguez
d4d5856fd4 7016881: JSR 292: JDI: sun.jvm.hotspot.utilities.AssertionFailure: index out of bounds
Reviewed-by: kvn, twisti
2011-09-02 22:00:49 -07:00
John Coomes
4a09997f51 Merge 2011-09-02 21:33:57 -07:00
Tom Rodriguez
32fd1b087d 7071307: MethodHandle bimorphic inlining should consider the frequency
Reviewed-by: twisti, roland, kvn, iveresov
2011-09-02 20:58:21 -07:00
John Coomes
c8c58542b3 Added tag hs22-b04 for changeset 741bcb34b337 2011-09-02 15:52:03 -07:00
Vladimir Kozlov
f7d7a6071a 7039731: arraycopy could use prefetch on SPARC
Use BIS and prefetch in arraycopy stubs for Sparc (BIS for T4 only).

Reviewed-by: never, iveresov
2011-09-02 12:13:33 -07:00
Christian Thalinger
1038fed51d 7071709: JSR 292: switchpoint invalidation should be pushed not pulled
Reviewed-by: never
2011-09-02 04:28:59 -07:00
Alejandro Murillo
096ba80aea 7086589: bump the hs22 build number to 04
Reviewed-by: johnc
2011-09-02 03:49:30 -07:00
John Coomes
d42d7de7ff Added tag hs22-b03 for changeset 52cac2467a60 2011-09-02 15:47:43 -07:00
John Coomes
87501184d9 Added tag hs22-b02 for changeset 7adf55aec150 2011-09-02 15:47:43 -07:00
John Coomes
b57839cc49 Added tag hs22-b01 for changeset 2143c41c2a90 2011-09-02 15:47:42 -07:00
Christian Thalinger
db44acbeb4 7085404: JSR 292: VolatileCallSites should have push notification too
Reviewed-by: never, kvn
2011-09-02 00:36:18 -07:00
Stefan Karlsson
5b6ba4e611 7085906: Replace the permgen allocated sentinelRef with a self-looped end
Remove the sentinelRef and let the last Reference in a discovered chain point back to itself.

Reviewed-by: ysr, jmasa
2011-09-01 16:18:17 +02:00
Christian Thalinger
fcc2a86582 7079673: JSR 292: C1 should inline bytecoded method handle adapters
Reviewed-by: never
2011-09-01 01:31:25 -07:00
Y. Srinivas Ramakrishna
74b5a420d5 Merge 2011-08-31 23:55:58 -07:00
Tom Rodriguez
fa7c124af1 7083786: dead various dead chunks of code
Reviewed-by: iveresov, kvn
2011-08-31 16:46:11 -07:00
John Cuthbertson
6c8c4fb321 7066841: remove MacroAssembler::br_on_reg_cond() on sparc
Remove the macro assembler routine br_on_reg_cond() and replace the remaining calls to that routine with an equivalent.

Reviewed-by: kvn, iveresov
2011-08-31 10:16:02 -07:00
Vladimir Kozlov
9c87ea9062 7085137: -XX:+VerifyOops is broken
Replace set() with patchable_set() to generate 8 instructions always.

Reviewed-by: iveresov, never, roland
2011-08-31 09:48:21 -07:00
Christian Thalinger
05b60b3662 7078382: JSR 292: don't count method handle adapters against inlining budgets
Reviewed-by: kvn, never
2011-08-31 01:40:45 -07:00
Igor Veresov
5903a384b4 7085279: C1 overflows code buffer with VerifyOops and CompressedOops
Increase the limit of code emitted per LIR instruction, increase the max size of the nmethod generated by C1

Reviewed-by: never, kvn, johnc
2011-08-30 19:01:58 -07:00
Tom Rodriguez
cebdce4479 7082263: Reflection::resolve_field/field_get/field_set are broken
Reviewed-by: kvn, dholmes, stefank, coleenp
2011-08-30 00:54:09 -07:00
Igor Veresov
d8fd276e35 7082645: Hotspot doesn't compile on old linuxes after 7060836
Move syscall ids definitions into os_linux.cpp

Reviewed-by: johnc
2011-08-29 17:42:39 -07:00
John Cuthbertson
1bec3a1bd3 7080389: G1: refactor marking code in evacuation pause copy closures
Refactor code marking code in the evacuation pause copy closures so that an evacuated object is only marked by the thread that successfully copies it.

Reviewed-by: stefank, brutisso, tonyp
2011-08-29 10:13:06 -07:00
Christian Thalinger
e3342531b4 7083184: JSR 292: don't store context class argument with call site dependencies
Reviewed-by: jrose, never
2011-08-29 05:07:35 -07:00
Igor Veresov
ec3f90d1b4 6591247: C2 cleans up the merge point too early during SplitIf
Remove region self reference last

Reviewed-by: kvn, never
2011-08-27 00:23:47 -07:00
Vladimir Kozlov
6446205688 7059037: Use BIS for zeroing on T4
Use BIS for zeroing new allocated big (2Kb and more) objects and arrays.

Reviewed-by: never, twisti, ysr
2011-08-26 08:52:22 -07:00
Tom Rodriguez
19f7fb98b8 7082949: JSR 292: missing ResourceMark in methodOopDesc::make_invoke_method
Reviewed-by: kvn, twisti
2011-08-25 20:29:30 -07:00
Tom Deneau
06d05b7c47 7082969: NUMA interleaving
Support interleaving on NUMA systems for collectors that don't have NUMA-awareness.

Reviewed-by: iveresov, ysr
2011-08-25 02:57:46 -07:00
1168 changed files with 67753 additions and 43014 deletions

View File

@@ -127,3 +127,7 @@ de9223c94f9c710b3eebb599cd3586f36c8b94a9 jdk8-b01
6815e85bf96d6d3875954f9777660372cd70d065 jdk8-b03
31f5c34d78081572ad9a2401c0bb0c6b9711dd65 jdk8-b04
c4f9ea1ecb55ff44e0dd21d2888ead308c86a3aa jdk8-b05
429da7734bf491bccde2a752fae97e9f225896dc jdk8-b06
bc5710332b294676661103bb20d47d2ea3ba8def jdk8-b07
24ee504f80412770c6874836cd9e55b536427b1d jdk8-b08
fbf3cabc9e3bb1fcf710941d777cb0400505fbe6 jdk8-b09

View File

@@ -127,3 +127,7 @@ f42e3d9394b40a423d345b8da22687b5462e5f25 jdk8-b01
587bb549dff83131b65f40aa51864f69562f34a7 jdk8-b03
0b66a233bfb9ba2ebda1e5cdfdb0373d6c1e3c69 jdk8-b04
b910aac18c772b823b1f7da03e2c6528725cc6de jdk8-b05
28cf2aec4dd7c3c75efc1c15078522467c781a6d jdk8-b06
0db7ae9f2b1017124c779bccd016c976928859a0 jdk8-b07
fb1bc13260d76447e269e843859eb593fe2a8ab2 jdk8-b08
8adb70647b5af5273dfe6a540f07be667cd50216 jdk8-b09

View File

@@ -127,3 +127,7 @@ ed8d94519a87b4adac270c3eec9134ff1f62bff5 jdk8-b02
cd0da00694fbce642db9be936d3e4909a71d911d jdk8-b03
60a68d688e24473cf84dedd1e60901a61ab82555 jdk8-b04
cc1b599b986a37cb57de4584c5e58169766ca535 jdk8-b05
45c43dde7ba7f176333a51a98f086275478836fa jdk8-b06
3d61f0856f349e2163bf98146465dab3b7437f63 jdk8-b07
0d52b1c87aa8fdea7fdc9c4126ea58f95ca6b351 jdk8-b08
a891732c1a83082177ff7a4cf1506068d9cc0a47 jdk8-b09

View File

@@ -179,3 +179,15 @@ c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143
3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03
0fa3ace511fe98fe948e751531f3e2b7c60c8376 jdk8-b04
dce7d24674f4d0bed00de24f00119057fdce7cfb jdk8-b05
0db80d8e77fccddf5e6fa49963226b54ac7d0f62 jdk8-b06
3f0cf875af83f55ec5e1a5cea80455315f9322a2 jdk8-b07
0cc8a70952c368e06de2adab1f2649a408f5e577 hs22-b01
7c29742c41b44fb0cd5a13c7ac8834f3f2ca649e hs22-b02
3a2fb61165dfc72e398179a2796d740c8da5b8c0 hs22-b03
ce9bde819dcba4a5d2822229d9183e69c74326ca hs22-b04
513a84dd0f8b56dc0836b4e0bdd5dd0a778fc634 hs22-b05
650d15d8f37255d3b805aa00c5bd1c30984b203d hs22-b06
da883b9e6d3788057f9577e72712998ed82c9b7e hs23-b01
49ed7eacfd16616166ff066493143889741097af jdk8-b08
7c20d272643f47195478708eff593a9cce40fec4 jdk8-b09
e4f412d2b75d2c797acff965aa2c420e3d358f09 hs23-b02

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -48,17 +48,18 @@ sun.jvm.hotspot.asm.x86 \
sun.jvm.hotspot.bugspot \
sun.jvm.hotspot.bugspot.tree \
sun.jvm.hotspot.c1 \
sun.jvm.hotspot.ci \
sun.jvm.hotspot.code \
sun.jvm.hotspot.compiler \
sun.jvm.hotspot.debugger \
sun.jvm.hotspot.debugger.amd64 \
sun.jvm.hotspot.debugger.bsd \
sun.jvm.hotspot.debugger.bsd.amd64 \
sun.jvm.hotspot.debugger.bsd.x86 \
sun.jvm.hotspot.debugger.cdbg \
sun.jvm.hotspot.debugger.cdbg.basic \
sun.jvm.hotspot.debugger.cdbg.basic.amd64 \
sun.jvm.hotspot.debugger.cdbg.basic.x86 \
sun.jvm.hotspot.debugger.dbx \
sun.jvm.hotspot.debugger.dbx.sparc \
sun.jvm.hotspot.debugger.dbx.x86 \
sun.jvm.hotspot.debugger.dummy \
sun.jvm.hotspot.debugger.ia64 \
sun.jvm.hotspot.debugger.linux \
@@ -76,7 +77,6 @@ sun.jvm.hotspot.debugger.remote.amd64 \
sun.jvm.hotspot.debugger.remote.sparc \
sun.jvm.hotspot.debugger.remote.x86 \
sun.jvm.hotspot.debugger.sparc \
sun.jvm.hotspot.debugger.win32 \
sun.jvm.hotspot.debugger.win32.coff \
sun.jvm.hotspot.debugger.windbg \
sun.jvm.hotspot.debugger.windbg.amd64 \
@@ -84,6 +84,7 @@ sun.jvm.hotspot.debugger.windbg.ia64 \
sun.jvm.hotspot.debugger.windbg.x86 \
sun.jvm.hotspot.debugger.x86 \
sun.jvm.hotspot.gc_implementation \
sun.jvm.hotspot.gc_implementation.g1 \
sun.jvm.hotspot.gc_implementation.parallelScavenge \
sun.jvm.hotspot.gc_implementation.shared \
sun.jvm.hotspot.gc_interface \
@@ -91,9 +92,14 @@ sun.jvm.hotspot.interpreter \
sun.jvm.hotspot.jdi \
sun.jvm.hotspot.livejvm \
sun.jvm.hotspot.memory \
sun.jvm.hotspot.opto \
sun.jvm.hotspot.oops \
sun.jvm.hotspot.prims \
sun.jvm.hotspot.runtime \
sun.jvm.hotspot.runtime.amd64 \
sun.jvm.hotspot.runtime.bsd \
sun.jvm.hotspot.runtime.bsd_amd64 \
sun.jvm.hotspot.runtime.bsd_x86 \
sun.jvm.hotspot.runtime.ia64 \
sun.jvm.hotspot.runtime.linux \
sun.jvm.hotspot.runtime.linux_amd64 \
@@ -139,17 +145,18 @@ sun/jvm/hotspot/asm/x86/*.java \
sun/jvm/hotspot/bugspot/*.java \
sun/jvm/hotspot/bugspot/tree/*.java \
sun/jvm/hotspot/c1/*.java \
sun/jvm/hotspot/ci/*.java \
sun/jvm/hotspot/code/*.java \
sun/jvm/hotspot/compiler/*.java \
sun/jvm/hotspot/debugger/*.java \
sun/jvm/hotspot/debugger/amd64/*.java \
sun/jvm/hotspot/debugger/bsd/*.java \
sun/jvm/hotspot/debugger/bsd/amd64/*.java \
sun/jvm/hotspot/debugger/bsd/x86/*.java \
sun/jvm/hotspot/debugger/cdbg/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \
sun/jvm/hotspot/debugger/dbx/*.java \
sun/jvm/hotspot/debugger/dbx/sparc/*.java \
sun/jvm/hotspot/debugger/dbx/x86/*.java \
sun/jvm/hotspot/debugger/dummy/*.java \
sun/jvm/hotspot/debugger/ia64/*.java \
sun/jvm/hotspot/debugger/linux/*.java \
@@ -165,19 +172,26 @@ sun/jvm/hotspot/debugger/remote/amd64/*.java \
sun/jvm/hotspot/debugger/remote/sparc/*.java \
sun/jvm/hotspot/debugger/remote/x86/*.java \
sun/jvm/hotspot/debugger/sparc/*.java \
sun/jvm/hotspot/debugger/win32/*.java \
sun/jvm/hotspot/debugger/win32/coff/*.java \
sun/jvm/hotspot/debugger/windbg/*.java \
sun/jvm/hotspot/debugger/windbg/ia64/*.java \
sun/jvm/hotspot/debugger/windbg/x86/*.java \
sun/jvm/hotspot/debugger/x86/*.java \
sun/jvm/hotspot/gc_implementation/g1/*.java \
sun/jvm/hotspot/gc_implementation/parallelScavenge/*.java \
sun/jvm/hotspot/gc_implementation/shared/*.java \
sun/jvm/hotspot/interpreter/*.java \
sun/jvm/hotspot/jdi/*.java \
sun/jvm/hotspot/livejvm/*.java \
sun/jvm/hotspot/memory/*.java \
sun/jvm/hotspot/oops/*.java \
sun/jvm/hotspot/opto/*.java \
sun/jvm/hotspot/prims/*.java \
sun/jvm/hotspot/runtime/*.java \
sun/jvm/hotspot/runtime/amd64/*.java \
sun/jvm/hotspot/runtime/bsd/*.java \
sun/jvm/hotspot/runtime/bsd_amd64/*.java \
sun/jvm/hotspot/runtime/bsd_x86/*.java \
sun/jvm/hotspot/runtime/ia64/*.java \
sun/jvm/hotspot/runtime/linux/*.java \
sun/jvm/hotspot/runtime/linux_amd64/*.java \

View File

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

View File

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

View File

@@ -0,0 +1,413 @@
/*
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdlib.h>
#include <jni.h>
#include "libproc.h"
#if defined(x86_64) && !defined(amd64)
#define amd64 1
#endif
#ifdef i386
#include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
#endif
#ifdef amd64
#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
#endif
#if defined(sparc) || defined(sparcv9)
#include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
#endif
static jfieldID p_ps_prochandle_ID = 0;
static jfieldID threadList_ID = 0;
static jfieldID loadObjectList_ID = 0;
static jmethodID createClosestSymbol_ID = 0;
static jmethodID createLoadObject_ID = 0;
static jmethodID getThreadForThreadId_ID = 0;
static jmethodID listAdd_ID = 0;
#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
(*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
}
static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
return (struct ps_prochandle*)(intptr_t)ptr;
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: init0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
(JNIEnv *env, jclass cls) {
jclass listClass;
if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) {
THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc");
}
// fields we use
p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
CHECK_EXCEPTION;
threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;");
CHECK_EXCEPTION;
loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
CHECK_EXCEPTION;
// methods we use
createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
"(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
CHECK_EXCEPTION;
createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
"(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
CHECK_EXCEPTION;
getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId",
"(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
CHECK_EXCEPTION;
// java.util.List method we call
listClass = (*env)->FindClass(env, "java/util/List");
CHECK_EXCEPTION;
listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
CHECK_EXCEPTION;
}
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
(JNIEnv *env, jclass cls)
{
#ifdef _LP64
return 8;
#else
return 4;
#endif
}
static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
int n = 0, i = 0;
// add threads
n = get_num_threads(ph);
for (i = 0; i < n; i++) {
jobject thread;
jobject threadList;
lwpid_t lwpid;
lwpid = get_lwp_id(ph, i);
thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID,
(jlong)lwpid);
CHECK_EXCEPTION;
threadList = (*env)->GetObjectField(env, this_obj, threadList_ID);
CHECK_EXCEPTION;
(*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread);
CHECK_EXCEPTION;
}
// add load objects
n = get_num_libs(ph);
for (i = 0; i < n; i++) {
uintptr_t base;
const char* name;
jobject loadObject;
jobject loadObjectList;
base = get_lib_base(ph, i);
name = get_lib_name(ph, i);
loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
(*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
CHECK_EXCEPTION;
loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
CHECK_EXCEPTION;
(*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
CHECK_EXCEPTION;
}
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: attach0
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
(JNIEnv *env, jobject this_obj, jint jpid) {
struct ps_prochandle* ph;
if ( (ph = Pgrab(jpid)) == NULL) {
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
}
(*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
fillThreadsAndLoadObjects(env, this_obj, ph);
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: attach0
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
(JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
const char *execName_cstr;
const char *coreName_cstr;
jboolean isCopy;
struct ps_prochandle* ph;
execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
CHECK_EXCEPTION;
coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
CHECK_EXCEPTION;
if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
(*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
}
(*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
(*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
fillThreadsAndLoadObjects(env, this_obj, ph);
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: detach0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
(JNIEnv *env, jobject this_obj) {
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
if (ph != NULL) {
Prelease(ph);
}
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: lookupByName0
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
const char *objectName_cstr, *symbolName_cstr;
jlong addr;
jboolean isCopy;
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
objectName_cstr = NULL;
if (objectName != NULL) {
objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
CHECK_EXCEPTION_(0);
}
symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
CHECK_EXCEPTION_(0);
addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
if (objectName_cstr != NULL) {
(*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
}
(*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
return addr;
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: lookupByAddress0
* Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
*/
JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
(JNIEnv *env, jobject this_obj, jlong addr) {
uintptr_t offset;
const char* sym = NULL;
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
if (sym == NULL) return 0;
return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
(*env)->NewStringUTF(env, sym), (jlong)offset);
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: readBytesFromProcess0
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
*/
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
jboolean isCopy;
jbyteArray array;
jbyte *bufPtr;
ps_err_e err;
array = (*env)->NewByteArray(env, numBytes);
CHECK_EXCEPTION_(0);
bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
CHECK_EXCEPTION_(0);
err = ps_pread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
(*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
return (err == PS_OK)? array : 0;
}
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
(JNIEnv *env, jobject this_obj, jint lwp_id) {
struct reg gregs;
jboolean isCopy;
jlongArray array;
jlong *regs;
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
}
#undef NPRGREG
#ifdef i386
#define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
#endif
#ifdef ia64
#define NPRGREG IA64_REG_COUNT
#endif
#ifdef amd64
#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
#endif
#if defined(sparc) || defined(sparcv9)
#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
#endif
array = (*env)->NewLongArray(env, NPRGREG);
CHECK_EXCEPTION_(0);
regs = (*env)->GetLongArrayElements(env, array, &isCopy);
#undef REG_INDEX
#ifdef i386
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg
regs[REG_INDEX(GS)] = (uintptr_t) gregs.r_gs;
regs[REG_INDEX(FS)] = (uintptr_t) gregs.r_fs;
regs[REG_INDEX(ES)] = (uintptr_t) gregs.r_es;
regs[REG_INDEX(DS)] = (uintptr_t) gregs.r_ds;
regs[REG_INDEX(EDI)] = (uintptr_t) gregs.r_edi;
regs[REG_INDEX(ESI)] = (uintptr_t) gregs.r_esi;
regs[REG_INDEX(FP)] = (uintptr_t) gregs.r_ebp;
regs[REG_INDEX(SP)] = (uintptr_t) gregs.r_isp;
regs[REG_INDEX(EBX)] = (uintptr_t) gregs.r_ebx;
regs[REG_INDEX(EDX)] = (uintptr_t) gregs.r_edx;
regs[REG_INDEX(ECX)] = (uintptr_t) gregs.r_ecx;
regs[REG_INDEX(EAX)] = (uintptr_t) gregs.r_eax;
regs[REG_INDEX(PC)] = (uintptr_t) gregs.r_eip;
regs[REG_INDEX(CS)] = (uintptr_t) gregs.r_cs;
regs[REG_INDEX(SS)] = (uintptr_t) gregs.r_ss;
#endif /* i386 */
#if ia64
regs = (*env)->GetLongArrayElements(env, array, &isCopy);
int i;
for (i = 0; i < NPRGREG; i++ ) {
regs[i] = 0xDEADDEAD;
}
#endif /* ia64 */
#ifdef amd64
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
regs[REG_INDEX(R15)] = gregs.r_r15;
regs[REG_INDEX(R14)] = gregs.r_r14;
regs[REG_INDEX(R13)] = gregs.r_r13;
regs[REG_INDEX(R12)] = gregs.r_r12;
regs[REG_INDEX(RBP)] = gregs.r_rbp;
regs[REG_INDEX(RBX)] = gregs.r_rbx;
regs[REG_INDEX(R11)] = gregs.r_r11;
regs[REG_INDEX(R10)] = gregs.r_r10;
regs[REG_INDEX(R9)] = gregs.r_r9;
regs[REG_INDEX(R8)] = gregs.r_r8;
regs[REG_INDEX(RAX)] = gregs.r_rax;
regs[REG_INDEX(RCX)] = gregs.r_rcx;
regs[REG_INDEX(RDX)] = gregs.r_rdx;
regs[REG_INDEX(RSI)] = gregs.r_rsi;
regs[REG_INDEX(RDI)] = gregs.r_rdi;
regs[REG_INDEX(RIP)] = gregs.r_rip;
regs[REG_INDEX(CS)] = gregs.r_cs;
regs[REG_INDEX(RSP)] = gregs.r_rsp;
regs[REG_INDEX(SS)] = gregs.r_ss;
// regs[REG_INDEX(FSBASE)] = gregs.fs_base;
// regs[REG_INDEX(GSBASE)] = gregs.gs_base;
// regs[REG_INDEX(DS)] = gregs.ds;
// regs[REG_INDEX(ES)] = gregs.es;
// regs[REG_INDEX(FS)] = gregs.fs;
// regs[REG_INDEX(GS)] = gregs.gs;
#endif /* amd64 */
#if defined(sparc) || defined(sparcv9)
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg
#ifdef _LP64
regs[REG_INDEX(R_PSR)] = gregs.tstate;
regs[REG_INDEX(R_PC)] = gregs.tpc;
regs[REG_INDEX(R_nPC)] = gregs.tnpc;
regs[REG_INDEX(R_Y)] = gregs.y;
#else
regs[REG_INDEX(R_PSR)] = gregs.psr;
regs[REG_INDEX(R_PC)] = gregs.pc;
regs[REG_INDEX(R_nPC)] = gregs.npc;
regs[REG_INDEX(R_Y)] = gregs.y;
#endif
regs[REG_INDEX(R_G0)] = 0 ;
regs[REG_INDEX(R_G1)] = gregs.u_regs[0];
regs[REG_INDEX(R_G2)] = gregs.u_regs[1];
regs[REG_INDEX(R_G3)] = gregs.u_regs[2];
regs[REG_INDEX(R_G4)] = gregs.u_regs[3];
regs[REG_INDEX(R_G5)] = gregs.u_regs[4];
regs[REG_INDEX(R_G6)] = gregs.u_regs[5];
regs[REG_INDEX(R_G7)] = gregs.u_regs[6];
regs[REG_INDEX(R_O0)] = gregs.u_regs[7];
regs[REG_INDEX(R_O1)] = gregs.u_regs[8];
regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9];
regs[REG_INDEX(R_O3)] = gregs.u_regs[10];
regs[REG_INDEX(R_O4)] = gregs.u_regs[11];
regs[REG_INDEX(R_O5)] = gregs.u_regs[12];
regs[REG_INDEX(R_O6)] = gregs.u_regs[13];
regs[REG_INDEX(R_O7)] = gregs.u_regs[14];
#endif /* sparc */
(*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
return array;
}

View File

@@ -0,0 +1,78 @@
#
# Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
ARCH := $(shell if ([ `uname -m` = "ia64" ]) ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
GCC = gcc
JAVAH = ${JAVA_HOME}/bin/javah
SOURCES = salibelf.c \
symtab.c \
libproc_impl.c \
ps_proc.c \
ps_core.c \
hsearch_r.c \
BsdDebuggerLocal.c
INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]")
OBJS = $(SOURCES:.c=.o)
LIBS = -lutil -lthread_db
CFLAGS = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES)
LIBSA = $(ARCH)/libsaproc.so
all: $(LIBSA)
BsdDebuggerLocal.o: BsdDebuggerLocal.c
$(JAVAH) -jni -classpath ../../../../../build/bsd-i586/hotspot/outputdir/bsd_i486_compiler2/generated/saclasses \
sun.jvm.hotspot.debugger.x86.X86ThreadContext \
sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
$(GCC) $(CFLAGS) $<
.c.obj:
$(GCC) $(CFLAGS)
ifndef LDNOMAP
LFLAGS_LIBSA = -Xlinker --version-script=mapfile
endif
$(LIBSA): $(OBJS) mapfile
if [ ! -d $(ARCH) ] ; then mkdir $(ARCH) ; fi
$(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(OBJS) $(LIBS)
test.o: $(LIBSA) test.c
$(GCC) -c -o test.o -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) test.c
test: test.o
$(GCC) -o test test.o -L$(ARCH) -lsaproc $(LIBS)
clean:
rm -f $(LIBSA)
rm -f $(OBJS)
rm -f test.o
-rmdir $(ARCH)

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdlib.h>
#include <jni.h>
#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
(*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: init0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
(JNIEnv *env, jclass cls) {
}
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
(JNIEnv *env, jclass cls)
{
#ifdef _LP64
return 8;
#else
return 4;
#endif
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: attach0
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
(JNIEnv *env, jobject this_obj, jint jpid) {
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: attach0
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
(JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: detach0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
(JNIEnv *env, jobject this_obj) {
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: lookupByName0
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
return 0;
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: lookupByAddress0
* Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
*/
JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
(JNIEnv *env, jobject this_obj, jlong addr) {
return 0;
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: readBytesFromProcess0
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
*/
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
return 0;
}
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
(JNIEnv *env, jobject this_obj, jint lwp_id) {
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,34 +22,37 @@
*
*/
#ifndef _PROCLIST_
#define _PROCLIST_
#ifndef _ELFMACROS_H_
#define _ELFMACROS_H_
#include <windows.h>
#include <vector>
#define ELF_NHDR Elf_Note
class ProcEntry {
public:
/** name may not be NULL */
ProcEntry(ULONG pid, USHORT nameLength, wchar_t* name);
ProcEntry(ULONG pid, USHORT nameLength, char* name);
~ProcEntry();
ProcEntry(const ProcEntry& arg);
ProcEntry& operator=(const ProcEntry& arg);
#if defined(_LP64)
#define ELF_EHDR Elf64_Ehdr
#define ELF_SHDR Elf64_Shdr
#define ELF_PHDR Elf64_Phdr
#define ELF_SYM Elf64_Sym
#define ELF_DYN Elf64_Dyn
#define ELF_ADDR Elf64_Addr
ULONG getPid();
/** Returns number of WCHAR characters in getName() */
USHORT getNameLength();
WCHAR* getName();
#ifndef ELF_ST_TYPE
#define ELF_ST_TYPE ELF64_ST_TYPE
#endif
private:
ULONG pid;
USHORT nameLength;
WCHAR* name;
void copyFrom(const ProcEntry& arg);
};
#else
typedef std::vector<ProcEntry> ProcEntryList;
void procList(ProcEntryList& processes);
#define ELF_EHDR Elf32_Ehdr
#define ELF_SHDR Elf32_Shdr
#define ELF_PHDR Elf32_Phdr
#define ELF_SYM Elf32_Sym
#define ELF_DYN Elf32_Dyn
#define ELF_ADDR Elf32_Addr
#endif // #defined _PROCLIST_
#ifndef ELF_ST_TYPE
#define ELF_ST_TYPE ELF32_ST_TYPE
#endif
#endif
#endif /* _ELFMACROS_H_ */

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _LIBPROC_H_
#define _LIBPROC_H_
#include <unistd.h>
#include <stdint.h>
#include <machine/reg.h>
#include <proc_service.h>
#if defined(sparc) || defined(sparcv9)
/*
If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64
otherwise it should be from /usr/include/asm-sparc
These two files define pt_regs structure differently
*/
#ifdef _LP64
#include "asm-sparc64/ptrace.h"
#else
#include "asm-sparc/ptrace.h"
#endif
#endif //sparc or sparcv9
/************************************************************************************
0. This is very minimal subset of Solaris libproc just enough for current application.
Please note that the bulk of the functionality is from proc_service interface. This
adds Pgrab__ and some missing stuff. We hide the difference b/w live process and core
file by this interface.
1. pthread_id is unique. We store this in OSThread::_pthread_id in JVM code.
2. All threads see the same pid when they call getpid().
We used to save the result of ::getpid() call in OSThread::_thread_id.
Because gettid returns actual pid of thread (lwp id), this is
unique again. We therefore use OSThread::_thread_id as unique identifier.
3. There is a unique LWP id under both thread libraries. libthread_db maps pthread_id
to its underlying lwp_id under both the thread libraries. thread_info.lwp_id stores
lwp_id of the thread. The lwp id is nothing but the actual pid of clone'd processes. But
unfortunately libthread_db does not work very well for core dumps. So, we get pthread_id
only for processes. For core dumps, we don't use libthread_db at all (like gdb).
4. ptrace operates on this LWP id under both the thread libraries. When we say 'pid' for
ptrace call, we refer to lwp_id of the thread.
5. for core file, we parse ELF files and read data from them. For processes we use
combination of ptrace and /proc calls.
*************************************************************************************/
// This C bool type must be int for compatibility with BSD calls and
// it would be a mistake to equivalence it to C++ bool on many platforms
typedef int bool;
#define true 1
#define false 0
struct ps_prochandle;
// attach to a process
struct ps_prochandle* Pgrab(pid_t pid);
// attach to a core dump
struct ps_prochandle* Pgrab_core(const char* execfile, const char* corefile);
// release a process or core
void Prelease(struct ps_prochandle* ph);
// functions not directly available in Solaris libproc
// initialize libproc (call this only once per app)
// pass true to make library verbose
bool init_libproc(bool verbose);
// get number of threads
int get_num_threads(struct ps_prochandle* ph);
// get lwp_id of n'th thread
lwpid_t get_lwp_id(struct ps_prochandle* ph, int index);
// get regs for a given lwp
bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lid, struct reg* regs);
// get number of shared objects
int get_num_libs(struct ps_prochandle* ph);
// get name of n'th lib
const char* get_lib_name(struct ps_prochandle* ph, int index);
// get base of lib
uintptr_t get_lib_base(struct ps_prochandle* ph, int index);
// returns true if given library is found in lib list
bool find_lib(struct ps_prochandle* ph, const char *lib_name);
// symbol lookup
uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
const char* sym_name);
// address->nearest symbol lookup. return NULL for no symbol
const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset);
#endif //__LIBPROC_H_

View File

@@ -0,0 +1,452 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <thread_db.h>
#include "libproc_impl.h"
static const char* alt_root = NULL;
static int alt_root_len = -1;
#define SA_ALTROOT "SA_ALTROOT"
static void init_alt_root() {
if (alt_root_len == -1) {
alt_root = getenv(SA_ALTROOT);
if (alt_root) {
alt_root_len = strlen(alt_root);
} else {
alt_root_len = 0;
}
}
}
int pathmap_open(const char* name) {
int fd;
char alt_path[PATH_MAX + 1];
init_alt_root();
fd = open(name, O_RDONLY);
if (fd >= 0) {
return fd;
}
if (alt_root_len > 0) {
strcpy(alt_path, alt_root);
strcat(alt_path, name);
fd = open(alt_path, O_RDONLY);
if (fd >= 0) {
print_debug("path %s substituted for %s\n", alt_path, name);
return fd;
}
if (strrchr(name, '/')) {
strcpy(alt_path, alt_root);
strcat(alt_path, strrchr(name, '/'));
fd = open(alt_path, O_RDONLY);
if (fd >= 0) {
print_debug("path %s substituted for %s\n", alt_path, name);
return fd;
}
}
}
return -1;
}
static bool _libsaproc_debug;
void print_debug(const char* format,...) {
if (_libsaproc_debug) {
va_list alist;
va_start(alist, format);
fputs("libsaproc DEBUG: ", stderr);
vfprintf(stderr, format, alist);
va_end(alist);
}
}
bool is_debug() {
return _libsaproc_debug;
}
// initialize libproc
bool init_libproc(bool debug) {
// init debug mode
_libsaproc_debug = debug;
// initialize the thread_db library
if (td_init() != TD_OK) {
print_debug("libthread_db's td_init failed\n");
return false;
}
return true;
}
static void destroy_lib_info(struct ps_prochandle* ph) {
lib_info* lib = ph->libs;
while (lib) {
lib_info *next = lib->next;
if (lib->symtab) {
destroy_symtab(lib->symtab);
}
free(lib);
lib = next;
}
}
static void destroy_thread_info(struct ps_prochandle* ph) {
thread_info* thr = ph->threads;
while (thr) {
thread_info *next = thr->next;
free(thr);
thr = next;
}
}
// ps_prochandle cleanup
// ps_prochandle cleanup
void Prelease(struct ps_prochandle* ph) {
// do the "derived class" clean-up first
ph->ops->release(ph);
destroy_lib_info(ph);
destroy_thread_info(ph);
free(ph);
}
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
return add_lib_info_fd(ph, libname, -1, base);
}
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
lib_info* newlib;
if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
print_debug("can't allocate memory for lib_info\n");
return NULL;
}
strncpy(newlib->name, libname, sizeof(newlib->name));
newlib->base = base;
if (fd == -1) {
if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
print_debug("can't open shared object %s\n", newlib->name);
free(newlib);
return NULL;
}
} else {
newlib->fd = fd;
}
// check whether we have got an ELF file. /proc/<pid>/map
// gives out all file mappings and not just shared objects
if (is_elf_file(newlib->fd) == false) {
close(newlib->fd);
free(newlib);
return NULL;
}
newlib->symtab = build_symtab(newlib->fd);
if (newlib->symtab == NULL) {
print_debug("symbol table build failed for %s\n", newlib->name);
}
else {
print_debug("built symbol table for %s\n", newlib->name);
}
// even if symbol table building fails, we add the lib_info.
// This is because we may need to read from the ELF file for core file
// address read functionality. lookup_symbol checks for NULL symtab.
if (ph->libs) {
ph->lib_tail->next = newlib;
ph->lib_tail = newlib;
} else {
ph->libs = ph->lib_tail = newlib;
}
ph->num_libs++;
return newlib;
}
// lookup for a specific symbol
uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
const char* sym_name) {
// ignore object_name. search in all libraries
// FIXME: what should we do with object_name?? The library names are obtained
// by parsing /proc/<pid>/maps, which may not be the same as object_name.
// What we need is a utility to map object_name to real file name, something
// dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
// now, we just ignore object_name and do a global search for the symbol.
lib_info* lib = ph->libs;
while (lib) {
if (lib->symtab) {
uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
if (res) return res;
}
lib = lib->next;
}
print_debug("lookup failed for symbol '%s' in obj '%s'\n",
sym_name, object_name);
return (uintptr_t) NULL;
}
const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
const char* res = NULL;
lib_info* lib = ph->libs;
while (lib) {
if (lib->symtab && addr >= lib->base) {
res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
if (res) return res;
}
lib = lib->next;
}
return NULL;
}
// add a thread to ps_prochandle
thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
thread_info* newthr;
if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
print_debug("can't allocate memory for thread_info\n");
return NULL;
}
// initialize thread info
newthr->pthread_id = pthread_id;
newthr->lwp_id = lwp_id;
// add new thread to the list
newthr->next = ph->threads;
ph->threads = newthr;
ph->num_threads++;
return newthr;
}
// struct used for client data from thread_db callback
struct thread_db_client_data {
struct ps_prochandle* ph;
thread_info_callback callback;
};
// callback function for libthread_db
static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
td_thrinfo_t ti;
td_err_e err;
memset(&ti, 0, sizeof(ti));
err = td_thr_get_info(th_p, &ti);
if (err != TD_OK) {
print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
return err;
}
print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
if (ptr->callback(ptr->ph, (pthread_t)ti.ti_tid, ti.ti_lid) != true)
return TD_ERR;
return TD_OK;
}
// read thread_info using libthread_db
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
struct thread_db_client_data mydata;
td_thragent_t* thread_agent = NULL;
if (td_ta_new(ph, &thread_agent) != TD_OK) {
print_debug("can't create libthread_db agent\n");
return false;
}
mydata.ph = ph;
mydata.callback = cb;
// we use libthread_db iterator to iterate thru list of threads.
if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
td_ta_delete(thread_agent);
return false;
}
// delete thread agent
td_ta_delete(thread_agent);
return true;
}
// get number of threads
int get_num_threads(struct ps_prochandle* ph) {
return ph->num_threads;
}
// get lwp_id of n'th thread
lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
int count = 0;
thread_info* thr = ph->threads;
while (thr) {
if (count == index) {
return thr->lwp_id;
}
count++;
thr = thr->next;
}
return -1;
}
// get regs for a given lwp
bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
return ph->ops->get_lwp_regs(ph, lwp_id, regs);
}
// get number of shared objects
int get_num_libs(struct ps_prochandle* ph) {
return ph->num_libs;
}
// get name of n'th solib
const char* get_lib_name(struct ps_prochandle* ph, int index) {
int count = 0;
lib_info* lib = ph->libs;
while (lib) {
if (count == index) {
return lib->name;
}
count++;
lib = lib->next;
}
return NULL;
}
// get base address of a lib
uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
int count = 0;
lib_info* lib = ph->libs;
while (lib) {
if (count == index) {
return lib->base;
}
count++;
lib = lib->next;
}
return (uintptr_t)NULL;
}
bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
lib_info *p = ph->libs;
while (p) {
if (strcmp(p->name, lib_name) == 0) {
return true;
}
p = p->next;
}
return false;
}
//--------------------------------------------------------------------------
// proc service functions
// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
// of the load object object_name in the target process identified by ph.
// It returns the symbol's value as an address in the target process in
// *sym_addr.
ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
const char *sym_name, psaddr_t *sym_addr) {
*sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name);
return (*sym_addr ? PS_OK : PS_NOSYM);
}
// read "size" bytes info "buf" from address "addr"
ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t addr,
void *buf, size_t size) {
return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR;
}
// write "size" bytes of data to debuggee at address "addr"
ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr,
const void *buf, size_t size) {
return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR;
}
// fill in ptrace_lwpinfo for lid
ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
return ph->ops->get_lwp_info(ph, lwp_id, linfo)? PS_OK: PS_ERR;
}
// needed for when libthread_db is compiled with TD_DEBUG defined
void
ps_plog (const char *format, ...)
{
va_list alist;
va_start(alist, format);
vfprintf(stderr, format, alist);
va_end(alist);
}
// ------------------------------------------------------------------------
// Functions below this point are not yet implemented. They are here only
// to make the linker happy.
ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) {
print_debug("ps_lsetfpregs not implemented\n");
return PS_OK;
}
ps_err_e ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) {
print_debug("ps_lsetregs not implemented\n");
return PS_OK;
}
ps_err_e ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) {
print_debug("ps_lgetfpregs not implemented\n");
return PS_OK;
}
ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
print_debug("ps_lgetfpregs not implemented\n");
return PS_OK;
}
ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lid) {
print_debug("ps_lstop not implemented\n");
return PS_OK;
}
ps_err_e ps_pcontinue(struct ps_prochandle *ph) {
print_debug("ps_pcontinue not implemented\n");
return PS_OK;
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _LIBPROC_IMPL_H_
#define _LIBPROC_IMPL_H_
#include <unistd.h>
#include <limits.h>
#include "libproc.h"
#include "symtab.h"
// data structures in this file mimic those of Solaris 8.0 - libproc's Pcontrol.h
#define BUF_SIZE (PATH_MAX + NAME_MAX + 1)
// list of shared objects
typedef struct lib_info {
char name[BUF_SIZE];
uintptr_t base;
struct symtab* symtab;
int fd; // file descriptor for lib
struct lib_info* next;
} lib_info;
// list of threads
typedef struct thread_info {
lwpid_t lwp_id;
pthread_t pthread_id; // not used cores, always -1
struct reg regs; // not for process, core uses for caching regset
struct thread_info* next;
} thread_info;
// list of virtual memory maps
typedef struct map_info {
int fd; // file descriptor
off_t offset; // file offset of this mapping
uintptr_t vaddr; // starting virtual address
size_t memsz; // size of the mapping
struct map_info* next;
} map_info;
// vtable for ps_prochandle
typedef struct ps_prochandle_ops {
// "derived class" clean-up
void (*release)(struct ps_prochandle* ph);
// read from debuggee
bool (*p_pread)(struct ps_prochandle *ph,
uintptr_t addr, char *buf, size_t size);
// write into debuggee
bool (*p_pwrite)(struct ps_prochandle *ph,
uintptr_t addr, const char *buf , size_t size);
// get integer regset of a thread
bool (*get_lwp_regs)(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs);
// get info on thread
bool (*get_lwp_info)(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo);
} ps_prochandle_ops;
// the ps_prochandle
struct core_data {
int core_fd; // file descriptor of core file
int exec_fd; // file descriptor of exec file
int interp_fd; // file descriptor of interpreter (ld-elf.so.1)
// part of the class sharing workaround
int classes_jsa_fd; // file descriptor of class share archive
uintptr_t dynamic_addr; // address of dynamic section of a.out
uintptr_t ld_base_addr; // base address of ld.so
size_t num_maps; // number of maps.
map_info* maps; // maps in a linked list
// part of the class sharing workaround
map_info* class_share_maps;// class share maps in a linked list
map_info** map_array; // sorted (by vaddr) array of map_info pointers
};
struct ps_prochandle {
ps_prochandle_ops* ops; // vtable ptr
pid_t pid;
int num_libs;
lib_info* libs; // head of lib list
lib_info* lib_tail; // tail of lib list - to append at the end
int num_threads;
thread_info* threads; // head of thread list
struct core_data* core; // data only used for core dumps, NULL for process
};
int pathmap_open(const char* name);
void print_debug(const char* format,...);
bool is_debug();
typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
// reads thread info using libthread_db and calls above callback for each thread
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb);
// adds a new shared object to lib list, returns NULL on failure
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base);
// adds a new shared object to lib list, supply open lib file descriptor as well
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
uintptr_t base);
// adds a new thread to threads list, returns NULL on failure
thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
// a test for ELF signature without using libelf
bool is_elf_file(int fd);
#endif //_LIBPROC_IMPL_H_

View File

@@ -0,0 +1,66 @@
#
#
# Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# Define public interface.
SUNWprivate_1.1 {
global:
# native methods of BsdDebuggerLocal class
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0;
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0;
# proc_service.h functions - to be used by libthread_db
ps_getpid;
ps_pglobal_lookup;
ps_pread;
ps_pwrite;
ps_lsetfpregs;
ps_lsetregs;
ps_lgetfpregs;
ps_lgetregs;
ps_lcontinue;
ps_lgetxmmregs;
ps_lsetxmmregs;
ps_lstop;
ps_linfo;
# used by attach test program
init_libproc;
Pgrab;
Pgrab_core;
Prelease;
local:
*;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,444 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/param.h>
#include <sys/user.h>
#include <elf.h>
#include <sys/elf_common.h>
#include <sys/link_elf.h>
#include <libutil.h>
#include "libproc_impl.h"
#include "elfmacros.h"
// This file has the libproc implementation specific to live process
// For core files, refer to ps_core.c
static inline uintptr_t align(uintptr_t ptr, size_t size) {
return (ptr & ~(size - 1));
}
// ---------------------------------------------
// ptrace functions
// ---------------------------------------------
// read "size" bytes of data from "addr" within the target process.
// unlike the standard ptrace() function, process_read_data() can handle
// unaligned address - alignment check, if required, should be done
// before calling process_read_data.
static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) {
int rslt;
size_t i, words;
uintptr_t end_addr = addr + size;
uintptr_t aligned_addr = align(addr, sizeof(int));
if (aligned_addr != addr) {
char *ptr = (char *)&rslt;
errno = 0;
rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
if (errno) {
print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
return false;
}
for (; aligned_addr != addr; aligned_addr++, ptr++);
for (; ((intptr_t)aligned_addr % sizeof(int)) && aligned_addr < end_addr;
aligned_addr++)
*(buf++) = *(ptr++);
}
words = (end_addr - aligned_addr) / sizeof(int);
// assert((intptr_t)aligned_addr % sizeof(int) == 0);
for (i = 0; i < words; i++) {
errno = 0;
rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
if (errno) {
print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
return false;
}
*(int *)buf = rslt;
buf += sizeof(int);
aligned_addr += sizeof(int);
}
if (aligned_addr != end_addr) {
char *ptr = (char *)&rslt;
errno = 0;
rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0);
if (errno) {
print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr);
return false;
}
for (; aligned_addr != end_addr; aligned_addr++)
*(buf++) = *(ptr++);
}
return true;
}
// null implementation for write
static bool process_write_data(struct ps_prochandle* ph,
uintptr_t addr, const char *buf , size_t size) {
return false;
}
// "user" should be a pointer to a reg
static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct reg *user) {
// we have already attached to all thread 'pid's, just use ptrace call
// to get regset now. Note that we don't cache regset upfront for processes.
if (ptrace(PT_GETREGS, pid, (caddr_t) user, 0) < 0) {
print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);
return false;
}
return true;
}
// fill in ptrace_lwpinfo for lid
static bool process_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
errno = 0;
ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo));
return (errno == 0)? true: false;
}
// attach to a process/thread specified by "pid"
static bool ptrace_attach(pid_t pid) {
if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {
print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
return false;
} else {
int ret;
int status;
do {
// Wait for debuggee to stop.
ret = waitpid(pid, &status, 0);
if (ret >= 0) {
if (WIFSTOPPED(status)) {
// Debuggee stopped.
return true;
} else {
print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
return false;
}
} else {
switch (errno) {
case EINTR:
continue;
break;
case ECHILD:
print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
break;
case EINVAL:
print_debug("waitpid() failed. Invalid options argument.\n");
break;
default:
print_debug("waitpid() failed. Unexpected error %d\n",errno);
}
return false;
}
} while(true);
}
}
// -------------------------------------------------------
// functions for obtaining library information
// -------------------------------------------------------
// callback for read_thread_info
static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
return add_thread_info(ph, pthread_id, lwp_id) != NULL;
}
#if defined(__FreeBSD__) && __FreeBSD_version < 701000
/*
* TEXT_START_ADDR from binutils/ld/emulparams/<arch_spec>.sh
* Not the most robust but good enough.
*/
#if defined(amd64) || defined(x86_64)
#define TEXT_START_ADDR 0x400000
#elif defined(i386)
#define TEXT_START_ADDR 0x8048000
#else
#error TEXT_START_ADDR not defined
#endif
#define BUF_SIZE (PATH_MAX + NAME_MAX + 1)
uintptr_t linkmap_addr(struct ps_prochandle *ph) {
uintptr_t ehdr_addr, phdr_addr, dyn_addr, dmap_addr, lmap_addr;
ELF_EHDR ehdr;
ELF_PHDR *phdrs, *phdr;
ELF_DYN *dyns, *dyn;
struct r_debug dmap;
unsigned long hdrs_size;
unsigned int i;
/* read ELF_EHDR at TEXT_START_ADDR and validate */
ehdr_addr = (uintptr_t)TEXT_START_ADDR;
if (process_read_data(ph, ehdr_addr, (char *)&ehdr, sizeof(ehdr)) != true) {
print_debug("process_read_data failed for ehdr_addr %p\n", ehdr_addr);
return (0);
}
if (!IS_ELF(ehdr) ||
ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||
ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
ehdr.e_phentsize != sizeof(ELF_PHDR) ||
ehdr.e_version != ELF_TARG_VER ||
ehdr.e_machine != ELF_TARG_MACH) {
print_debug("not an ELF_EHDR at %p\n", ehdr_addr);
return (0);
}
/* allocate space for all ELF_PHDR's and read */
phdr_addr = ehdr_addr + ehdr.e_phoff;
hdrs_size = ehdr.e_phnum * sizeof(ELF_PHDR);
if ((phdrs = malloc(hdrs_size)) == NULL)
return (0);
if (process_read_data(ph, phdr_addr, (char *)phdrs, hdrs_size) != true) {
print_debug("process_read_data failed for phdr_addr %p\n", phdr_addr);
return (0);
}
/* find PT_DYNAMIC section */
for (i = 0, phdr = phdrs; i < ehdr.e_phnum; i++, phdr++) {
if (phdr->p_type == PT_DYNAMIC)
break;
}
if (i >= ehdr.e_phnum) {
print_debug("PT_DYNAMIC section not found!\n");
free(phdrs);
return (0);
}
/* allocate space and read in ELF_DYN headers */
dyn_addr = phdr->p_vaddr;
hdrs_size = phdr->p_memsz;
free(phdrs);
if ((dyns = malloc(hdrs_size)) == NULL)
return (0);
if (process_read_data(ph, dyn_addr, (char *)dyns, hdrs_size) != true) {
print_debug("process_read_data failed for dyn_addr %p\n", dyn_addr);
free(dyns);
return (0);
}
/* find DT_DEBUG */
dyn = dyns;
while (dyn->d_tag != DT_DEBUG && dyn->d_tag != DT_NULL) {
dyn++;
}
if (dyn->d_tag != DT_DEBUG) {
print_debug("failed to find DT_DEBUG\n");
free(dyns);
return (0);
}
/* read struct r_debug into dmap */
dmap_addr = (uintptr_t)dyn->d_un.d_ptr;
free(dyns);
if (process_read_data(ph, dmap_addr, (char *)&dmap, sizeof(dmap)) != true) {
print_debug("process_read_data failed for dmap_addr %p\n", dmap_addr);
return (0);
}
lmap_addr = (uintptr_t)dmap.r_map;
return (lmap_addr);
}
#endif // __FreeBSD__ && __FreeBSD_version < 701000
static bool read_lib_info(struct ps_prochandle* ph) {
#if defined(__FreeBSD__) && __FreeBSD_version >= 701000
struct kinfo_vmentry *freep, *kve;
int i, cnt;
freep = kinfo_getvmmap(ph->pid, &cnt);
if (freep == NULL) {
print_debug("can't get vm map for pid\n", ph->pid);
return false;
}
for (i = 0; i < cnt; i++) {
kve = &freep[i];
if ((kve->kve_flags & KVME_FLAG_COW) &&
kve->kve_path != NULL &&
strlen(kve->kve_path) > 0) {
if (find_lib(ph, kve->kve_path) == false) {
lib_info* lib;
if ((lib = add_lib_info(ph, kve->kve_path,
(uintptr_t) kve->kve_start)) == NULL)
continue; // ignore, add_lib_info prints error
// we don't need to keep the library open, symtab is already
// built. Only for core dump we need to keep the fd open.
close(lib->fd);
lib->fd = -1;
}
}
}
free(freep);
return true;
#else
char *l_name;
struct link_map *lmap;
uintptr_t lmap_addr;
if ((l_name = malloc(BUF_SIZE)) == NULL)
return false;
if ((lmap = malloc(sizeof(*lmap))) == NULL) {
free(l_name);
return false;
}
lmap_addr = linkmap_addr(ph);
if (lmap_addr == 0) {
free(l_name);
free(lmap);
return false;
}
do {
if (process_read_data(ph, lmap_addr, (char *)lmap, sizeof(*lmap)) != true) {
print_debug("process_read_data failed for lmap_addr %p\n", lmap_addr);
free (l_name);
free (lmap);
return false;
}
if (process_read_data(ph, (uintptr_t)lmap->l_name, l_name,
BUF_SIZE) != true) {
print_debug("process_read_data failed for lmap->l_name %p\n",
lmap->l_name);
free (l_name);
free (lmap);
return false;
}
if (find_lib(ph, l_name) == false) {
lib_info* lib;
if ((lib = add_lib_info(ph, l_name,
(uintptr_t) lmap->l_addr)) == NULL)
continue; // ignore, add_lib_info prints error
// we don't need to keep the library open, symtab is already
// built. Only for core dump we need to keep the fd open.
close(lib->fd);
lib->fd = -1;
}
lmap_addr = (uintptr_t)lmap->l_next;
} while (lmap->l_next != NULL);
free (l_name);
free (lmap);
return true;
#endif
}
// detach a given pid
static bool ptrace_detach(pid_t pid) {
if (pid && ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0) {
print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n", pid);
return false;
} else {
return true;
}
}
static void process_cleanup(struct ps_prochandle* ph) {
ptrace_detach(ph->pid);
}
static ps_prochandle_ops process_ops = {
.release= process_cleanup,
.p_pread= process_read_data,
.p_pwrite= process_write_data,
.get_lwp_regs= process_get_lwp_regs,
.get_lwp_info= process_get_lwp_info
};
// attach to the process. One and only one exposed stuff
struct ps_prochandle* Pgrab(pid_t pid) {
struct ps_prochandle* ph = NULL;
thread_info* thr = NULL;
if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
print_debug("can't allocate memory for ps_prochandle\n");
return NULL;
}
if (ptrace_attach(pid) != true) {
free(ph);
return NULL;
}
// initialize ps_prochandle
ph->pid = pid;
// initialize vtable
ph->ops = &process_ops;
// read library info and symbol tables, must do this before attaching threads,
// as the symbols in the pthread library will be used to figure out
// the list of threads within the same process.
if (read_lib_info(ph) != true) {
ptrace_detach(pid);
free(ph);
return NULL;
}
// read thread info
read_thread_info(ph, add_new_thread);
return ph;
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "salibelf.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
extern void print_debug(const char*,...);
// ELF file parsing helpers. Note that we do *not* use libelf here.
int read_elf_header(int fd, ELF_EHDR* ehdr) {
if (pread(fd, ehdr, sizeof (ELF_EHDR), 0) != sizeof (ELF_EHDR) ||
memcmp(&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 ||
ehdr->e_version != EV_CURRENT) {
return 0;
}
return 1;
}
bool is_elf_file(int fd) {
ELF_EHDR ehdr;
return read_elf_header(fd, &ehdr);
}
// read program header table of an ELF file
ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr) {
ELF_PHDR* phbuf = 0;
// allocate memory for program header table
size_t nbytes = hdr->e_phnum * hdr->e_phentsize;
if ((phbuf = (ELF_PHDR*) malloc(nbytes)) == NULL) {
print_debug("can't allocate memory for reading program header table\n");
return NULL;
}
if (pread(fd, phbuf, nbytes, hdr->e_phoff) != nbytes) {
print_debug("ELF file is truncated! can't read program header table\n");
free(phbuf);
return NULL;
}
return phbuf;
}
// read section header table of an ELF file
ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr) {
ELF_SHDR* shbuf = 0;
// allocate memory for section header table
size_t nbytes = hdr->e_shnum * hdr->e_shentsize;
if ((shbuf = (ELF_SHDR*) malloc(nbytes)) == NULL) {
print_debug("can't allocate memory for reading section header table\n");
return NULL;
}
if (pread(fd, shbuf, nbytes, hdr->e_shoff) != nbytes) {
print_debug("ELF file is truncated! can't read section header table\n");
free(shbuf);
return NULL;
}
return shbuf;
}
// read a particular section's data
void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr) {
void *buf = NULL;
if (shdr->sh_type == SHT_NOBITS || shdr->sh_size == 0) {
return buf;
}
if ((buf = calloc(shdr->sh_size, 1)) == NULL) {
print_debug("can't allocate memory for reading section data\n");
return NULL;
}
if (pread(fd, buf, shdr->sh_size, shdr->sh_offset) != shdr->sh_size) {
free(buf);
print_debug("section data read failed\n");
return NULL;
}
return buf;
}
uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) {
uintptr_t baseaddr = (uintptr_t)-1;
int cnt;
ELF_PHDR *phbuf, *phdr;
// read program header table
if ((phbuf = read_program_header_table(fd, ehdr)) == NULL) {
goto quit;
}
// the base address of a shared object is the lowest vaddr of
// its loadable segments (PT_LOAD)
for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) {
if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) {
baseaddr = phdr->p_vaddr;
}
}
quit:
if (phbuf) free(phbuf);
return baseaddr;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,54 +22,31 @@
*
*/
#include "nt4internals.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#ifndef _SALIBELF_H_
#define _SALIBELF_H_
namespace NT4 {
#include <elf.h>
#include "elfmacros.h"
#include "libproc_impl.h"
static HMODULE ntDLL = NULL;
// read ELF file header.
int read_elf_header(int fd, ELF_EHDR* ehdr);
HMODULE loadNTDLL() {
if (ntDLL == NULL) {
ntDLL = LoadLibrary("NTDLL.DLL");
}
// is given file descriptor corresponds to an ELF file?
bool is_elf_file(int fd);
assert(ntDLL != NULL);
return ntDLL;
}
// read program header table of an ELF file. caller has to
// free the result pointer after use. NULL on failure.
ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr);
void unloadNTDLL() {
if (ntDLL != NULL) {
FreeLibrary(ntDLL);
ntDLL = NULL;
}
}
// read section header table of an ELF file. caller has to
// free the result pointer after use. NULL on failure.
ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr);
} // namespace NT4
// read a particular section's data. caller has to free the
// result pointer after use. NULL on failure.
void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr);
static HMODULE psapiDLL = NULL;
HMODULE
loadPSAPIDLL() {
if (psapiDLL == NULL) {
psapiDLL = LoadLibrary("PSAPI.DLL");
}
if (psapiDLL == NULL) {
fprintf(stderr, "Simple Windows Debug Server requires PSAPI.DLL on Windows NT 4.0.\n");
fprintf(stderr, "Please install this DLL from the SDK and restart the server.\n");
exit(1);
}
return psapiDLL;
}
void
unloadPSAPIDLL() {
if (psapiDLL != NULL) {
FreeLibrary(psapiDLL);
psapiDLL = NULL;
}
}
// find the base address at which the library wants to load itself
uintptr_t find_base_address(int fd, ELF_EHDR* ehdr);
#endif /* _SALIBELF_H_ */

View File

@@ -0,0 +1,239 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <unistd.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <db.h>
#include <fcntl.h>
#include "symtab.h"
#include "salibelf.h"
// ----------------------------------------------------
// functions for symbol lookups
// ----------------------------------------------------
struct elf_section {
ELF_SHDR *c_shdr;
void *c_data;
};
struct elf_symbol {
char *name;
uintptr_t offset;
uintptr_t size;
};
typedef struct symtab {
char *strs;
size_t num_symbols;
struct elf_symbol *symbols;
DB* hash_table;
} symtab_t;
// read symbol table from given fd.
struct symtab* build_symtab(int fd) {
ELF_EHDR ehdr;
struct symtab* symtab = NULL;
// Reading of elf header
struct elf_section *scn_cache = NULL;
int cnt = 0;
ELF_SHDR* shbuf = NULL;
ELF_SHDR* cursct = NULL;
ELF_PHDR* phbuf = NULL;
int symtab_found = 0;
int dynsym_found = 0;
uint32_t symsection = SHT_SYMTAB;
uintptr_t baseaddr = (uintptr_t)-1;
lseek(fd, (off_t)0L, SEEK_SET);
if (! read_elf_header(fd, &ehdr)) {
// not an elf
return NULL;
}
// read ELF header
if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) {
goto quit;
}
baseaddr = find_base_address(fd, &ehdr);
scn_cache = calloc(ehdr.e_shnum, sizeof(*scn_cache));
if (scn_cache == NULL) {
goto quit;
}
for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
scn_cache[cnt].c_shdr = cursct;
if (cursct->sh_type == SHT_SYMTAB ||
cursct->sh_type == SHT_STRTAB ||
cursct->sh_type == SHT_DYNSYM) {
if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
goto quit;
}
}
if (cursct->sh_type == SHT_SYMTAB)
symtab_found++;
if (cursct->sh_type == SHT_DYNSYM)
dynsym_found++;
cursct++;
}
if (!symtab_found && dynsym_found)
symsection = SHT_DYNSYM;
for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
if (shdr->sh_type == symsection) {
ELF_SYM *syms;
int j, n, rslt;
size_t size;
// FIXME: there could be multiple data buffers associated with the
// same ELF section. Here we can handle only one buffer. See man page
// for elf_getdata on Solaris.
// guarantee(symtab == NULL, "multiple symtab");
symtab = calloc(1, sizeof(*symtab));
if (symtab == NULL) {
goto quit;
}
// the symbol table
syms = (ELF_SYM *)scn_cache[cnt].c_data;
// number of symbols
n = shdr->sh_size / shdr->sh_entsize;
// create hash table, we use berkeley db to
// manipulate the hash table.
symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
// guarantee(symtab->hash_table, "unexpected failure: dbopen");
// shdr->sh_link points to the section that contains the actual strings
// for symbol names. the st_name field in ELF_SYM is just the
// string table index. we make a copy of the string table so the
// strings will not be destroyed by elf_end.
size = scn_cache[shdr->sh_link].c_shdr->sh_size;
symtab->strs = malloc(size);
memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size);
// allocate memory for storing symbol offset and size;
symtab->num_symbols = n;
symtab->symbols = calloc(n , sizeof(*symtab->symbols));
// copy symbols info our symtab and enter them info the hash table
for (j = 0; j < n; j++, syms++) {
DBT key, value;
char *sym_name = symtab->strs + syms->st_name;
// skip non-object and non-function symbols
int st_type = ELF_ST_TYPE(syms->st_info);
if ( st_type != STT_FUNC && st_type != STT_OBJECT)
continue;
// skip empty strings and undefined symbols
if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
symtab->symbols[j].name = sym_name;
symtab->symbols[j].offset = syms->st_value - baseaddr;
symtab->symbols[j].size = syms->st_size;
key.data = sym_name;
key.size = strlen(sym_name) + 1;
value.data = &(symtab->symbols[j]);
value.size = sizeof(void *);
(*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
}
}
}
quit:
if (shbuf) free(shbuf);
if (phbuf) free(phbuf);
if (scn_cache) {
for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
if (scn_cache[cnt].c_data != NULL) {
free(scn_cache[cnt].c_data);
}
}
free(scn_cache);
}
return symtab;
}
void destroy_symtab(struct symtab* symtab) {
if (!symtab) return;
if (symtab->strs) free(symtab->strs);
if (symtab->symbols) free(symtab->symbols);
if (symtab->hash_table) {
symtab->hash_table->close(symtab->hash_table);
}
free(symtab);
}
uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
const char *sym_name, int *sym_size) {
DBT key, value;
int ret;
// library does not have symbol table
if (!symtab || !symtab->hash_table)
return 0;
key.data = (char*)(uintptr_t)sym_name;
key.size = strlen(sym_name) + 1;
ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
if (ret == 0) {
struct elf_symbol *sym = value.data;
uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
if (sym_size) *sym_size = sym->size;
return rslt;
}
quit:
return 0;
}
const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
uintptr_t* poffset) {
int n = 0;
if (!symtab) return NULL;
for (; n < symtab->num_symbols; n++) {
struct elf_symbol* sym = &(symtab->symbols[n]);
if (sym->name != NULL &&
offset >= sym->offset && offset < sym->offset + sym->size) {
if (poffset) *poffset = (offset - sym->offset);
return sym->name;
}
}
return NULL;
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _SYMTAB_H_
#define _SYMTAB_H_
#include <stdint.h>
// interface to manage ELF symbol tables
struct symtab;
// build symbol table for a given ELF file descriptor
struct symtab* build_symtab(int fd);
// destroy the symbol table
void destroy_symtab(struct symtab* symtab);
// search for symbol in the given symbol table. Adds offset
// to the base uintptr_t supplied. Returns NULL if not found.
uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
const char *sym_name, int *sym_size);
// look for nearest symbol for a given offset (not address - base
// subtraction done by caller
const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
uintptr_t* poffset);
#endif /*_SYMTAB_H_*/

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "libproc.h"
int main(int argc, char** argv) {
struct ps_prochandle* ph;
init_libproc(true);
switch (argc) {
case 2: {
// process
ph = Pgrab(atoi(argv[1]));
break;
}
case 3: {
// core
ph = Pgrab_core(argv[1], argv[2]);
break;
}
default: {
fprintf(stderr, "usage %s <pid> or %s <exec file> <core file>\n", argv[0], argv[0]);
return 1;
}
}
if (ph) {
Prelease(ph);
return 0;
} else {
printf("can't connect to debuggee\n");
return 1;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,25 +22,30 @@
*
*/
package sun.jvm.hotspot.debugger.dbx.sparc;
package sun.jvm.hotspot;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.types.basic.*;
public class DbxSPARCThreadContext extends SPARCThreadContext {
private DbxDebugger debugger;
public class BsdVtblAccess extends BasicVtblAccess {
private String vt;
public DbxSPARCThreadContext(DbxDebugger debugger) {
super();
this.debugger = debugger;
public BsdVtblAccess(SymbolLookup symbolLookup,
String[] dllNames) {
super(symbolLookup, dllNames);
if (symbolLookup.lookup("libjvm.so", "__vt_10JavaThread") != null ||
symbolLookup.lookup("libjvm_g.so", "__vt_10JavaThread") != null) {
// old C++ ABI
vt = "__vt_";
} else {
// new C++ ABI
vt = "_ZTV";
}
}
public void setRegisterAsAddress(int index, Address value) {
setRegister(index, debugger.getAddressValue(value));
}
public Address getRegisterAsAddress(int index) {
return debugger.newAddress(getRegister(index));
protected String vtblSymbolForType(Type type) {
return vt + type.getName().length() + type;
}
}

View File

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

View File

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

View File

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

View File

@@ -1740,7 +1740,7 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
else if (f.isCompiledFrame()) { tty.print("compiled"); }
else if (f.isEntryFrame()) { tty.print("entry"); }
else if (f.isNativeFrame()) { tty.print("native"); }
else if (f.isGlueFrame()) { tty.print("glue"); }
else if (f.isRuntimeFrame()) { tty.print("runtime"); }
else { tty.print("external"); }
tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP());
if (f.isSignalHandlerFrameDbg()) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,10 +28,9 @@ import java.io.PrintStream;
import java.net.*;
import java.rmi.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.debugger.bsd.*;
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.debugger.remote.*;
import sun.jvm.hotspot.debugger.win32.*;
import sun.jvm.hotspot.debugger.windbg.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.memory.*;
@@ -337,6 +336,8 @@ public class HotSpotAgent {
setupDebuggerWin32();
} else if (os.equals("linux")) {
setupDebuggerLinux();
} else if (os.equals("bsd")) {
setupDebuggerBsd();
} else {
// Add support for more operating systems here
throw new DebuggerException("Operating system " + os + " not yet supported");
@@ -392,6 +393,10 @@ public class HotSpotAgent {
db = new HotSpotTypeDataBase(machDesc,
new LinuxVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
} else if (os.equals("bsd")) {
db = new HotSpotTypeDataBase(machDesc,
new BsdVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
} else {
throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess yet)");
}
@@ -436,113 +441,35 @@ public class HotSpotAgent {
private void setupDebuggerSolaris() {
setupJVMLibNamesSolaris();
if(System.getProperty("sun.jvm.hotspot.debugger.useProcDebugger") != null) {
ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
debugger = dbg;
attachDebugger();
ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
debugger = dbg;
attachDebugger();
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's " +
"address size");
}
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
} else if (cpu.equals("amd64")) {
machDesc = new MachineDescriptionAMD64();
} else {
throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's " +
"address size");
}
dbg.setMachineDescription(machDesc);
return;
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
} else if (cpu.equals("amd64")) {
machDesc = new MachineDescriptionAMD64();
} else {
String dbxPathName;
String dbxPathPrefix;
String dbxSvcAgentDSOPathName;
String dbxSvcAgentDSOPathPrefix;
String[] dbxSvcAgentDSOPathNames = null;
// use path names/prefixes specified on command
dbxPathName = System.getProperty("dbxPathName");
if (dbxPathName == null) {
dbxPathPrefix = System.getProperty("dbxPathPrefix");
if (dbxPathPrefix == null) {
dbxPathPrefix = defaultDbxPathPrefix;
}
dbxPathName = dbxPathPrefix + fileSep + os + fileSep + cpu + fileSep + "bin" + fileSep + "dbx";
}
dbxSvcAgentDSOPathName = System.getProperty("dbxSvcAgentDSOPathName");
if (dbxSvcAgentDSOPathName != null) {
dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathName } ;
} else {
dbxSvcAgentDSOPathPrefix = System.getProperty("dbxSvcAgentDSOPathPrefix");
if (dbxSvcAgentDSOPathPrefix == null) {
dbxSvcAgentDSOPathPrefix = defaultDbxSvcAgentDSOPathPrefix;
}
if (cpu.equals("sparc")) {
dbxSvcAgentDSOPathNames = new String[] {
// FIXME: bad hack for SPARC v9. This is necessary because
// there are two dbx executables on SPARC, one for v8 and one
// for v9, and it isn't obvious how to tell the two apart
// using the dbx command line. See
// DbxDebuggerLocal.importDbxModule().
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + "v9" + fileSep + "lib" +
fileSep + "libsvc_agent_dbx.so",
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" +
fileSep + "libsvc_agent_dbx.so",
};
} else {
dbxSvcAgentDSOPathNames = new String[] {
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" +
fileSep + "libsvc_agent_dbx.so"
};
}
}
// Note we do not use a cache for the local debugger in server
// mode; it's taken care of on the client side
DbxDebuggerLocal dbg = new DbxDebuggerLocal(null, dbxPathName, dbxSvcAgentDSOPathNames, !isServer);
debugger = dbg;
attachDebugger();
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's " +
"address size. It's possible that the Serviceability Agent's dbx module failed to " +
"initialize. Examine the standard output and standard error streams from the dbx " +
"process for more information.");
}
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
}
dbg.setMachineDescription(machDesc);
throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
}
dbg.setMachineDescription(machDesc);
return;
}
private void connectRemoteDebugger() throws DebuggerException {
@@ -557,6 +484,8 @@ public class HotSpotAgent {
setupJVMLibNamesWin32();
} else if (os.equals("linux")) {
setupJVMLibNamesLinux();
} else if (os.equals("bsd")) {
setupJVMLibNamesBsd();
} else {
throw new RuntimeException("Unknown OS type");
}
@@ -589,11 +518,7 @@ public class HotSpotAgent {
// mode; it will be taken care of on the client side (once remote
// debugging is implemented).
if (System.getProperty("sun.jvm.hotspot.debugger.useWindbgDebugger") != null) {
debugger = new WindbgDebuggerLocal(machDesc, !isServer);
} else {
debugger = new Win32DebuggerLocal(machDesc, !isServer);
}
debugger = new WindbgDebuggerLocal(machDesc, !isServer);
attachDebugger();
@@ -638,6 +563,31 @@ public class HotSpotAgent {
jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" };
}
//
// BSD
//
private void setupDebuggerBsd() {
setupJVMLibNamesBsd();
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("amd64")) {
machDesc = new MachineDescriptionAMD64();
} else {
throw new DebuggerException("BSD only supported on x86/amd64");
}
BsdDebuggerLocal dbg = new BsdDebuggerLocal(machDesc, !isServer);
debugger = dbg;
attachDebugger();
}
private void setupJVMLibNamesBsd() {
jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" };
}
/** Convenience routine which should be called by per-platform
debugger setup. Should not be called when startupMode is
REMOTE_MODE. */

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,10 +29,9 @@ import java.net.*;
import java.rmi.*;
import sun.jvm.hotspot.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dbx.*;
import sun.jvm.hotspot.debugger.bsd.*;
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.win32.*;
import sun.jvm.hotspot.debugger.windbg.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.debugger.sparc.*;
@@ -516,6 +515,8 @@ public class BugSpotAgent {
setupDebuggerWin32();
} else if (os.equals("linux")) {
setupDebuggerLinux();
} else if (os.equals("bsd")) {
setupDebuggerBsd();
} else {
// Add support for more operating systems here
throw new DebuggerException("Operating system " + os + " not yet supported");
@@ -567,6 +568,9 @@ public class BugSpotAgent {
} else if (os.equals("linux")) {
db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
} else if (os.equals("bsd")) {
db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames),
debugger, jvmLibNames);
} else {
throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)");
}
@@ -627,104 +631,33 @@ public class BugSpotAgent {
private void setupDebuggerSolaris() {
setupJVMLibNamesSolaris();
String prop = System.getProperty("sun.jvm.hotspot.debugger.useProcDebugger");
if (prop != null && !prop.equals("false")) {
ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
debugger = dbg;
attachDebugger();
ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
debugger = dbg;
attachDebugger();
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's address size");
}
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
} else if (cpu.equals("amd64")) {
machDesc = new MachineDescriptionAMD64();
} else {
throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's address size");
}
dbg.setMachineDescription(machDesc);
return;
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
} else if (cpu.equals("amd64")) {
machDesc = new MachineDescriptionAMD64();
} else {
String dbxPathName;
String dbxPathPrefix;
String dbxSvcAgentDSOPathName;
String dbxSvcAgentDSOPathPrefix;
String[] dbxSvcAgentDSOPathNames = null;
// use path names/prefixes specified on command
dbxPathName = System.getProperty("dbxPathName");
if (dbxPathName == null) {
dbxPathPrefix = System.getProperty("dbxPathPrefix");
if (dbxPathPrefix == null) {
dbxPathPrefix = defaultDbxPathPrefix;
}
dbxPathName = dbxPathPrefix + fileSep + os + fileSep + cpu + fileSep + "bin" + fileSep + "dbx";
}
dbxSvcAgentDSOPathName = System.getProperty("dbxSvcAgentDSOPathName");
if (dbxSvcAgentDSOPathName != null) {
dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathName } ;
} else {
dbxSvcAgentDSOPathPrefix = System.getProperty("dbxSvcAgentDSOPathPrefix");
if (dbxSvcAgentDSOPathPrefix == null) {
dbxSvcAgentDSOPathPrefix = defaultDbxSvcAgentDSOPathPrefix;
}
if (cpu.equals("sparc")) {
dbxSvcAgentDSOPathNames = new String[] {
// FIXME: bad hack for SPARC v9. This is necessary because
// there are two dbx executables on SPARC, one for v8 and one
// for v9, and it isn't obvious how to tell the two apart
// using the dbx command line. See
// DbxDebuggerLocal.importDbxModule().
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + "v9" + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so",
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so",
};
} else {
dbxSvcAgentDSOPathNames = new String[] {
dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so"
};
}
}
// Note we do not use a cache for the local debugger in server
// mode; it's taken care of on the client side
DbxDebuggerLocal dbg = new DbxDebuggerLocal(null, dbxPathName, dbxSvcAgentDSOPathNames, !isServer);
debugger = dbg;
attachDebugger();
// Set up CPU-dependent stuff
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("sparc")) {
int addressSize = dbg.getRemoteProcessAddressSize();
if (addressSize == -1) {
throw new DebuggerException("Error occurred while trying to determine the remote process's address size. It's possible that the Serviceability Agent's dbx module failed to initialize. Examine the standard output and standard error streams from the dbx process for more information.");
}
if (addressSize == 32) {
machDesc = new MachineDescriptionSPARC32Bit();
} else if (addressSize == 64) {
machDesc = new MachineDescriptionSPARC64Bit();
} else {
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
}
}
dbg.setMachineDescription(machDesc);
throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
}
dbg.setMachineDescription(machDesc);
}
private void connectRemoteDebugger() throws DebuggerException {
@@ -739,6 +672,8 @@ public class BugSpotAgent {
setupJVMLibNamesWin32();
} else if (os.equals("linux")) {
setupJVMLibNamesLinux();
} else if (os.equals("bsd")) {
setupJVMLibNamesBsd();
} else {
throw new RuntimeException("Unknown OS type");
}
@@ -772,11 +707,7 @@ public class BugSpotAgent {
// mode; it will be taken care of on the client side (once remote
// debugging is implemented).
if (System.getProperty("sun.jvm.hotspot.debugger.useWindbgDebugger") != null) {
debugger = new WindbgDebuggerLocal(machDesc, !isServer);
} else {
debugger = new Win32DebuggerLocal(machDesc, !isServer);
}
debugger = new WindbgDebuggerLocal(machDesc, !isServer);
attachDebugger();
}
@@ -822,6 +753,34 @@ public class BugSpotAgent {
setupJVMLibNamesSolaris();
}
//
// BSD
//
private void setupDebuggerBsd() {
setupJVMLibNamesBsd();
if (cpu.equals("x86")) {
machDesc = new MachineDescriptionIntelX86();
} else if (cpu.equals("amd64")) {
machDesc = new MachineDescriptionAMD64();
} else {
throw new DebuggerException("Bsd only supported on x86/amd64");
}
// Note we do not use a cache for the local debugger in server
// mode; it will be taken care of on the client side (once remote
// debugging is implemented).
debugger = new BsdDebuggerLocal(machDesc, !isServer);
attachDebugger();
}
private void setupJVMLibNamesBsd() {
// same as solaris
setupJVMLibNamesSolaris();
}
/** Convenience routine which should be called by per-platform
debugger setup. Should not be called when startupMode is
REMOTE_MODE. */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -102,6 +102,11 @@ public class CodeBlob extends VMObject {
/** On-Stack Replacement method */
public boolean isOSRMethod() { return false; }
public NMethod asNMethodOrNull() {
if (isNMethod()) return (NMethod)this;
return null;
}
// Boundaries
public Address headerBegin() {
return addr;
@@ -195,7 +200,7 @@ public class CodeBlob extends VMObject {
}
// Returns true, if the next frame is responsible for GC'ing oops passed as arguments
public boolean callerMustGCArguments(JavaThread thread) { return false; }
public boolean callerMustGCArguments() { return false; }
public String getName() {
return CStringUtilities.getString(nameField.getValue(addr));

View File

@@ -59,6 +59,7 @@ public class CodeCache {
virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class);
virtualConstructor.addMapping("RicochetBlob", RicochetBlob.class);
virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class);
virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class);
virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class);
virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class);
if (VM.getVM().isServerCompiler()) {
@@ -126,6 +127,10 @@ public class CodeCache {
Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)),
"found wrong CodeBlob");
}
if (result.isRicochetBlob()) {
// This should probably be done for other SingletonBlobs
return VM.getVM().ricochetBlob();
}
return result;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,31 +22,37 @@
*
*/
package sun.jvm.hotspot.runtime.amd64;
package sun.jvm.hotspot.code;
import sun.jvm.hotspot.asm.amd64.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
public class AMD64RegisterMap extends RegisterMap {
/** This is the only public constructor */
public AMD64RegisterMap(JavaThread thread, boolean updateMap) {
super(thread, updateMap);
public class MethodHandlesAdapterBlob extends AdapterBlob {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
protected AMD64RegisterMap(RegisterMap map) {
super(map);
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("MethodHandlesAdapterBlob");
// FIXME: add any needed fields
}
public Object clone() {
AMD64RegisterMap retval = new AMD64RegisterMap(this);
return retval;
public MethodHandlesAdapterBlob(Address addr) {
super(addr);
}
// no PD state to clear or copy:
protected void clearPD() {}
protected void initializePD() {}
protected void initializeFromPD(RegisterMap map) {}
protected Address getLocationPD(VMReg reg) { return null; }
public boolean isMethodHandlesAdapterBlob() {
return true;
}
public String getName() {
return "MethodHandlesAdapterBlob: " + super.getName();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@ public class NMethod extends CodeBlob {
/** Offsets for different nmethod parts */
private static CIntegerField exceptionOffsetField;
private static CIntegerField deoptOffsetField;
private static CIntegerField deoptMhOffsetField;
private static CIntegerField origPCOffsetField;
private static CIntegerField stubOffsetField;
private static CIntegerField oopsOffsetField;
@@ -95,6 +96,7 @@ public class NMethod extends CodeBlob {
exceptionOffsetField = type.getCIntegerField("_exception_offset");
deoptOffsetField = type.getCIntegerField("_deoptimize_offset");
deoptMhOffsetField = type.getCIntegerField("_deoptimize_mh_offset");
origPCOffsetField = type.getCIntegerField("_orig_pc_offset");
stubOffsetField = type.getCIntegerField("_stub_offset");
oopsOffsetField = type.getCIntegerField("_oops_offset");
@@ -136,10 +138,11 @@ public class NMethod extends CodeBlob {
/** Boundaries for different parts */
public Address constantsBegin() { return contentBegin(); }
public Address constantsEnd() { return getEntryPoint(); }
public Address instsBegin() { return codeBegin(); }
public Address instsBegin() { return codeBegin(); }
public Address instsEnd() { return headerBegin().addOffsetTo(getStubOffset()); }
public Address exceptionBegin() { return headerBegin().addOffsetTo(getExceptionOffset()); }
public Address deoptBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); }
public Address deoptHandlerBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); }
public Address deoptMhHandlerBegin() { return headerBegin().addOffsetTo(getDeoptMhOffset()); }
public Address stubBegin() { return headerBegin().addOffsetTo(getStubOffset()); }
public Address stubEnd() { return headerBegin().addOffsetTo(getOopsOffset()); }
public Address oopsBegin() { return headerBegin().addOffsetTo(getOopsOffset()); }
@@ -187,6 +190,8 @@ public class NMethod extends CodeBlob {
public boolean handlerTableContains(Address addr) { return handlerTableBegin().lessThanOrEqual(addr) && handlerTableEnd().greaterThan(addr); }
public boolean nulChkTableContains (Address addr) { return nulChkTableBegin() .lessThanOrEqual(addr) && nulChkTableEnd() .greaterThan(addr); }
public int getOopsLength() { return (int) (oopsSize() / VM.getVM().getOopSize()); }
/** Entry points */
public Address getEntryPoint() { return entryPointField.getValue(addr); }
public Address getVerifiedEntryPoint() { return verifiedEntryPointField.getValue(addr); }
@@ -195,7 +200,7 @@ public class NMethod extends CodeBlob {
public OopHandle getOopAt(int index) {
if (index == 0) return null;
if (Assert.ASSERTS_ENABLED) {
Assert.that(index > 0 && index <= oopsSize(), "must be a valid non-zero index");
Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index");
}
return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize());
}
@@ -250,6 +255,22 @@ public class NMethod extends CodeBlob {
return (int) scavengeRootStateField.getValue(addr);
}
// MethodHandle
public boolean isMethodHandleReturn(Address returnPc) {
// Hard to read a bit fields from Java and it's only there for performance
// so just go directly to the PCDesc
// if (!hasMethodHandleInvokes()) return false;
PCDesc pd = getPCDescAt(returnPc);
if (pd == null)
return false;
return pd.isMethodHandleInvoke();
}
// Deopt
// Return true is the PC is one would expect if the frame is being deopted.
public boolean isDeoptPc (Address pc) { return isDeoptEntry(pc) || isDeoptMhEntry(pc); }
public boolean isDeoptEntry (Address pc) { return pc == deoptHandlerBegin(); }
public boolean isDeoptMhEntry (Address pc) { return pc == deoptMhHandlerBegin(); }
/** Tells whether frames described by this nmethod can be
deoptimized. Note: native wrappers cannot be deoptimized. */
@@ -388,6 +409,7 @@ public class NMethod extends CodeBlob {
private int getEntryBCI() { return (int) entryBCIField .getValue(addr); }
private int getExceptionOffset() { return (int) exceptionOffsetField .getValue(addr); }
private int getDeoptOffset() { return (int) deoptOffsetField .getValue(addr); }
private int getDeoptMhOffset() { return (int) deoptMhOffsetField .getValue(addr); }
private int getStubOffset() { return (int) stubOffsetField .getValue(addr); }
private int getOopsOffset() { return (int) oopsOffsetField .getValue(addr); }
private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); }

View File

@@ -38,6 +38,9 @@ public class PCDesc extends VMObject {
private static CIntegerField scopeDecodeOffsetField;
private static CIntegerField objDecodeOffsetField;
private static CIntegerField pcFlagsField;
private static int reexecuteMask;
private static int isMethodHandleInvokeMask;
private static int returnOopMask;
static {
VM.registerVMInitializedObserver(new Observer() {
@@ -54,6 +57,10 @@ public class PCDesc extends VMObject {
scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset");
objDecodeOffsetField = type.getCIntegerField("_obj_decode_offset");
pcFlagsField = type.getCIntegerField("_flags");
reexecuteMask = db.lookupIntConstant("PcDesc::PCDESC_reexecute");
isMethodHandleInvokeMask = db.lookupIntConstant("PcDesc::PCDESC_is_method_handle_invoke");
returnOopMask = db.lookupIntConstant("PcDesc::PCDESC_return_oop");
}
public PCDesc(Address addr) {
@@ -81,7 +88,12 @@ public class PCDesc extends VMObject {
public boolean getReexecute() {
int flags = (int)pcFlagsField.getValue(addr);
return ((flags & 0x1)== 1); //first is the reexecute bit
return (flags & reexecuteMask) != 0;
}
public boolean isMethodHandleInvoke() {
int flags = (int)pcFlagsField.getValue(addr);
return (flags & isMethodHandleInvokeMask) != 0;
}
public void print(NMethod code) {

View File

@@ -41,11 +41,15 @@ public class RicochetBlob extends SingletonBlob {
}
private static void initialize(TypeDataBase db) {
// Type type = db.lookupType("RicochetBlob");
Type type = db.lookupType("RicochetBlob");
// FIXME: add any needed fields
bounceOffsetField = type.getCIntegerField("_bounce_offset");
exceptionOffsetField = type.getCIntegerField("_exception_offset");
}
private static CIntegerField bounceOffsetField;
private static CIntegerField exceptionOffsetField;
public RicochetBlob(Address addr) {
super(addr);
}
@@ -53,4 +57,14 @@ public class RicochetBlob extends SingletonBlob {
public boolean isRicochetBlob() {
return true;
}
public Address bounceAddr() {
return codeBegin().addOffsetTo(bounceOffsetField.getValue(addr));
}
public boolean returnsToBounceAddr(Address pc) {
Address bouncePc = bounceAddr();
return (pc.equals(bouncePc) || pc.addOffsetTo(Frame.pcReturnOffset()).equals(bouncePc));
}
}

View File

@@ -30,6 +30,8 @@ import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
public class RuntimeStub extends CodeBlob {
private static CIntegerField callerMustGCArgumentsField;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@@ -40,6 +42,7 @@ public class RuntimeStub extends CodeBlob {
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("RuntimeStub");
callerMustGCArgumentsField = type.getCIntegerField("_caller_must_gc_arguments");
// FIXME: add any needed fields
}
@@ -52,6 +55,11 @@ public class RuntimeStub extends CodeBlob {
return true;
}
public boolean callerMustGCArguments() {
return callerMustGCArgumentsField.getValue(addr) != 0;
}
public String getName() {
return "RuntimeStub: " + super.getName();
}

View File

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

View File

@@ -246,7 +246,7 @@ public class OopMapSet extends VMObject {
}
// Check if caller must update oop argument
regMap.setIncludeArgumentOops(cb.callerMustGCArguments(regMap.getThread()));
regMap.setIncludeArgumentOops(cb.callerMustGCArguments());
int nofCallee = 0;
Address[] locs = new Address[2 * REG_COUNT + 1];

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