/*******************************************************************************
 * Copyright (c) 2009, 2010 Nokia 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:
 * Nokia - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.debug.edc.services;

import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.edc.disassembler.CodeBufferUnderflowException;
import org.eclipse.cdt.debug.edc.disassembler.DisassembledInstruction;
import org.eclipse.cdt.debug.edc.disassembler.EDCInstruction;
import org.eclipse.cdt.debug.edc.disassembler.EDCInstructionFunctionInfo;
import org.eclipse.cdt.debug.edc.disassembler.EDCMixedInstruction;
import org.eclipse.cdt.debug.edc.disassembler.IDisassembledInstruction;
import org.eclipse.cdt.debug.edc.disassembler.IDisassembler;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.services.dsf.EDCServicesMessages;
import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
import org.eclipse.cdt.debug.edc.symbols.ILineEntry;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IDisassembly;
import org.eclipse.cdt.dsf.debug.service.IInstruction;
import org.eclipse.cdt.dsf.debug.service.IMemory;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.debug.service.IMixedInstruction;
import org.eclipse.cdt.dsf.debug.service.IModules;
import org.eclipse.cdt.dsf.debug.service.IModules.AddressRange;
import org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.model.MemoryByte;
import org.eclipse.tm.tcf.services.IMemory.MemoryError;


public class Disassembly extends AbstractEDCService implements IDisassembly {

	/**
	 * @param classNames
	 *            the type names the service will be registered under. See
	 *            AbstractDsfService#register for details. We tack on base DSF's
	 *            IDisassembly and this class to the list if not provided.
	 * @since 2.0
	 */
	public Disassembly(DsfSession session, String[] classNames) {
		super(session,
				massageClassNames(classNames, 
						new String[] { IDisassembly.class.getName(), Disassembly.class.getName() }));
	}

	/**
	 * @return IStatus.ERROR containing NLS string indicating disassembler not yet available
	 * @since 2.0
	 */
	public static IStatus statusNoDisassembler() {
		return new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
						  EDCServicesMessages.Disassembly_NoDisassemblerYet, null);
	}

	/**
	 * @param memoryAt 1st location of unreadable memory
	 * @param memoryLength length of unreadable memory
	 * @return IStatus.ERROR containing formatted message with location & length
	 */
	private static IStatus statusCannotReadMemory(String memoryAt, Integer memoryLength) {
		return new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
						  cantReadMemory(memoryAt, memoryLength.toString()), null);
	}

	/**
	 * string for use in both status for error return and in
	 * pseudo-instruction used in error recovery mode for disassembly view
	 * @param memoryAt 1st location of unreadable memory
	 * @param memoryLength length of unreadable memory (incoming null will "unknown" for length)
	 * @return formatted message with location & length
	 */
	private static String cantReadMemory(String memoryAt, String memoryLength) {
		memoryLength = (memoryLength == null) ? "unknown" : memoryLength;
		return MessageFormat.format(EDCServicesMessages.Disassembly_CannotReadMemoryAt,
									memoryAt, memoryLength);
	}

	/**
	 * check each byte of incoming MemoryByte[] array to see if readable;
	 * fills the RequestMonitor status in case of unreadable bytes.
	 * @param memBytes data to translate
	 * @param start address of first byte of memBytes
	 * @param rm with which to set status in case of error
	 * @return code buffer translated from incoming memByte array, null if any are unreadable
	 * @since 2.0
	 */
	public static ByteBuffer translateMemoryBytes(MemoryByte[] memBytes,
			IAddress start, RequestMonitor rm) {
		byte[] bytes = new byte[memBytes.length];
		for (int i = 0; i < memBytes.length; i++) {
			// check each byte
			if (!memBytes[i].isReadable()) {
				rm.setStatus(statusCannotReadMemory(start.add(i).toHexAddressString(), 
													memBytes.length-i));
				rm.done();
				return null;
			}
			bytes[i] = memBytes[i].getValue();
		}
		return ByteBuffer.wrap(bytes);
	}

	/**
	 * return a buffer of instruction code whose readability matches the
	 * first byte of the data for as long as all such bytes are the same
	 * @param memBytes data to translate
	 * @return a code buffer either full of readable bytes
	 * 		or empty representing the unreadable region
	 */
	@SuppressWarnings("null")	// memByte can't be null if memByteReadable is true
	private ByteBuffer translateMemoryBytes(List<MemoryByte> memBytes) {
		int count = 0;
		byte[] bytes = new byte[memBytes.size()];
		MemoryByte firstByte = memBytes.get(0);
		boolean firstIsReadable = firstByte != null && firstByte.isReadable();
		for (MemoryByte memByte : memBytes) {
			boolean memByteReadable = memByte != null && memByte.isReadable();
			// check each byte
			if (memByteReadable != firstIsReadable)
				break;
			bytes[count++] = memByteReadable ? memByte.getValue() : 0;		
		}

		return ByteBuffer.wrap(bytes, 0, count);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.debug.service.IDisassembly#getInstructions(org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.math.BigInteger, java.math.BigInteger, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
	 */
	public void getInstructions(final IDisassemblyDMContext context, BigInteger startAddress, BigInteger endAddress,
			final DataRequestMonitor<IInstruction[]> drm) {

		// FIXME: ignoring null startAddress and null endAddress semantics

		ITargetEnvironment env = getTargetEnvironmentService();
		final IDisassembler disassembler = (env != null) ? env.getDisassembler() : null;
		if (disassembler == null) {
			drm.setStatus(statusNoDisassembler());
			drm.done();
			return;
		}

		DsfServicesTracker services = getServicesTracker();
		if (services == null) // could be null if async invoked as or after debug session ends
			return;

		IMemory memoryService = services.getService(IMemory.class);
		if (memoryService == null) // could be null if async invoked as or after debug session ends
			return;

		final int size = endAddress.intValue() - startAddress.intValue() + 16;

		final IMemoryDMContext mem_dmc = DMContexts.getAncestorOfType(context, IMemoryDMContext.class);
		final IAddress start = new Addr64(startAddress);

		memoryService.getMemory(mem_dmc, start, 0, 1, size,
								new DataRequestMonitor<MemoryByte[]>(getExecutor(), drm) {
			/**
			 * overridden to create a non-error status plus pseudoInstruction data-set
			 * in the DRM requested by DisassemblyBackendDsf, where a DRM.status of
			 * ERROR is turned into an "invalid" block in its document map.  Such
			 * blocks are repeatedly re-requested ... causing scrolling oddities & performance issues.
			 * @see failedMemoryDsfPseudoInstructions
			 */
			@Override
			protected void handleError() {
				IStatus s = getStatus();
		    	Throwable e = s.getException();
		    	if (e instanceof MemoryError && s.getMessage().contains("Fail to read memory")) {
					drm.setData(failedMemoryDsfPseudoInstructions(start, size, s.getMessage()));
					drm.done();
				} else {
					super.handleError();
		        }
		        
		    }

		    @Override
			protected void handleSuccess() {
				List<MemoryByte> memBytes = Arrays.asList(getData());
				Map<String, Object> options = new HashMap<String, Object>();
				try {
					ArrayList<IInstruction> instrs
					  = fillDisassemblyViewInstructions(memBytes, start, context,
														disassembler, options);
					drm.setData(instrs.toArray(new IInstruction[instrs.size()]));
				} catch (CoreException e) {
					drm.setStatus(e.getStatus());
				}
				drm.done();
			}
		});

	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.debug.service.IDisassembly#getInstructions(org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.lang.String, int, int, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
	 */
	public void getInstructions(final IDisassemblyDMContext context, String filename, int linenum, final int lines,
			final DataRequestMonitor<IInstruction[]> drm) {

		// FIXME: ignoring "lines" semantics

		IModules modulesService = getServicesTracker().getService(IModules.class);

		ISymbolDMContext sym_dmc = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);

		filename = EDCLaunch.getLaunchForSession(getSession().getId()).getCompilationPath(filename);

		modulesService.calcAddressInfo(sym_dmc, filename, linenum, 0,
									   new DataRequestMonitor<AddressRange[]>(getExecutor(), drm) {
			@Override
			protected void handleSuccess() {
				AddressRange[] addr_ranges = getData();

				IAddress start = addr_ranges[0].getStartAddress();
				IAddress end = start.add(lines * 4); // kind of arbitrary end
														// address hint.

				getInstructions(context, start.getValue(), end.getValue(), drm);
			}
		});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.debug.service.IDisassembly#getMixedInstructions(org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.math.BigInteger, java.math.BigInteger, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
	 */
	public void getMixedInstructions(final IDisassemblyDMContext context, BigInteger startAddress, BigInteger endAddress,
			final DataRequestMonitor<IMixedInstruction[]> drm) {

		// FIXME: ignoring null startAddress and null endAddress semantics

		DsfServicesTracker services = getServicesTracker();
		if (services == null) // could be null if async invoked as or after debug session ends
			return;

		IEDCSymbols symbolsService = services.getService(IEDCSymbols.class);
		if (symbolsService == null) // could be null if async invoked as or after debug session ends
			return;

		IEDCModules modulesService = services.getService(IEDCModules.class);
		if (modulesService == null) // could be null if async invoked as or after debug session ends
			return;

		final ISymbolDMContext sym_dmc = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);

		// These are absolute runtime addresses.
		final IAddress end = new Addr64(endAddress);
		final IAddress start
		  = getStartAddressForLineEntryContainingAddress(symbolsService, modulesService, sym_dmc,
				  										 new Addr64(startAddress), end);

		ILineEntry startEntry = symbolsService.getLineEntryForAddress(sym_dmc, start);

		if (startEntry == null) {
			// startAddress has no source
			getInstructions(context, startAddress, endAddress,
							new DataRequestMonitor<IInstruction[]>(getExecutor(), drm) {
				@Override
				protected void handleSuccess() {
					IMixedInstruction[] ret = new IMixedInstruction[1];
					ret[0] = new EDCMixedInstruction("unknown", 0, getData()); //$NON-NLS-1$
					drm.setData(ret);
					drm.done();
				}
			});
		} else { // there is source for start address.

			final IEDCModuleDMContext module = modulesService.getModuleByAddress(sym_dmc, start);
			final List<ILineEntry> codeLines = symbolsService.getLineEntriesForAddressRange(sym_dmc, start, end);

			getInstructions(context, startAddress, endAddress,
							new DataRequestMonitor<IInstruction[]>(getExecutor(), drm) {
				@Override
				protected void handleSuccess() {
					List<IMixedInstruction> mixedInstructions = new ArrayList<IMixedInstruction>();

					mixSource(mixedInstructions, null, module, codeLines, getData());

					drm.setData(mixedInstructions.toArray(new IMixedInstruction[mixedInstructions.size()]));
					drm.done();
				}
			});
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.debug.service.IDisassembly#getMixedInstructions(org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.lang.String, int, int, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
	 */
	public void getMixedInstructions(final IDisassemblyDMContext context, String filename, final int linenum,
			final int lines, final DataRequestMonitor<IMixedInstruction[]> drm) {

		// FIXME: ignoring "lines" semantics

		final ITargetEnvironment env = getTargetEnvironmentService();
		final IDisassembler disassembler = (env != null) ? env.getDisassembler() : null;
		if (disassembler == null) {
			drm.setStatus(statusNoDisassembler());
			drm.done();
			return;
		}

		IModules modulesService = getServicesTracker().getService(IModules.class);

		ISymbolDMContext sym_dmc = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);

		filename = EDCLaunch.getLaunchForSession(getSession().getId()).getCompilationPath(filename);

		modulesService.calcAddressInfo(sym_dmc, filename, linenum, 0,
									   new DataRequestMonitor<AddressRange[]>(getExecutor(), drm) {
			@Override
			protected void handleSuccess() {
				AddressRange[] addr_ranges = getData();

				IAddress start = addr_ranges[0].getStartAddress();
				IAddress end = start.add(lines * 4); // kind of arbitrary end  address hint.
				getMixedInstructions(context, start.getValue(), end.getValue(), drm);
			}
		});
	}

	private static EDCInstruction pseudoInstruction(IAddress address, int size, String pseudoMnemonic) {
		DisassembledInstruction pseudoInstruction = new DisassembledInstruction();
		pseudoInstruction.setAddress(address);
		pseudoInstruction.setSize(size);
		pseudoInstruction.setMnemonics(pseudoMnemonic);
		return new EDCInstruction(pseudoInstruction);
	}

	/**
	 * used in failedMemoryDsfPseudoInstructions() below as chunk boundary for
	 * each of the pseudoInstructions in a larger chunk of retrieved memory.
	 */
	private static final int asmFence = 0x20;

	/**
	 * this utility function creates pseudo-mnemonics indicating failed memory
	 * read. it was refactored from memoryService.getMemory().handleError() so
	 * that it could be utilized by subclass override getInstructions() methods
	 * making the same memoryService.getMemory() call.
	 * <p>
	 * <i>background:</i>
	 * <p>
	 * as of 2010.oct.01, EDC memoryService no longer caches blocks of memory that
	 * cannot be read (a correct change, given that this was blocking the caching
	 * of good memory on the boundaries of such blocks, causing other problems).
	 * <p>
	 * when this change was made, Disassembly#fillDisassemblyViewInstructions()
	 * stopped getting reached through memoryService.getMemory().handleSuccess() .
	 * therefore, actual bad blocks of memory were not getting filled with pseudo
	 * mnemonics indicating bad memory .  in other words, when "Fail to read memory"
	 * errors from TCF caused invocation of memoryService.getMemory().handleFailure()
	 * ... and thus eventually also handleError() ... the result was that
	 * DsfBackendDisassembly would fill the DisassemblyDocument with "invalid"
	 * sections based upon address but no size.  it's algorithm then later attempts
	 * to fill any missing/invalid sections corresponding with the document.  this
	 * results in a visual anomaly where "Unable to retrieve disassembly" would be
	 * populated in the DisassemblyView one block at a time, until there would be a 
	 * large, mostly useless portion of the document view populated with the same
	 * message repeated once for every byte the user had attempted to scroll to.
	 * <p>
	 * the handleError() override implementations that call this utility function
	 * solve the problem whereby DisassemblyBackendDsf interprets DRM.status as
	 * "invalid" sections in its the DisassemblyDocument it is associated with.
	 * <p>
	 * the point of this re-factored code is to create "fences" on regular
	 * boundaries so that chunks of failed memory always get placed on similar
	 * boundaries, thus drastically ameliorating the occurrence of small "invalid"
	 * chunks in the DisassemblyDocument map between chunks of pseudoInstructions
	 * that DisassemblyBackendDsf considers "valid".
	 * <p>
	 * in user terms, this means that scrolling in the view is more consistent
	 * and even, with better performance thanks to fewer attempts to re-retrieve
	 * memory for small "invalid" sections in its map at the boundaries of
	 * previously inserted pseudo-instructions.
	 * 
	 * @param size size of the chunk to break up
	 * @param start location of memory chunk
	 * @param msg message from the target agent
	 * @return array containing 1 or more pseudo-instructions, mostly on asmFence boundaries
	 * @since 2.0
	 */
	protected static IInstruction[] failedMemoryDsfPseudoInstructions(
			IAddress start, final int size, String msg) {
		ArrayList<IInstruction> pseudoInstr = new ArrayList<IInstruction>();
		int offset = 0, chunkSize = Math.min(size, asmFence - start.getValue().intValue() % asmFence);
		do {
			pseudoInstr.add(pseudoInstruction(start.add(offset), chunkSize,
											  msg + "..[length=" + chunkSize + ']'));
			offset += chunkSize;
			chunkSize = Math.min(asmFence, size-offset);
		} while (offset < size);
		return pseudoInstr.toArray(new IInstruction[pseudoInstr.size()]);
	}

	/**
	 * Creates the array of instructions to be used to fill the disassembly view.
	 * for a range containing any unreadable instructions, it will create a
	 * fake instruction consisting of the address, the entire unreadable range,
	 * and a message to fill in the mnemonics section about the unreadable range.
	 * @param memBytes the buffer containing the bytes to be disassembled
	 * @param start starting address corresponding to the buffer
	 * @param context context for disassembly
	 * @param disassembler the disassembler object to use
	 * @param options to be passed to the disassembleInstructions() call
	 * @return array of IInstruction
	 * @throws CoreException can be thrown by disassembleInstructions().
	 * @since 2.0
	 */
	protected ArrayList<IInstruction> fillDisassemblyViewInstructions(
			final List<MemoryByte> memBytes, final IAddress start,
			final IDisassemblyDMContext context, final IDisassembler disassembler,
			Map<String, Object> options)
			throws CoreException {
		ArrayList<IInstruction> ret = new ArrayList<IInstruction>();
		for (int offset = 0, last = memBytes.size(); offset < last ;) {
			ByteBuffer codeBuf = translateMemoryBytes(memBytes.subList(offset, last));
			int codeBufSize = codeBuf.limit();
			IAddress block = start.add(offset);
			MemoryByte firstByte = memBytes.get(offset);
			if (firstByte != null && firstByte.isReadable()) {
				try {
					List<IDisassembledInstruction> insts
					  = disassembler.disassembleInstructions(block, block.add(codeBufSize),
							  								 codeBuf, options, context);
					if (insts.size() == 0)
						break;
					for (int i = 0; i < insts.size(); i++) {
						ret.add(new EDCInstruction(insts.get(i)));
						offset += insts.get(i).getSize();
					}
				} catch (CodeBufferUnderflowException e) {
					if (offset == 0 && codeBufSize == last) {
						// nothing in entire block can be disassembled;
						// at least tell the Disassembly view code this much
						ret.add(pseudoInstruction(start, codeBufSize,
												  "Buffer Underflow during disassembly")); //$NON-NLS-1$
					}
					offset += codeBufSize;
				}
			} else {	// this will only occur when the target supports partial bad blocks
				ret.add(pseudoInstruction(block, codeBufSize,
										  cantReadMemory(block.toHexAddressString(),
			  					   						 ((Integer)codeBufSize).toString())));
				offset += codeBufSize;
			}
		}
		return ret;
	}

	/**
	 * whereas the default implementation of getMixedInstructions() gets and
	 * processes all the disassembly in one pass, some variants are known to need
	 * to override the default implementation to break the retrieval into chunks.
	 * <p>
	 * this portion of the mixing is still the same within those chunks, though,
	 * and so has been extracted and protected for use by extending variant classes.
	 * @param mixedInstructions the growing list of instructions being processed
	 * @param wholeFunctionName name for whole function; if null, will be calculated per line
	 * @param module the module for this block of code
	 * @param codeLines list of ILineEntry containing info for mixing
	 * @param instructions the instructions to be mixed with the source
	 * @since 2.0
	 */
	protected void mixSource(List<IMixedInstruction> mixedInstructions,
			final EDCInstructionFunctionInfo wholeBlockInfo,
			final IEDCModuleDMContext module,
			final List<ILineEntry> codeLines,
			final IInstruction[] instructions) {

		List<IInstruction> instsForLine = new ArrayList<IInstruction>();

		IPath filePath = null;
		String osString = null;

		EDCInstructionFunctionInfo functionInfo = wholeBlockInfo;
		int k = 0, instsCnt = instructions.length, lineCnt = codeLines.size();
		for (int i = 0; i < lineCnt && k < instsCnt; i++) {
			// Now map the instructions to source lines to generate
			// MixedInstructions.
			instsForLine.clear();
			ILineEntry line = codeLines.get(i);

			if (wholeBlockInfo == null && module != null) {
				functionInfo = new EDCInstructionFunctionInfo(module, line);
			}

			while (k < instsCnt) {
				EDCInstruction inst = (EDCInstruction)instructions[k];
				IAddress linkAddress = module.toLinkAddress(new Addr64(inst.getAdress()));
				if (linkAddress.compareTo(line.getHighAddress()) >= 0)
					break;

				if (functionInfo != null) {
					inst.setFunctionName(functionInfo.getFunctionName());
					IAddress functionBase = functionInfo.getFunctionStartAddress();
					if (functionBase != null) {
						inst.setOffset(functionBase.distanceTo(linkAddress).intValue());
					}
				}
				instsForLine.add(inst);
				k++;
			}
			if (line.getFilePath() != filePath) {
				filePath = line.getFilePath();
				osString = (filePath != null) ? filePath.toOSString() : null;
			}
			mixedInstructions.add(new EDCMixedInstruction(osString, line.getLineNumber(),
								  						  instsForLine.toArray(new IInstruction[instsForLine.size()])));
		}
	}

	/**
	 * disassembly utility function to find the first address for a line-entry 
	 * for an address contained by that line-entry
	 * @param symbolsService
	 * @param modulesService
	 * @param sym_dmc symbol context used to retrieve LineEntry for address
	 * @param initialStartAddress the address of interest
	 * @param endAddress the last address of a range to search
	 * @return the first address of an associated LineEntry if it can be found, else the initialStartAddress
	 * @since 2.0
	 */
	protected static IAddress getStartAddressForLineEntryContainingAddress(final IEDCSymbols symbolsService,
			final IEDCModules modulesService, final ISymbolDMContext sym_dmc, final IAddress initialStartAddress,
			final IAddress endAddress) {
		assert symbolsService != null && modulesService != null;
		if (symbolsService == null || modulesService == null)
			return initialStartAddress;

		if (sym_dmc != null) {
			// in case the caller requested a start that falls somewhere other than the
			// boundary of an instruction, back up to that boundary for the first instruction
			if (symbolsService.getLineEntryForAddress(sym_dmc, initialStartAddress) != null) {
				IEDCModuleDMContext module = modulesService.getModuleByAddress(sym_dmc, initialStartAddress);
				if (module != null) {
					List<ILineEntry> allLines
					  = symbolsService.getLineEntriesForAddressRange(sym_dmc, initialStartAddress, endAddress);
					if (allLines != null && !allLines.isEmpty())
					{
						return module.toRuntimeAddress(allLines.get(0).getLowAddress());
					}
				}
			}
		}
		return initialStartAddress;
	}
}
