This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] Disassembly improvements


On 10/11/2013 05:45 PM, Abid, Hafiz wrote:
> 
>>> But it seems to me that will just disable the optimization for buffer
>>> line > 1.
>>>
>>> LEN here I think will the disassembler considers to be the maximum
>>> length of an instruction for the arquitecture it is disassembling.
>>> We want to read _more_ than that from memory in one go, otherwise,
>>> we'll not be buffering anything.  What we do not want, is for that
>>> over fetching to read beyond the range that was passed to
>> gdb_disassembly.
> We come in the else case only if we have exhausted the initial buffer allocated
> in gdb_disassembly. You are right that current code will read LEN bytes in that case
> instead of reading the larger buffer but I think that should not be very common and
> we don't lose the optimization gained from the buffering for the first ' DIS_BUF_SIZE'
> bytes. So I think this patch is useful on its own and the other enhancement can be built
> on top of it.

But then that makes for a sort of a half baked implementation.

I just tried "disassemble main" against gdbserver, and I got more than
DIS_BUF_SIZE...  Enough for 3 buffer fetches actually.  I think it'll
be quite common to overflow DIS_BUF_SIZE, and it's worth it to re-fill
the buffer properly.

> Also if user provides a range of address to the disassembly command then it is possible that
> end address is in the middle of the instruction and gdb will end up reading beyond the end
> address given in the command. So we probably cannot forbid that here anyway.

Yes, but while it's still passable to assume a few instructions
off of the requested range are still text/code, it's not so
safe if we try to read much beyond that.

I still think that it's worth it from a correctness perspective to
not make GDB worse than what it is today.  Arguably that libopcodes
behavior could be changed, (or fixed, depending on perspective),
though it may be a bunch of work.

>>> I think we'll need to derive from "struct disassemble_info", and add
>>> the original range to that new struct, or record that info directly in
>>> "struct disassemble_info", which is in include/dis-asm.h.
>>
>> I now noticed there's a struct disassemble_info->application_data field,
>> which GDB currently uses to put the gdbarch in.  We could put a disasm.c
>> specific structure there instead.
> I noticed that this field is already being used in spu-tdep.c. Any changes
> to it will break that code. 

This shows that extending the struct is a better approach than a
void * field that is part of the structure.  With the "subclass"
approach, we can have multiple layers each stacking their own
data, and they'll all be happy.  With a single void* field, we'd
need to add coupling between the layers to sort that out.

I took a stab at it.  I ended up touching other things too, and
reworking some of the comments.  The patch below is the result.

Tested on x86_64 Fedora 17, native and gdbserver,
and also built with --enable-targets=all.

Manually debugging against gdbserver, enabling "set debug
remote", and trying out "disassemble" commands, I can see
the optimization triggering as expected.

Before:

(gdb) set debug remote 1
(gdb) disassemble main
Dump of assembler code for function main:
Sending packet: $m410766,1#02...Packet received: 55
   0x0000000000410766 <+0>:     push   %rbp
Sending packet: $m410767,1#03...Packet received: 48
Sending packet: $m410768,1#04...Packet received: 89
Sending packet: $m410769,1#05...Packet received: e5
   0x0000000000410767 <+1>:     mov    %rsp,%rbp
Sending packet: $m41076a,1#2d...Packet received: 53
   0x000000000041076a <+4>:     push   %rbx
Sending packet: $m41076b,1#2e...Packet received: 48
Sending packet: $m41076c,1#2f...Packet received: 83
Sending packet: $m41076d,1#30...Packet received: ec
Sending packet: $m41076e,1#31...Packet received: 68
   0x000000000041076b <+5>:     sub    $0x68,%rsp
Sending packet: $m41076f,1#32...Packet received: 89
Sending packet: $m410770,1#fd...Packet received: 7d
Sending packet: $m410771,1#fe...Packet received: 9c
   0x000000000041076f <+9>:     mov    %edi,-0x64(%rbp)
Sending packet: $m410772,1#ff...Packet received: 48
Sending packet: $m410773,1#00...Packet received: 89
Sending packet: $m410774,1#01...Packet received: 75
Sending packet: $m410775,1#02...Packet received: 90
   0x0000000000410772 <+12>:    mov    %rsi,-0x70(%rbp)
