Skip to content

Commit 4eb1273

Browse files
committed
WIP
1 parent 8bcee06 commit 4eb1273

File tree

4 files changed

+18890
-23
lines changed

4 files changed

+18890
-23
lines changed

dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/events/SmapEntryFactory.java

Lines changed: 148 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@
33
import datadog.trace.api.Platform;
44
import datadog.trace.bootstrap.instrumentation.jfr.JfrHelper;
55
import de.thetaphi.forbiddenapis.SuppressForbidden;
6+
7+
import java.io.BufferedReader;
68
import java.io.File;
9+
import java.io.FileInputStream;
710
import java.io.FileNotFoundException;
11+
import java.io.IOException;
12+
import java.io.InputStreamReader;
813
import java.lang.management.ManagementFactory;
14+
import java.nio.file.Files;
15+
import java.nio.file.Paths;
916
import java.util.ArrayList;
1017
import java.util.Arrays;
1118
import java.util.Collections;
@@ -34,7 +41,8 @@ public class SmapEntryFactory {
3441
private static final Pattern SYSTEM_MAP_ENTRY_PATTERN =
3542
Pattern.compile(
3643
"([0-9a-fA-Fx]+)\\s+-\\s+([0-9a-fA-Fx]+)\\s+(\\d+)\\s+(\\S+)\\s+(\\S+)(?:\\s+(.*))?");
37-
private static final String VSYSCALL_START_ADDRESS = "ffffffffff600000";
44+
private static final String VSYSCALL_START_ADDRESS_STR = "ffffffffff600000";
45+
private static final long VSYSCALL_START_ADDRESS = 0xffffffffff600000L;
3846
private static final SmapEntryEvent SMAP_ENTRY_EVENT = new SmapEntryEvent();
3947

4048
private enum ErrorReason {
@@ -81,6 +89,57 @@ public static void registerEvents() {
8189
}
8290
}
8391

92+
static class AnnotatedRegion {
93+
final long startAddress;
94+
final String description;
95+
96+
AnnotatedRegion(long startAddress, String description) {
97+
this.startAddress = startAddress;
98+
this.description = description;
99+
}
100+
}
101+
102+
static AnnotatedRegion fromAnnotatedEntry(String line) {
103+
boolean isRegion = line.startsWith("0x");
104+
if (isRegion) {
105+
// 0x0000000420000000 - 0x000000043b000000 452984832 rw-p 00000000 JAVAHEAP
106+
boolean isVsyscall = line.startsWith("0x" + VSYSCALL_START_ADDRESS_STR); // can't be parsed to Long safely(?)
107+
long startAddress = -1;
108+
int dashIndex = line.indexOf('-');
109+
if (dashIndex > 0) {
110+
startAddress = isVsyscall ? -0x1000 - 1 : Long.decode(line.substring(0, dashIndex - 1));
111+
String description = extractElement(line, 4, dashIndex + 1);
112+
if (description == null || description.isEmpty()) {
113+
return new AnnotatedRegion(startAddress, "UNDEFINED");
114+
} else if (description.startsWith("STACK")) {
115+
return new AnnotatedRegion(startAddress, "STACK");
116+
} else if (description.startsWith("[") || description.startsWith("/")) {
117+
return new AnnotatedRegion(startAddress, "SYSTEM");
118+
} else {
119+
return new AnnotatedRegion(startAddress, description);
120+
}
121+
}
122+
}
123+
return null;
124+
}
125+
126+
static String extractElement(String line, int index, int from) {
127+
int wsCount = 0;
128+
int wsIndex = line.indexOf(' ', from + 1);
129+
if (wsIndex > 0) {
130+
wsCount++;
131+
while (wsCount < index) {
132+
while (line.charAt(++wsIndex) == ' ') {}
133+
wsIndex = line.indexOf(' ', wsIndex + 1);
134+
if (wsIndex <= 0) {
135+
break;
136+
}
137+
wsCount++;
138+
}
139+
}
140+
return wsCount == index ? line.substring(wsIndex + 1).trim() : null;
141+
}
142+
84143
@SuppressForbidden
85144
private static HashMap<Long, String> getAnnotatedRegions() {
86145
if (annotatedMapsAvailable) {
@@ -97,28 +156,33 @@ private static HashMap<Long, String> getAnnotatedRegions() {
97156
HashMap<Long, String> annotatedRegions = new HashMap<>();
98157

99158
for (String line : lines) {
100-
Matcher matcher = SYSTEM_MAP_ENTRY_PATTERN.matcher(line);
101-
if (matcher.matches()) {
102-
long startAddress;
103-
if (matcher.group(1).equals("0x" + VSYSCALL_START_ADDRESS)) {
104-
// See how smap entry parsing is done for vsyscall
105-
startAddress = -0x1000 - 1;
106-
} else {
107-
startAddress = Long.decode(matcher.group(1));
108-
}
109-
String description = matcher.group(6);
110-
annotatedRegions.put(startAddress, description);
111-
if (description.isEmpty()) {
112-
annotatedRegions.put(startAddress, "UNDEFINED");
113-
} else if (description.startsWith("STACK")) {
114-
annotatedRegions.put(startAddress, "STACK");
115-
} else if (description.startsWith("[") || description.startsWith("/")) {
116-
annotatedRegions.put(startAddress, "SYSTEM");
117-
} else {
118-
annotatedRegions.put(startAddress, description.split("\\s+")[0]);
119-
}
159+
AnnotatedRegion region = fromAnnotatedEntry(line);
160+
if (region != null) {
161+
annotatedRegions.put(region.startAddress, region.description);
120162
}
121163
}
164+
// Matcher matcher = SYSTEM_MAP_ENTRY_PATTERN.matcher(line);
165+
// if (matcher.matches()) {
166+
// long startAddress;
167+
// if (matcher.group(1).equals("0x" + VSYSCALL_START_ADDRESS)) {
168+
// // See how smap entry parsing is done for vsyscall
169+
// startAddress = -0x1000 - 1;
170+
// } else {
171+
// startAddress = Long.decode(matcher.group(1));
172+
// }
173+
// String description = matcher.group(6);
174+
// annotatedRegions.put(startAddress, description);
175+
// if (description.isEmpty()) {
176+
// annotatedRegions.put(startAddress, "UNDEFINED");
177+
// } else if (description.startsWith("STACK")) {
178+
// annotatedRegions.put(startAddress, "STACK");
179+
// } else if (description.startsWith("[") || description.startsWith("/")) {
180+
// annotatedRegions.put(startAddress, "SYSTEM");
181+
// } else {
182+
// annotatedRegions.put(startAddress, description.split("\\s+")[0]);
183+
// }
184+
// }
185+
// }
122186
return annotatedRegions;
123187
} catch (Exception e) {
124188
new SmapParseErrorEvent(ErrorReason.VM_MAP_PARSING_ERROR).commit();
@@ -130,6 +194,67 @@ private static HashMap<Long, String> getAnnotatedRegions() {
130194
}
131195
}
132196

197+
private static int nextDelimitedStart(String line, int from) {
198+
if (from < 0) {
199+
return from;
200+
}
201+
int idx = line.indexOf(' ', from + 1);
202+
while (line.charAt(++idx) == ' ') {}
203+
return idx;
204+
}
205+
206+
private static int nextDelimitedEnd(String line, int from) {
207+
if (from < 0) {
208+
return from;
209+
}
210+
int idx = line.indexOf(' ', from + 1);
211+
if (idx <= 0) {
212+
return line.length();
213+
}
214+
return idx;
215+
}
216+
217+
static final class SmapHeader {
218+
long startAddress;
219+
long endAddress;
220+
String perms;
221+
long offset;
222+
String dev;
223+
int inode;
224+
String pathname = "";
225+
}
226+
227+
static int nextValueIdx(String line, int from) {
228+
int limit = line.length() - 1;
229+
while (from < limit && line.charAt(++from) == ' ') {}
230+
if (from == limit) {
231+
return -1;
232+
}
233+
int next = line.indexOf(' ', from + 1);
234+
return next == -1 ? limit + 1 : next;
235+
}
236+
237+
static long nextLongValue(String line, int[] position) {
238+
int from = position[0];
239+
int limit = line.length() - 1;
240+
while (from < limit && line.charAt(++from) == ' ') {}
241+
if (from == limit) {
242+
position[0] = -1;
243+
return -1;
244+
}
245+
long val = 0;
246+
while (from < limit && line.charAt(++from) != ' ') {
247+
char c = line.charAt(from);
248+
if (c < '0' || c > '9') {
249+
position[0] = -1;
250+
return -1;
251+
}
252+
val = val * 10 + (c - '0');
253+
}
254+
position[0] = from + 1;
255+
return val;
256+
}
257+
133258
@SuppressForbidden // split with one-char String use a fast-path without regex usage
134259
static List<? extends Event> collectEvents() {
135260
if (!SMAP_ENTRY_EVENT.isEnabled()) {
@@ -178,7 +303,7 @@ static List<? extends Event> collectEvents() {
178303
while (scanner.hasNextLine()) {
179304
boolean encounteredForeignKeys = false;
180305
String[] addresses = scanner.next().split("-");
181-
if (!addresses[0].equals(VSYSCALL_START_ADDRESS)) {
306+
if (!addresses[0].equals(VSYSCALL_START_ADDRESS_STR)) {
182307
startAddress = Long.parseLong(addresses[0], 16);
183308
endAddress = Long.parseLong(addresses[1], 16);
184309
} else {
@@ -347,7 +472,7 @@ static List<? extends Event> collectEvents() {
347472
nmtCategory));
348473
}
349474
return events;
350-
} catch (FileNotFoundException e) {
475+
} catch (IOException e) {
351476
return List.of(new SmapParseErrorEvent(ErrorReason.SMAP_FILE_NOT_FOUND));
352477
} catch (Exception e) {
353478
return List.of(new SmapParseErrorEvent(ErrorReason.SMAP_PARSING_ERROR));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.datadog.profiling.controller.openjdk.events;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.io.BufferedReader;
7+
import java.io.InputStreamReader;
8+
import java.util.Objects;
9+
10+
import static org.junit.jupiter.api.Assertions.assertNotNull;
11+
12+
public class SmapEntryFactoryTest {
13+
@Test
14+
void testAnnotatedRegionsSanity() throws Exception {
15+
try (BufferedReader br = new BufferedReader(new InputStreamReader(Objects.requireNonNull(SmapEntryFactory.class.getResourceAsStream("/smap/annotated_regions.txt"))))) {
16+
String line = null;
17+
while ((line = br.readLine()) != null) {
18+
SmapEntryFactory.AnnotatedRegion region = SmapEntryFactory.fromAnnotatedEntry(line);
19+
if (line.startsWith("0x")) {
20+
assertNotNull(region);
21+
}
22+
}
23+
}
24+
}
25+
26+
@Test
27+
void testNextLongValue() throws Exception {
28+
String line = "3232 fsdasg 1232352523";
29+
int[] pos = new int[]{0};
30+
long val = SmapEntryFactory.nextLongValue(line, pos);
31+
val = SmapEntryFactory.nextLongValue(line, pos);
32+
val = SmapEntryFactory.nextLongValue(line, pos);
33+
}
34+
}

0 commit comments

Comments
 (0)