Skip to content

Commit 2a2077a

Browse files
committed
[GR-20866] Debug info prototype.
PullRequest: graal/5814
2 parents 796593c + 261045f commit 2a2077a

38 files changed

+6121
-7
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ matrix:
2727
- env: JDK="jdk8" GATE="style,fullbuild" PRIMARY="substratevm"
2828
- env: JDK="jdk8" GATE="build,test" PRIMARY="compiler"
2929
- env: JDK="jdk8" GATE="build,test,helloworld" PRIMARY="substratevm"
30+
- env: JDK="jdk8" GATE="build,test,helloworld_debug" PRIMARY="substratevm"
3031
- env: JDK="jdk8" GATE="build,bootstraplite" PRIMARY="compiler"
3132
- env: JDK="jdk8" GATE="style,fullbuild,sulongBasic" PRIMARY="sulong"
3233
addons:

substratevm/DEBUGINFO.md

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
Using the debug info feature
2+
----------------------------
3+
4+
To add debug info to a generated native image add flag
5+
-H:GenerateDebugInfo=<N> to the native image command line (where N is
6+
a positive integer value -- the default value 0 means generate no
7+
debug info). For example,
8+
9+
$ javac Hello.java
10+
$ mx native-image -H:GenerateDebugInfo=1 Hello
11+
12+
The resulting image should contain code (method) debug records in a
13+
format gdb understands (Windows support is still under development).
14+
At present it makes no difference which positive value is supplied as
15+
argument to the GenerateDebugInfo option.
16+
17+
The GenerateDebugInfo option also enables caching of sources for any
18+
JDK runtime classes, GraalVM classes and application classes which can
19+
be located during native image generation. The cache is created under
20+
local subdirectory sources. It is used to configure source file search
21+
path roots for the debugger. Files in the cache are located in a
22+
directory hierarchy that matches the file path information included in
23+
the native image debug records. The source cache should contain all
24+
the files needed to debug the generated image and nothing more. This
25+
local cache provides a convenient way of making just the necessary
26+
sources available to the debugger/IDE when debugging a native image.
27+
28+
The implementation tries to be smart about locating source files. It
29+
uses the current JAVA_HOME to locate the JDK src.zip when searching
30+
for JDK runtime sources. It also uses entries in the classpath to
31+
suggest locations for GraalVM source files and application source
32+
files (see below for precise details of the scheme used to identify
33+
source locations). However, source layouts do vary and it may not be
34+
possible to find all sources. Hence, users can specify the location of
35+
source files explicitly on the command line using option
36+
DebugInfoSourceSearchPath:
37+
38+
$ javac --source-path apps/greeter/src \
39+
-d apps/greeter/classes org/my/greeter/*Greeter.java
40+
$ javac -cp apps/greeter/classes \
41+
--source-path apps/hello/src \
42+
-d apps/hello/classes org/my/hello/Hello.java
43+
$ mx native-image -H:GenerateDebugInfo=1 \
44+
-H:DebugInfoSourceSearchPath=apps/hello/src \
45+
-H:DebugInfoSourceSearchPath=apps/greeter/src \
46+
-cp apps/hello/classes:apps/greeter/classes org.my.hello.Hello
47+
48+
Option DebugInfoSourceSearchPath can be repeated as many times as
49+
required to notify all the target source locations. The value passed
50+
to this option can be either an absolute or relative path. It can
51+
identify either a directory, a source jar or a source zip file. It is
52+
also possible to specify several source roots at once using a comma
53+
separator:
54+
55+
$ mx native-image -H:GenerateDebugInfo=1 \
56+
-H:DebugInfoSourceSearchPath=apps/hello/target/hello-sources.jar,apps/greeter/target/greeter-sources.jar \
57+
-cp apps/target/hello.jar:apps/target/greeter.jar \
58+
org.my.Hello
59+
60+
Note that in both the examples above the DebugInfoSourceSearchPath
61+
options are actually redundant. In the first case the classpath
62+
entries for apps/hello/classes and apps/greeter/classes will be used
63+
to derive the default search roots apps/hello/src and
64+
apps/greeter/src. In the second case classpath entries
65+
apps/target/hello.jar and apps/target/greeter.jar will be used to
66+
derive the default search roots apps/target/hello-sources.jar and
67+
apps/target/greeter-sources.jar.
68+
69+
What is currently implemented
70+
-----------------------------
71+
72+
The currently implemented features include:
73+
74+
- break points configured by file and line or by method name
75+
- single stepping by line including both into and over function calls
76+
- stack backtraces (not including frames detailing inlined code)
77+
78+
Note that single stepping within a compiled method includes file and
79+
line number info for inlined code, including inlined Graal methods.
80+
So, gdb may switch files even though you are still in the same
81+
compiled method.
82+
83+
Identifying the location of source code
84+
---------------------------------------
85+
86+
One goal of the implementation is to make it simple to configure your
87+
debugger so that it can identify the relevant source file when it
88+
stops during program execution. The native image generator tries to
89+
achieve this by accumulating the relevant sources in a suitably
90+
structured file cache.
91+
92+
The native image generator uses different strategies to locate source
93+
files for JDK runtime classes, GraalVM classes and application source
94+
classes for inclusion in the local sources cache. It identifies which
95+
strategy to use based on the package name of the class. So, for
96+
example, packages starting with java.* or jdk.* are JDK classes;
97+
packages starting with org.graal.* or com.oracle.svm.* are GraalVM
98+
classes; any other packages are regarded as application classes.
99+
100+
Sources for JDK runtime classes are retrieved from the src.zip found
101+
in the JDK release used to run the native image generation process.
102+
Retrieved files are cached under subdirectory sources/jdk, using the
103+
module name (for JDK11) and package name of the associated class to
104+
define the directory hierarchy in which the source is located.
105+
106+
So, for example, on Linux the source for class java.util.HashMap will
107+
be cached in file sources/jdk/java.base/java/util/HashMap.java. Debug
108+
info records for this class and its methods will identify this source
109+
file using the relative directory path java.base/java/util and file
110+
name HashMap.java. On Windows things will be the same modulo use of
111+
'\' rather than '/' as the file separator.
112+
113+
Sources for GraalVM classes are retrieved from zip files or source
114+
directories derived from entries in the classpath. Retrieved files are
115+
cached under subdirectory sources/graal, using the package name of the
116+
associated class to define the directory hierarchy in which the source
117+
is located (e.g. class com.oracle.svm.core.VM has its source file
118+
cached at sources/graal/com/oracle/svm/core/VM.java).
119+
120+
The lookup scheme for cached GraalVM sources varies depending upon
121+
what is found in each classpath entry. Given a jar file entry like
122+
/path/to/foo.jar, the corresponding file /path/to/foo.src.zip is
123+
considered as a candidate zip file system from which source files may
124+
be extracted. When the entry specifies a dir like /path/to/bar then
125+
directories /path/to/bar/src and /path/to/bar/src_gen are considered
126+
as candidates. Candidates are skipped when i) the zip file or source
127+
directory does not exist or ii) it does not contain at least one
128+
subdirectory hierarchy that matches one of the the expected GraalVM
129+
package hierarchies.
130+
131+
Sources for application classes are retrieved from source jar files or
132+
source directories derived from entries in the classpath. Retrieved
133+
files are cached under subdirectory sources/src, using the package
134+
name of the associated class to define the directory hierarchy in
135+
which the source is located (e.g. class org.my.foo.Foo has its
136+
source file cached as sources/src/org/my/foo/Foo.java).
137+
138+
The lookup scheme for cached Application sources varies depending upon
139+
what is found in each classpath entry. Given a jar file entry like
140+
/path/to/foo.jar, the corresponding jar /path/to/foo-sources.jar is
141+
considered as a candidate zip file system from which source files may
142+
be extracted. When the entry specifies a dir like /path/to/bar/classes
143+
or /path/to/bar/target/classes then directory /path/to/bar/src is
144+
considered as a candidate. Finally, the current directory in which the
145+
native image program is being run is also considered as a candidate.
146+
147+
These lookup strategies are only provisional and may need extending in
148+
future. Note however that it is possible to make missing sources
149+
available by other means. One option is to unzip extra app source jars
150+
or copying extra app source trees into the cache. Another is to
151+
configure extra source search paths (see below).
152+
153+
Configuring source paths in gdb
154+
-------------------------------
155+
156+
In order for gdb to be able to locate the source files for your app
157+
classes, Graal classes and JDK runtime classes you need to provide gdb
158+
with a list of source root dirs using the 'set directories' command:
159+
160+
(gdb) set directories /path/to/sources/jdk:/path/to/sources/graal:/path/to/sources/src
161+
162+
Directory .../sources/jdk should contain source files for all JDK runtime
163+
classes referenced from debug records.
164+
165+
Directory .../sources/graal should contain source files for all GraalVM
166+
classes referenced from debug records. Note that the current
167+
implementation does not yet find some sources for the GraalVM JIT
168+
compiler in the org.graalvm.compiler* package subspace.
169+
170+
Directory .../sources/src should contain source files for all
171+
application classes referenced from debug records, assuming they can
172+
be located using the lookup strategy described above.
173+
174+
You can supplement the files cached in sources/src by unzipping
175+
application source jars or copying application source trees into the
176+
cache. You need to ensure that any new subdirectory you add to
177+
sources/src corresponds to the top level package for the classes whose
178+
sources are being included.
179+
180+
You can also add extra directories to the search path. Note that gdb
181+
does not understand zip format file systems so any extra entries you
182+
add must identify a directory tree containing the relevant
183+
sources. Once again. top level entries in the directory added to the
184+
search path must correspond to the top level package for the classes
185+
whose sources are being included.
186+
187+
Configuring source paths in VS
188+
------------------------------
189+
190+
TO BE ADDED
191+
192+
Checking debug info on Linux
193+
----------------------------
194+
195+
n.b. this is only of interest to those who want to understand how the
196+
debug info implementation works or want to trouble shoot problems
197+
encountered during debugging that might relate to the debug info
198+
encoding.
199+
200+
The objdump command can be used to display the debug info embedded
201+
into a native image. The following commands (which all assume the
202+
target binary is called hello) can be used to display all currently
203+
generated content:
204+
205+
$ objdump --dwarf=info hello > info
206+
$ objdump --dwarf=abbrev hello > abbrev
207+
$ objdump --dwarf=ranges hello > ranges
208+
$ objdump --dwarf=decodedline hello > decodedline
209+
$ objdump --dwarf=rawline hello > rawline
210+
$ objdump --dwarf=str hello > str
211+
$ objdump --dwarf=frames hello > frames
212+
213+
The *info* section includes details of all compiled Java methods.
214+
215+
The *abbrev* section defines the layout of records in the info section
216+
that describe Java files (compilation units) and methods.
217+
218+
The *ranges* section details the start and end addresses of method
219+
code segments
220+
221+
The *decodedline* section maps subsegments of method code range
222+
segments to files and line numbers. This mapping includes entries
223+
for files and line numbers for inlined methods.
224+
225+
The *rawline* segment provides details of how the line table is
226+
generated using DWARF state machine instructions that encode file,
227+
line and address transitions.
228+
229+
The *str* section provides a lookup table for strings referenced
230+
from records in the info section
231+
232+
The *frames* section lists transition points in compiled methods
233+
where a (fixed size) stack frame is pushed or popped, allowing
234+
the debugger to identify each frame's current and previous stack
235+
pointers and it's return address.
236+
237+
Note that some of the content embedded in the debug records is
238+
generated by the C compiler and belongs to code that is either in
239+
libraries or the C lib bootstrap code that is bundled in with the
240+
Java method code.
241+
242+
Currently supported targets
243+
---------------------------
244+
245+
The prototype is currently implemented only for gdb on Linux.
246+
247+
- Linux/x86_64 support has been tested and should work
248+
correctly.
249+
250+
- Linux/AArch64 support is present but has not yet been fully
251+
verified (break points should work ok but stack backtraces
252+
may be incorrect).
253+
254+
Windows support is still under development.

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ def __getattr__(self, name):
359359

360360
GraalTags = Tags([
361361
'helloworld',
362+
'helloworld_debug',
362363
'test',
363364
'maven',
364365
'js',
@@ -468,6 +469,19 @@ def svm_gate_body(args, tasks):
468469
cinterfacetutorial([])
469470
clinittest([])
470471

472+
with Task('image demos debuginfo', tasks, tags=[GraalTags.helloworld_debug]) as t:
473+
if t:
474+
if svm_java8():
475+
javac_image(['--output-path', svmbuild_dir(), '-H:GenerateDebugInfo=1'])
476+
javac_command = ['--javac-command', ' '.join(javac_image_command(svmbuild_dir())), '-H:GenerateDebugInfo=1']
477+
else:
478+
# Building javac image currently only supported for Java 8
479+
javac_command = ['-H:GenerateDebugInfo=1']
480+
helloworld(['--output-path', svmbuild_dir()] + javac_command)
481+
helloworld(['--output-path', svmbuild_dir(), '--shared', '-H:GenerateDebugInfo=1']) # Build and run helloworld as shared library
482+
cinterfacetutorial(['-H:GenerateDebugInfo=1'])
483+
clinittest([])
484+
471485
with Task('native unittests', tasks, tags=[GraalTags.test]) as t:
472486
if t:
473487
with tempfile.NamedTemporaryFile(mode='w') as blacklist:

substratevm/mx.substratevm/suite.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,9 @@
604604
"com.oracle.objectfile" : {
605605
"subDir": "src",
606606
"sourceDirs" : ["src"],
607-
"dependencies" : [],
607+
"dependencies" : [
608+
"compiler:GRAAL"
609+
],
608610
"checkstyle" : "com.oracle.svm.hosted",
609611
"javaCompliance" : "8+",
610612
"annotationProcessors" : ["compiler:GRAAL_PROCESSOR"],
@@ -920,7 +922,9 @@
920922
"dependencies": [
921923
"com.oracle.objectfile"
922924
],
923-
},
925+
"distDependencies": [
926+
"compiler:GRAAL",
927+
], },
924928

925929
"GRAAL_HOTSPOT_LIBRARY": {
926930
"subDir": "src",

0 commit comments

Comments
 (0)