Sending packet: $m410776,1#03...Packet received: 48
Sending packet: $m410777,1#04...Packet received: 8b
Sending packet: $m410778,1#05...Packet received: 45
Sending packet: $m410779,1#06...Packet received: 90
=> 0x0000000000410776 <+16>:    mov    -0x70(%rbp),%rax
Sending packet: $m41077a,1#2e...Packet received: 48
Sending packet: $m41077b,1#2f...Packet received: 83
Sending packet: $m41077c,1#30...Packet received: c0
Sending packet: $m41077d,1#31...Packet received: 08
   0x000000000041077a <+20>:    add    $0x8,%rax
Sending packet: $m41077e,1#32...Packet received: 48
Sending packet: $m41077f,1#33...Packet received: 89
Sending packet: $m410780,1#fe...Packet received: 45
Sending packet: $m410781,1#ff...Packet received: e0
   0x000000000041077e <+24>:    mov    %rax,-0x20(%rbp)
Sending packet: $m410782,1#00...Packet received: c7
Sending packet: $m410783,1#01...Packet received: 45
Sending packet: $m410784,1#02...Packet received: a4
Sending packet: $m410785,4#06...Packet received: 00000000
   0x0000000000410782 <+28>:    movl   $0x0,-0x5c(%rbp)
Sending packet: $m410789,1#07...Packet received: c7
Sending packet: $m41078a,1#2f...Packet received: 45
Sending packet: $m41078b,1#30...Packet received: a0
Sending packet: $m41078c,4#34...Packet received: 00000000
   0x0000000000410789 <+35>:    movl   $0x0,-0x60(%rbp)
Sending packet: $m410790,1#ff...Packet received: e9
Sending packet: $m410791,4#03...Packet received: f5030000
   0x0000000000410790 <+42>:    jmpq   0x410b8a <main+1060>
... many more ...


After:

(gdb) disassemble main
Dump of assembler code for function main:
Sending packet: $m410766,400#65...Packet received: 554889e5534883ec68897d9c48897590488b45904883c008488945e0c745a400000000c745a000000000e9f5030000488b45e0488b00be2fd943004889c7e8471effff85c0750fe895fcffffbf00000000e8d421ffff488b45e0488b00be39d943004889c7e8201effff85c07519488b0525a624004889c7e888fcffffbf00000000e8a321ffff488b45e0488b00be40d943004889c7e8ef1dffff85c0750cc745a001000000e973030000488b45e0488b00be49d943004889c7e8cb1dffff85c0750cc745a401000000e94f030000488b45e0488b00be51d943004889c7e8a71dffff85c0757d488345e008488b45e04889055bc62400eb05488345e008488b45e0488b004885c07418488b45e0488b00be5bd943004889c7e86c1dffff85c075d7488b0529c62400483945e0740c488b45e0488b004885c07519488b0568a524004889c7e8bbfbffffbf01000000e8d620ffff488b45e048c70000000000e9ba020000488b45e0488b00be5ed943004889c7e8121dffff85c0750fc70564d5240001000000e993020000488b45e0488b00be66d943004889c7e8eb1cffff85c0750fc7054da5240001000000e96c020000488b45e0488b00be75d943004889c7e8c41cffff85c07519488b05c9a424004889c7e8!
 86fbffffbf
