Bug 115786 - disassembly fails when disassembling into another C/C++ module
Summary: disassembly fails when disassembling into another C/C++ module
Status: NEW
Alias: None
Product: CDT
Classification: Tools
Component: cdt-debug (show other bugs)
Version: 3.0   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: cdt-debug-inbox@eclipse.org CLA
QA Contact: Jonah Graham CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-11-10 04:54 EST by Marcel Mettes CLA
Modified: 2020-09-04 15:20 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marcel Mettes CLA 2005-11-10 04:54:03 EST
1.The disassembly has a problem when disassembling into a consecutive
C module. It still uses the first C file.
2.Furthermore, if that first C file is shorter than the second one,
the view attempts to read beyond end-of-file.
----------------------------------------------------------------------
Here is the modified source to cope with these problems.
It's an adaptation from the CDT june-2005 release, class file
org.eclipse.cdt.debug.internal.core.model.DisassemblyBlock.java
----------------------------------------------------------------------
Here is the patch
----------------------------------------------------------------------
--- Disasorg.java	2005-11-10 10:40:45.915191000 +0100
+++ DisassemblyBlock-2-fixes.java	2005-11-10 10:40:07.900655000 +0100
@@ -136,50 +136,72 @@
 	private static IAsmSourceLine[] createSourceLines( IAddressFactory factory,
ISourceLocator locator, ICDIMixedInstruction[] mi ) {
 		IAsmSourceLine[] result = new IAsmSourceLine[mi.length];
 		LineNumberReader reader = null;
-		if ( result.length > 0 && locator != null ) {
-			String fileName = mi[0].getFileName();
-			Object element = null;
-			if ( locator instanceof ISourceLookupDirector ) {
-				element = ((ISourceLookupDirector)locator).getSourceElement( fileName );
-			}
-			if ( locator instanceof ICSourceLocator ) {
-				element = ((ICSourceLocator)locator).findSourceElement( fileName );
-			}
-			File file= null;
-			if ( element instanceof IFile ) {
-				file = ((IFile)element).getLocation().toFile();
-			}
-			else if ( element instanceof IStorage ) {
-				file = ((IStorage)element).getFullPath().toFile();
-			}
-			if ( file != null ) {
-				try {
-					reader = new LineNumberReader( new FileReader( file ) );
-				}
-				catch( FileNotFoundException e ) {
-				}				
-			}
-		}
-		for ( int i = 0; i < result.length; ++i ) {
-			String text = null;
-			if ( reader != null ) {
-				int lineNumber = mi[i].getLineNumber();
-				while( reader.getLineNumber() + 1 < lineNumber ) {
-					try {
-						reader.readLine();
+		
+		String prevFileName = "";
+		if ( result.length > 0 && locator != null ) 
+		{
+			for ( int i = 0; i < result.length; ++i ) {
+				String fileName = mi[i].getFileName();
+			
+				if (fileName != null && ! fileName.equals(prevFileName))
+				{
+					prevFileName = fileName;
+					
+					Object element = null;
+					
+					if ( locator instanceof ISourceLookupDirector ) 
+					{
+						element = ((ISourceLookupDirector)locator).getSourceElement( fileName );
+					}
+					if ( locator instanceof ICSourceLocator ) 
+					{
+						element = ((ICSourceLocator)locator).findSourceElement( fileName );
+					}
+					File file= null;
+					if ( element instanceof IFile ) 
+					{
+						file = ((IFile)element).getLocation().toFile();
+					}
+					else if ( element instanceof IStorage ) 
+					{
+						file = ((IStorage)element).getFullPath().toFile();
 					}
-					catch( IOException e ) {
+					if ( file != null ) 
+					{
+						try {
+							reader = new LineNumberReader( new FileReader( file ) );
+						}
+						catch( FileNotFoundException e ) {
+						}				
 					}
 				}
-				if ( reader.getLineNumber() + 1 == lineNumber ) {
-					try {
-						text = reader.readLine() + '\n';
+				
+				String text = null;
+				if ( reader != null ) 
+				{
+					int lineNumber = mi[i].getLineNumber();
+					while( reader.getLineNumber() + 1 < lineNumber ) {
+						try {
+							if (reader.readLine() == null)
+							{
+								// EOF
+								break;
+							}
+						}
+						catch( IOException e ) {
+						}
 					}
-					catch( IOException e ) {
+					if ( reader.getLineNumber() + 1 == lineNumber ) {
+						try {
+							text = reader.readLine() + '\n';
+						}
+						catch( IOException e ) {
+						}
 					}
 				}
+				
+				result[i] = new AsmSourceLine( factory, text, mi[i].getInstructions() );
 			}
-			result[i] = new AsmSourceLine( factory, text, mi[i].getInstructions() );
 		}
 		return result;
 	}
----------------------------------------------------------------------
Here is the complete source
----------------------------------------------------------------------
/**********************************************************************
 * Copyright (c) 2004 QNX Software Systems and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors: 
 * QNX Software Systems - Initial API and implementation
***********************************************************************/
package com.tasking.cdt.debug.internal.core.model;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.IAddressFactory;
import com.tasking.cdt.debug.core.cdi.model.ICDIInstruction;
import com.tasking.cdt.debug.core.cdi.model.ICDIMixedInstruction;
import com.tasking.cdt.debug.core.model.IAsmInstruction;
import com.tasking.cdt.debug.core.model.IAsmSourceLine;
import com.tasking.cdt.debug.core.model.ICStackFrame;
import com.tasking.cdt.debug.core.model.IDisassembly;
import com.tasking.cdt.debug.core.model.IDisassemblyBlock;
import com.tasking.cdt.debug.core.model.IExecFileInfo;
import com.tasking.cdt.debug.core.sourcelookup.ICSourceLocator;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;

/**
 * CDI-based implementation of <code>IDisassemblyBlock</code>.
 */
public class DisassemblyBlock implements IDisassemblyBlock, IAdaptable {

	private IDisassembly fDisassembly;
	
	private IAsmSourceLine[] fSourceLines;

	private IAddress fStartAddress = null;

	private IAddress fEndAddress = null;
	
	private boolean fMixedMode = false;

	/**
	 * Constructor for DisassemblyBlock.
	 */
	private DisassemblyBlock( IDisassembly disassembly ) {
		fDisassembly = disassembly;
	}

	public static DisassemblyBlock create( IDisassembly disassembly,
ICDIMixedInstruction[] instructions ) {
		DisassemblyBlock block = new DisassemblyBlock( disassembly );
		block.setMixedMode( true );
		ISourceLocator locator =
disassembly.getDebugTarget().getLaunch().getSourceLocator();
		IAddressFactory factory =
((CDebugTarget)disassembly.getDebugTarget()).getAddressFactory();
		block.setSourceLines( createSourceLines( factory, locator, instructions ) );
		block.initializeAddresses();
		return block;
	}

	public static DisassemblyBlock create( IDisassembly disassembly,
ICDIInstruction[] instructions ) {
		DisassemblyBlock block = new DisassemblyBlock( disassembly );
		IAddressFactory factory =
((CDebugTarget)disassembly.getDebugTarget()).getAddressFactory();
		block.setMixedMode( false );
		block.setSourceLines( createSourceLines( factory, instructions ) );
		block.initializeAddresses();
		return block;
	}

	/* (non-Javadoc)
	 * @see com.tasking.cdt.debug.core.model.IDisassemblyBlock#getDisassembly()
	 */
	public IDisassembly getDisassembly() {
		return fDisassembly;
	}

	/* (non-Javadoc)
	 * @see com.tasking.cdt.debug.core.model.IDisassemblyBlock#getModuleFile()
	 */
	public String getModuleFile() {
		IDisassembly d = getDisassembly();
		if ( d != null ) {
			IExecFileInfo info = (IExecFileInfo)d.getAdapter( IExecFileInfo.class );
			if ( info != null && info.getExecFile() != null ) {
				return info.getExecFile().getPath().toOSString();
			}
		}
		return ""; //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see
com.tasking.cdt.debug.core.model.IDisassemblyBlock#contains(com.tasking.cdt.debug.core.model.ICStackFrame)
	 */
	public boolean contains( ICStackFrame frame ) {
		if ( !getDisassembly().getDebugTarget().equals( frame.getDebugTarget() ) )
			return false;
		if ( fStartAddress == null || fEndAddress == null )
			return false;
		IAddress address = frame.getAddress();
		return (address.compareTo( fStartAddress ) >= 0 && address.compareTo(
fEndAddress ) <= 0);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.tasking.cdt.debug.core.model.IDisassemblyBlock#getSourceLines()
	 */
	public IAsmSourceLine[] getSourceLines() {
		return fSourceLines;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
	 */
	public Object getAdapter( Class adapter ) {
		return null;
	}

	/* (non-Javadoc)
	 * @see com.tasking.cdt.debug.core.model.IDisassemblyBlock#isMixedMode()
	 */
	public boolean isMixedMode() {
		return fMixedMode;
	}

	public void dispose() {
	}

	private static IAsmSourceLine[] createSourceLines( IAddressFactory factory,
ISourceLocator locator, ICDIMixedInstruction[] mi ) {
		IAsmSourceLine[] result = new IAsmSourceLine[mi.length];
		LineNumberReader reader = null;
		
		String prevFileName = "";
		if ( result.length > 0 && locator != null ) 
		{
			for ( int i = 0; i < result.length; ++i ) {
				String fileName = mi[i].getFileName();
			
				if (fileName != null && ! fileName.equals(prevFileName))
				{
					prevFileName = fileName;
					
					Object element = null;
					
					if ( locator instanceof ISourceLookupDirector ) 
					{
						element = ((ISourceLookupDirector)locator).getSourceElement( fileName );
					}
					if ( locator instanceof ICSourceLocator ) 
					{
						element = ((ICSourceLocator)locator).findSourceElement( fileName );
					}
					File file= null;
					if ( element instanceof IFile ) 
					{
						file = ((IFile)element).getLocation().toFile();
					}
					else if ( element instanceof IStorage ) 
					{
						file = ((IStorage)element).getFullPath().toFile();
					}
					if ( file != null ) 
					{
						try {
							reader = new LineNumberReader( new FileReader( file ) );
						}
						catch( FileNotFoundException e ) {
						}				
					}
				}
				
				String text = null;
				if ( reader != null ) 
				{
					int lineNumber = mi[i].getLineNumber();
					while( reader.getLineNumber() + 1 < lineNumber ) {
						try {
							if (reader.readLine() == null)
							{
								// EOF
								break;
							}
						}
						catch( IOException e ) {
						}
					}
					if ( reader.getLineNumber() + 1 == lineNumber ) {
						try {
							text = reader.readLine() + '\n';
						}
						catch( IOException e ) {
						}
					}
				}
				
				result[i] = new AsmSourceLine( factory, text, mi[i].getInstructions() );
			}
		}
		return result;
	}

	private static IAsmSourceLine[] createSourceLines( IAddressFactory factory,
ICDIInstruction[] instructions ) {
		return new IAsmSourceLine[] { new AsmSourceLine( factory, "", instructions )
}; //$NON-NLS-1$
	}

	private void initializeAddresses() {
		for ( int i = 0; i < fSourceLines.length; ++i ) {
			IAsmInstruction[] instr = fSourceLines[i].getInstructions();
			if ( instr.length > 0 ) {
				if ( fStartAddress == null )
					fStartAddress = instr[0].getAdress();
				fEndAddress = instr[instr.length - 1].getAdress();
			}
		}
	}

	private void setMixedMode( boolean mixedMode ) {
		this.fMixedMode = mixedMode;
	}

	private void setSourceLines( IAsmSourceLine[] sourceLines ) {
		this.fSourceLines = sourceLines;
	}
}
----------------------------------------------------------------------
Comment 1 Nobody - feel free to take it CLA 2005-11-10 16:22:00 EST
Can you please attach a small test case to reproduce this problem?
Comment 2 Marcel Mettes CLA 2005-11-11 07:19:11 EST
Unfortunately using gdb no test case can be produced.
The gdb/mi -data-disassemble command limits disassembly always to the current
module.

We are in the process of connecting our own debugger to
Eclipse, and our debugger produces the requested number of disassembly lines,
being 100, independent of whether the disassembled instructions still
belong to the same module as the first instructions.

The solution to our problem is to avoid delivering disassembly
across module boundaries, similar to what gdb/mi does.

If possible, the proposed source change is still useful,
since it allows disassembly to be shown from multiple
modules simultaneously in the disassembly view.

Thanks for replying.
(In reply to comment #1)
> Can you please attach a small test case to reproduce this problem?

Comment 3 Nobody - feel free to take it CLA 2005-11-11 10:29:51 EST
No problem. I can't apply the patch directly - the format is not good. But now 
I know exactly what the problem is, so it would be a problem to change the code.
Comment 4 Nobody - feel free to take it CLA 2005-11-11 15:35:30 EST
The patch is not correct. fSourecElement is not set and it affects the 
breakpoints set in the Disassembly view.
The current implementation is based on the assumption that a block is 
associated with a single source file which is not correct.
The getSourceElement method of IDisassemblyBlock needs to be changed to accept 
an address as an argument.
Comment 5 Nobody - feel free to take it CLA 2006-01-25 15:57:31 EST
Needs serious changes. Moving target milestone to 3.1.
Comment 6 Nobody - feel free to take it CLA 2006-05-25 11:17:58 EDT
Deferred.