From cf4ae8ebfe96f3242a651eb1b1f4c10bbae946d4 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Fri, 3 Dec 2004 02:15:20 +0000 Subject: [PATCH] 2004-12-02 Alain Magloire Fix for PR 40081. For Cygwin use NM to get the global variables. * utils/org/eclipse/cdt/utils/DefaultGnuToolFactory.java * utils/org/eclipse/cdt/utils/IGnuToolFactory.java * utils/org/eclipse/cdt/utils/NM.java * utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java * utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java --- core/org.eclipse.cdt.core/ChangeLog | 9 + .../cdt/utils/DefaultGnuToolFactory.java | 34 ++++ .../eclipse/cdt/utils/IGnuToolFactory.java | 2 + .../utils/org/eclipse/cdt/utils/NM.java | 162 ++++++++++++++++++ .../coff/parser/CygwinPEBinaryObject.java | 84 ++++++++- .../cdt/utils/coff/parser/PEBinaryObject.java | 11 +- 6 files changed, 292 insertions(+), 10 deletions(-) create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/NM.java diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index c2119d374a7..b046290830f 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,12 @@ +2004-12-02 Alain Magloire + Fix for PR 40081. + For Cygwin use NM to get the global variables. + * utils/org/eclipse/cdt/utils/DefaultGnuToolFactory.java + * utils/org/eclipse/cdt/utils/IGnuToolFactory.java + * utils/org/eclipse/cdt/utils/NM.java + * utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java + * utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java + 2004-11-25 Alain Magloire Fix PR 79076 * utils/org/eclipse/cdt/utils/elf/Elf.java diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/DefaultGnuToolFactory.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/DefaultGnuToolFactory.java index a0b532b4844..de1d76eaeb2 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/DefaultGnuToolFactory.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/DefaultGnuToolFactory.java @@ -72,6 +72,22 @@ public class DefaultGnuToolFactory implements IGnuToolFactory { return objdump; } + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.IGnuToolProvider#getObjdump(org.eclipse.core.runtime.IPath) + */ + public NM getNM(IPath path) { + IPath nmPath = getNMPath(); + String nmArgs = getNMArgs(); + NM nm = null; + if (nmPath != null && !nmPath.isEmpty()) { + try { + nm = new NM(nmPath.toOSString(), nmArgs, path.toOSString()); + } catch (IOException e1) { + } + } + return nm; + } + protected IPath getAddr2linePath() { ICExtensionReference ref = fExtension.getExtensionReference(); String value = ref.getExtensionData("addr2line"); //$NON-NLS-1$ @@ -116,4 +132,22 @@ public class DefaultGnuToolFactory implements IGnuToolFactory { } return new Path(value); } + + protected IPath getNMPath() { + ICExtensionReference ref = fExtension.getExtensionReference(); + String value = ref.getExtensionData("nm"); //$NON-NLS-1$ + if (value == null || value.length() == 0) { + value = "nm"; //$NON-NLS-1$ + } + return new Path(value); + } + + protected String getNMArgs() { + ICExtensionReference ref = fExtension.getExtensionReference(); + String value = ref.getExtensionData("nmArgs"); //$NON-NLS-1$ + if (value == null || value.length() == 0) { + value = ""; //$NON-NLS-1$ + } + return value; + } } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/IGnuToolFactory.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/IGnuToolFactory.java index f2b2f467251..b9d6a18decd 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/IGnuToolFactory.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/IGnuToolFactory.java @@ -21,4 +21,6 @@ public interface IGnuToolFactory { CPPFilt getCPPFilt(); Objdump getObjdump(IPath path); + + NM getNM(IPath path); } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/NM.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/NM.java new file mode 100644 index 00000000000..66316581cf7 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/NM.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.utils.spawner.ProcessFactory; + +/** + */ +public class NM { + + public class AddressNamePair { + public String name; + + public long address; + + public AddressNamePair(String n, long a) { + name = n; + address = a; + } + + public String toString() { + return (name + "@" + Long.toHexString(address)); + } + + } + + private static Pattern undef_pattern = null; + private static Pattern normal_pattern = null; + + private List undef_symbols; + private List text_symbols; + private List bss_symbols; + private List data_symbols; + + private void parseOutput(InputStream stream) throws IOException { + + BufferedReader reader = new BufferedReader( + new InputStreamReader(stream)); + String line; + + // See matcher.java for regular expression string data definitions. + + if (undef_pattern == null) { + undef_pattern = Pattern.compile("^\\s+U\\s+(\\S+)"); //$NON-NLS-1$ + } + + if (normal_pattern == null) { + normal_pattern = Pattern.compile("^(\\S+)\\s+([AaTtBbDd])\\s+(\\S+)"); //$NON-NLS-1$ + } + while ((line = reader.readLine()) != null) { + Matcher undef_matcher = undef_pattern.matcher(line); + Matcher normal_matcher = normal_pattern.matcher(line); + try { + if (undef_matcher.matches()) { + undef_symbols.add(undef_matcher.group(1)); + } else if (normal_matcher.matches()) { + char type = normal_matcher.group(2).charAt(0); + String name = normal_matcher.group(3); + long address = Long.parseLong(normal_matcher.group(1), 16); + AddressNamePair val = new AddressNamePair(name, address); + + switch (type) { + case 'T': + case 't': + text_symbols.add(val); + break; + case 'B': + case 'b': + bss_symbols.add(val); + break; + case 'D': + case 'd': + data_symbols.add(val); + break; + } + } + } catch (NumberFormatException e) { + // ignore. + } catch (IndexOutOfBoundsException e) { + // ignore + } + } + + } + + public NM(String file, boolean dynamic_only) throws IOException { + this ("nm", file, dynamic_only); //$NON-NLS-1$ + } + + public NM(String command, String file, boolean dynamic_only) throws IOException { + this(command, (dynamic_only) ? new String[] {"-C", "-D"}: null, file); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public NM(String command, String param, String file) throws IOException { + String[] params; + if (param == null || param.length() == 0) { + params = new String[0]; + } else { + // FIXME: This is wrong we have to check for quoted strings. + params = param.split("\\s"); //$NON-NLS-1$ + } + init(command, params, file); + } + + public NM(String command, String[] params, String file) throws IOException { + init(command, params, file); + } + + protected void init(String command, String[] params, String file) throws IOException { + String[] args = null; + if (params == null || params.length == 0) { + args = new String[] {command, "-C", file}; //$NON-NLS-1$ + } else { + args = new String[params.length + 1]; + args[0] = command; + System.arraycopy(params, 0, args, 1, params.length); + } + + undef_symbols = new ArrayList(); + text_symbols = new ArrayList(); + data_symbols = new ArrayList(); + bss_symbols = new ArrayList(); + Process process = ProcessFactory.getFactory().exec(args); + parseOutput(process.getInputStream()); + process.destroy(); + } + + public String[] getUndefSymbols() { + return (String[]) undef_symbols.toArray(new String[0]); + } + + public AddressNamePair[] getTextSymbols() { + return (AddressNamePair[]) text_symbols.toArray(new AddressNamePair[0]); + } + + public AddressNamePair[] getDataSymbols() { + return (AddressNamePair[]) data_symbols.toArray(new AddressNamePair[0]); + } + + public AddressNamePair[] getBSSSymbols() { + return (AddressNamePair[]) bss_symbols.toArray(new AddressNamePair[0]); + } + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java index 81c666525ce..ee1d876bc47 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java @@ -11,6 +11,8 @@ package org.eclipse.cdt.utils.coff.parser; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.eclipse.cdt.core.IAddress; @@ -21,6 +23,7 @@ import org.eclipse.cdt.utils.Addr32; import org.eclipse.cdt.utils.CPPFilt; import org.eclipse.cdt.utils.CygPath; import org.eclipse.cdt.utils.ICygwinToolsFactroy; +import org.eclipse.cdt.utils.NM; import org.eclipse.cdt.utils.Objdump; import org.eclipse.cdt.utils.AR.ARHeader; import org.eclipse.cdt.utils.coff.Coff; @@ -97,7 +100,7 @@ public class CygwinPEBinaryObject extends PEBinaryObject { } private Addr2line getAddr2line() { - ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getAdapter(ICygwinToolsFactroy.class); + ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class); if (factory != null) { return factory.getAddr2line(getPath()); } @@ -110,7 +113,7 @@ public class CygwinPEBinaryObject extends PEBinaryObject { * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getCPPFilt() */ protected CPPFilt getCPPFilt() { - ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getAdapter(ICygwinToolsFactroy.class); + ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class); if (factory != null) { return factory.getCPPFilt(); } @@ -123,7 +126,7 @@ public class CygwinPEBinaryObject extends PEBinaryObject { * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getObjdump() */ protected Objdump getObjdump() { - ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getAdapter(ICygwinToolsFactroy.class); + ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class); if (factory != null) { return factory.getObjdump(getPath()); } @@ -134,13 +137,23 @@ public class CygwinPEBinaryObject extends PEBinaryObject { * @return */ protected CygPath getCygPath() { - ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getAdapter(ICygwinToolsFactroy.class); + ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class); if (factory != null) { return factory.getCygPath(); } return null; } + /** + */ + protected NM getNM() { + ICygwinToolsFactroy factory = (ICygwinToolsFactroy)getBinaryParser().getAdapter(ICygwinToolsFactroy.class); + if (factory != null) { + return factory.getNM(getPath()); + } + return null; + } + /** * @throws IOException * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents() @@ -166,7 +179,25 @@ public class CygwinPEBinaryObject extends PEBinaryObject { symbolLoadingAddr2line = getAddr2line(false); symbolLoadingCPPFilt = getCPPFilt(); symbolLoadingCygPath = getCygPath(); - super.loadSymbols(pe); + + + ArrayList list = new ArrayList(); + super.loadSymbols(pe, list); + + // Add any global symbols + NM nm = getNM(); + NM.AddressNamePair[] pairs = nm.getBSSSymbols(); + for (int i = 0; i < pairs.length; ++i) { + addSymbol(pairs[i], list, ISymbol.VARIABLE); + } +// pairs = nm.getTextSymbols(); +// for (int i = 0; i < pairs.length; ++i) { +// addSymbol(pairs[i], list, ISymbol.FUNCTION); +// } + symbols = (ISymbol[]) list.toArray(NO_SYMBOLS); + Arrays.sort(symbols); + list.clear(); + if (symbolLoadingAddr2line != null) { symbolLoadingAddr2line.dispose(); symbolLoadingAddr2line = null; @@ -181,6 +212,49 @@ public class CygwinPEBinaryObject extends PEBinaryObject { } } + private void addSymbol(NM.AddressNamePair p, List list, int type) { + String name = p.name; + if (name != null && name.length() > 0 && Character.isJavaIdentifierStart(name.charAt(0))) { + IAddress addr = new Addr32(p.address); + int size = 4; + if (symbolLoadingCPPFilt != null) { + try { + name = symbolLoadingCPPFilt.getFunction(name); + } catch (IOException e1) { + symbolLoadingCPPFilt.dispose(); + symbolLoadingCPPFilt = null; + } + } + if (symbolLoadingAddr2line != null) { + try { + String filename = symbolLoadingAddr2line.getFileName(addr); + // Addr2line returns the funny "??" when it can not find + // the file. + if (filename != null && filename.equals("??")) { //$NON-NLS-1$ + filename = null; + } + if (filename != null) { + try { + if (symbolLoadingCygPath != null) { + filename = symbolLoadingCygPath.getFileName(filename); + } + } catch (IOException e) { + symbolLoadingCygPath.dispose(); + symbolLoadingCygPath = null; + } + } + IPath file = filename != null ? new Path(filename) : Path.EMPTY; + int startLine = symbolLoadingAddr2line.getLineNumber(addr); + int endLine = symbolLoadingAddr2line.getLineNumber(addr.add(size - 1)); + list.add(new CygwinSymbol(this, name, type, addr, size, file, startLine, endLine)); + } catch (IOException e) { + symbolLoadingAddr2line.dispose(); + symbolLoadingAddr2line = null; + } + } + } + } + /* * (non-Javadoc) * diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java index e32b9f92af6..cf988d79e7f 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java @@ -137,15 +137,16 @@ public class PEBinaryObject extends BinaryObjectAdapter { protected void loadSymbols(PE pe) throws IOException { ArrayList list = new ArrayList(); - - Coff.Symbol[] peSyms = pe.getSymbols(); - byte[] table = pe.getStringTable(); - addSymbols(peSyms, table, list); - + loadSymbols(pe, list); symbols = (ISymbol[]) list.toArray(NO_SYMBOLS); Arrays.sort(symbols); list.clear(); } + protected void loadSymbols(PE pe, List list) throws IOException { + Coff.Symbol[] peSyms = pe.getSymbols(); + byte[] table = pe.getStringTable(); + addSymbols(peSyms, table, list); + } protected void addSymbols(Coff.Symbol[] peSyms, byte[] table, List list) { for (int i = 0; i < peSyms.length; i++) {