/******************************************************************************* * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - Initial API and implementation *******************************************************************************/ 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.IAddressFactory; import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.core.ISymbolReader; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.utils.AR; import org.eclipse.cdt.utils.Addr32; import org.eclipse.cdt.utils.Addr32Factory; import org.eclipse.cdt.utils.BinaryObjectAdapter; import org.eclipse.cdt.utils.Symbol; import org.eclipse.cdt.utils.coff.Coff; import org.eclipse.cdt.utils.coff.PE; import org.eclipse.core.runtime.IPath; /** */ public class PEBinaryObject extends BinaryObjectAdapter { BinaryObjectInfo info; IAddressFactory addressFactory; ISymbol[] symbols; AR.ARHeader header; public PEBinaryObject(IBinaryParser parser, IPath path, AR.ARHeader header) { super(parser, path, IBinaryFile.OBJECT); } public PEBinaryObject(IBinaryParser parser, IPath p, int type) { super(parser, p, type); } /* (non-Javadoc) * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getName() */ @Override public String getName() { if (header != null) { return header.getObjectName(); } return super.getName(); } /* (non-Javadoc) * @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getContents() */ @Override public InputStream getContents() throws IOException { if (getPath() != null && header != null) { return new ByteArrayInputStream(header.getObjectData()); } return super.getContents(); } /** * @see org.eclipse.cdt.core.IBinaryParser.IBinaryObject#getSymbols() */ @Override public ISymbol[] getSymbols() { if (hasChanged() || symbols == null) { try { loadAll(); } catch (IOException e) { symbols = NO_SYMBOLS; } } return symbols; } /* * (non-Javadoc) * * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getBinaryObjectInfo() */ @Override protected BinaryObjectInfo getBinaryObjectInfo() { if (hasChanged() || info == null) { try { loadInfo(); } catch (IOException e) { info = new BinaryObjectInfo(); } } return info; } @SuppressWarnings("rawtypes") @Override public Object getAdapter(Class adapter) { if (adapter.equals(PE.class)) { try { if (header != null) { return new PE(getPath().toOSString(), header.getObjectDataOffset()); } return new PE(getPath().toOSString()); } catch (IOException e) { } } if (adapter.equals(ISymbolReader.class)) { PE pe = (PE)getAdapter(PE.class); if (pe != null) { return pe.getSymbolReader(); } } return super.getAdapter(adapter); } protected PE getPE() throws IOException { if (header != null) { return new PE(getPath().toOSString(), header.getObjectDataOffset()); } return new PE(getPath().toOSString()); } protected void loadAll() throws IOException { PE pe = null; try { pe = getPE(); loadInfo(pe); loadSymbols(pe); } finally { if (pe != null) { pe.dispose(); } } } protected void loadInfo() throws IOException { PE pe = null; try { pe = getPE(); loadInfo(pe); } finally { if (pe != null) { pe.dispose(); } } } protected void loadInfo(PE pe) throws IOException { info = new BinaryObjectInfo(); PE.Attribute attribute = getPE().getAttribute(); info.isLittleEndian = attribute.isLittleEndian(); info.hasDebug = attribute.hasDebug(); info.cpu = attribute.getCPU(); } protected void loadSymbols(PE pe) throws IOException { ArrayList<Symbol> list = new ArrayList<Symbol>(); loadSymbols(pe, list); symbols = list.toArray(NO_SYMBOLS); Arrays.sort(symbols); list.clear(); } protected void loadSymbols(PE pe, List<Symbol> 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<Symbol> list) { for (org.eclipse.cdt.utils.coff.Coff.Symbol peSym : peSyms) { if (peSym.isFunction() || peSym.isPointer() || peSym.isArray()) { String name = peSym.getName(table); if (name == null || name.trim().length() == 0 || !Character.isJavaIdentifierStart(name.charAt(0))) { continue; } int type = peSym.isFunction() ? ISymbol.FUNCTION : ISymbol.VARIABLE; list.add(new Symbol(this, name, type, new Addr32(peSym.n_value), peSym.getSize())); } } } /* (non-Javadoc) * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getAddressFactory() */ @Override public IAddressFactory getAddressFactory() { if (addressFactory == null) { addressFactory = new Addr32Factory(); } return addressFactory; } }