From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17872 invoked by alias); 22 Nov 2008 23:56:21 -0000 Received: (qmail 17390 invoked by uid 22791); 22 Nov 2008 23:56:17 -0000 X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 22 Nov 2008 23:55:21 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id mAMNsugu022540; Sat, 22 Nov 2008 18:54:56 -0500 Received: from pobox.stuttgart.redhat.com (pobox.stuttgart.redhat.com [172.16.2.10]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id mAMNstKP017585; Sat, 22 Nov 2008 18:54:55 -0500 Received: from host0.dyn.jankratochvil.net (sebastian-int.corp.redhat.com [172.16.52.221]) by pobox.stuttgart.redhat.com (8.13.1/8.13.1) with ESMTP id mAMNsrAm001344; Sat, 22 Nov 2008 18:54:54 -0500 Received: from host0.dyn.jankratochvil.net (localhost [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.3/8.14.2) with ESMTP id mAMNspq4018239; Sun, 23 Nov 2008 00:54:52 +0100 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.3/8.14.2/Submit) id mAMNsoWN018236; Sun, 23 Nov 2008 00:54:50 +0100 Date: Mon, 24 Nov 2008 07:09:00 -0000 From: Jan Kratochvil To: Joel Brobecker Cc: Eli Zaretskii , gdb-patches@sourceware.org Subject: Re: [patch] ia64: Fix breakpoints memory shadow Message-ID: <20081122235450.GA17397@host0.dyn.jankratochvil.net> References: <20081028172816.GA1284@host0.dyn.jankratochvil.net> <20081029210242.GA3635@adacore.com> <20081030144841.GA26606@host0.dyn.jankratochvil.net> <20081101185410.GB15606@adacore.com> <20081111131726.GA3272@host0.dyn.jankratochvil.net> <20081113053100.GL5112@adacore.com> <20081120144936.GA25926@host0.dyn.jankratochvil.net> <20081122181525.GG4318@adacore.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="i7F3eY7HS/tUJxUd" Content-Disposition: inline In-Reply-To: <20081122181525.GG4318@adacore.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-IsSubscribed: yes 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 X-SW-Source: 2008-11/txt/msg00622.txt.bz2 --i7F3eY7HS/tUJxUd Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 6113 On Sat, 22 Nov 2008 12:30:04 +0100, Eli Zaretskii wrote: > > gdb/doc/ > > This part is approved, thanks. OK, thanks. On Sat, 22 Nov 2008 19:15:25 +0100, Joel Brobecker wrote: > > > + instr_breakpoint = slotN_contents (bundle_mem, slotnum); > > > + if (instr_breakpoint != IA64_BREAKPOINT) > > > + warning (_("Breakpoint removal cannot find the placed breakpoint at %s"), > > > + paddr_nz (bp_tgt->placed_address)); > > > > Can this happen as part of normal GDB behavior? If not, we should > > make this internal_error, I think. If indeed this is a warning, we > > should tell users what to do with such a warning, either as part of > > the message or at least in the manual. [...] > I would agree that some extra documentation explaining this warning > might be useful. That being said, I'm not opposed to changing the > warning into an internal_error, if you still think it's better. As the remote target memory may change arbitrarily across time I do not find there internal error appropriate. Still I rather found another defect compared to mem-break.c in the ia64 breakpoints code. It is another problem unrelated to the original intention of this ia64 patch. target_write_memory result was not checked and thus failed write to readonly memory still made ia64_memory_insert_breakpoint to succeed. The write fails in the testcases for VDSO memory range which is not writable on ia64: kernel-xen-2.6.18-92.el5.ia64 a000000000000000-a000000000020000 r-xp 00000000 00:00 0 [vdso] ptrace(PTRACE_PEEKTEXT, 30592, 0xa000000000000000, NULL) = 282584257676671 ptrace(PTRACE_PEEKTEXT, 30592, 0xa000000000000008, NULL) = 0 ptrace(PTRACE_POKEDATA, 30592, 0xa000000000000000, 0x100006666601f) = -1 EIO (Input/output error) ptrace(PTRACE_POKETEXT, 30592, 0xa000000000000000, 0x100006666601f) = -1 EIO (Input/output error) But on x86_64 (using PTRACE_POKE* error checking mem-break.c) it is writable: kernel-2.6.25.10-86.fc9.x86_64 7ffff7ffd000-7ffff7fff000 r-xp 7ffff7ffd000 00:00 0 [vdso] ptrace(PTRACE_PEEKTEXT, 2761, 0x7ffff7ffd7a0, [0x8bfffffd41058b48]) = 0 ptrace(PTRACE_POKEDATA, 2761, 0x7ffff7ffd7a0, 0x8bfffffd41058bcc) = 0 ptrace(PTRACE_PEEKTEXT, 2761, 0x7ffff7ffd7a0, [0x8bfffffd41058bcc]) = 0 The attached patch changes on ia64 the breakpoints to readonly memory to fail: (gdb) b *0xa000000000000000 Breakpoint 2 at 0xa000000000000000 Warning: Cannot insert breakpoint 2. Error accessing memory address 0xa000000000000000: Input/output error. (gdb) info break Num Type Disp Enb Address What 2 breakpoint keep y 0xa000000000000000 (gdb) delete 2 (gdb) Unaware how to invoke the ia64_memory_remove_breakpoint error of (instr_breakpoint != IA64_BREAKPOINT) but by patching GDB code one can get: (gdb) b *0xa000000000000000 Breakpoint 2 at 0xa000000000000000 (gdb) info break Num Type Disp Enb Address What 2 breakpoint keep y 0xa000000000000000 (gdb) delete 2 warning: Error removing breakpoint 2 (gdb) info break No breakpoints or watchpoints. For the ia64-specific code: > > > + instr_breakpoint = slotN_contents (bundle_mem, slotnum); > > > + if (instr_breakpoint != IA64_BREAKPOINT) > > > + warning (_("Breakpoint removal cannot find the placed breakpoint at %s"), > > > + paddr_nz (bp_tgt->placed_address)); -> + instr_breakpoint = slotN_contents (bundle_mem, slotnum); + if (instr_breakpoint != IA64_BREAKPOINT) + return -1; I am open to a possibility to also give a warning() there besides the current failure (-1) return. Requesting another approval due to this change although the patch covers now more ia64 parts than it was not intended for. Thanks for pinpointing this another ia64-tdep.c bug, Jan ia64 testsuite changes (no regression) with this patch: -FAIL: gdb.base/advance.exp: advance line number +PASS: gdb.base/advance.exp: advance line number -FAIL: gdb.base/advance.exp: advance func +PASS: gdb.base/advance.exp: advance func -FAIL: gdb.base/advance.exp: advance function not called by current frame +PASS: gdb.base/advance.exp: advance function not called by current frame -FAIL: gdb.base/advance.exp: continue to call to func3 in main (the program is no longer running) +PASS: gdb.base/advance.exp: continue to call to func3 in main -FAIL: gdb.base/advance.exp: advance with no argument +PASS: gdb.base/advance.exp: advance with no argument -FAIL: gdb.base/sigaltstack.exp: finish from catch LEAF +FAIL: gdb.base/sigaltstack.exp: finish from catch LEAF (could not set breakpoint) -FAIL: gdb.base/sigaltstack.exp: finish to throw INNER +FAIL: gdb.base/sigaltstack.exp: finish to throw INNER (could not set breakpoint) -FAIL: gdb.base/sigaltstack.exp: finish to catch INNER +FAIL: gdb.base/sigaltstack.exp: finish to catch INNER (could not set breakpoint) -FAIL: gdb.base/sigaltstack.exp: finish from catch INNER +FAIL: gdb.base/sigaltstack.exp: finish from catch INNER (could not set breakpoint) -FAIL: gdb.base/sigaltstack.exp: finish to OUTER +FAIL: gdb.base/sigaltstack.exp: finish to OUTER (could not set breakpoint) -FAIL: gdb.base/sigaltstack.exp: finish to catch MAIN +FAIL: gdb.base/sigaltstack.exp: finish to catch MAIN (could not set breakpoint) -FAIL: gdb.base/sigaltstack.exp: finish to MAIN +FAIL: gdb.base/sigaltstack.exp: finish to MAIN (could not set breakpoint) -FAIL: gdb.base/sigstep.exp: finish from handleri; leave handler (hit breakpoint again) -FAIL: gdb.base/sigstep.exp: finish from handleri; leave signal trampoline +FAIL: gdb.base/sigstep.exp: finish from handleri; leave handler (could not set breakpoint) +Running ../.././gdb/testsuite/gdb.base/breakpoint-shadow.exp ... +PASS: gdb.base/breakpoint-shadow.exp: set breakpoint always-inserted on +PASS: gdb.base/breakpoint-shadow.exp: show breakpoint always-inserted +PASS: gdb.base/breakpoint-shadow.exp: disassembly without breakpoints +PASS: gdb.base/breakpoint-shadow.exp: First breakpoint placed +PASS: gdb.base/breakpoint-shadow.exp: Second breakpoint placed +PASS: gdb.base/breakpoint-shadow.exp: disassembly with breakpoints --i7F3eY7HS/tUJxUd Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="ia64-align5.patch" Content-length: 18625 gdb/ 2008-11-23 Jan Kratochvil Fix automatic restoration of breakpoints memory for ia64. * ia64-tdep.c: New #if check on BREAKPOINT_MAX vs. BUNDLE_LEN. (ia64_memory_insert_breakpoint): New comment part for SHADOW_CONTENTS content. Remove variable instr. New variable cleanup. Force automatic breakpoints restoration. PLACED_SIZE and SHADOW_LEN are now set larger, to BUNDLE_LEN - 2. Variable `bundle' type update. Return error if even just final target_write_memory has failed. (ia64_memory_remove_breakpoint): Rename variables bundle to bundle_mem and instr to instr_saved. New variables bundle_saved and instr_breakpoint. Comment new reasons why we need to disable automatic restoration of breakpoints. Assert PLACED_SIZE and SHADOW_LEN. New check of the original memory content. Return error if even just final target_write_memory has failed. (ia64_breakpoint_from_pc): Implement the emulation of permanent breakpoints compatible with current bp_loc_is_permanent. (template_encoding_table): Make it `const'. * breakpoint.c (bp_loc_is_permanent): Support unsupported software breakpoints. New variables `cleanup' and `retval'. * monitor.c (monitor_insert_breakpoint): Remove unused variable `bp'. gdb/doc/ 2008-11-23 Jan Kratochvil * gdbint.texinfo (Target Conditionals): Extend the gdbarch_breakpoint_from_pc description. gdb/testsuite/ 2008-11-23 Jan Kratochvil * gdb.base/breakpoint-shadow.exp, gdb.base/breakpoint-shadow.c: New. * gdb.base/start.exp: New comment about an alternative - `runto_main'. --- ./gdb/breakpoint.c 22 Nov 2008 04:41:45 -0000 1.362 +++ ./gdb/breakpoint.c 22 Nov 2008 17:36:51 -0000 @@ -5010,19 +5010,32 @@ bp_loc_is_permanent (struct bp_location CORE_ADDR addr; const gdb_byte *brk; gdb_byte *target_mem; + struct cleanup *cleanup; + int retval = 0; gdb_assert (loc != NULL); addr = loc->address; brk = gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &len); + /* Software breakpoints unsupported? */ + if (brk == NULL) + return 0; + target_mem = alloca (len); + /* Enable the automatic memory restoration from breakpoints while + we read the memory. Otherwise we could say about our temporary + breakpoints they are permanent. */ + cleanup = make_show_memory_breakpoints_cleanup (0); + if (target_read_memory (loc->address, target_mem, len) == 0 && memcmp (target_mem, brk, len) == 0) - return 1; + retval = 1; - return 0; + do_cleanups (cleanup); + + return retval; } --- ./gdb/ia64-tdep.c 13 Nov 2008 05:05:07 -0000 1.185 +++ ./gdb/ia64-tdep.c 22 Nov 2008 17:36:51 -0000 @@ -110,6 +110,12 @@ typedef enum instruction_type #define BUNDLE_LEN 16 +/* See the saved memory layout comment for ia64_memory_insert_breakpoint. */ + +#if BREAKPOINT_MAX < BUNDLE_LEN - 2 +# error "BREAKPOINT_MAX < BUNDLE_LEN - 2" +#endif + static gdbarch_init_ftype ia64_gdbarch_init; static gdbarch_register_name_ftype ia64_register_name; @@ -442,7 +448,7 @@ replace_slotN_contents (char *bundle, lo replace_bit_field (bundle, instr, 5+41*slotnum, 41); } -static enum instruction_type template_encoding_table[32][3] = +static const enum instruction_type template_encoding_table[32][3] = { { M, I, I }, /* 00 */ { M, I, I }, /* 01 */ @@ -545,7 +551,45 @@ fetch_instruction (CORE_ADDR addr, instr simulators. So I changed the pattern slightly to do "break.i 0x080001" instead. But that didn't work either (I later found out that this pattern was used by the simulator that I was using.) So I ended up - using the pattern seen below. */ + using the pattern seen below. + + SHADOW_CONTENTS has byte-based addressing (PLACED_ADDRESS and SHADOW_LEN) + while we need bit-based addressing as the instructions length is 41 bits and + we must not modify/corrupt the adjacent slots in the same bundle. + Fortunately we may store larger memory incl. the adjacent bits with the + original memory content (not the possibly already stored breakpoints there). + We need to be careful in ia64_memory_remove_breakpoint to always restore + only the specific bits of this instruction ignoring any adjacent stored + bits. + + We use the original addressing with the low nibble in the range <0..2> which + gets incorrectly interpreted by generic non-ia64 breakpoint_restore_shadows + as the direct byte offset of SHADOW_CONTENTS. We store whole BUNDLE_LEN + bytes just without these two possibly skipped bytes to not to exceed to the + next bundle. + + If we would like to store the whole bundle to SHADOW_CONTENTS we would have + to store already the base address (`address & ~0x0f') into PLACED_ADDRESS. + In such case there is no other place where to store + SLOTNUM (`adress & 0x0f', value in the range <0..2>). We need to know + SLOTNUM in ia64_memory_remove_breakpoint. + + ia64 16-byte bundle layout: + | 5 bits | slot 0 with 41 bits | slot 1 with 41 bits | slot 2 with 41 bits | + + The current addressing used by the code below: + original PC placed_address placed_size required covered + == bp_tgt->shadow_len reqd \subset covered + 0xABCDE0 0xABCDE0 0xE <0x0...0x5> <0x0..0xD> + 0xABCDE1 0xABCDE1 0xE <0x5...0xA> <0x1..0xE> + 0xABCDE2 0xABCDE2 0xE <0xA...0xF> <0x2..0xF> + + `objdump -d' and some other tools show a bit unjustified offsets: + original PC byte where starts the instruction objdump offset + 0xABCDE0 0xABCDE0 0xABCDE0 + 0xABCDE1 0xABCDE5 0xABCDE6 + 0xABCDE2 0xABCDEA 0xABCDEC + */ #define IA64_BREAKPOINT 0x00003333300LL @@ -554,34 +598,44 @@ ia64_memory_insert_breakpoint (struct gd struct bp_target_info *bp_tgt) { CORE_ADDR addr = bp_tgt->placed_address; - char bundle[BUNDLE_LEN]; + gdb_byte bundle[BUNDLE_LEN]; int slotnum = (int) (addr & 0x0f) / SLOT_MULTIPLIER; - long long instr; int val; int template; + struct cleanup *cleanup; if (slotnum > 2) error (_("Can't insert breakpoint for slot numbers greater than 2.")); addr &= ~0x0f; + /* Enable the automatic memory restoration from breakpoints while + we read our instruction bundle. Otherwise, we could store into + SHADOW_CONTENTS an already stored breakpoint at the same location. + In practice it is already being prevented by the DUPLICATE field and + update_global_location_list. */ + cleanup = make_show_memory_breakpoints_cleanup (0); val = target_read_memory (addr, bundle, BUNDLE_LEN); - /* Check for L type instruction in 2nd slot, if present then - bump up the slot number to the 3rd slot */ + /* Check for L type instruction in slot 1, if present then bump up the slot + number to the slot 2. */ template = extract_bit_field (bundle, 0, 5); - if (slotnum == 1 && template_encoding_table[template][1] == L) - { - slotnum = 2; - } + if (slotnum == 1 && template_encoding_table[template][slotnum] == L) + slotnum = 2; + + /* Slot number 2 may skip at most 2 bytes at the beginning. */ + bp_tgt->placed_size = bp_tgt->shadow_len = BUNDLE_LEN - 2; + + /* Store the whole bundle, except for the initial skipped bytes by the slot + number interpreted as bytes offset in PLACED_ADDRESS. */ + memcpy (bp_tgt->shadow_contents, bundle + slotnum, bp_tgt->shadow_len); - instr = slotN_contents (bundle, slotnum); - memcpy (bp_tgt->shadow_contents, &instr, sizeof (instr)); - bp_tgt->placed_size = bp_tgt->shadow_len = sizeof (instr); replace_slotN_contents (bundle, IA64_BREAKPOINT, slotnum); if (val == 0) - target_write_memory (addr, bundle, BUNDLE_LEN); + val = target_write_memory (addr + slotnum, bundle + slotnum, + bp_tgt->shadow_len); + do_cleanups (cleanup); return val; } @@ -590,9 +644,9 @@ ia64_memory_remove_breakpoint (struct gd struct bp_target_info *bp_tgt) { CORE_ADDR addr = bp_tgt->placed_address; - char bundle[BUNDLE_LEN]; + gdb_byte bundle_mem[BUNDLE_LEN], bundle_saved[BUNDLE_LEN]; int slotnum = (addr & 0x0f) / SLOT_MULTIPLIER; - long long instr; + long long instr_breakpoint, instr_saved; int val; int template; struct cleanup *cleanup; @@ -601,40 +655,91 @@ ia64_memory_remove_breakpoint (struct gd /* Disable the automatic memory restoration from breakpoints while we read our instruction bundle. Otherwise, the general restoration - mechanism kicks in and ends up corrupting our bundle, because it - is not aware of the concept of instruction bundles. */ + mechanism kicks in and we would possibly remove parts of the adjacent + placed breakpoints. It is due to our SHADOW_CONTENTS overlapping the real + breakpoint instruction bits region. */ cleanup = make_show_memory_breakpoints_cleanup (1); - val = target_read_memory (addr, bundle, BUNDLE_LEN); + val = target_read_memory (addr, bundle_mem, BUNDLE_LEN); - /* Check for L type instruction in 2nd slot, if present then - bump up the slot number to the 3rd slot */ - template = extract_bit_field (bundle, 0, 5); - if (slotnum == 1 && template_encoding_table[template][1] == L) - { - slotnum = 2; - } + /* Check for L type instruction in slot 1, if present then bump up the slot + number to the slot 2. */ + template = extract_bit_field (bundle_mem, 0, 5); + if (slotnum == 1 && template_encoding_table[template][slotnum] == L) + slotnum = 2; + + gdb_assert (bp_tgt->placed_size == BUNDLE_LEN - 2); + gdb_assert (bp_tgt->placed_size == bp_tgt->shadow_len); - memcpy (&instr, bp_tgt->shadow_contents, sizeof instr); - replace_slotN_contents (bundle, instr, slotnum); + instr_breakpoint = slotN_contents (bundle_mem, slotnum); + if (instr_breakpoint != IA64_BREAKPOINT) + return -1; + + /* Extract the original saved instruction from SLOTNUM normalizing its + bit-shift for INSTR_SAVED. */ + memcpy (bundle_saved, bundle_mem, BUNDLE_LEN); + memcpy (bundle_saved + slotnum, bp_tgt->shadow_contents, bp_tgt->shadow_len); + instr_saved = slotN_contents (bundle_saved, slotnum); + + /* In BUNDLE_MEM be careful to modify only the bits belonging to SLOTNUM and + never any other possibly also stored in SHADOW_CONTENTS. */ + replace_slotN_contents (bundle_mem, instr_saved, slotnum); if (val == 0) - target_write_memory (addr, bundle, BUNDLE_LEN); + val = target_write_memory (addr, bundle_mem, BUNDLE_LEN); do_cleanups (cleanup); return val; } -/* We don't really want to use this, but remote.c needs to call it in order - to figure out if Z-packets are supported or not. Oh, well. */ -const unsigned char * +/* As gdbarch_breakpoint_from_pc ranges have byte granularity and ia64 + instruction slots ranges are bit-granular (41 bits) we have to provide an + extended range as described for ia64_memory_insert_breakpoint. We also take + care of preserving the `break' instruction 21-bit (or 62-bit) parameter to + make a match for permanent breakpoints. */ + +static const gdb_byte * ia64_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) { - static unsigned char breakpoint[] = - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - *lenptr = sizeof (breakpoint); -#if 0 - *pcptr &= ~0x0f; -#endif - return breakpoint; + CORE_ADDR addr = *pcptr; + static gdb_byte bundle[BUNDLE_LEN]; + int slotnum = (int) (*pcptr & 0x0f) / SLOT_MULTIPLIER; + long long instr_fetched; + int val; + int template; + struct cleanup *cleanup; + + if (slotnum > 2) + error (_("Can't insert breakpoint for slot numbers greater than 2.")); + + addr &= ~0x0f; + + /* Enable the automatic memory restoration from breakpoints while + we read our instruction bundle to match bp_loc_is_permanent. */ + cleanup = make_show_memory_breakpoints_cleanup (0); + val = target_read_memory (addr, bundle, BUNDLE_LEN); + do_cleanups (cleanup); + + /* The memory might be unreachable. This can happen, for instance, + when the user inserts a breakpoint at an invalid address. */ + if (val != 0) + return NULL; + + /* Check for L type instruction in slot 1, if present then bump up the slot + number to the slot 2. */ + template = extract_bit_field (bundle, 0, 5); + if (slotnum == 1 && template_encoding_table[template][slotnum] == L) + slotnum = 2; + + /* A break instruction has its all its opcode bits cleared except for + the parameter value. For L+X slot pair we are at the X slot (slot 2) so + we should not touch the L slot - the upper 41 bits of the parameter. */ + instr_fetched = slotN_contents (bundle, slotnum); + instr_fetched &= 0x1003ffffc0; + replace_slotN_contents (bundle, instr_fetched, slotnum); + + *lenptr = BUNDLE_LEN - 2; + + /* SLOTNUM is possibly already locally modified - use caller's *PCPTR. */ + return bundle + (*pcptr & 0x0f); } static CORE_ADDR --- ./gdb/doc/gdbint.texinfo 27 Oct 2008 11:37:40 -0000 1.292 +++ ./gdb/doc/gdbint.texinfo 22 Nov 2008 17:36:51 -0000 @@ -3430,16 +3430,23 @@ favor of @code{gdbarch_breakpoint_from_p @findex gdbarch_breakpoint_from_pc @anchor{gdbarch_breakpoint_from_pc} Use the program counter to determine the contents and size of a breakpoint instruction. It returns a pointer to -a string of bytes that encode a breakpoint instruction, stores the +a static string of bytes that encode a breakpoint instruction, stores the length of the string to @code{*@var{lenptr}}, and adjusts the program counter (if necessary) to point to the actual memory location where the -breakpoint should be inserted. +breakpoint should be inserted. May return @code{NULL} to indicate that +software breakpoints are not supported. Although it is common to use a trap instruction for a breakpoint, it's not required; for instance, the bit pattern could be an invalid instruction. The breakpoint must be no longer than the shortest instruction of the architecture. +Provided breakpoint bytes can be also used by @code{bp_loc_is_permanent} to +detect permanent breakpoints. @code{gdbarch_breakpoint_from_pc} should return +an unchanged memory copy if it was called for a location with permanent +breakpoint as some architectures use breakpoint instructions containing +arbitrary parameter value. + Replaces all the other @var{BREAKPOINT} macros. @item int gdbarch_memory_insert_breakpoint (@var{gdbarch}, @var{bp_tgt}) --- .//dev/null 1 Jan 1970 00:00:00 -0000 +++ ./gdb/testsuite/gdb.base/breakpoint-shadow.c 22 Nov 2008 17:36:51 -0000 @@ -0,0 +1,27 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +int +main (void) +{ + volatile int i; + + i = 1; /* break-first */ + i = 2; /* break-second */ + + return 0; +} --- .//dev/null 1 Jan 1970 00:00:00 -0000 +++ ./gdb/testsuite/gdb.base/breakpoint-shadow.exp 22 Nov 2008 17:36:51 -0000 @@ -0,0 +1,63 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set testfile breakpoint-shadow +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# We need to start the inferior to place the breakpoints in the memory at all. +if ![runto_main] { + untested start + return -1 +} + +# The default "auto" mode removes all the breakpoints when we stop (and not +# running the nonstop mode). We would not be able to test the shadow. +gdb_test "set breakpoint always-inserted on" +gdb_test "show breakpoint always-inserted" "Always inserted breakpoint mode is on." + +set match "\nDump of assembler code for function main:\r\n(.*)End of assembler dump.\r\n$gdb_prompt $" + +set test "disassembly without breakpoints" +gdb_test_multiple "disass main" $test { + -re $match { + set orig $expect_out(1,string) + pass $test + } +} + +gdb_test "b [gdb_get_line_number "break-first"]" "Breakpoint \[0-9\] at .*" "First breakpoint placed" +gdb_test "b [gdb_get_line_number "break-second"]" "Breakpoint \[0-9\] at .*" "Second breakpoint placed" + +set test "disassembly with breakpoints" +gdb_test_multiple "disass main" $test { + -re $match { + set got $expect_out(1,string) + if [string equal -nocase $orig $got] { + pass $test + } else { + fail $test + } + } +} --- ./gdb/testsuite/gdb.base/start.exp 1 Jan 2008 22:53:19 -0000 1.5 +++ ./gdb/testsuite/gdb.base/start.exp 22 Nov 2008 17:36:51 -0000 @@ -35,6 +35,9 @@ gdb_start gdb_reinitialize_dir $srcdir/$subdir gdb_load ${binfile} +# This is a testcase specifically for the `start' GDB command. For regular +# stop-in-main goal in the testcases consider using `runto_main' instead. + # For C programs, "start" should stop in main(). if { [gdb_start_cmd] < 0 } { untested start @@ -44,4 +47,3 @@ if { [gdb_start_cmd] < 0 } { gdb_test "" \ "main \\(\\) at .*start.c.*" \ "start" - --i7F3eY7HS/tUJxUd--