/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River 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:
* Wind River Systems - initial API and implementation
* Ericsson AB - Modules implementation for GDB
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
import java.math.BigInteger;
import java.util.Hashtable;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IModules;
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoSharedLibraryInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoSharedLibraryInfo.DsfMISharedInfo;
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.osgi.framework.BundleContext;
/**
*
*/
public class MIModules extends AbstractDsfService implements IModules, ICachingService {
private CommandCache fModulesCache;
private CommandFactory fCommandFactory;
public MIModules(DsfSession session) {
super(session);
}
@Override
protected BundleContext getBundleContext() {
return GdbPlugin.getBundleContext();
}
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(
new RequestMonitor(ImmediateExecutor.getInstance(), requestMonitor) {
@Override
protected void handleSuccess() {
doInitialize(requestMonitor);
}});
}
private void doInitialize(RequestMonitor requestMonitor) {
// Cache for holding Modules data
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
fModulesCache = new CommandCache(getSession(), commandControl);
fModulesCache.setContextAvailable(commandControl.getContext(), true);
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
/*
* Make ourselves known so clients can use us.
*/
register(new String[]{IModules.class.getName(), MIModules.class.getName()}, new Hashtable<String,String>());
requestMonitor.done();
}
@Override
public void shutdown(RequestMonitor requestMonitor) {
unregister();
super.shutdown(requestMonitor);
}
static class ModuleDMContext extends AbstractDMContext implements IModuleDMContext {
private final String fFile;
ModuleDMContext(MIModules service, IDMContext[] parents, String file) {
super(service, parents);
fFile = file;
}
@Override
public boolean equals(Object obj) {
return baseEquals(obj) && fFile.equals(((ModuleDMContext)obj).fFile);
}
@Override
public int hashCode() {
return baseHashCode() + fFile.hashCode();
}
}
static class ModuleDMData implements IModuleDMData {
private final String fFile;
private final String fFromAddress;
private final String fToAddress;
private final boolean fIsSymbolsRead;
public ModuleDMData(ModuleDMContext dmc) {
fFile = dmc.fFile;
fFromAddress = null;
fToAddress = null;
fIsSymbolsRead = false;
}
public ModuleDMData(String fileName, String fromAddress, String toAddress, boolean isSymsRead){
fFile = fileName;
fFromAddress = fromAddress;
fToAddress = toAddress;
fIsSymbolsRead = isSymsRead;
}
public String getFile() {
return fFile;
}
public String getName() {
return fFile;
}
public long getTimeStamp() {
return 0;
}
public String getBaseAddress() {
return fFromAddress;
}
public String getToAddress() {
return fToAddress;
}
public boolean isSymbolsLoaded() {
return fIsSymbolsRead;
}
public long getSize() {
long result = 0;
if(getBaseAddress() == null || getToAddress() == null)
return result;
BigInteger start = MIFormat.getBigInteger(getBaseAddress());
BigInteger end = MIFormat.getBigInteger(getToAddress());
if ( end.compareTo( start ) > 0 )
result = end.subtract( start ).longValue();
return result;
}
}
public void getModules(final ISymbolDMContext symCtx, final DataRequestMonitor<IModuleDMContext[]> rm) {
if(symCtx != null){
fModulesCache.execute(fCommandFactory.createCLIInfoSharedLibrary(symCtx),
new DataRequestMonitor<CLIInfoSharedLibraryInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(makeModuleContexts(symCtx, getData()));
rm.done();
}
});
}
else{
rm.setData(new IModuleDMContext[] { new ModuleDMContext(this, DMContexts.EMPTY_CONTEXTS_ARRAY, "example module 1"), new ModuleDMContext(this, DMContexts.EMPTY_CONTEXTS_ARRAY, "example module 2") }); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
}
}
private IModuleDMContext[] makeModuleContexts(IDMContext symCtxt, CLIInfoSharedLibraryInfo info){
DsfMISharedInfo[] sharedInfos = info.getMIShared();
ModuleDMContext[] modules = new ModuleDMContext[sharedInfos.length];
int i = 0;
for(DsfMISharedInfo shared : sharedInfos){
modules[i++] = new ModuleDMContext(this, new IDMContext[]{symCtxt}, shared.getName());
}
return modules;
}
public void getModuleData(final IModuleDMContext dmc, final DataRequestMonitor<IModuleDMData> rm) {
assert dmc != null;
if (dmc instanceof ModuleDMContext) {
fModulesCache.execute(fCommandFactory.createCLIInfoSharedLibrary(dmc),
new DataRequestMonitor<CLIInfoSharedLibraryInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData( createSharedLibInfo((ModuleDMContext)dmc, getData()) );
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DM Context", null)); //$NON-NLS-1$
rm.done();
}
}
private IModuleDMData createSharedLibInfo(ModuleDMContext dmc, CLIInfoSharedLibraryInfo info){
for (CLIInfoSharedLibraryInfo.DsfMISharedInfo shared : info.getMIShared()) {
if(shared.getName().equals(dmc.fFile)){
return new ModuleDMData(shared.getName(), shared.getFrom(), shared.getTo(), shared.isRead());
}
}
return new ModuleDMData("","", "", false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public void calcAddressInfo(ISymbolDMContext symCtx, String file, int line, int col, DataRequestMonitor<AddressRange[]> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Functionality not supported", null)); //$NON-NLS-1$
rm.done();
}
public void calcLineInfo(ISymbolDMContext symCtx, IAddress address, DataRequestMonitor<LineInfo[]> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Functionality not supported", null)); //$NON-NLS-1$
rm.done();
}
/**
* {@inheritDoc}
* @since 1.1
*/
public void flushCache(IDMContext context) {
fModulesCache.reset();
}
}