lttng: Remove discriminator part when parsing addr2line output
[deliverable/tracecompass.git] / lttng / org.eclipse.tracecompass.lttng2.ust.core / src / org / eclipse / tracecompass / internal / lttng2 / ust / core / analysis / debuginfo / FileOffsetMapper.java
1 /*******************************************************************************
2 * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
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
10 package org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo;
11
12 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13
14 import java.io.BufferedReader;
15 import java.io.File;
16 import java.io.IOException;
17 import java.io.InputStreamReader;
18 import java.nio.file.Files;
19 import java.util.Arrays;
20 import java.util.LinkedList;
21 import java.util.List;
22 import java.util.stream.Collectors;
23
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.eclipse.tracecompass.tmf.core.event.lookup.TmfCallsite;
26
27 /**
28 * Utility class to get file name, function/symbol name and line number from a
29 * given offset. In TMF this is represented as a {@link TmfCallsite}.
30 *
31 * @author Alexandre Montplaisir
32 */
33 public final class FileOffsetMapper {
34
35 private static final String DISCRIMINATOR = "\\(discriminator.*\\)";
36 private static final String ADDR2LINE_EXECUTABLE = "addr2line"; //$NON-NLS-1$
37
38 private FileOffsetMapper() {}
39
40 /**
41 * Generate the callsites from a given binary file and address offset.
42 *
43 * Due to function inlining, it is possible for one offset to actually have
44 * multiple call sites. This is why we can return more than one callsite per
45 * call.
46 *
47 * @param file
48 * The binary file to look at
49 * @param offset
50 * The memory offset in the file
51 * @return The list of callsites corresponding to the offset, reported from
52 * the "highest" inlining location, down to the initial definition.
53 */
54 public static @Nullable Iterable<TmfCallsite> getCallsiteFromOffset(File file, long offset) {
55 if (!Files.exists((file.toPath()))) {
56 return null;
57 }
58 return getCallsiteFromOffsetWithAddr2line(file, offset);
59 }
60
61 private static @Nullable Iterable<TmfCallsite> getCallsiteFromOffsetWithAddr2line(File file, long offset) {
62 List<TmfCallsite> callsites = new LinkedList<>();
63
64 // FIXME Could eventually use CDT's Addr2line class once it imlements --inlines
65 List<String> output = getOutputFromCommand(checkNotNull(Arrays.asList(
66 ADDR2LINE_EXECUTABLE, "-i", "-e", file.toString(), "0x" + Long.toHexString(offset)))); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
67
68 if (output == null) {
69 /* Command returned an error */
70 return null;
71 }
72
73 for (String outputLine : output) {
74 // Remove discriminator part, for example: /build/buildd/glibc-2.21/elf/dl-object.c:78 (discriminator 8)
75 outputLine = outputLine.replaceFirst(DISCRIMINATOR, "").trim(); //$NON-NLS-1$
76
77 String[] elems = outputLine.split(":"); //$NON-NLS-1$
78 String fileName = elems[0];
79 if (fileName.equals("??")) { //$NON-NLS-1$
80 continue;
81 }
82 long lineNumber = Long.parseLong(elems[1]);
83
84 callsites.add(new TmfCallsite(fileName, null, lineNumber));
85 }
86
87 return callsites;
88 }
89
90 private static @Nullable List<String> getOutputFromCommand(List<String> command) {
91 try {
92 ProcessBuilder builder = new ProcessBuilder(command);
93 builder.redirectErrorStream(true);
94
95 Process p = builder.start();
96 BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
97 int ret = p.waitFor();
98 List<String> lines = br.lines().collect(Collectors.toList());
99
100 return (ret == 0 ? lines : null);
101
102 } catch (IOException | InterruptedException e) {
103 return null;
104 }
105 }
106 }
This page took 0.03213 seconds and 5 git commands to generate.