lttng: Make use of "is_pic" event field in debug info analysis
[deliverable/tracecompass.git] / lttng / org.eclipse.tracecompass.lttng2.ust.core / src / org / eclipse / tracecompass / lttng2 / ust / core / analysis / debuginfo / UstDebugInfoAnalysisModule.java
CommitLineData
ef7f180d 1/*******************************************************************************
ed48dc75 2 * Copyright (c) 2015, 2016 EfficiOS Inc., Alexandre Montplaisir
ef7f180d
AM
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9
10package org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo;
11
12import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13
14import java.util.Collection;
15import java.util.Collections;
16import java.util.List;
17import java.util.NavigableSet;
bbadfd0a 18import java.util.Optional;
ef7f180d
AM
19import java.util.Set;
20import java.util.TreeSet;
bbadfd0a 21import java.util.stream.Collectors;
ef7f180d
AM
22
23import org.eclipse.jdt.annotation.Nullable;
24import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryFile;
522dff53 25import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoLoadedBinaryFile;
ef7f180d
AM
26import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoStateProvider;
27import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
28import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
29import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
30import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
31import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
32import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
33import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
58080002 34import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAbstractAnalysisRequirement;
ef7f180d
AM
35import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
36import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
37import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
38import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
39import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfUtils;
40
ef7f180d 41import com.google.common.collect.ImmutableList;
ef7f180d
AM
42
43/**
44 * Analysis to provide TMF Callsite information by mapping IP (instruction
45 * pointer) contexts to address/line numbers via debug information.
46 *
47 * @author Alexandre Montplaisir
48 * @since 2.0
49 */
50public class UstDebugInfoAnalysisModule extends TmfStateSystemAnalysisModule {
51
52 /**
53 * Analysis ID, it should match that in the plugin.xml file
54 */
55 public static final String ID = "org.eclipse.linuxtools.lttng2.ust.analysis.debuginfo"; //$NON-NLS-1$
56
57 @Override
58 protected ITmfStateProvider createStateProvider() {
59 return new UstDebugInfoStateProvider(checkNotNull(getTrace()));
60 }
61
62 @Override
63 public boolean setTrace(ITmfTrace trace) throws TmfAnalysisException {
64 if (!(trace instanceof LttngUstTrace)) {
65 return false;
66 }
67 return super.setTrace(trace);
68 }
69
70 @Override
71 protected @Nullable LttngUstTrace getTrace() {
72 return (LttngUstTrace) super.getTrace();
73 }
74
75 @Override
58080002 76 public Iterable<TmfAbstractAnalysisRequirement> getAnalysisRequirements() {
ef7f180d
AM
77 // TODO specify actual requirements once the requirement-checking is
78 // implemented. This analysis needs "ip" and "vpid" contexts.
df2597e0 79 return Collections.EMPTY_SET;
ef7f180d
AM
80 }
81
82 @Override
83 public boolean canExecute(ITmfTrace trace) {
84 /* The analysis can only work with LTTng-UST traces... */
85 if (!(trace instanceof LttngUstTrace)) {
86 return false;
87 }
88 LttngUstTrace ustTrace = (LttngUstTrace) trace;
89 String tracerName = CtfUtils.getTracerName(ustTrace);
90 int majorVersion = CtfUtils.getTracerMajorVersion(ustTrace);
91 int minorVersion = CtfUtils.getTracerMinorVersion(ustTrace);
92
93 /* ... taken with UST >= 2.8 ... */
94 if (!LttngUstTrace.TRACER_NAME.equals(tracerName)) {
95 return false;
96 }
97 if (majorVersion < 2) {
98 return false;
99 }
100 if (majorVersion == 2 && minorVersion < 8) {
101 return false;
102 }
103
104 /* ... that respect the ip/vpid contexts requirements. */
105 return super.canExecute(trace);
106 }
107
108 // ------------------------------------------------------------------------
109 // Class-specific operations
110 // ------------------------------------------------------------------------
111
112 /**
113 * Return all the binaries that were detected in the trace.
114 *
115 * @return The binaries (executables or libraries) referred to in the trace.
116 */
117 public Collection<UstDebugInfoBinaryFile> getAllBinaries() {
118 waitForCompletion();
119 ITmfStateSystem ss = checkNotNull(getStateSystem());
120
121 Set<UstDebugInfoBinaryFile> files = new TreeSet<>();
ed48dc75
PT
122 ImmutableList.Builder<Integer> builder = ImmutableList.builder();
123 List<Integer> vpidQuarks = ss.getSubAttributes(-1, false);
124 for (Integer vpidQuark : vpidQuarks) {
125 builder.addAll(ss.getSubAttributes(vpidQuark, false));
126 }
127 List<Integer> baddrQuarks = builder.build();
ef7f180d 128
ed48dc75
PT
129 /*
130 * For each "baddr" attribute, get the "buildId" sub-attribute,
131 * whose value is the file path.
132 */
ef7f180d 133
ed48dc75 134 for (Integer baddrQuark : baddrQuarks) {
ef7f180d 135
ed48dc75
PT
136 List<Integer> buildIdQuarks = ss.getSubAttributes(baddrQuark, false);
137 for (Integer buildIdQuark : buildIdQuarks) {
138 String buildId = ss.getAttributeName(buildIdQuark);
ef7f180d 139
ed48dc75
PT
140 /*
141 * Explore the history of this attribute "horizontally",
142 * even though there should only be one valid interval.
143 */
144 ITmfStateInterval interval = StateSystemUtils.queryUntilNonNullValue(ss, buildIdQuark, ss.getStartTime(), Long.MAX_VALUE);
145 if (interval == null) {
ef7f180d 146 /*
ed48dc75
PT
147 * If we created the attribute, we should have assigned
148 * a value to it!
ef7f180d 149 */
ed48dc75 150 throw new IllegalStateException();
ef7f180d 151 }
ed48dc75
PT
152 String filePath = interval.getStateValue().unboxStr();
153
d89151ba
AM
154 /* Retrieve the value of "is_pic" at that time */
155 try {
156 int isPicQuark = ss.getQuarkRelative(buildIdQuark, UstDebugInfoStateProvider.IS_PIC_ATTRIB);
157 int isPicVal = ss.querySingleState(interval.getStartTime(), isPicQuark).getStateValue().unboxInt();
158 boolean isPic = (isPicVal != 0);
159
160 files.add(new UstDebugInfoBinaryFile(filePath, buildId, isPic));
161
162 } catch (AttributeNotFoundException e) {
163 /* We should have built "is_pic" sub-attributes */
164 throw new IllegalStateException("Missing expected \"is_pic\" attribute"); //$NON-NLS-1$
165 } catch (StateSystemDisposedException e) {
166 /* We're closing down, ignore */
167 }
ef7f180d 168 }
ef7f180d
AM
169 }
170 return files;
171 }
172
173 /**
174 * Get the binary file (executable or library) that corresponds to a given
175 * instruction pointer, at a given time.
176 *
177 * @param ts
178 * The timestamp
179 * @param vpid
180 * The VPID of the process we are querying for
181 * @param ip
182 * The instruction pointer of the trace event. Normally comes
183 * from a 'ip' context.
184 * @return The {@link UstDebugInfoBinaryFile} object, containing both the binary's path
185 * and its build ID.
186 */
522dff53 187 @Nullable UstDebugInfoLoadedBinaryFile getMatchingFile(long ts, long vpid, long ip) {
ef7f180d
AM
188 waitForCompletion();
189 final ITmfStateSystem ss = checkNotNull(getStateSystem());
190
191 List<Integer> possibleBaddrQuarks = ss.getQuarks(String.valueOf(vpid), "*"); //$NON-NLS-1$
192
193 /* Get the most probable base address from all the known ones */
bbadfd0a
AM
194 NavigableSet<Long> possibleBaddrs = possibleBaddrQuarks.stream()
195 .map(quark -> {
0e4f957e 196 String baddrStr = ss.getAttributeName(quark.intValue());
bbadfd0a
AM
197 return checkNotNull(Long.valueOf(baddrStr));
198 })
199 .collect(Collectors.toCollection(TreeSet::new));
200
ef7f180d 201 final Long potentialBaddr = possibleBaddrs.floor(ip);
5406cf6c
MAL
202 if (potentialBaddr == null) {
203 return null;
204 }
ef7f180d
AM
205
206 /* Make sure the 'ip' fits in the expected memory range */
207 try {
208 final List<ITmfStateInterval> fullState = ss.queryFullState(ts);
209
210 final int baddrQuark = ss.getQuarkAbsolute(String.valueOf(vpid), String.valueOf(potentialBaddr));
211 final long endAddr = fullState.get(baddrQuark).getStateValue().unboxLong();
212
213 if (!(ip < endAddr)) {
214 /*
215 * Not the correct memory range after all. We do not have
216 * information about the library that was loaded here.
217 */
218 return null;
219 }
220
221 /*
222 * We've found the correct base address, now to determine what
223 * library was loaded there at that time.
224 */
225 List<Integer> buildIds = ss.getSubAttributes(baddrQuark, false);
bbadfd0a
AM
226 Optional<Integer> potentialBuildIdQuark = buildIds.stream()
227 .filter(id -> {
0e4f957e 228 int quark = id.intValue();
ef7f180d
AM
229 ITmfStateValue value = fullState.get(quark).getStateValue();
230 return (!value.isNull());
bbadfd0a
AM
231 })
232 .findFirst();
ef7f180d
AM
233
234 if (!potentialBuildIdQuark.isPresent()) {
235 /* We didn't have the information after all. */
236 return null;
237 }
238
239 /* Ok, we have everything we need! Return the information. */
522dff53
AM
240 long baddr = Long.parseLong(ss.getAttributeName(baddrQuark));
241
ef7f180d
AM
242 int buildIdQuark = potentialBuildIdQuark.get().intValue();
243 String buildId = ss.getAttributeName(buildIdQuark);
244 String filePath = fullState.get(buildIdQuark).getStateValue().unboxStr();
d89151ba
AM
245
246 int isPicQuark = ss.getQuarkRelative(buildIdQuark, UstDebugInfoStateProvider.IS_PIC_ATTRIB);
247 int isPicVal = fullState.get(isPicQuark).getStateValue().unboxInt();
248 boolean isPic = (isPicVal != 0);
249
250 return new UstDebugInfoLoadedBinaryFile(baddr, filePath, buildId, isPic);
ef7f180d
AM
251
252 } catch (AttributeNotFoundException e) {
253 /* We're only using quarks we've checked for. */
254 throw new IllegalStateException(e);
255 } catch (StateSystemDisposedException e) {
256 return null;
257 }
258
259 }
ef7f180d 260}
This page took 0.04545 seconds and 5 git commands to generate.