/*******************************************************************************
* Copyright (c) 2004, 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.debug.internal.core.model;
import java.math.BigInteger;
import com.ibm.icu.text.MessageFormat;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.IAddressFactory;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ISourceRoot;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.cdi.CDIException;
import org.eclipse.cdt.debug.core.cdi.model.ICDIObject;
import org.eclipse.cdt.debug.core.cdi.model.ICDISharedLibrary;
import org.eclipse.cdt.debug.core.model.ICModule;
import org.eclipse.cdt.internal.core.model.Binary;
import org.eclipse.cdt.internal.core.model.CModelManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugException;
/**
* The CDI based implementation of <code>ICModule</code>.
*
* This implementation is experimental and needs to be changed when
* the CDI level support is available.
*/
public class CModule extends CDebugElement implements ICModule {
private int fType = 0;
private Binary fBinary;
private ICDIObject fCDIObject;
private IPath fImageName;
private IPath fSymbolsFileName;
public static CModule createExecutable( CDebugTarget target, IPath path ) {
// TODO Add support for executables to CDI.
return new CModule( EXECUTABLE, target, path );
}
public static CModule createSharedLibrary( CDebugTarget target, ICDISharedLibrary lib ) {
return new CModule( SHARED_LIBRARY, target, lib );
}
/**
* Constructor for CModule. Used for the program.
*/
private CModule( int type, CDebugTarget target, IPath path ) {
super( target );
fType = type;
fBinary = createBinary(path);
fCDIObject = null;
fImageName = path;
fSymbolsFileName = path;
}
/**
* Constructor for CModule. Used for shared libraries.
*/
private CModule( int type, CDebugTarget target, ICDIObject cdiObject ) {
super( target );
fType = type;
if ( cdiObject instanceof ICDISharedLibrary ) {
ICDISharedLibrary cdiSharedLib = (ICDISharedLibrary)cdiObject;
fBinary = createBinary(new Path(cdiSharedLib.getFileName()));
}
fCDIObject = cdiObject;
fImageName = ( ( cdiObject instanceof ICDISharedLibrary ) ) ? new Path( ((ICDISharedLibrary)cdiObject).getFileName() ) : new Path( CoreModelMessages.getString( "CModule.0" ) ); //$NON-NLS-1$
fSymbolsFileName = fImageName;
}
/**
* We used to ask the CoreModel to create the Binary (ICElement) for us but
* it will do so only for binary files that are in a project output
* directory (for performance reasons). So, we do all the leg work
* ourselves, duplicating much of the code, unfortunately.
*
* THE OLD WAY...
* fCElement = CoreModel.getDefault().create(path);
*/
private Binary createBinary(IPath path) {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IFile file = root.getFileForLocation(path);
if (file != null && !file.exists()) {
file = null;
}
// In case this is an external resource see if we can find
// a file for it.
if (file == null) {
IFile[] files = root.findFilesForLocation(path);
if (files.length > 0) {
file = files[0];
}
}
if (file != null) {
ICProject cproject = CoreModel.getDefault().create(file.getProject());
IPath resourcePath = file.getParent().getFullPath();
try {
ICElement cfolder = cproject.findElement(resourcePath);
// Check if folder is a source root and use that instead
ISourceRoot sourceRoot = cproject.findSourceRoot(resourcePath);
if (sourceRoot != null)
cfolder = sourceRoot;
IBinaryFile bin = CModelManager.getDefault().createBinaryFile(file);
if (bin != null) {
return new Binary(cfolder, file, (IBinaryObject)bin);
}
} catch (CModelException e) {
CDebugCorePlugin.log(e);
}
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getType()
*/
public int getType() {
return fType;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getName()
*/
public String getName() {
return fImageName.lastSegment().toString();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getImageName()
*/
public IPath getImageName() {
return fImageName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getSymbolsFileName()
*/
public IPath getSymbolsFileName() {
return fSymbolsFileName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#setSymbolsFileName(org.eclipse.core.runtime.IPath)
*/
public void setSymbolsFileName( IPath symbolsFile ) throws DebugException {
loadSymbolsFromFile( symbolsFile );
fSymbolsFileName = symbolsFile;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getBaseAddress()
*/
public IAddress getBaseAddress() {
return ( fCDIObject instanceof ICDISharedLibrary ) ? getAddressFactory().createAddress( ((ICDISharedLibrary)fCDIObject).getStartAddress() ) : getAddressFactory().getZero();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getSize()
*/
public long getSize() {
long result = 0;
if ( fCDIObject instanceof ICDISharedLibrary ) {
BigInteger start = ((ICDISharedLibrary)fCDIObject).getStartAddress();
BigInteger end = ((ICDISharedLibrary)fCDIObject).getEndAddress();
if ( end.compareTo( start ) > 0 )
result = end.subtract( start ).longValue();
}
return result;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#areSymbolsLoaded()
*/
public boolean areSymbolsLoaded() {
if (fCDIObject instanceof ICDISharedLibrary)
return ((ICDISharedLibrary)fCDIObject).areSymbolsLoaded();
if (fBinary != null)
return fBinary.hasDebug();
return false;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#canLoadSymbols()
*/
public boolean canLoadSymbols() {
return ( getDebugTarget().isSuspended() && !areSymbolsLoaded() );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#loadSymbols()
*/
public void loadSymbols() throws DebugException {
loadSymbolsFromFile( getSymbolsFileName() );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getPlatform()
*/
public String getPlatform() {
return ( fBinary != null ) ? fBinary.getCPU() : CoreModelMessages.getString( "CModule.1" ); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#isLittleEndian()
*/
public boolean isLittleEndian() {
return ( fBinary != null ) ? fBinary.isLittleEndian() : ((CDebugTarget)getDebugTarget()).isLittleEndian();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getAddressFactory()
*/
public IAddressFactory getAddressFactory() {
return ((CDebugTarget)getDebugTarget()).getAddressFactory();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICModule#getCPU()
*/
public String getCPU() {
return ( fBinary != null ) ? fBinary.getCPU() : null;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
public Object getAdapter( Class adapter ) {
if ( ICElement.class.equals( adapter ) ) {
return getCElement();
}
if ( IBinary.class.equals( adapter ) && getCElement() instanceof IBinary ) {
return getCElement();
}
return super.getAdapter( adapter );
}
public void dispose() {
}
public boolean equals( ICDIObject cdiObject ) {
return ( fCDIObject != null ) ? fCDIObject.equals( cdiObject ) : false;
}
protected ICElement getCElement() {
return fBinary;
}
private void loadSymbolsFromFile(IPath path) throws DebugException {
if (fCDIObject instanceof ICDISharedLibrary) {
if (path == null || path.isEmpty()) {
requestFailed(CoreModelMessages.getString("CModule.2"), null); //$NON-NLS-1$
} else {
if (path.equals(getSymbolsFileName())) {
try {
((ICDISharedLibrary) fCDIObject).loadSymbols();
} catch (CDIException e) {
targetRequestFailed(e.getMessage(), null);
}
} else {
String message = MessageFormat.format( //
CoreModelMessages.getString("CModule.5"), //$NON-NLS-1$
new Object[] { path.toString() });
targetRequestFailed(message, null);
}
}
}
}
}