00000000e84720ffff488b45e0488b00ba11000000be86d943004889c7e8be19ffff85c00f855c010000488b45e0488b00488d5011488b45e0488910488b45e0488b00488945c0488b45c0be98d943004889c7e8081fffff488945d0e915010000488b45d04889c6bf9ad94300e83e1cffff85c0750fc70544da240001000000e9de000000488b45d04889c6bfa0d94300e81a1cffff85c0750fc7056cda240001000000e9ba000000488b45d04889c6bf35d34300e8f61bffff85c0750fc705f4d9240001000000e996000000488b45d04889c6bf42d34300e8d21bffff85c0750cc70520d4240001000000eb75488b45d04889c6bf39d24300e8b11bffff85c0752ac705b7d9240001000000c705f9d9240001000000c7059bd9240001000000c705e1d3240001000000eb36488b059ca32400488b55d0bea8d943004889c7b800000000e8961bffff488b057fa324004889c7e82cfaffffbf01000000e8ed1effffbe98d94300bf00000000e8ee1dffff488945d048837dd0000f85e0feffffe9be000000488b45e0488b00becad943004889c7e8161bffff85c07510488b45e048c700ccd94300e9ba000000488b45e0488b00bed2d943004889c7e8ee1affff85c0750cc705107d240001000000eb72488b45e0488b00beead943004889c7e8ca1affff85c0750cc705ec7c2!
 4000000000
0eb4e488b45e0488b00be05da43004889c7e8a61affff85c0750cc705e8d2240001000000eb2a488b45e0488b10488b05a8a2
   0x0000000000410766 <+0>:     push   %rbp
   0x0000000000410767 <+1>:     mov    %rsp,%rbp
   0x000000000041076a <+4>:     push   %rbx
   0x000000000041076b <+5>:     sub    $0x68,%rsp
   0x000000000041076f <+9>:     mov    %edi,-0x64(%rbp)
   0x0000000000410772 <+12>:    mov    %rsi,-0x70(%rbp)
=> 0x0000000000410776 <+16>:    mov    -0x70(%rbp),%rax
   0x000000000041077a <+20>:    add    $0x8,%rax
   0x000000000041077e <+24>:    mov    %rax,-0x20(%rbp)
   0x0000000000410782 <+28>:    movl   $0x0,-0x5c(%rbp)
   0x0000000000410789 <+35>:    movl   $0x0,-0x60(%rbp)
   0x0000000000410790 <+42>:    jmpq   0x410b8a <main+1060>
... lots more insns printed before the next fetch ...
   0x0000000000410b5e <+1016>:  mov    (%rax),%rdx
Sending packet: $m410b66,400#90...Packet received: 2400be0cda43004889c7b800000000e8a61affffbf01000000e80c1effff488345e00890488b45e0488b004885c07412488b45e0488b000fb6003c2d0f84edfbffffbf60de6500e81e1affff85c07428488b0553a224004889c1ba08000000be01000000bf22da4300e8dc1dffffbf01000000e8b21dffff488b45e0488b00488945b8488345e00848837db800741a8b45a085c0752c8b45a485c07525488b45e0488b004885c07519488b05faa124004889c7e84df8ffffbf01000000e8681dffffe8272a0100488b45b84889c7e81a6bffffc745ec00000000c745e800000000488b45e0488b004885c07424488b45e0488b00be40d943004889c7e88919ffff85c0750cc745a001000000488345e0088b45a085c07460488b45e0488b004885c0744d488b45e0488b000fb60084c0743f488b45e0488b00488d4da8ba000000004889ce4889c7e83d1cffff8945e8837de800741b488b45a80fb60084c07510488b45e04883c008488b004885c07407c745ec01000000837dec007419488b0525a124004889c7e878f7ffffbf01000000e8931cffffe8f77cffffb800000000e8d0dc0100e8ee690000488b0548d72400488b80200100004885c07419488b0535d72400488b8020010000ffd085c07405e87509!
 0100bf0140
0000e8990b0100488905aac12400bf00400000e8880b0100488905a1c12400837de8000f85c4000000488b45e0488b004885c00f84b40000008b559c488b4de0488b45904889cb4829c34889d848c1f80389d129c189c88945b48b45b483c001489848c1e0034889c7e8320b0100488905fbc02400c745cc00000000eb3b488b05ebc024008b55cc4863d248c1e203488d1c108b45cc4898488d14c500000000488b45e04801d0488b004889c7e8512600004889038345cc018b45cc3b45b47cbd488b05a8c024008b55cc4863d248c1e2034801d048c70000000000488b058dc024004889c7e8589affffeb62837de800741e8b45e889c7e876a0ffff83f8ff754dbf30da4300b800000000e87c270000c70565c0240000000000c70563c0240000000000488b05447c24004889056dc02400488b053e7c240048890567c02400488b05387c240048890561c02400e8b1300100c70592d6240000000000bf60de6500e82817ffff85c0743dbf60de6500e81a17ffff85c07507e8fef7ffffeb1e488b05489f24004889c1ba20000000be01000000bf58da4300e8d11affffbf01000000e8a71affff8b05d1bf240085c0740b8b05c7bf240083f8027509c745dc00000000eb07c745dc01000000837ddc0075308b45a485c07529488b05ee9e24004889c1ba29000000be0100000!
 0bf80da430
