|
| 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. |
0 commit comments