1
/*******************************************************************************
2
* Copyright (c) 2000, 2008 QNX Software Systems and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* QNX Software Systems - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.utils.coff.parser;
13
import java.io.ByteArrayInputStream;
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.util.ArrayList;
17
import java.util.Arrays;
18
import java.util.List;
20
import org.eclipse.cdt.core.CConventions;
21
import org.eclipse.cdt.core.IAddress;
22
import org.eclipse.cdt.core.IBinaryParser;
23
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
24
import org.eclipse.cdt.utils.Addr2line;
25
import org.eclipse.cdt.utils.Addr32;
26
import org.eclipse.cdt.utils.CPPFilt;
27
import org.eclipse.cdt.utils.CygPath;
28
import org.eclipse.cdt.utils.ICygwinToolsFactroy;
29
import org.eclipse.cdt.utils.NM;
30
import org.eclipse.cdt.utils.Objdump;
31
import org.eclipse.cdt.utils.Symbol;
32
import org.eclipse.cdt.utils.AR.ARHeader;
33
import org.eclipse.cdt.utils.coff.Coff;
34
import org.eclipse.cdt.utils.coff.PE;
35
import org.eclipse.core.runtime.IPath;
36
import org.eclipse.core.runtime.Path;
39
* CygwinPEBinaryObject
41
public class CygwinPEBinaryObject extends PEBinaryObject {
43
private Addr2line autoDisposeAddr2line;
44
private Addr2line symbolLoadingAddr2line;
45
private CygPath symbolLoadingCygPath;
46
private CPPFilt symbolLoadingCPPFilt;
54
public CygwinPEBinaryObject(IBinaryParser parser, IPath path, ARHeader header) {
55
super(parser, path, header);
58
public CygwinPEBinaryObject(IBinaryParser parser, IPath path, int type) {
59
super(parser, path, type);
62
public Addr2line getAddr2line(boolean autodisposing) {
64
return getAddr2line();
66
if (autoDisposeAddr2line == null) {
67
autoDisposeAddr2line = getAddr2line();
68
if (autoDisposeAddr2line != null) {
69
starttime = System.currentTimeMillis();
70
Runnable worker = new Runnable() {
74
long diff = System.currentTimeMillis() - starttime;
75
while (diff < 10000) {
78
} catch (InterruptedException e) {
81
diff = System.currentTimeMillis() - starttime;
86
new Thread(worker, "Addr2line Reaper").start(); //$NON-NLS-1$
89
starttime = System.currentTimeMillis(); // reset autodispose timeout
91
return autoDisposeAddr2line;
94
synchronized void stopAddr2Line() {
95
if (autoDisposeAddr2line != null) {
96
autoDisposeAddr2line.dispose();
98
autoDisposeAddr2line = null;
101
private Addr2line getAddr2line() {
102
ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class);
103
if (factory != null) {
104
return factory.getAddr2line(getPath());
112
* @see org.eclipse.cdt.utils.BinaryObjectAdapter#getCPPFilt()
114
protected CPPFilt getCPPFilt() {
115
ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class);
116
if (factory != null) {
117
return factory.getCPPFilt();
125
* @see org.eclipse.cdt.utils.BinaryObjectAdapter#getObjdump()
127
protected Objdump getObjdump() {
128
ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class);
129
if (factory != null) {
130
return factory.getObjdump(getPath());
135
protected CygPath getCygPath() {
136
ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class);
137
if (factory != null) {
138
return factory.getCygPath();
145
protected NM getNM() {
146
ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class);
147
if (factory != null) {
148
return factory.getNM(getPath());
154
* @throws IOException
155
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getContents()
158
public InputStream getContents() throws IOException {
159
InputStream stream = null;
160
Objdump objdump = getObjdump();
161
if (objdump != null) {
163
byte[] contents = objdump.getOutput();
164
stream = new ByteArrayInputStream(contents);
165
} catch (IOException e) {
169
if (stream == null) {
170
stream = super.getContents();
176
protected void loadSymbols(PE pe) throws IOException {
177
symbolLoadingAddr2line = getAddr2line(false);
178
symbolLoadingCPPFilt = getCPPFilt();
179
symbolLoadingCygPath = getCygPath();
182
ArrayList<Symbol> list = new ArrayList<Symbol>();
183
super.loadSymbols(pe, list);
185
// Add any global symbols
188
NM.AddressNamePair[] pairs = nm.getBSSSymbols();
189
for (int i = 0; i < pairs.length; ++i) {
190
addSymbol(pairs[i], list, ISymbol.VARIABLE);
192
pairs = nm.getDataSymbols();
193
for (int i = 0; i < pairs.length; ++i) {
194
addSymbol(pairs[i], list, ISymbol.VARIABLE);
197
// pairs = nm.getTextSymbols();
198
// for (int i = 0; i < pairs.length; ++i) {
199
// addSymbol(pairs[i], list, ISymbol.FUNCTION);
201
symbols = list.toArray(NO_SYMBOLS);
202
Arrays.sort(symbols);
205
if (symbolLoadingAddr2line != null) {
206
symbolLoadingAddr2line.dispose();
207
symbolLoadingAddr2line = null;
209
if (symbolLoadingCPPFilt != null) {
210
symbolLoadingCPPFilt.dispose();
211
symbolLoadingCPPFilt = null;
213
if (symbolLoadingCygPath != null) {
214
symbolLoadingCygPath.dispose();
215
symbolLoadingCygPath = null;
219
private void addSymbol(NM.AddressNamePair p, List<Symbol> list, int type) {
220
String name = p.name;
221
if (name != null && name.length() > 0 && CConventions.isValidIdentifier(name)) {
222
IAddress addr = new Addr32(p.address);
224
if (symbolLoadingCPPFilt != null) {
226
name = symbolLoadingCPPFilt.getFunction(name);
227
} catch (IOException e1) {
228
symbolLoadingCPPFilt.dispose();
229
symbolLoadingCPPFilt = null;
232
if (symbolLoadingAddr2line != null) {
234
String filename = symbolLoadingAddr2line.getFileName(addr);
235
// Addr2line returns the funny "??" when it can not find
237
if (filename != null && filename.equals("??")) { //$NON-NLS-1$
240
if (filename != null) {
242
if (symbolLoadingCygPath != null) {
243
filename = symbolLoadingCygPath.getFileName(filename);
245
} catch (IOException e) {
246
symbolLoadingCygPath.dispose();
247
symbolLoadingCygPath = null;
250
IPath file = filename != null ? new Path(filename) : Path.EMPTY;
251
int startLine = symbolLoadingAddr2line.getLineNumber(addr);
252
int endLine = symbolLoadingAddr2line.getLineNumber(addr.add(size - 1));
253
list.add(new CygwinSymbol(this, name, type, addr, size, file, startLine, endLine));
254
} catch (IOException e) {
255
symbolLoadingAddr2line.dispose();
256
symbolLoadingAddr2line = null;
265
* @see org.eclipse.cdt.utils.coff.parser.PEBinaryObject#addSymbols(org.eclipse.cdt.utils.coff.Coff.Symbol[],
266
* byte[], java.util.List)
269
protected void addSymbols(Coff.Symbol[] peSyms, byte[] table, List<Symbol> list) {
270
for (Coff.Symbol peSym : peSyms) {
271
if (peSym.isFunction() || peSym.isPointer() || peSym.isArray()) {
272
String name = peSym.getName(table);
273
if (name == null || name.trim().length() == 0 || !Character.isJavaIdentifierStart(name.charAt(0))) {
276
int type = peSym.isFunction() ? ISymbol.FUNCTION : ISymbol.VARIABLE;
277
IAddress addr = new Addr32(peSym.n_value);
279
if (symbolLoadingCPPFilt != null) {
281
name = symbolLoadingCPPFilt.getFunction(name);
282
} catch (IOException e1) {
283
symbolLoadingCPPFilt.dispose();
284
symbolLoadingCPPFilt = null;
287
if (symbolLoadingAddr2line != null) {
289
String filename = symbolLoadingAddr2line.getFileName(addr);
290
// Addr2line returns the funny "??" when it can not find
292
if (filename != null && filename.equals("??")) { //$NON-NLS-1$
296
if (filename != null) {
298
if (symbolLoadingCygPath != null) {
299
filename = symbolLoadingCygPath.getFileName(filename);
301
} catch (IOException e) {
302
symbolLoadingCygPath.dispose();
303
symbolLoadingCygPath = null;
306
IPath file = filename != null ? new Path(filename) : Path.EMPTY;
307
int startLine = symbolLoadingAddr2line.getLineNumber(addr);
308
int endLine = symbolLoadingAddr2line.getLineNumber(addr.add(size - 1));
309
list.add(new CygwinSymbol(this, name, type, addr, size, file, startLine, endLine));
310
} catch (IOException e) {
311
symbolLoadingAddr2line.dispose();
312
symbolLoadingAddr2line = null;
313
// the symbol still needs to be added
314
list.add(new CygwinSymbol(this, name, type, addr, size));
317
list.add(new CygwinSymbol(this, name, type, addr, size));
327
* @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
329
@SuppressWarnings("unchecked")
331
public Object getAdapter(Class adapter) {
332
if (adapter == Addr2line.class) {
333
return getAddr2line(false);
334
} else if (adapter == CPPFilt.class) {
336
} else if (adapter == CygPath.class) {
339
return super.getAdapter(adapter);