0e8771affffbf01000000e84d1affff90c705169f240000000000c705fcd4240000000000c7053e7b2400ffffffff488b45b8
   0x0000000000410b61 <+1019>:  mov    0x24a2a8(%rip),%rax        # 0x65ae10 <stderr@@GLIBC_2.2.5>
   0x0000000000410b68 <+1026>:  mov    $0x43da0c,%esi
... lots more insns printed before the next fetch, etc. ...



I'll write a proper commit log if people agree this is good.

--------
2013-10-11  Taimoor Mirza  <taimoor_mirza@mentor.com>
	    Pedro Alves  <palves@redhat.com>

	* disasm.c: Don't include "dis-asm.h" here.
	(DIS_BUF_SIZE): New define.
	(dis_asm_read_memory): Over-fetch into a buffer, and serve from
	that buffer.
	(gdb_disassemble_info): Adjust to return a struct
	gdb_disassemble_info object.
	(gdb_disassembly): Adjust to allocate a struct
	gdb_disassemble_info object with a buffer instead of a plain
	disassemble_info object.
	(gdb_print_insn): Adjust to allocate a struct gdb_disassemble_info
	object instead of a plain disassemble_info object.
	* disasm.h: Include "dis-asm.h" here.
	(struct gdb_disassemble_info): New type.
	* arm-tdep.c: Include "disasm.h".
	(gdb_print_insn_arm): Adjust.
	* mips-tdep.c: Include "disasm.h".
	(gdb_print_insn_mips): Adjust.
	* spu-tdep.c: Include "disasm.h".
	(struct spu_dis_asm_data): Delete.
	(struct spu_disassemble_info): New type.
	(spu_dis_asm_print_address): Adjust.
	(gdb_print_insn_spu): Adjust to wrap the incoming struct
	gdb_disassemble_info object in a new spu_disassemble_info object
	instead of using the disassemble_info->application_data field.
---

 gdb/arm-tdep.c  |    4 +
 gdb/disasm.c    |  153 ++++++++++++++++++++++++++++++++++++++++++++++---------
 gdb/disasm.h    |   23 ++++++++
 gdb/mips-tdep.c |    4 +
 gdb/spu-tdep.c  |   24 ++++-----
 5 files changed, 169 insertions(+), 39 deletions(-)

diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 7c78a61..edc4f31 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -57,6 +57,7 @@
 
 #include "record.h"
 #include "record-full.h"
+#include "disasm.h"
 
 #include "features/arm-with-m.c"
 #include "features/arm-with-m-fpa-layout.c"
