1 /*******************************************************************************
2 * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
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 *******************************************************************************/
10 package org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo;
12 import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.FileOffsetMapper;
18 import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoLoadedBinaryFile;
19 import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
20 import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout;
21 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
22 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
23 import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
24 import org.eclipse.tracecompass.tmf.core.event.lookup.TmfCallsite;
25 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
27 import com.google.common.collect.Iterables;
30 * Event aspect of UST traces to generate a {@link TmfCallsite} using the debug
31 * info analysis and the IP (instruction pointer) context.
33 * @author Alexandre Montplaisir
36 public class UstDebugInfoSourceAspect implements ITmfEventAspect {
38 /** Singleton instance */
39 public static final UstDebugInfoSourceAspect INSTANCE = new UstDebugInfoSourceAspect();
41 private UstDebugInfoSourceAspect() {}
44 public String getName() {
45 return nullToEmptyString(Messages.UstDebugInfoAnalysis_AspectName);
49 public String getHelpText() {
50 return nullToEmptyString(Messages.UstDebugInfoAnalysis_AspectHelpText);
54 public @Nullable TmfCallsite resolve(ITmfEvent event) {
55 /* This aspect only supports UST traces */
56 if (!(event.getTrace() instanceof LttngUstTrace)) {
60 ILttngUstEventLayout layout = ((LttngUstTrace) event.getTrace()).getEventLayout();
62 /* We need both the vpid and ip contexts */
63 ITmfEventField vpidField = event.getContent().getField(layout.contextVpid());
64 ITmfEventField ipField = event.getContent().getField(layout.contextIp());
65 if (vpidField == null || ipField == null) {
68 Long vpid = (Long) vpidField.getValue();
69 Long ip = (Long) ipField.getValue();
72 * First match the IP to the correct binary or library, by using the
73 * UstDebugInfoAnalysis.
75 UstDebugInfoAnalysisModule module =
76 TmfTraceUtils.getAnalysisModuleOfClass(event.getTrace(),
77 UstDebugInfoAnalysisModule.class, UstDebugInfoAnalysisModule.ID);
80 * The analysis is not available for this trace, we won't be
81 * able to find the information.
85 long ts = event.getTimestamp().getValue();
86 UstDebugInfoLoadedBinaryFile file = module.getMatchingFile(ts, vpid, ip);
92 if (isMainBinary(file)) {
94 * In the case of the object being the main binary (loaded at a very
95 * low address), we must pass the actual ip address to addr2line.
97 offset = ip.longValue();
99 offset = (ip.longValue() - file.getBaseAddress());
103 throw new IllegalStateException();
106 Iterable<TmfCallsite> callsites = FileOffsetMapper.getCallsiteFromOffset(new File(file.getFilePath()), offset);
108 if (callsites == null || Iterables.isEmpty(callsites)) {
112 * TMF only supports the notion of one callsite per event at the moment.
113 * We will take the "deepest" one in the stack, which should refer to
114 * the initial, non-inlined location.
116 return Iterables.getLast(callsites);
119 private static boolean isMainBinary(UstDebugInfoLoadedBinaryFile file) {
121 * Ghetto binary/library identification for now. It would be possible to
122 * parse the ELF binary to check if it is position-independent
123 * (-fPIC/-fPIE) or not.
125 return (!file.getFilePath().endsWith(".so")); //$NON-NLS-1$