public inbox for frysk@sourceware.org
 help / color / mirror / Atom feed
* [patch] disassembly window
@ 2007-08-17  8:47 Zhao Shujing
  2007-08-20  9:07 ` Zhao Shujing
  2007-08-20 13:32 ` Andrew Cagney
  0 siblings, 2 replies; 5+ messages in thread
From: Zhao Shujing @ 2007-08-17  8:47 UTC (permalink / raw)
  To: frysk

[-- Attachment #1: Type: text/plain, Size: 960 bytes --]

Hi

This patch is to fix bug #4932 and other bugs of disassembly window. 
rowPrepend is added to prepend rows by calculating memory information
like rowAppend. Because the methods that are provided by class
Disassembler, disassembleInstructions and
disassembleInstructionsStartEnd, can only read the instructions that are
following some address, rowPrepend have to use two while execution
control to read the instructions that are preceding some address.
Any suggestions are welcomed.

--ChangeLog--
2007-08-17  Zhao Shujing <pearly.zhao@oracle.com>

    *disassembler/DisassemblyWindow.java: fix bug #4932
	(fromBox.entryEvent): Use fromSpin.setValue to invoke fromSpin
entryEvent.
	(toBox.entryEvent): Ditto.
	(refreshList): Change to get next instruction after finishing model
setValue.
	(rowPrepend): Added.
	(handleFromSpin): Prepend rows provided by rowPrepend and remove
redundant instructions according to the change of memory address.


Cheers
Pearly

[-- Attachment #2: Type: text/x-patch, Size: 6951 bytes --]

Index: frysk-gui/frysk/gui/disassembler/DisassemblyWindow.java
===================================================================
RCS file: /cvs/frysk/frysk-gui/frysk/gui/disassembler/DisassemblyWindow.java,v
retrieving revision 1.29
diff -u -r1.29 DisassemblyWindow.java
--- frysk-gui/frysk/gui/disassembler/DisassemblyWindow.java	27 Jul 2007 21:07:22 -0000	1.29
+++ frysk-gui/frysk/gui/disassembler/DisassemblyWindow.java	17 Aug 2007 07:34:32 -0000
@@ -44,6 +44,7 @@
 import java.util.prefs.Preferences;
 import java.util.List;
 import java.util.Iterator;
+import java.util.ListIterator;
 import java.util.Observable;
 import java.util.Observer;
 
@@ -354,7 +355,15 @@
             try
             {
               double d = (double) Long.parseLong(str, 16);
-              handleFromSpin(d);
+              if (d < lastKnownFrom) 
+              {
+        	  if (lastKnownFrom == lastKnownTo)
+        	      handleToSpin(lastKnownFrom);
+        	  else
+        	      toSpin.setValue(lastKnownFrom);
+              }
+              else
+        	  toSpin.setValue(d);
             }
             catch (NumberFormatException nfe)
             {
@@ -377,7 +386,15 @@
               try
               {
                 double d = (double) Long.parseLong(str, 16);
-                handleToSpin(d);
+                if (d < lastKnownFrom) 
+                {
+                    if (lastKnownFrom == lastKnownTo)
+                	handleToSpin(lastKnownFrom);
+                    else
+                	toSpin.setValue(lastKnownFrom);
+                }
+                else
+                    toSpin.setValue(d);
               }
               catch (NumberFormatException nfe)
               {
@@ -537,22 +554,23 @@
             this.model.setValue(iter, (DataColumnString) cols[2], ins.instruction);
             
             this.pcOffset += ins.address;
-            
-            if (li.hasNext())
-              ins = (Instruction) li.next();
-            else
-              {
-                this.toSpin.setValue((double) ins.address);
-                this.toBox.setText(Long.toHexString(ins.address));
-                this.lastKnownTo = ins.address;
-                ins = null;
-              }
           }
         else
           this.model.setValue(iter, (DataColumnString) cols[1], "");
 
         this.model.setValue(iter, (DataColumnObject) cols[OBJ], ins);
         
+        
+        if (li.hasNext())
+            ins = (Instruction) li.next();
+        else
+        {
+            this.toSpin.setValue((double) ins.address);
+            this.toBox.setText(Long.toHexString(ins.address));
+            this.lastKnownTo = ins.address;
+            ins = null;        
+        }
+        
         iter = iter.getNextIter();
       }
     
@@ -568,7 +586,7 @@
   /**
    * Helper function for calculating memory information and putting it into rows
    * to be displayed.
-   * By default append rows to the end; occasionally prepend rows to the front.
+   * By default append rows to the end.
    * 
    * @param i   The address to be displayed
    * @param iter    The TreeIter representing the row to be added.
@@ -617,6 +635,70 @@
     this.lastKnownTo = ins.address;
   }
   
+  /**
+   * Helper function for calculating memory information and putting it into rows
+   * to be displayed.
+   * By default prepend rows to the front.
+   * 
+   * @param val   The address to be displayed
+   * @param nums   The numbers of rows to be prepend.
+   */
+  private synchronized void rowPrepend(long val, int addressAdded)
+  {
+      TreeIter iter = model.getFirstIter();
+      TreePath path = iter.getPath();
+      List instructionsList = diss.disassembleInstructions((long)(val-20), addressAdded+20);
+      ListIterator li = instructionsList.listIterator(0);
+      Instruction ins = (Instruction) li.next();
+      while (li.hasNext() && ins.address < lastKnownFrom)
+      {
+	  ins = (Instruction) li.next();
+	  if (ins.address == lastKnownFrom)
+	      break;
+	  
+      }
+      while (li.hasPrevious())
+      {
+	  if (ins.address < (long) val) {
+	      ins = (Instruction) li.next();
+	      break;
+	  }
+	  ins = (Instruction) li.previous();	 
+      }
+      if (addressAdded > 1) // if num==1, it should fetch the previous instruction
+	  ins = (Instruction) li.next();
+      
+      long newlastFrom = ins.address;
+      
+      while (ins != null && ins.address < lastKnownFrom) {
+	  iter = model.insertRowBefore(model.getIter(path));
+	  this.lastPath.next();
+	  if (ins != null) {
+	      model.setValue(iter, (DataColumnString) cols[1], "<pc+"
+		      + (ins.address - this.pc) + ">: ");
+	      model.setValue(iter, (DataColumnString) cols[LOC], "0x"
+		      + Long.toHexString(ins.address));
+	      model.setValue(iter, (DataColumnString) cols[2],
+		      ins.instruction);
+	      model.setValue(iter, (DataColumnObject) cols[3], ins);
+	      this.numInstructions++;		  
+	      if (li.hasNext()) {
+		  ins = (Instruction) li.next();
+		  path.next();
+	      }
+	      else
+		  ins = null;
+	    }
+	  else
+	      model.setValue(iter, (DataColumnString) cols[1], "");
+	  
+      }
+
+      this.lastKnownFrom = newlastFrom;
+      this.fromSpin.setValue((double) newlastFrom);
+      this.fromBox.setText(Long.toHexString(newlastFrom));
+  }
+  
   private void desensitize ()
   {
     this.disassemblerView.setSensitive(false);
@@ -661,28 +743,38 @@
 
     if (val > this.lastKnownFrom)
       {
-        TreeIter iter = model.getFirstIter();
-
-        for (int i = (int) lastKnownFrom; i < (int) val; i++)
-          {
-            this.numInstructions--;
-            model.removeRow(iter);
-            iter = iter.getNextIter();
-          }
+	if (this.numInstructions < 1)
+            return;
+        
+	TreeIter iter = model.getFirstIter();
+	Instruction ins = (Instruction) this.model.getValue(iter, (DataColumnObject) cols[OBJ]);
+	//--this.numInstructions;
+        
+	while (ins != null && ins.address < val)
+	{
+	    this.model.removeRow(iter);
+	    this.lastPath.previous();
+	    ins = (Instruction) this.model.getValue(iter,(DataColumnObject) cols[OBJ]);
+	    --this.numInstructions;
+	}
+	if (ins == null)
+	    return;
+
+	this.lastKnownFrom = ins.address;
+	this.fromBox.setText(Long.toHexString(ins.address));
+	this.fromSpin.setValue((double)ins.address);
+	refreshList();
+	return;
       }
     else
       {
-        for (long i = (long) val; i < lastKnownFrom; i++)
-          {
-            this.numInstructions++;
-            model.prependRow();
-          }
+	int addressAdded = 0;
+	for (long i = (long)lastKnownFrom; i > (long)val; i--)
+	    addressAdded++;
+	if (addressAdded == 0)
+	    return;
+	rowPrepend((long)val, addressAdded);
       }
-    
-    this.fromSpin.setValue(val);
-    this.lastKnownFrom = val;
-    this.fromBox.setText(Long.toHexString((long) val));
-    refreshList();
   }
 
   boolean toToggle = false;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] disassembly window
  2007-08-17  8:47 [patch] disassembly window Zhao Shujing
@ 2007-08-20  9:07 ` Zhao Shujing
  2007-08-20 13:32 ` Andrew Cagney
  1 sibling, 0 replies; 5+ messages in thread
From: Zhao Shujing @ 2007-08-20  9:07 UTC (permalink / raw)
  To: frysk

[-- Attachment #1: Type: text/plain, Size: 1205 bytes --]

Sorry, I make a mistake with fromBox.entryEvent to use the same code
with toBox.entryEvent at the last patch. It is fixed at this one. 
On Fri, 2007-08-17 at 16:50 +0800, Zhao Shujing wrote:
> Hi
> 
> This patch is to fix bug #4932 and other bugs of disassembly window. 
> rowPrepend is added to prepend rows by calculating memory information
> like rowAppend. Because the methods that are provided by class
> Disassembler, disassembleInstructions and
> disassembleInstructionsStartEnd, can only read the instructions that are
> following some address, rowPrepend have to use two while execution
> control to read the instructions that are preceding some address.
> Any suggestions are welcomed.
> 
> --ChangeLog--
> 2007-08-17  Zhao Shujing <pearly.zhao@oracle.com>
> 
>     *disassembler/DisassemblyWindow.java: fix bug #4932
> 	(fromBox.entryEvent): Use fromSpin.setValue to invoke fromSpin
> entryEvent.
> 	(toBox.entryEvent): Ditto.
> 	(refreshList): Change to get next instruction after finishing model
> setValue.
> 	(rowPrepend): Added.
> 	(handleFromSpin): Prepend rows provided by rowPrepend and remove
> redundant instructions according to the change of memory address.
> 
> 
> Cheers
> Pearly

[-- Attachment #2: Type: text/x-patch, Size: 6920 bytes --]

Index: frysk/gui/disassembler/DisassemblyWindow.java
===================================================================
RCS file: /cvs/frysk/frysk-gui/frysk/gui/disassembler/DisassemblyWindow.java,v
retrieving revision 1.29
diff -u -r1.29 DisassemblyWindow.java
--- frysk/gui/disassembler/DisassemblyWindow.java	27 Jul 2007 21:07:22 -0000	1.29
+++ frysk/gui/disassembler/DisassemblyWindow.java	20 Aug 2007 08:56:51 -0000
@@ -44,6 +44,7 @@
 import java.util.prefs.Preferences;
 import java.util.List;
 import java.util.Iterator;
+import java.util.ListIterator;
 import java.util.Observable;
 import java.util.Observer;
 
@@ -354,7 +355,15 @@
             try
             {
               double d = (double) Long.parseLong(str, 16);
-              handleFromSpin(d);
+              if (d > lastKnownTo)
+              {
+        	  if (lastKnownTo == lastKnownFrom)
+        	      handleFromSpin(lastKnownTo);
+        	  else
+        	      fromSpin.setValue(lastKnownTo);
+              }
+              else
+        	  fromSpin.setValue(d);
             }
             catch (NumberFormatException nfe)
             {
@@ -377,7 +386,15 @@
               try
               {
                 double d = (double) Long.parseLong(str, 16);
-                handleToSpin(d);
+                if (d < lastKnownFrom) 
+                {
+                    if (lastKnownFrom == lastKnownTo)
+                	handleToSpin(lastKnownFrom);
+                    else
+                	toSpin.setValue(lastKnownFrom);
+                }
+                else
+                    toSpin.setValue(d);
               }
               catch (NumberFormatException nfe)
               {
@@ -537,22 +554,23 @@
             this.model.setValue(iter, (DataColumnString) cols[2], ins.instruction);
             
             this.pcOffset += ins.address;
-            
-            if (li.hasNext())
-              ins = (Instruction) li.next();
-            else
-              {
-                this.toSpin.setValue((double) ins.address);
-                this.toBox.setText(Long.toHexString(ins.address));
-                this.lastKnownTo = ins.address;
-                ins = null;
-              }
           }
         else
           this.model.setValue(iter, (DataColumnString) cols[1], "");
 
         this.model.setValue(iter, (DataColumnObject) cols[OBJ], ins);
         
+        
+        if (li.hasNext())
+            ins = (Instruction) li.next();
+        else
+        {
+            this.toSpin.setValue((double) ins.address);
+            this.toBox.setText(Long.toHexString(ins.address));
+            this.lastKnownTo = ins.address;
+            ins = null;        
+        }
+        
         iter = iter.getNextIter();
       }
     
@@ -568,7 +586,7 @@
   /**
    * Helper function for calculating memory information and putting it into rows
    * to be displayed.
-   * By default append rows to the end; occasionally prepend rows to the front.
+   * By default append rows to the end.
    * 
    * @param i   The address to be displayed
    * @param iter    The TreeIter representing the row to be added.
@@ -617,6 +635,70 @@
     this.lastKnownTo = ins.address;
   }
   
+  /**
+   * Helper function for calculating memory information and putting it into rows
+   * to be displayed.
+   * By default prepend rows to the front.
+   * 
+   * @param val   The address to be displayed
+   * @param nums   The numbers of rows to be prepend.
+   */
+  private synchronized void rowPrepend(long val, int addressAdded)
+  {
+      TreeIter iter = model.getFirstIter();
+      TreePath path = iter.getPath();
+      List instructionsList = diss.disassembleInstructions((long)(val-20), addressAdded+20);
+      ListIterator li = instructionsList.listIterator(0);
+      Instruction ins = (Instruction) li.next();
+      while (li.hasNext() && ins.address < lastKnownFrom)
+      {
+	  ins = (Instruction) li.next();
+	  if (ins.address == lastKnownFrom)
+	      break;
+	  
+      }
+      while (li.hasPrevious())
+      {
+	  if (ins.address < (long) val) {
+	      ins = (Instruction) li.next();
+	      break;
+	  }
+	  ins = (Instruction) li.previous();	 
+      }
+      if (addressAdded > 1) // if num==1, it should fetch the previous instruction
+	  ins = (Instruction) li.next();
+      
+      long newlastFrom = ins.address;
+      
+      while (ins != null && ins.address < lastKnownFrom) {
+	  iter = model.insertRowBefore(model.getIter(path));
+	  this.lastPath.next();
+	  if (ins != null) {
+	      model.setValue(iter, (DataColumnString) cols[1], "<pc+"
+		      + (ins.address - this.pc) + ">: ");
+	      model.setValue(iter, (DataColumnString) cols[LOC], "0x"
+		      + Long.toHexString(ins.address));
+	      model.setValue(iter, (DataColumnString) cols[2],
+		      ins.instruction);
+	      model.setValue(iter, (DataColumnObject) cols[3], ins);
+	      this.numInstructions++;		  
+	      if (li.hasNext()) {
+		  ins = (Instruction) li.next();
+		  path.next();
+	      }
+	      else
+		  ins = null;
+	    }
+	  else
+	      model.setValue(iter, (DataColumnString) cols[1], "");
+	  
+      }
+
+      this.lastKnownFrom = newlastFrom;
+      this.fromSpin.setValue((double) newlastFrom);
+      this.fromBox.setText(Long.toHexString(newlastFrom));
+  }
+  
   private void desensitize ()
   {
     this.disassemblerView.setSensitive(false);
@@ -661,28 +743,38 @@
 
     if (val > this.lastKnownFrom)
       {
-        TreeIter iter = model.getFirstIter();
-
-        for (int i = (int) lastKnownFrom; i < (int) val; i++)
-          {
-            this.numInstructions--;
-            model.removeRow(iter);
-            iter = iter.getNextIter();
-          }
+	if (this.numInstructions < 1)
+            return;
+        
+	TreeIter iter = model.getFirstIter();
+	Instruction ins = (Instruction) this.model.getValue(iter, (DataColumnObject) cols[OBJ]);
+	//--this.numInstructions;
+        
+	while (ins != null && ins.address < val)
+	{
+	    this.model.removeRow(iter);
+	    this.lastPath.previous();
+	    ins = (Instruction) this.model.getValue(iter,(DataColumnObject) cols[OBJ]);
+	    --this.numInstructions;
+	}
+	if (ins == null)
+	    return;
+
+	this.lastKnownFrom = ins.address;
+	this.fromBox.setText(Long.toHexString(ins.address));
+	this.fromSpin.setValue((double)ins.address);
+	refreshList();
+	return;
       }
     else
       {
-        for (long i = (long) val; i < lastKnownFrom; i++)
-          {
-            this.numInstructions++;
-            model.prependRow();
-          }
+	int addressAdded = 0;
+	for (long i = (long)lastKnownFrom; i > (long)val; i--)
+	    addressAdded++;
+	if (addressAdded == 0)
+	    return;
+	rowPrepend((long)val, addressAdded);
       }
-    
-    this.fromSpin.setValue(val);
-    this.lastKnownFrom = val;
-    this.fromBox.setText(Long.toHexString((long) val));
-    refreshList();
   }
 
   boolean toToggle = false;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] disassembly window
  2007-08-17  8:47 [patch] disassembly window Zhao Shujing
  2007-08-20  9:07 ` Zhao Shujing
@ 2007-08-20 13:32 ` Andrew Cagney
  2007-08-22  9:14   ` Zhao Shujing
  1 sibling, 1 reply; 5+ messages in thread
From: Andrew Cagney @ 2007-08-20 13:32 UTC (permalink / raw)
  To: pearly.zhao; +Cc: frysk

Zhao Shujing wrote:
> Hi
>
> This patch is to fix bug #4932 and other bugs of disassembly window. 
> rowPrepend is added to prepend rows by calculating memory information
> like rowAppend. Because the methods that are provided by class
> Disassembler, disassembleInstructions and
> disassembleInstructionsStartEnd, can only read the instructions that are
> following some address, rowPrepend have to use two while execution
> control to read the instructions that are preceding some address.
> Any suggestions are welcomed.
>   

Pearly, nice work.

The challenge here, and the reason why the disassembler only goes 
forward from PC is that, in general, it isn't possible to disassemble 
backwards.  This is because architectures such as the i386 and x86-64 
have variable length instructions making it effectively impossible to 
figure out where, looking backwards, an instruction starts.  For 
instance, looking backwards is that a one byte int80 instruction, or a 
multi-byte instruction loading the hex code for int80?

For disassembling a range, can I suggest doing something similar to the 
disassembler command in frysk.hpd.DisassemblerCommand.  That code first 
attempts to fetch the frysk.symtab.Symbol at the frame's 
adjusted-address and then uses its address/size to determine the start 
address and size to disassemble.  If the symbol isn't available, then 
I'd just disassemble a small range from the frame's PC.

One heads up for you; you may want to consider configuring your personal 
build with --with-libopcodes.

Andrew

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] disassembly window
  2007-08-20 13:32 ` Andrew Cagney
@ 2007-08-22  9:14   ` Zhao Shujing
  2007-08-22 13:09     ` Andrew Cagney
  0 siblings, 1 reply; 5+ messages in thread
From: Zhao Shujing @ 2007-08-22  9:14 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: frysk

Hi, Andrew
Thanks for the explanation of disassemble backwards.

If the symbol isn't available, gdb's disassemble command would return
"No function contains specified address". Would frysk's disassemble
command disassemble a small range from the frame's PC, not just return
some warning sentence?

Thanks
Pearly
On Mon, 2007-08-20 at 09:32 -0400, Andrew Cagney wrote:
> Zhao Shujing wrote:
> > Hi
> >
> > This patch is to fix bug #4932 and other bugs of disassembly window. 
> > rowPrepend is added to prepend rows by calculating memory information
> > like rowAppend. Because the methods that are provided by class
> > Disassembler, disassembleInstructions and
> > disassembleInstructionsStartEnd, can only read the instructions that are
> > following some address, rowPrepend have to use two while execution
> > control to read the instructions that are preceding some address.
> > Any suggestions are welcomed.
> >   
> 
> Pearly, nice work.
> 
> The challenge here, and the reason why the disassembler only goes 
> forward from PC is that, in general, it isn't possible to disassemble 
> backwards.  This is because architectures such as the i386 and x86-64 
> have variable length instructions making it effectively impossible to 
> figure out where, looking backwards, an instruction starts.  For 
> instance, looking backwards is that a one byte int80 instruction, or a 
> multi-byte instruction loading the hex code for int80?
> 
> For disassembling a range, can I suggest doing something similar to the 
> disassembler command in frysk.hpd.DisassemblerCommand.  That code first 
> attempts to fetch the frysk.symtab.Symbol at the frame's 
> adjusted-address and then uses its address/size to determine the start 
> address and size to disassemble.  If the symbol isn't available, then 
> I'd just disassemble a small range from the frame's PC.
> 
> One heads up for you; you may want to consider configuring your personal 
> build with --with-libopcodes.
> 
> Andrew
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] disassembly window
  2007-08-22  9:14   ` Zhao Shujing
@ 2007-08-22 13:09     ` Andrew Cagney
  0 siblings, 0 replies; 5+ messages in thread
From: Andrew Cagney @ 2007-08-22 13:09 UTC (permalink / raw)
  To: pearly.zhao; +Cc: frysk

Zhao Shujing wrote:
> Hi, Andrew
> Thanks for the explanation of disassemble backwards.
>
> If the symbol isn't available, gdb's disassemble command would return
> "No function contains specified address". Would frysk's disassemble
> command disassemble a small range from the frame's PC, not just return
> some warning sentence?
>   
Pearly,

yes, the command-line will still disassemble.  And I like the idea of 
the disassembler-window can do something similar.

Andrew

> Thanks
> Pearly
> On Mon, 2007-08-20 at 09:32 -0400, Andrew Cagney wrote:
>   
>> Zhao Shujing wrote:
>>     
>>> Hi
>>>
>>> This patch is to fix bug #4932 and other bugs of disassembly window. 
>>> rowPrepend is added to prepend rows by calculating memory information
>>> like rowAppend. Because the methods that are provided by class
>>> Disassembler, disassembleInstructions and
>>> disassembleInstructionsStartEnd, can only read the instructions that are
>>> following some address, rowPrepend have to use two while execution
>>> control to read the instructions that are preceding some address.
>>> Any suggestions are welcomed.
>>>   
>>>       
>> Pearly, nice work.
>>
>> The challenge here, and the reason why the disassembler only goes 
>> forward from PC is that, in general, it isn't possible to disassemble 
>> backwards.  This is because architectures such as the i386 and x86-64 
>> have variable length instructions making it effectively impossible to 
>> figure out where, looking backwards, an instruction starts.  For 
>> instance, looking backwards is that a one byte int80 instruction, or a 
>> multi-byte instruction loading the hex code for int80?
>>
>> For disassembling a range, can I suggest doing something similar to the 
>> disassembler command in frysk.hpd.DisassemblerCommand.  That code first 
>> attempts to fetch the frysk.symtab.Symbol at the frame's 
>> adjusted-address and then uses its address/size to determine the start 
>> address and size to disassemble.  If the symbol isn't available, then 
>> I'd just disassemble a small range from the frame's PC.
>>
>> One heads up for you; you may want to consider configuring your personal 
>> build with --with-libopcodes.
>>
>> Andrew
>>
>>     
>
>
>   

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-08-22 13:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-17  8:47 [patch] disassembly window Zhao Shujing
2007-08-20  9:07 ` Zhao Shujing
2007-08-20 13:32 ` Andrew Cagney
2007-08-22  9:14   ` Zhao Shujing
2007-08-22 13:09     ` Andrew Cagney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).