@@ -8702,7 +8703,8 @@ arm_displaced_step_fixup (struct gdbarch *gdbarch,
 static int
 gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
 {
-  struct gdbarch *gdbarch = info->application_data;
+  struct gdb_disassemble_info *gdb_info = (struct gdb_disassemble_info *) info;
+  struct gdbarch *gdbarch = gdb_info->gdbarch;
 
   if (arm_pc_is_thumb (gdbarch, memaddr))
     {
diff --git a/gdb/disasm.c b/gdb/disasm.c
index e643c2d..f5fa70c 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -24,7 +24,6 @@
 #include "gdb_string.h"
 #include "disasm.h"
 #include "gdbcore.h"
-#include "dis-asm.h"
 
 /* Disassemble functions.
    FIXME: We should get rid of all the duplicate code in gdb that does
@@ -42,11 +41,95 @@ struct dis_line_entry
   CORE_ADDR end_pc;
 };
 
-/* Like target_read_memory, but slightly different parameters.  */
+/* Size of the disassembly over-read memory buffer.  */
+#define DIS_BUF_SIZE 1024
+
+/* Interface adjustment callback installed in libopcodes' disassembly
+   routine, to fetch memory off the target.  */
+
 static int
 dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
 		     struct disassemble_info *info)
 {
+  struct gdb_disassemble_info *gdb_info = (struct gdb_disassemble_info *) info;
+
+  /* The libopcodes disassembler fetches instructions off of memory
+     one at a time.  This results in lots of roundtrips to the target
+     to fetch many tiny chunks of memory.  As we can assume the
+     disassembler always reads memory forwards, and we can also
+     reasonably assume that fetching a reasonable medium sized buffer
+     takes as much as reading a small buffer (IOW, roundtrip latency
+     dominates), we can optimize disassembly performance by
+     over-fetching larger chunks into a buffer, and serving libopcodes
+     off of that buffer most of the time.  Note we avoid over reading
+     beyond the original requested range, as we don't know what might
+     be there --- could be memory mapped registers, etc.  */
+  if (gdb_info->low != gdb_info->high)
+    {
+      unsigned int org_len = len;
+      unsigned int org_memaddr = memaddr;
+
+      while (len != 0)
+	{
+	  if (info->buffer_vma <= memaddr
+	      && memaddr < info->buffer_vma + info->buffer_length)
+	    {
+	      unsigned int offset = (memaddr - info->buffer_vma);
+	      unsigned int l = min (len, info->buffer_length - offset);
+
+	      memcpy (myaddr, info->buffer + offset, l);
+
+	      memaddr += l;
+	      myaddr += l;
+	      len -= l;
+
+	      if (len == 0)
+		return 0;
+	    }
+	  else if (gdb_info->low <= memaddr && memaddr < gdb_info->high)
+	    {
+	      /* Refill the buffer, taking care to not read beyond the
+		 originally requested range.  */
+	      int rval;
+	      unsigned int left = gdb_info->high - memaddr;
+	      unsigned int buffer_length = min (left, DIS_BUF_SIZE);
+
+	      /* If we fail to read memory halfway, we'll have
+		 clobbered the buffer, so don't trust it anymore, even
+		 on fail.  */
+	      info->buffer_length = 0;
+	      rval = target_read_memory (memaddr, info->buffer, buffer_length);
+	      if (rval != 0)
+		{
+		  /* Over fetching failed.  Try reading only what is
+		     necessary to fulfill the caller's request.  We
+		     don't disable buffering completely as following
+		     calls may still be within the original requested
+		     range passed to gdb_disassembly (e.g., mixed
+		     source disassembly mode).  */
+		  buffer_length = org_len;
+		  memaddr = org_memaddr;
+		  rval = target_read_memory (memaddr, info->buffer, buffer_length);
+		  if (rval != 0)
+		    return rval;
+		}
+
+	      info->buffer_vma = memaddr;
+	      info->buffer_length = buffer_length;
+	    }
+	  else
+	    {
+	      /* libopcodes is trying to read beyond the originally
+		 requested range...  This will happen e.g., if the
+		 last instruction is a multi-byte instruction that
+		 starts within the range, but extends beyond it.  */
+	      len = org_len;
+	      memaddr = org_memaddr;
+	      break;
+	    }
+	}
+    }
+
   return target_read_memory (memaddr, myaddr, len);
 }
 
@@ -376,15 +459,16 @@ fprintf_disasm (void *stream, const char *format, ...)
   return 0;
 }
 
-static struct disassemble_info
+static struct gdb_disassemble_info
 gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct disassemble_info di;
+  struct gdb_disassemble_info gdb_di;
+  struct disassemble_info *di = &gdb_di.di;
 
-  init_disassemble_info (&di, file, fprintf_disasm);
-  di.flavour = bfd_target_unknown_flavour;
-  di.memory_error_func = dis_asm_memory_error;
-  di.print_address_func = dis_asm_print_address;
+  init_disassemble_info (di, file, fprintf_disasm);
+  di->flavour = bfd_target_unknown_flavour;
+  di->memory_error_func = dis_asm_memory_error;
+  di->print_address_func = dis_asm_print_address;
   /* NOTE: cagney/2003-04-28: The original code, from the old Insight
      disassembler had a local optomization here.  By default it would
      access the executable file, instead of the target memory (there
@@ -393,14 +477,19 @@ gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
      didn't work as they relied on the access going to the target.
      Further, it has been supperseeded by trust-read-only-sections
      (although that should be superseeded by target_trust..._p()).  */
-  di.read_memory_func = dis_asm_read_memory;
-  di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
-  di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
-  di.endian = gdbarch_byte_order (gdbarch);
-  di.endian_code = gdbarch_byte_order_for_code (gdbarch);
-  di.application_data = gdbarch;
-  disassemble_init_for_target (&di);
-  return di;
+  di->read_memory_func = dis_asm_read_memory;
+  di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
+  di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+  di->endian = gdbarch_byte_order (gdbarch);
+  di->endian_code = gdbarch_byte_order_for_code (gdbarch);
+  di->application_data = gdbarch;
+  disassemble_init_for_target (di);
+
+  gdb_di.gdbarch = gdbarch;
+  gdb_di.low = 0;
+  gdb_di.high = 0;
+
+  return gdb_di;
 }
 
 void
