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; |
c469808d AM |
19 | import org.eclipse.tracecompass.internal.lttng2.ust.core.trace.layout.LttngUst20EventLayout; |
20 | import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace; | |
21 | import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout; | |
2bdf0193 AM |
22 | import org.eclipse.tracecompass.tmf.core.callstack.CallStackStateProvider; |
23 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; | |
24 | import org.eclipse.tracecompass.tmf.core.event.ITmfEventField; | |
25 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
9722e5d7 | 26 | import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEvent; |
1c6660ca | 27 | |
c469808d AM |
28 | import com.google.common.collect.ImmutableSet; |
29 | ||
1c6660ca AM |
30 | /** |
31 | * Callstack provider for LTTng-UST traces. | |
32 | * | |
33 | * If the traces contains 'func_entry' and 'func_exit' event (see the | |
34 | * lttng-ust-cyg-profile manpage), AND contains vtid and procname contexts, we | |
35 | * can use this information to populate the TMF Callstack View. | |
36 | * | |
37 | * Granted, most UST traces will not contain this information. In this case, | |
38 | * this will simply build an empty state system, and the view will remain | |
39 | * unavailable. | |
40 | * | |
41 | * @author Alexandre Montplaisir | |
42 | */ | |
43 | public class LttngUstCallStackProvider extends CallStackStateProvider { | |
44 | ||
5da83da5 AM |
45 | /** |
46 | * Version number of this state provider. Please bump this if you modify | |
47 | * the contents of the generated state history in some way. | |
48 | */ | |
aaee1ffb | 49 | private static final int VERSION = 2; |
5da83da5 | 50 | |
c469808d AM |
51 | /** Event names indicating function entry */ |
52 | private final @NonNull Set<String> funcEntryEvents; | |
53 | ||
54 | /** Event names indicating function exit */ | |
55 | private final @NonNull Set<String> funcExitEvents; | |
56 | ||
57 | private final @NonNull ILttngUstEventLayout fLayout; | |
58 | ||
1c6660ca AM |
59 | // ------------------------------------------------------------------------ |
60 | // Constructor | |
61 | // ------------------------------------------------------------------------ | |
62 | ||
63 | /** | |
64 | * Constructor | |
65 | * | |
66 | * @param trace | |
67 | * The UST trace | |
68 | */ | |
d0c7e4ba | 69 | public LttngUstCallStackProvider(@NonNull ITmfTrace trace) { |
1c6660ca | 70 | super(trace); |
c469808d AM |
71 | |
72 | if (trace instanceof LttngUstTrace) { | |
73 | fLayout = ((LttngUstTrace) trace).getEventLayout(); | |
74 | } else { | |
75 | /* For impostor trace types, assume they use the LTTng 2.0 layout */ | |
76 | fLayout = LttngUst20EventLayout.getInstance(); | |
77 | } | |
78 | ||
0e4f957e | 79 | funcEntryEvents = ImmutableSet.of( |
c469808d | 80 | fLayout.eventCygProfileFuncEntry(), |
0e4f957e | 81 | fLayout.eventCygProfileFastFuncEntry()); |
c469808d | 82 | |
0e4f957e | 83 | funcExitEvents = ImmutableSet.of( |
c469808d | 84 | fLayout.eventCygProfileFuncExit(), |
0e4f957e | 85 | fLayout.eventCygProfileFastFuncExit()); |
1c6660ca AM |
86 | } |
87 | ||
88 | // ------------------------------------------------------------------------ | |
89 | // Methods from AbstractTmfStateProvider | |
90 | // ------------------------------------------------------------------------ | |
91 | ||
1c6660ca AM |
92 | @Override |
93 | public LttngUstCallStackProvider getNewInstance() { | |
94 | return new LttngUstCallStackProvider(getTrace()); | |
95 | } | |
96 | ||
5da83da5 AM |
97 | @Override |
98 | public int getVersion() { | |
99 | return VERSION; | |
100 | } | |
101 | ||
1c6660ca AM |
102 | // ------------------------------------------------------------------------ |
103 | // Methods from CallStackStateProvider | |
104 | // ------------------------------------------------------------------------ | |
105 | ||
106 | /** | |
107 | * Check that this event contains the required information we need to be | |
108 | * used in the call stack view. We need at least the "procname" and "vtid" | |
109 | * contexts. | |
110 | */ | |
111 | @Override | |
112 | protected boolean considerEvent(ITmfEvent event) { | |
113 | if (!(event instanceof CtfTmfEvent)) { | |
114 | return false; | |
115 | } | |
116 | ITmfEventField content = ((CtfTmfEvent) event).getContent(); | |
c469808d AM |
117 | if (content.getField(fLayout.contextVtid()) == null || |
118 | content.getField(fLayout.contextProcname()) == null) { | |
1c6660ca AM |
119 | return false; |
120 | } | |
121 | return true; | |
122 | } | |
123 | ||
124 | @Override | |
125 | public String functionEntry(ITmfEvent event) { | |
578716e6 | 126 | String eventName = event.getName(); |
c469808d | 127 | if (!funcEntryEvents.contains(eventName)) { |
1c6660ca AM |
128 | return null; |
129 | } | |
c469808d | 130 | Long address = (Long) event.getContent().getField(fLayout.fieldAddr()).getValue(); |
5da83da5 | 131 | return Long.toHexString(address); |
1c6660ca AM |
132 | } |
133 | ||
134 | @Override | |
135 | public String functionExit(ITmfEvent event) { | |
578716e6 | 136 | String eventName = event.getName(); |
c469808d | 137 | if (!funcExitEvents.contains(eventName)) { |
1c6660ca AM |
138 | return null; |
139 | } | |
140 | /* | |
141 | * The 'addr' field may or may not be present in func_exit events, | |
142 | * depending on if cyg-profile.so or cyg-profile-fast.so was used. | |
143 | */ | |
c469808d | 144 | ITmfEventField field = event.getContent().getField(fLayout.fieldAddr()); |
1c6660ca AM |
145 | if (field == null) { |
146 | return CallStackStateProvider.UNDEFINED; | |
147 | } | |
148 | Long address = (Long) field.getValue(); | |
5da83da5 | 149 | return Long.toHexString(address); |
1c6660ca AM |
150 | } |
151 | ||
152 | @Override | |
153 | public String getThreadName(ITmfEvent event) { | |
154 | /* Class type and content was already checked if we get called here */ | |
155 | ITmfEventField content = ((CtfTmfEvent) event).getContent(); | |
c469808d AM |
156 | String procName = (String) content.getField(fLayout.contextProcname()).getValue(); |
157 | Long vtid = (Long) content.getField(fLayout.contextVtid()).getValue(); | |
1c6660ca AM |
158 | |
159 | if (procName == null || vtid == null) { | |
160 | throw new IllegalStateException(); | |
161 | } | |
162 | ||
787117a0 | 163 | return procName + '-' + vtid.toString(); |
1c6660ca | 164 | } |
ac31f2fb PT |
165 | |
166 | @Override | |
167 | protected Long getThreadId(ITmfEvent event) { | |
168 | ITmfEventField content = ((CtfTmfEvent) event).getContent(); | |
c469808d | 169 | return (Long) content.getField(fLayout.contextVtid()).getValue(); |
ac31f2fb | 170 | } |
1c6660ca | 171 | } |