From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 650 invoked by alias); 11 Oct 2013 21:12:54 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 638 invoked by uid 89); 11 Oct 2013 21:12:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS,T_FRT_LOLITA1 autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 11 Oct 2013 21:12:51 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r9BLCm09002556 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 11 Oct 2013 17:12:48 -0400 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r9BLCj2s023627; Fri, 11 Oct 2013 17:12:47 -0400 Message-ID: <525869CD.9090507@redhat.com> Date: Fri, 11 Oct 2013 21:12:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130625 Thunderbird/17.0.7 MIME-Version: 1.0 To: "Abid, Hafiz" CC: "gdb-patches@sourceware.org" , "Mirza, Taimoor" Subject: Re: [patch] Disassembly improvements References: <5256ACED.7040402@redhat.com> <5256BF1B.9010202@redhat.com> <5256C41A.8020403@redhat.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-SW-Source: 2013-10/txt/msg00399.txt.bz2 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 ... 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 ... 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 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 Pedro Alves * 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); }