@@ -410,7 +499,7 @@ gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
 {
   struct ui_file *stb = mem_fileopen ();
   struct cleanup *cleanups = make_cleanup_ui_file_delete (stb);
-  struct disassemble_info di = gdb_disassemble_info (gdbarch, stb);
+  struct gdb_disassemble_info gdb_di = gdb_disassemble_info (gdbarch, stb);
   /* To collect the instruction outputted from opcodes.  */
   struct symtab *symtab = NULL;
   struct linetable_entry *le = NULL;
@@ -426,13 +515,27 @@ gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
       nlines = symtab->linetable->nitems;
     }
 
+  /* Set things up for the read-ahead buffer optimization in
+     dis_asm_read_memory.  We always allocate the maximum buffer size,
+     as mixed source disassembly may hop back and forth.  Even though
+     over-reading a buffer chunk might fail for a line, it could
+     succeed for the next line (and then we could need to grow the
+     buffer).  struct disassemble_info is a value struct (it's passed
+     around by copy at places), so this is the simplest, as we don't
+     need to care for special memory management.  */
+  gdb_di.di.buffer = xmalloc (DIS_BUF_SIZE);
+  make_cleanup (xfree, gdb_di.di.buffer);
+  gdb_di.low = low;
+  gdb_di.high = high;
+
   if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
       || symtab == NULL || symtab->linetable == NULL)
-    do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
+    do_assembly_only (gdbarch, uiout, &gdb_di.di,
+		      low, high, how_many, flags, stb);
 
   else if (flags & DISASSEMBLY_SOURCE)
-    do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
-				  high, symtab, how_many, flags, stb);
+    do_mixed_source_and_assembly (gdbarch, uiout, &gdb_di.di, nlines, le,
+				  low, high, symtab, how_many, flags, stb);
 
   do_cleanups (cleanups);
   gdb_flush (gdb_stdout);
