|
| 1 | +/******************************************************************************* |
| 2 | + * Copyright (c) 2026 École Polytechnique de Montréal |
| 3 | + * |
| 4 | + * All rights reserved. This program and the accompanying materials are |
| 5 | + * made available under the terms of the Eclipse Public License 2.0 which |
| 6 | + * accompanies this distribution, and is available at |
| 7 | + * https://www.eclipse.org/legal/epl-2.0/ |
| 8 | + * |
| 9 | + * SPDX-License-Identifier: EPL-2.0 |
| 10 | + *******************************************************************************/ |
1 | 11 | package org.eclipse.tracecompass.incubator.internal.virtual.machine.analysis.core.flow.analysis; |
2 | 12 |
|
3 | | -import java.io.File; |
4 | | -import java.io.FileOutputStream; |
5 | | -import java.io.IOException; |
6 | | -import java.io.PrintWriter; |
7 | 13 | import java.util.ArrayList; |
8 | 14 | import java.util.Comparator; |
9 | 15 | import java.util.HashMap; |
@@ -35,9 +41,6 @@ public class ProcessFlowInfo { |
35 | 41 | private final Set<String> seenTransitions = new HashSet<>(); |
36 | 42 | private boolean currentlyInHost = false; |
37 | 43 |
|
38 | | - // Store execution sequences for analysis |
39 | | - private List<ExecutionSequence> executionSequences = new ArrayList<>(); |
40 | | - |
41 | 44 | // Constructor for non-virtualized environments |
42 | 45 | ProcessFlowInfo(String phase, String processName) { |
43 | 46 | this(phase, processName, false, null); |
@@ -165,11 +168,19 @@ public void addEvent(KernelEventInfo evt) { |
165 | 168 | return; // we don't want to track the hypervisor because we are on the native system |
166 | 169 | } |
167 | 170 |
|
| 171 | + if (!processName.equals(evt.processName)) { |
| 172 | + return; |
| 173 | + } |
| 174 | + |
168 | 175 | // For native systems, if we have a target thread, only track that thread |
169 | 176 | if (targetThreadId != null && !targetThreadId.equals(evt.tid)) { |
170 | 177 | return; |
171 | 178 | } |
172 | 179 |
|
| 180 | + ThreadFlowInfo threadInfo = threadsByTid.computeIfAbsent(evt.tid, |
| 181 | + k -> new ThreadFlowInfo(k, processName)); |
| 182 | + threadInfo.addEvent(evt); |
| 183 | + |
173 | 184 | String key = "NATIVE" + "_" + evt.timestamp + "_" + evt.cpuid + "_" + evt.tid; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
174 | 185 |
|
175 | 186 | if (seenTransitions.contains(key)) { |
@@ -287,112 +298,12 @@ private void buildExecutionSequences() { |
287 | 298 | default: |
288 | 299 | break; |
289 | 300 | } |
290 | | - |
291 | | - // Close sequence after VM_ENTRY (which comes after hypervisor events) |
292 | | - // Actually, let's close it when we see the next VM_ENTRY or at the end |
293 | 301 | } |
294 | 302 |
|
295 | 303 | // Add any remaining sequence |
296 | 304 | if (currentSequence != null) { |
297 | 305 | sequences.add(currentSequence); |
298 | 306 | } |
299 | | - |
300 | | - this.executionSequences = sequences; |
301 | | - } |
302 | | - |
303 | | - /** |
304 | | - * Print the unified execution flow |
305 | | - */ |
306 | | - void printUnifiedFlow() throws IOException { |
307 | | - System.out.printf("\n=== Unified Flow for Process %s (Phase: %s) ===\n", //$NON-NLS-1$ |
308 | | - processName, phase); |
309 | | - |
310 | | - if (targetThreadId != null) { |
311 | | - System.out.printf("Tracking Thread: %d", targetThreadId); //$NON-NLS-1$ |
312 | | - if (targetVcpuId != null) { |
313 | | - System.out.printf(" (vCPU: %d)", targetVcpuId); //$NON-NLS-1$ |
314 | | - } |
315 | | - System.out.println(); |
316 | | - } |
317 | | - |
318 | | - if (!trackHypervisor) { |
319 | | - printSimpleFlow(); |
320 | | - return; |
321 | | - } |
322 | | - |
323 | | - printVirtualizedFlow(); |
324 | | - } |
325 | | - |
326 | | - private void printSimpleFlow() throws IOException { |
327 | | - System.out.printf("Events: %d, Threads: %d\n", unifiedFlow.size(), threadsByTid.size()); //$NON-NLS-1$ |
328 | | - |
329 | | - FileOutputStream fos = new FileOutputStream(new File("/home/philippe/Desktop/natif_flow.txt"), true); //$NON-NLS-1$ |
330 | | - try (PrintWriter writer = new PrintWriter(fos)) { |
331 | | - for (FlowEvent flowEvent : unifiedFlow) { |
332 | | - KernelEventInfo evt = flowEvent.kernelEvent; |
333 | | - String output = String.format(" [%d] %s (TID:%d)\n", //$NON-NLS-1$ |
334 | | - evt.timestamp, evt.name, evt.tid); |
335 | | - System.out.print(output); |
336 | | - writer.print(output); |
337 | | - } |
338 | | - } |
339 | | - } |
340 | | - |
341 | | - private void printVirtualizedFlow() throws IOException { |
342 | | - System.out.printf("Execution Sequences: %d\n", executionSequences.size()); //$NON-NLS-1$ |
343 | | - |
344 | | - int sequenceNum = 1; |
345 | | - for (ExecutionSequence seq : executionSequences) { |
346 | | - System.out.printf("\n--- Sequence %d ---\n", sequenceNum++); //$NON-NLS-1$ |
347 | | - seq.printSequence(); |
348 | | - } |
349 | | - |
350 | | - // Also print raw chronological flow |
351 | | - System.out.println("\n--- Raw Chronological Flow ---"); //$NON-NLS-1$ |
352 | | - FileOutputStream fos = new FileOutputStream(new File("/home/philippe/Desktop/virtualized_flow_raw.txt"), true); //$NON-NLS-1$ |
353 | | - try (PrintWriter writer = new PrintWriter(fos)) { |
354 | | - for (FlowEvent flowEvent : unifiedFlow) { |
355 | | - printFlowEvent(flowEvent, writer); |
356 | | - } |
357 | | - } |
358 | | - } |
359 | | - |
360 | | - private static void printFlowEvent(FlowEvent flowEvent, PrintWriter writer) { |
361 | | - KernelEventInfo evt = flowEvent.kernelEvent; |
362 | | - String prefix = getEventPrefix(flowEvent.type); |
363 | | - |
364 | | - String output = String.format(" [%d] %s%s", evt.timestamp, prefix, evt.name); //$NON-NLS-1$ |
365 | | - |
366 | | - if (evt.tid >= 0) { |
367 | | - output += String.format(" (TID:%d", evt.tid); //$NON-NLS-1$ |
368 | | - if (evt.cpuid >= 0) { |
369 | | - output += String.format(", CPU:%d", evt.cpuid); //$NON-NLS-1$ |
370 | | - } |
371 | | - if (evt.vcpuid >= 0) { |
372 | | - output += String.format(", VCPU:%d", evt.vcpuid); //$NON-NLS-1$ |
373 | | - } |
374 | | - if (!evt.exitReason.equals("UNKNOWN_EXIT_REASON")) { //$NON-NLS-1$ |
375 | | - output += String.format(", exit_reason:%s", evt.exitReason); //$NON-NLS-1$ |
376 | | - } |
377 | | - output += ")"; //$NON-NLS-1$ |
378 | | - } |
379 | | - output += "\n"; //$NON-NLS-1$ |
380 | | - |
381 | | - System.out.print(output); |
382 | | - if (writer != null) { |
383 | | - writer.print(output); |
384 | | - } |
385 | | - } |
386 | | - |
387 | | - private static String getEventPrefix(FlowEventType type) { |
388 | | - switch (type) { |
389 | | - case GUEST_EVENT: return "[GUEST] "; //$NON-NLS-1$ |
390 | | - case VM_EXIT: return "[VM_EXIT] "; //$NON-NLS-1$ |
391 | | - case HYPERVISOR_EVENT: return "[HOST] "; //$NON-NLS-1$ |
392 | | - case VM_ENTRY: return "[VM_ENTRY] "; //$NON-NLS-1$ |
393 | | - case NATIVE: return "[NATIVE] "; //$NON-NLS-1$ |
394 | | - default: return ""; //$NON-NLS-1$ |
395 | | - } |
396 | 307 | } |
397 | 308 |
|
398 | 309 | boolean isMultiThreaded() { |
|
0 commit comments