analysis: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / internal / tmf / core / callstack / FunctionNameMapper.java
CommitLineData
5da83da5 1/*******************************************************************************
318c06c9 2 * Copyright (c) 2013, 2015 Ericsson
5da83da5
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
41d9ce5b 11 * Marc-Andre Laperle - Map from binary file
5da83da5
AM
12 *******************************************************************************/
13
318c06c9 14package org.eclipse.tracecompass.internal.tmf.core.callstack;
5da83da5
AM
15
16import java.io.BufferedReader;
17import java.io.File;
41d9ce5b 18import java.io.FileInputStream;
5da83da5
AM
19import java.io.FileNotFoundException;
20import java.io.FileReader;
21import java.io.IOException;
41d9ce5b
MAL
22import java.io.InputStream;
23import java.util.ArrayList;
5da83da5 24import java.util.HashMap;
41d9ce5b 25import java.util.List;
5da83da5 26import java.util.Map;
25af0e4c 27import java.util.regex.Pattern;
5da83da5 28
41d9ce5b
MAL
29import org.eclipse.cdt.core.CCorePlugin;
30import org.eclipse.cdt.core.IBinaryParser;
31import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
32import org.eclipse.cdt.core.IBinaryParser.ISymbol;
33import org.eclipse.core.runtime.IConfigurationElement;
34import org.eclipse.core.runtime.IPath;
35import org.eclipse.core.runtime.ISafeRunnable;
36import org.eclipse.core.runtime.Path;
37import org.eclipse.core.runtime.Platform;
38import org.eclipse.core.runtime.SafeRunner;
5da83da5 39import org.eclipse.jdt.annotation.Nullable;
318c06c9 40import org.eclipse.tracecompass.internal.tmf.core.Activator;
5da83da5 41
25af0e4c
AM
42import com.google.common.collect.ImmutableMap;
43
5da83da5
AM
44/**
45 * Class containing the different methods to import an address->name mapping.
46 *
47 * @author Alexandre Montplaisir
48 */
25af0e4c
AM
49public final class FunctionNameMapper {
50
51 private FunctionNameMapper() {}
52
53 private static final Pattern REMOVE_ZEROS_PATTERN = Pattern.compile("^0+(?!$)"); //$NON-NLS-1$
5da83da5 54
318c06c9
AM
55 /**
56 * Get the function name mapping from a text file obtained by doing
57 *
58 * <pre>
59 * nm[--demangle][binary] &gt; file.txt
60 * </pre>
61 *
62 * @param mappingFile
63 * The file to import
64 * @return A map&lt;address, function name&gt; of the results
65 */
5da83da5 66 public static @Nullable Map<String, String> mapFromNmTextFile(File mappingFile) {
507b1336 67 Map<String, String> map = new HashMap<>();
5da83da5 68
507b1336
AM
69 try (FileReader fr = new FileReader(mappingFile);
70 BufferedReader reader = new BufferedReader(fr);) {
5da83da5 71 for (String line = reader.readLine(); line != null; line = reader.readLine()) {
e5ecc9ac 72 line = line.trim();
5da83da5 73 /* Only lines with 3 elements contain addresses */
a9b1f367 74 String[] elems = line.split(" ", 3); //$NON-NLS-1$
5da83da5 75 if (elems.length == 3) {
318c06c9 76 String address = stripLeadingZeros(elems[0]);
5da83da5
AM
77 String name = elems[elems.length - 1];
78 map.put(address, name);
79 }
80 }
507b1336
AM
81 } catch (FileNotFoundException e) {
82 return null;
5da83da5
AM
83 } catch (IOException e) {
84 /* Stop reading the file at this point */
5da83da5
AM
85 }
86
87 if (map.isEmpty()) {
88 return null;
89 }
25af0e4c 90 return ImmutableMap.copyOf(map);
41d9ce5b
MAL
91 }
92
318c06c9
AM
93 /**
94 * Get the function name mapping from an executable binary.
95 *
96 * @param file
97 * The file to import
98 * @return A map&lt;address, function name&gt; of the results
99 */
41d9ce5b
MAL
100 public static @Nullable Map<String, String> mapFromBinaryFile(File file) {
101 Map<String, String> map = new HashMap<>();
102 IBinaryParser.IBinaryObject binaryObject = getBinaryObject(file);
103 if (binaryObject != null) {
104 ISymbol[] symbols = binaryObject.getSymbols();
105 for (ISymbol symbol : symbols) {
106 String address = symbol.getAddress().toHexAddressString();
107 /* Remove "0x" */
108 address = address.substring(2);
109 /* Strip the leading zeroes from the address */
110 address = stripLeadingZeros(address);
111 map.put(address, symbol.getName());
112 }
113 }
114
25af0e4c
AM
115 return ImmutableMap.copyOf(map);
116 }
117
118
119 /**
120 * Strip the leading zeroes from the address
121 * */
122 private static String stripLeadingZeros(String address) {
123 return REMOVE_ZEROS_PATTERN.matcher(address).replaceFirst(""); //$NON-NLS-1$
41d9ce5b
MAL
124 }
125
126 private static @Nullable IBinaryParser.IBinaryObject getBinaryObject(File file) {
127 IPath filePath = new Path(file.toString());
128
129 /* Get all the available binary parsers */
130 final List<IBinaryParser> binaryParsers = new ArrayList<>();
131 IConfigurationElement[] elements = Platform.getExtensionRegistry()
132 .getConfigurationElementsFor(CCorePlugin.BINARY_PARSER_UNIQ_ID);
133 for (IConfigurationElement element : elements) {
134 IConfigurationElement[] children = element.getChildren("run"); //$NON-NLS-1$
135 for (final IConfigurationElement run : children) {
136 SafeRunner.run(new ISafeRunnable() {
137 @Override
138 public void run() throws Exception {
139 IBinaryParser binaryParser = (IBinaryParser) run.createExecutableExtension("class"); //$NON-NLS-1$
140 binaryParsers.add(binaryParser);
141 }
142
143 @Override
144 public void handleException(Throwable exception) {
318c06c9 145 Activator.logError("Error creating binary parser", exception); //$NON-NLS-1$
41d9ce5b
MAL
146 }
147 });
148 }
149 }
150
151 /* Find the maximum "hint" buffer size we'll need from all the parsers */
152 int hintBufferSize = 0;
153 for (IBinaryParser parser : binaryParsers) {
154 if (parser.getHintBufferSize() > hintBufferSize) {
155 hintBufferSize = Math.max(hintBufferSize, parser.getHintBufferSize());
156 }
157 }
158
159 /* Read the initial "hint" bytes */
160 byte[] hintBuffer = new byte[hintBufferSize];
161 if (hintBufferSize > 0) {
162 try (InputStream is = new FileInputStream(file) ){
163
164 int count = 0;
165 // Make sure we read up to 'hints' bytes if we possibly can
166 while (count < hintBufferSize) {
167 int bytesRead = is.read(hintBuffer, count, hintBufferSize - count);
168 if (bytesRead < 0) {
169 break;
170 }
171 count += bytesRead;
172 }
173 if (count > 0 && count < hintBuffer.length) {
174 byte[] array = new byte[count];
175 System.arraycopy(hintBuffer, 0, array, 0, count);
176 hintBuffer = array;
177 }
178 } catch (IOException e) {
318c06c9 179 Activator.logError("Error reading initial bytes of binary file", e); //$NON-NLS-1$
41d9ce5b
MAL
180 return null;
181 }
182 }
183
184 /* For all binary parsers, try to get a binary object */
185 for (IBinaryParser parser : binaryParsers) {
186 if (parser.isBinary(hintBuffer, filePath)) {
187 IBinaryFile binFile;
188 try {
189 binFile = parser.getBinary(hintBuffer, filePath);
bba6b570 190 if (binFile instanceof IBinaryParser.IBinaryObject) {
41d9ce5b
MAL
191 return (IBinaryParser.IBinaryObject)binFile;
192 }
193 } catch (IOException e) {
318c06c9 194 Activator.logError("Error parsing binary file", e); //$NON-NLS-1$
41d9ce5b
MAL
195 }
196 }
197 }
198
199 return null;
200 }
201
5da83da5 202}
This page took 0.115893 seconds and 5 git commands to generate.