@@ -446,15 +549,15 @@ int
 gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
 		struct ui_file *stream, int *branch_delay_insns)
 {
-  struct disassemble_info di;
+  struct gdb_disassemble_info gdb_di;
   int length;
 
-  di = gdb_disassemble_info (gdbarch, stream);
-  length = gdbarch_print_insn (gdbarch, memaddr, &di);
+  gdb_di = gdb_disassemble_info (gdbarch, stream);
+  length = gdbarch_print_insn (gdbarch, memaddr, &gdb_di.di);
   if (branch_delay_insns)
     {
-      if (di.insn_info_valid)
-	*branch_delay_insns = di.branch_delay_insns;
+      if (gdb_di.di.insn_info_valid)
+	*branch_delay_insns = gdb_di.di.branch_delay_insns;
       else
 	*branch_delay_insns = 0;
     }
diff --git a/gdb/disasm.h b/gdb/disasm.h
index 3743ccc..6a63eee 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -25,9 +25,32 @@
 #define DISASSEMBLY_FILENAME	(0x1 << 3)
 #define DISASSEMBLY_OMIT_PC	(0x1 << 4)
 
+#include "dis-asm.h"
+
 struct ui_out;
 struct ui_file;
 
+/* A "subclass" of libopcodes' struct disassemble_info.  GDB always
+   passes uses this type instead of plain struct disassemble_info.  It
+   includes a "struct disassemble_info" as a kind of base class; users
+   downcast to "struct disassemble_info *" when needed.  */
+
+struct gdb_disassemble_info
+{
+  /* The base class.  */
+  struct disassemble_info di;
+
+  /* The architecture being used to interpret memory.  */
+  struct gdbarch *gdbarch;
+
+  /* The range of memory the caller of gdb_disassembly wanted
+     disassembled.  HIGH is exclusive.  GDB over-fetches memory off
+     the target for performance (by reducing roundtrips to the
+     target), but for safeness, won't try outside this range.  */
+  CORE_ADDR low;
+  CORE_ADDR high;
+};
+
 extern void gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
 			     char *file_string, int flags, int how_many,
 			     CORE_ADDR low, CORE_ADDR high);
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index bcbdcc5..56bfe4c 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -57,6 +57,7 @@
 #include "user-regs.h"
 #include "valprint.h"
 #include "ax.h"
+#include "disasm.h"
 
 static const struct objfile_data *mips_pdr_data;
 
@@ -6773,7 +6774,8 @@ reinit_frame_cache_sfunc (char *args, int from_tty,
 static int
 gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
 {
-  struct gdbarch *gdbarch = info->application_data;
+  struct gdb_disassemble_info *gdb_info = (struct gdb_disassemble_info *) info;
+  struct gdbarch *gdbarch = gdb_info->gdbarch;
 
   /* FIXME: cagney/2003-06-26: Is this even necessary?  The
      disassembler needs to be able to locally determine the ISA, and
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index 46f3e2c..423cdc8 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -46,6 +46,7 @@
 #include "dwarf2.h"
 #include "exceptions.h"
 #include "spu-tdep.h"
+#include "disasm.h"
 
 
 /* The list of available "set spu " and "show spu " commands.  */
@@ -1662,17 +1663,17 @@ spu_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
 
 /* Disassembler.  */
 
-struct spu_dis_asm_data
+struct spu_disassemble_info
 {
-  struct gdbarch *gdbarch;
+  struct gdb_disassemble_info gdb_di;
   int id;
 };
 
 static void
 spu_dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
 {
-  struct spu_dis_asm_data *data = info->application_data;
-  print_address (data->gdbarch, SPUADDR (data->id, addr), info->stream);
+  struct spu_disassemble_info *spu_info = (struct spu_disassemble_info *) info;
+  print_address (spu_info->gdb_di.gdbarch, SPUADDR (spu_info->id, addr), info->stream);
 }
 
 static int
@@ -1681,14 +1682,13 @@ gdb_print_insn_spu (bfd_vma memaddr, struct disassemble_info *info)
   /* The opcodes disassembler does 18-bit address arithmetic.  Make
      sure the SPU ID encoded in the high bits is added back when we
      call print_address.  */
-  struct disassemble_info spu_info = *info;
-  struct spu_dis_asm_data data;
-  data.gdbarch = info->application_data;
-  data.id = SPUADDR_SPU (memaddr);
-
-  spu_info.application_data = &data;
-  spu_info.print_address_func = spu_dis_asm_print_address;
-  return print_insn_spu (memaddr, &spu_info);
+  struct gdb_disassemble_info *gdb_info = (struct gdb_disassemble_info *) info;
+  struct spu_disassemble_info spu_info;
+
+  spu_info.gdb_di = *gdb_info;
+  spu_info.id = SPUADDR_SPU (memaddr);
+  spu_info.gdb_di.di.print_address_func = spu_dis_asm_print_address;
+  return print_insn_spu (memaddr, (struct disassemble_info *) &spu_info);
 }
 
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]