Commit | Line | Data |
---|---|---|
1c6660ca | 1 | /******************************************************************************* |
ed902a2b | 2 | * Copyright (c) 2013, 2015 Ericsson |
1c6660ca AM |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * Alexandre Montplaisir - Initial API and implementation | |
ac31f2fb | 11 | * Patrick Tasse - Add support for thread id |
1c6660ca AM |
12 | *******************************************************************************/ |
13 | ||
116738ad | 14 | package org.eclipse.tracecompass.internal.lttng2.ust.core.callstack; |
1c6660ca | 15 | |
1c6660ca AM |
16 | import java.util.Set; |
17 | ||
d0c7e4ba | 18 | import org.eclipse.jdt.annotation.NonNull; |
7f86b721 AM |
19 | import org.eclipse.jdt.annotation.NonNullByDefault; |
20 | import org.eclipse.jdt.annotation.Nullable; | |
c469808d AM |
21 | import org.eclipse.tracecompass.internal.lttng2.ust.core.trace.layout.LttngUst20EventLayout; |
22 | import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace; | |
23 | import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout; | |
c3777c23 MK |
24 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; |
25 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
2bdf0193 AM |
26 | import org.eclipse.tracecompass.tmf.core.callstack.CallStackStateProvider; |
27 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; | |
28 | import org.eclipse.tracecompass.tmf.core.event.ITmfEventField; | |
29 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
9722e5d7 | 30 | import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEvent; |
1c6660ca | 31 | |
c469808d AM |
32 | import com.google.common.collect.ImmutableSet; |
33 | ||
1c6660ca AM |
34 | /** |
35 | * Callstack provider for LTTng-UST traces. | |
36 | * | |
37 | * If the traces contains 'func_entry' and 'func_exit' event (see the | |
38 | * lttng-ust-cyg-profile manpage), AND contains vtid and procname contexts, we | |
39 | * can use this information to populate the TMF Callstack View. | |
40 | * | |
41 | * Granted, most UST traces will not contain this information. In this case, | |
42 | * this will simply build an empty state system, and the view will remain | |
43 | * unavailable. | |
44 | * | |
45 | * @author Alexandre Montplaisir | |
46 | */ | |
7f86b721 | 47 | @NonNullByDefault |
1c6660ca AM |
48 | public class LttngUstCallStackProvider extends CallStackStateProvider { |
49 | ||
5da83da5 AM |
50 | /** |
51 | * Version number of this state provider. Please bump this if you modify | |
52 | * the contents of the generated state history in some way. | |
53 | */ | |
7f86b721 | 54 | private static final int VERSION = 3; |
5da83da5 | 55 | |
c469808d | 56 | /** Event names indicating function entry */ |
7f86b721 | 57 | private final Set<String> funcEntryEvents; |
c469808d AM |
58 | |
59 | /** Event names indicating function exit */ | |
7f86b721 | 60 | private final Set<String> funcExitEvents; |
c469808d | 61 | |
7f86b721 | 62 | private final ILttngUstEventLayout fLayout; |
c469808d | 63 | |
1c6660ca AM |
64 | // ------------------------------------------------------------------------ |
65 | // Constructor | |
66 | // ------------------------------------------------------------------------ | |
67 | ||
68 | /** | |
69 | * Constructor | |
70 | * | |
71 | * @param trace | |
72 | * The UST trace | |
73 | */ | |
7f86b721 | 74 | public LttngUstCallStackProvider(ITmfTrace trace) { |
1c6660ca | 75 | super(trace); |
c469808d AM |
76 | |
77 | if (trace instanceof LttngUstTrace) { | |
78 | fLayout = ((LttngUstTrace) trace).getEventLayout(); | |
79 | } else { | |
80 | /* For impostor trace types, assume they use the LTTng 2.0 layout */ | |
81 | fLayout = LttngUst20EventLayout.getInstance(); | |
82 | } | |
83 | ||
0e4f957e | 84 | funcEntryEvents = ImmutableSet.of( |
c469808d | 85 | fLayout.eventCygProfileFuncEntry(), |
0e4f957e | 86 | fLayout.eventCygProfileFastFuncEntry()); |
c469808d | 87 | |
0e4f957e | 88 | funcExitEvents = ImmutableSet.of( |
c469808d | 89 | fLayout.eventCygProfileFuncExit(), |
0e4f957e | 90 | fLayout.eventCygProfileFastFuncExit()); |
1c6660ca AM |
91 | } |
92 | ||
93 | // ------------------------------------------------------------------------ | |
94 | // Methods from AbstractTmfStateProvider | |
95 | // ------------------------------------------------------------------------ | |
96 | ||
1c6660ca AM |
97 | @Override |
98 | public LttngUstCallStackProvider getNewInstance() { | |
99 | return new LttngUstCallStackProvider(getTrace()); | |
100 | } | |
101 | ||
5da83da5 AM |
102 | @Override |
103 | public int getVersion() { | |
104 | return VERSION; | |
105 | } | |
106 | ||
1c6660ca AM |
107 | // ------------------------------------------------------------------------ |
108 | // Methods from CallStackStateProvider | |
109 | // ------------------------------------------------------------------------ | |
110 | ||
111 | /** | |
112 | * Check that this event contains the required information we need to be | |
113 | * used in the call stack view. We need at least the "procname" and "vtid" | |
114 | * contexts. | |
7f86b721 AM |
115 | * |
116 | * The "vpid" is useful too, but optional. | |
1c6660ca AM |
117 | */ |
118 | @Override | |
119 | protected boolean considerEvent(ITmfEvent event) { | |
120 | if (!(event instanceof CtfTmfEvent)) { | |
121 | return false; | |
122 | } | |
123 | ITmfEventField content = ((CtfTmfEvent) event).getContent(); | |
c469808d AM |
124 | if (content.getField(fLayout.contextVtid()) == null || |
125 | content.getField(fLayout.contextProcname()) == null) { | |
1c6660ca AM |
126 | return false; |
127 | } | |
128 | return true; | |
129 | } | |
130 | ||
131 | @Override | |
c3777c23 | 132 | public @Nullable ITmfStateValue functionEntry(ITmfEvent event) { |
578716e6 | 133 | String eventName = event.getName(); |
c469808d | 134 | if (!funcEntryEvents.contains(eventName)) { |
1c6660ca AM |
135 | return null; |
136 | } | |
c469808d | 137 | Long address = (Long) event.getContent().getField(fLayout.fieldAddr()).getValue(); |
c3777c23 | 138 | return TmfStateValue.newValueLong(address); |
1c6660ca AM |
139 | } |
140 | ||
141 | @Override | |
c3777c23 | 142 | public @Nullable ITmfStateValue functionExit(ITmfEvent event) { |
578716e6 | 143 | String eventName = event.getName(); |
c469808d | 144 | if (!funcExitEvents.contains(eventName)) { |
1c6660ca AM |
145 | return null; |
146 | } | |
147 | /* | |
148 | * The 'addr' field may or may not be present in func_exit events, | |
149 | * depending on if cyg-profile.so or cyg-profile-fast.so was used. | |
150 | */ | |
c469808d | 151 | ITmfEventField field = event.getContent().getField(fLayout.fieldAddr()); |
1c6660ca | 152 | if (field == null) { |
c3777c23 | 153 | return TmfStateValue.nullValue(); |
1c6660ca AM |
154 | } |
155 | Long address = (Long) field.getValue(); | |
c3777c23 | 156 | return TmfStateValue.newValueLong(address); |
1c6660ca AM |
157 | } |
158 | ||
159 | @Override | |
7f86b721 AM |
160 | protected int getProcessId(@NonNull ITmfEvent event) { |
161 | /* The "vpid" context may not be present! We need to check */ | |
162 | ITmfEventField content = event.getContent(); | |
163 | ITmfEventField vpidContextField = content.getField(fLayout.contextVpid()); | |
164 | if (vpidContextField == null) { | |
165 | return UNDEFINED_PID; | |
1c6660ca | 166 | } |
7f86b721 AM |
167 | return ((Long) vpidContextField.getValue()).intValue(); |
168 | } | |
1c6660ca | 169 | |
7f86b721 AM |
170 | @Override |
171 | protected long getThreadId(ITmfEvent event) { | |
172 | /* We checked earlier that the "vtid" context is present */ | |
173 | ITmfEventField content = event.getContent(); | |
174 | return ((Long) content.getField(fLayout.contextVtid()).getValue()).longValue(); | |
1c6660ca | 175 | } |
ac31f2fb PT |
176 | |
177 | @Override | |
7f86b721 AM |
178 | public String getThreadName(ITmfEvent event) { |
179 | /* We checked earlier that the "procname" context is present */ | |
180 | ITmfEventField content = event.getContent(); | |
181 | String procName = (String) content.getField(fLayout.contextProcname()).getValue(); | |
182 | long vtid = getThreadId(event); | |
183 | return (procName + '-' + Long.toString(vtid)); | |
ac31f2fb | 184 | } |
1c6660ca | 185 | } |