/******************************************************************************* * 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.elf.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.Addr32Factory; import org.eclipse.cdt.utils.BinaryObjectAdapter; import org.eclipse.cdt.utils.Symbol; import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.elf.ElfHelper; import org.eclipse.core.runtime.IPath; /* * ElfBinaryObject */ public class ElfBinaryObject extends BinaryObjectAdapter { private BinaryObjectInfo info; private ISymbol[] symbols; private final AR.ARHeader header; private IAddressFactory addressFactory; private volatile Elf.Attribute fElfAttributes; public ElfBinaryObject(IBinaryParser parser, IPath p, AR.ARHeader h){ super(parser, p, IBinaryFile.OBJECT); header = h; } public ElfBinaryObject(IBinaryParser parser, IPath p, int type){ super(parser, p, type); header = null; } /** * @param elfAttributes the elfAttributes to set */ void setElfAttributes(Elf.Attribute elfAttributes) { fElfAttributes= elfAttributes; } /* (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(); } /* (non-Javadoc) * @see org.eclipse.cdt.core.IBinaryParser.IBinaryObject#getSymbols() */ @Override public ISymbol[] getSymbols() { // Call the hasChanged first, to initialize the timestamp 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() { // Call the hasChanged first, to initialize the timestamp if (hasChanged() || info == null) { try { loadInfo(); } catch (IOException e) { info = new BinaryObjectInfo(); } } return info; } protected ElfHelper getElfHelper() throws IOException { if (header != null) { return new ElfHelper(header.getArchiveName(), header.getObjectDataOffset()); } return new ElfHelper(getPath().toOSString()); } protected void loadAll() throws IOException { ElfHelper helper = null; try { helper = getElfHelper(); loadInfo(helper); loadSymbols(helper); } finally { if (helper != null) { helper.dispose(); } } } protected void loadInfo() throws IOException { ElfHelper helper = null; try { helper = getElfHelper(); loadInfo(helper); } finally { if (helper != null) { helper.dispose(); } } } protected void loadInfo(ElfHelper helper) throws IOException { info = new BinaryObjectInfo(); Elf.Dynamic[] sharedlibs = helper.getNeeded(); info.needed = new String[sharedlibs.length]; for (int i = 0; i < sharedlibs.length; i++) { info.needed[i] = sharedlibs[i].toString(); } ElfHelper.Sizes sizes = helper.getSizes(); info.bss = sizes.bss; info.data = sizes.data; info.text = sizes.text; info.soname = helper.getSoname(); Elf.Attribute attribute = helper.getElf().getAttributes(); info.isLittleEndian = attribute.isLittleEndian(); info.hasDebug = attribute.hasDebug(); info.cpu = attribute.getCPU(); addressFactory = attribute.getAddressFactory(); fElfAttributes= null; } protected void loadSymbols(ElfHelper helper) throws IOException { ArrayList<Symbol> list = new ArrayList<Symbol>(); // addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION, list); addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION, list); // addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE, list); addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE, list); list.trimToSize(); symbols = list.toArray(NO_SYMBOLS); Arrays.sort(symbols); list.clear(); } protected void addSymbols(Elf.Symbol[] array, int type, List<Symbol> list) { for (org.eclipse.cdt.utils.elf.Elf.Symbol element : array) { // Multiple function symbol entries for the same address are generated // do not add duplicate symbols with 0 size to the list boolean duplicateAddressFound = false; if (type == ISymbol.FUNCTION && element.st_size == 0){ for (Symbol s : list) { if (s.getAddress().equals(element.st_value)){ duplicateAddressFound = true; break; } } } if (!duplicateAddressFound) list.add(new Symbol(this, element.toString(), type, element.st_value, element.st_size)); } } /* (non-Javadoc) * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ @SuppressWarnings("rawtypes") @Override public Object getAdapter(Class adapter) { if (adapter.equals(Elf.class)) { try { return new Elf(getPath().toOSString()); } catch (IOException e) { } } if (adapter.equals(ISymbolReader.class)) { Elf elf = (Elf)getAdapter(Elf.class); if (elf != null) { return elf.getSymbolReader(); } } return super.getAdapter(adapter); } /* (non-Javadoc) * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getAddressFactory() */ @Override public IAddressFactory getAddressFactory() { if (addressFactory == null) { if (fElfAttributes != null) { addressFactory= fElfAttributes.getAddressFactory(); } if (addressFactory == null) { try { loadInfo(); } catch (IOException e) { return new Addr32Factory(); } } } return addressFactory; } /* * @see org.eclipse.cdt.utils.BinaryObjectAdapter#isLittleEndian() */ @Override public boolean isLittleEndian() { if (fElfAttributes != null) { return fElfAttributes.isLittleEndian(); } return super.isLittleEndian(); } /* * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getCPU() */ @Override public String getCPU() { if (fElfAttributes != null) { return fElfAttributes.getCPU(); } return super.getCPU(); } }