Skip to content

Commit eb08fb0

Browse files
committed
feat(crashtracking): J9 register parsing
Parse the GPINFO register section (1XHREGISTERS / 2XHREGISTER tags) from J9/OpenJ9 javacore crash dumps mirroring what was done for HotSpot. Register format: 1XHREGISTERS Registers: 2XHREGISTER RIP: 00007F8B7C0B3D7D (x86-64) 2XHREGISTER PC: 0000FFFF98B9FB6C (aarch64) Added crash dumps from IBM J9 (Java 8) and IBM Semeru / OpenJ9 (Java 11) that were obtained using Docker and this crashing program: ```java import sun.misc.Unsafe; import java.lang.reflect.Field; public class Crash { public static void main(String[] args) throws Exception { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe unsafe = (Unsafe) f.get(null); unsafe.putInt(0L, 42); // SIGSEGV -> GPF dump } } ``` ``` docker run --rm -v /tmp/j9-crash-test:/work ibmjava:8-sdk \ bash -c "cd /work && javac Crash.java && \ java -Xdump:java:events=gpf,file=/work/javacore.ibmj9.txt Crash" ``` ``` docker run --rm -v /tmp/j9-crash-test:/work ibm-semeru-runtimes:open-11-jdk \ bash -c "cd /work && javac Crash.java && \ java -Xdump:java:events=gpf,file=/work/javacore.openj9.txt Crash" ```
1 parent 1097c06 commit eb08fb0

File tree

4 files changed

+4938
-1
lines changed

4 files changed

+4938
-1
lines changed

dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/J9JavacoreParser.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import datadog.crashtracking.buildid.BuildInfo;
88
import datadog.crashtracking.dto.CrashLog;
99
import datadog.crashtracking.dto.ErrorData;
10+
import datadog.crashtracking.dto.Experimental;
1011
import datadog.crashtracking.dto.Metadata;
1112
import datadog.crashtracking.dto.OSInfo;
1213
import datadog.crashtracking.dto.ProcInfo;
@@ -21,8 +22,10 @@
2122
import java.time.format.DateTimeFormatter;
2223
import java.time.format.DateTimeParseException;
2324
import java.util.ArrayList;
25+
import java.util.LinkedHashMap;
2426
import java.util.List;
2527
import java.util.Locale;
28+
import java.util.Map;
2629
import java.util.regex.Matcher;
2730
import java.util.regex.Pattern;
2831

@@ -80,6 +83,11 @@ public J9JavacoreParser() {
8083
private static final Pattern NATIVE_STACK_PATTERN = Pattern.compile("4XENATIVESTACK\\s+(.+)");
8184
private static final Pattern EXCEPTION_DETAIL_PATTERN =
8285
Pattern.compile("1TISIGINFO.*[Dd]etail\\s+\"(.+?)\".*");
86+
// Matches register entries in J9 GPINFO section, e.g.:
87+
// 2XHREGISTER RDI: 0000000000000001 (x86-64)
88+
// 2XHREGISTER R29: 0000FFFF990CDB50 (aarch64)
89+
private static final Pattern REGISTER_ENTRY_PARSER =
90+
Pattern.compile("([A-Za-z][A-Za-z0-9]*)\\s*:\\s*([0-9a-fA-F]+)");
8391

8492
// Date time formatter for J9 format: YYYY/MM/DD at HH:MM:SS
8593
private static final DateTimeFormatter J9_DATETIME_FORMATTER =
@@ -108,6 +116,8 @@ public CrashLog parse(String uuid, String javacoreContent) {
108116
boolean incomplete = false;
109117
boolean foundThreadSection = false;
110118

119+
Map<String, String> registers = null;
120+
111121
String[] lines = NEWLINE_SPLITTER.split(javacoreContent);
112122

113123
for (String line : lines) {
@@ -148,6 +158,14 @@ public CrashLog parse(String uuid, String javacoreContent) {
148158
// OS level and CPU architecture are available in GPINFO section but currently
149159
// not extracted since OSInfo.current() is used for the crash report.
150160
// If needed in the future, parse 2XHOSLEVEL and 3XHCPUARCH tags here.
161+
if (line.startsWith("1XHREGISTERS")) {
162+
registers = new LinkedHashMap<>();
163+
} else if (registers != null && line.startsWith("2XHREGISTER")) {
164+
final Matcher m = REGISTER_ENTRY_PARSER.matcher(line);
165+
while (m.find()) {
166+
registers.put(m.group(1), "0x" + m.group(2));
167+
}
168+
}
151169
break;
152170

153171
case ENVINFO:
@@ -267,9 +285,20 @@ public CrashLog parse(String uuid, String javacoreContent) {
267285
Metadata metadata = new Metadata("dd-trace-java", VersionInfo.VERSION, "java", null);
268286
Integer parsedPid = safelyParseInt(pid);
269287
ProcInfo procInfo = parsedPid != null ? new ProcInfo(parsedPid) : null;
288+
Experimental experimental =
289+
(registers != null && !registers.isEmpty()) ? new Experimental(registers) : null;
270290

271291
return new CrashLog(
272-
uuid, incomplete, datetime, error, metadata, OSInfo.current(), procInfo, sigInfo, "1.0");
292+
uuid,
293+
incomplete,
294+
datetime,
295+
error,
296+
metadata,
297+
OSInfo.current(),
298+
procInfo,
299+
sigInfo,
300+
"1.0",
301+
experimental);
273302
}
274303

275304
private static Integer safelyParseInt(String value) {

dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/parsers/J9JavacoreParserTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.UUID;
1717
import java.util.stream.Collectors;
1818
import org.junit.jupiter.api.Test;
19+
import org.tabletest.junit.TableTest;
1920

2021
public class J9JavacoreParserTest {
2122

@@ -65,6 +66,26 @@ public void testParseGpfCrash() throws Exception {
6566
assertTrue(crashLog.error.stack.frames.length >= 4); // 3 java + native frames
6667
}
6768

69+
@TableTest({
70+
"scenario | resource | pcRegister | spRegister",
71+
"IBM J9 8 (amd64) | sample-ibmj9-8-javacore-gpf.txt | RIP | RSP ",
72+
"OpenJ9 11 (aarch64) | sample-openj9-11-javacore-gpf.txt | PC | SP "
73+
})
74+
public void testParseRealGpfCrash(String resource, String pcRegister, String spRegister)
75+
throws Exception {
76+
final CrashLog crashLog =
77+
new J9JavacoreParser().parse(UUID.randomUUID().toString(), readFileAsString(resource));
78+
79+
assertFalse(crashLog.incomplete);
80+
assertEquals("SIGSEGV", crashLog.sigInfo.name);
81+
assertEquals(11, crashLog.sigInfo.number);
82+
83+
assertNotNull(crashLog.experimental);
84+
assertFalse(crashLog.experimental.ucontext.isEmpty());
85+
assertTrue(crashLog.experimental.ucontext.containsKey(pcRegister));
86+
assertTrue(crashLog.experimental.ucontext.containsKey(spRegister));
87+
}
88+
6889
@Test
6990
public void testParseOomCrash() throws Exception {
7091
// Given

0 commit comments

Comments
 (0)