import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.FileOffsetMapper;
-import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoLoadedBinaryFile;
import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
-import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
-import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
import org.eclipse.tracecompass.tmf.core.event.lookup.TmfCallsite;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
-
-import com.google.common.collect.Iterables;
/**
* Event aspect of UST traces to generate a {@link TmfCallsite} using the debug
* info analysis and the IP (instruction pointer) context.
*
* @author Alexandre Montplaisir
- * @since 2.0
+ * @since 3.0
*/
-public class UstDebugInfoSourceAspect implements ITmfEventAspect {
+public class UstDebugInfoSourceAspect implements ITmfEventAspect<TmfCallsite> {
/** Singleton instance */
public static final UstDebugInfoSourceAspect INSTANCE = new UstDebugInfoSourceAspect();
@Override
public String getName() {
- return nullToEmptyString(Messages.UstDebugInfoAnalysis_AspectName);
+ return nullToEmptyString(Messages.UstDebugInfoAnalysis_SourceAspectName);
}
@Override
public String getHelpText() {
- return nullToEmptyString(Messages.UstDebugInfoAnalysis_AspectHelpText);
+ return nullToEmptyString(Messages.UstDebugInfoAnalysis_SourceAspectHelpText);
}
- // TODO Will return a TmfCallsite eventually
+ /**
+ * @since 2.1
+ */
@Override
public @Nullable TmfCallsite resolve(ITmfEvent event) {
/* This aspect only supports UST traces */
if (!(event.getTrace() instanceof LttngUstTrace)) {
return null;
}
-
- ILttngUstEventLayout layout = ((LttngUstTrace) event.getTrace()).getEventLayout();
-
- /* We need both the vpid and ip contexts */
- ITmfEventField vpidField = event.getContent().getField(layout.contextVpid());
- ITmfEventField ipField = event.getContent().getField(layout.contextIp());
- if (vpidField == null || ipField == null) {
- return null;
- }
- Long vpid = (Long) vpidField.getValue();
- Long ip = (Long) ipField.getValue();
+ LttngUstTrace trace = (LttngUstTrace) event.getTrace();
/*
- * First match the IP to the correct binary or library, by using the
- * UstDebugInfoAnalysis.
+ * Resolve the binary callsite first, from there we can use the file's
+ * debug information if it is present.
*/
- UstDebugInfoAnalysisModule module =
- TmfTraceUtils.getAnalysisModuleOfClass(event.getTrace(),
- UstDebugInfoAnalysisModule.class, UstDebugInfoAnalysisModule.ID);
- if (module == null) {
- /*
- * The analysis is not available for this trace, we won't be
- * able to find the information.
- */
+ BinaryCallsite bc = UstDebugInfoBinaryAspect.INSTANCE.resolve(event);
+ if (bc == null) {
return null;
}
- long ts = event.getTimestamp().getValue();
- UstDebugInfoLoadedBinaryFile file = module.getMatchingFile(ts, vpid, ip);
- if (file == null) {
- return null;
- }
-
- long offset;
- if (isMainBinary(file)) {
- /*
- * In the case of the object being the main binary (loaded at a very
- * low address), we must pass the actual ip address to addr2line.
- */
- offset = ip.longValue();
- } else {
- offset = (ip.longValue() - file.getBaseAddress());
- }
- if (offset < 0) {
- throw new IllegalStateException();
- }
-
- Iterable<TmfCallsite> callsites = FileOffsetMapper.getCallsiteFromOffset(new File(file.getFilePath()), offset);
-
- if (callsites == null || Iterables.isEmpty(callsites)) {
+ TmfCallsite callsite = FileOffsetMapper.getCallsiteFromOffset(
+ new File(bc.getBinaryFilePath()),
+ bc.getBuildId(),
+ bc.getOffset());
+ if (callsite == null) {
return null;
}
- /*
- * TMF only supports the notion of one callsite per event at the moment.
- * We will take the "deepest" one in the stack, which should refer to
- * the initial, non-inlined location.
- */
- return Iterables.getLast(callsites);
- }
- private static boolean isMainBinary(UstDebugInfoLoadedBinaryFile file) {
/*
- * Ghetto binary/library identification for now. It would be possible to
- * parse the ELF binary to check if it is position-independent
- * (-fPIC/-fPIE) or not.
+ * Apply the path prefix again, this time on the path given from
+ * addr2line. If applicable.
*/
- return (!file.getFilePath().endsWith(".so")); //$NON-NLS-1$
- }
+ String pathPrefix = trace.getSymbolProviderConfig().getActualRootDirPath();
+ if (pathPrefix.isEmpty()) {
+ return callsite;
+ }
+ String fullFileName = (pathPrefix + callsite.getFileName());
+ return new TmfCallsite(fullFileName, callsite.getLineNo());
+ }
}