aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/mem-break.c
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2019-12-15 07:37:06 -0700
committerTom Tromey <tromey@adacore.com>2020-02-07 08:42:25 -0700
commit919adfe8409211c726c1d05b47ca59890ee648f1 (patch)
treed2ef4abf9e5590b43a59f3f8747b0d5bab94ab6f /gdb/gdbserver/mem-break.c
parente8319fde715960466aca2461c74cec8907abd391 (diff)
downloadgdb-919adfe8409211c726c1d05b47ca59890ee648f1.zip
gdb-919adfe8409211c726c1d05b47ca59890ee648f1.tar.gz
gdb-919adfe8409211c726c1d05b47ca59890ee648f1.tar.bz2
Move gdbserver to top level
This patch moves gdbserver to the top level. This patch is as close to a pure move as possible -- gdbserver still builds its own variant of gnulib and gdbsupport. Changing this will be done in a separate patch. [v2] Note that, per Simon's review comment, this patch changes the tree so that gdbserver is not built for or1k or score. This makes sense, because there is apparently not actually a gdbserver port here. [v3] This version of the patch also splits out some configury into a new file, gdbserver/configure.host, so that the top-level configure script can simply rely on it in order to decide whether gdbserver should be built. [v4] This version adds documentation and removes some unnecessary top-level dependencies. [v5] Update docs to mention "make all-gdbserver" and change how top-level configure decides whether to build gdbserver, switching to a single, shared script. Tested by the buildbot. ChangeLog 2020-02-07 Tom Tromey <tom@tromey.com> Pedro Alves <palves@redhat.com> * src-release.sh (GDB_SUPPORT_DIRS): Add gdbserver. * gdbserver: New directory, moved from gdb/gdbserver. * configure.ac (host_tools): Add gdbserver. Only build gdbserver on certain systems. * Makefile.in, configure: Rebuild. * Makefile.def (host_modules, dependencies): Add gdbserver. * MAINTAINERS: Add gdbserver. gdb/ChangeLog 2020-02-07 Tom Tromey <tom@tromey.com> * README: Update gdbserver documentation. * gdbserver: Move to top level. * configure.tgt (build_gdbserver): Remove. * configure.ac: Remove --enable-gdbserver. * configure: Rebuild. * Makefile.in (distclean): Don't mention gdbserver. Change-Id: I826b7565b54604711dc7a11edea0499cd51ff39e
Diffstat (limited to 'gdb/gdbserver/mem-break.c')
-rw-r--r--gdb/gdbserver/mem-break.c2237
1 files changed, 0 insertions, 2237 deletions
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
deleted file mode 100644
index 1b6f236..0000000
--- a/gdb/gdbserver/mem-break.c
+++ /dev/null
@@ -1,2237 +0,0 @@
-/* Memory breakpoint operations for the remote server for GDB.
- Copyright (C) 2002-2020 Free Software Foundation, Inc.
-
- Contributed by MontaVista Software.
-
- This file is part of GDB.
-
- 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 <http://www.gnu.org/licenses/>. */
-
-#include "server.h"
-#include "regcache.h"
-#include "ax.h"
-
-#define MAX_BREAKPOINT_LEN 8
-
-/* Helper macro used in loops that append multiple items to a singly-linked
- list instead of inserting items at the head of the list, as, say, in the
- breakpoint lists. LISTPP is a pointer to the pointer that is the head of
- the new list. ITEMP is a pointer to the item to be added to the list.
- TAILP must be defined to be the same type as ITEMP, and initialized to
- NULL. */
-
-#define APPEND_TO_LIST(listpp, itemp, tailp) \
- do \
- { \
- if ((tailp) == NULL) \
- *(listpp) = (itemp); \
- else \
- (tailp)->next = (itemp); \
- (tailp) = (itemp); \
- } \
- while (0)
-
-/* GDB will never try to install multiple breakpoints at the same
- address. However, we can see GDB requesting to insert a breakpoint
- at an address is had already inserted one previously in a few
- situations.
-
- - The RSP documentation on Z packets says that to avoid potential
- problems with duplicate packets, the operations should be
- implemented in an idempotent way.
-
- - A breakpoint is set at ADDR, an address in a shared library.
- Then the shared library is unloaded. And then another, unrelated,
- breakpoint at ADDR is set. There is not breakpoint removal request
- between the first and the second breakpoint.
-
- - When GDB wants to update the target-side breakpoint conditions or
- commands, it re-inserts the breakpoint, with updated
- conditions/commands associated.
-
- Also, we need to keep track of internal breakpoints too, so we do
- need to be able to install multiple breakpoints at the same address
- transparently.
-
- We keep track of two different, and closely related structures. A
- raw breakpoint, which manages the low level, close to the metal
- aspect of a breakpoint. It holds the breakpoint address, and for
- software breakpoints, a buffer holding a copy of the instructions
- that would be in memory had not been a breakpoint there (we call
- that the shadow memory of the breakpoint). We occasionally need to
- temporarilly uninsert a breakpoint without the client knowing about
- it (e.g., to step over an internal breakpoint), so we keep an
- `inserted' state associated with this low level breakpoint
- structure. There can only be one such object for a given address.
- Then, we have (a bit higher level) breakpoints. This structure
- holds a callback to be called whenever a breakpoint is hit, a
- high-level type, and a link to a low level raw breakpoint. There
- can be many high-level breakpoints at the same address, and all of
- them will point to the same raw breakpoint, which is reference
- counted. */
-
-/* The low level, physical, raw breakpoint. */
-struct raw_breakpoint
-{
- struct raw_breakpoint *next;
-
- /* The low level type of the breakpoint (software breakpoint,
- watchpoint, etc.) */
- enum raw_bkpt_type raw_type;
-
- /* A reference count. Each high level breakpoint referencing this
- raw breakpoint accounts for one reference. */
- int refcount;
-
- /* The breakpoint's insertion address. There can only be one raw
- breakpoint for a given PC. */
- CORE_ADDR pc;
-
- /* The breakpoint's kind. This is target specific. Most
- architectures only use one specific instruction for breakpoints, while
- others may use more than one. E.g., on ARM, we need to use different
- breakpoint instructions on Thumb, Thumb-2, and ARM code. Likewise for
- hardware breakpoints -- some architectures (including ARM) need to
- setup debug registers differently depending on mode. */
- int kind;
-
- /* The breakpoint's shadow memory. */
- unsigned char old_data[MAX_BREAKPOINT_LEN];
-
- /* Positive if this breakpoint is currently inserted in the
- inferior. Negative if it was, but we've detected that it's now
- gone. Zero if not inserted. */
- int inserted;
-};
-
-/* The type of a breakpoint. */
-enum bkpt_type
- {
- /* A GDB breakpoint, requested with a Z0 packet. */
- gdb_breakpoint_Z0,
-
- /* A GDB hardware breakpoint, requested with a Z1 packet. */
- gdb_breakpoint_Z1,
-
- /* A GDB write watchpoint, requested with a Z2 packet. */
- gdb_breakpoint_Z2,
-
- /* A GDB read watchpoint, requested with a Z3 packet. */
- gdb_breakpoint_Z3,
-
- /* A GDB access watchpoint, requested with a Z4 packet. */
- gdb_breakpoint_Z4,
-
- /* A software single-step breakpoint. */
- single_step_breakpoint,
-
- /* Any other breakpoint type that doesn't require specific
- treatment goes here. E.g., an event breakpoint. */
- other_breakpoint,
- };
-
-struct point_cond_list
-{
- /* Pointer to the agent expression that is the breakpoint's
- conditional. */
- struct agent_expr *cond;
-
- /* Pointer to the next condition. */
- struct point_cond_list *next;
-};
-
-struct point_command_list
-{
- /* Pointer to the agent expression that is the breakpoint's
- commands. */
- struct agent_expr *cmd;
-
- /* Flag that is true if this command should run even while GDB is
- disconnected. */
- int persistence;
-
- /* Pointer to the next command. */
- struct point_command_list *next;
-};
-
-/* A high level (in gdbserver's perspective) breakpoint. */
-struct breakpoint
-{
- struct breakpoint *next;
-
- /* The breakpoint's type. */
- enum bkpt_type type;
-
- /* Link to this breakpoint's raw breakpoint. This is always
- non-NULL. */
- struct raw_breakpoint *raw;
-};
-
-/* Breakpoint requested by GDB. */
-
-struct gdb_breakpoint
-{
- struct breakpoint base;
-
- /* Pointer to the condition list that should be evaluated on
- the target or NULL if the breakpoint is unconditional or
- if GDB doesn't want us to evaluate the conditionals on the
- target's side. */
- struct point_cond_list *cond_list;
-
- /* Point to the list of commands to run when this is hit. */
- struct point_command_list *command_list;
-};
-
-/* Breakpoint used by GDBserver. */
-
-struct other_breakpoint
-{
- struct breakpoint base;
-
- /* Function to call when we hit this breakpoint. If it returns 1,
- the breakpoint shall be deleted; 0 or if this callback is NULL,
- it will be left inserted. */
- int (*handler) (CORE_ADDR);
-};
-
-/* Breakpoint for single step. */
-
-struct single_step_breakpoint
-{
- struct breakpoint base;
-
- /* Thread the reinsert breakpoint belongs to. */
- ptid_t ptid;
-};
-
-/* Return the breakpoint size from its kind. */
-
-static int
-bp_size (struct raw_breakpoint *bp)
-{
- int size = 0;
-
- the_target->sw_breakpoint_from_kind (bp->kind, &size);
- return size;
-}
-
-/* Return the breakpoint opcode from its kind. */
-
-static const gdb_byte *
-bp_opcode (struct raw_breakpoint *bp)
-{
- int size = 0;
-
- return the_target->sw_breakpoint_from_kind (bp->kind, &size);
-}
-
-/* See mem-break.h. */
-
-enum target_hw_bp_type
-raw_bkpt_type_to_target_hw_bp_type (enum raw_bkpt_type raw_type)
-{
- switch (raw_type)
- {
- case raw_bkpt_type_hw:
- return hw_execute;
- case raw_bkpt_type_write_wp:
- return hw_write;
- case raw_bkpt_type_read_wp:
- return hw_read;
- case raw_bkpt_type_access_wp:
- return hw_access;
- default:
- internal_error (__FILE__, __LINE__,
- "bad raw breakpoint type %d", (int) raw_type);
- }
-}
-
-/* See mem-break.h. */
-
-static enum bkpt_type
-Z_packet_to_bkpt_type (char z_type)
-{
- gdb_assert ('0' <= z_type && z_type <= '4');
-
- return (enum bkpt_type) (gdb_breakpoint_Z0 + (z_type - '0'));
-}
-
-/* See mem-break.h. */
-
-enum raw_bkpt_type
-Z_packet_to_raw_bkpt_type (char z_type)
-{
- switch (z_type)
- {
- case Z_PACKET_SW_BP:
- return raw_bkpt_type_sw;
- case Z_PACKET_HW_BP:
- return raw_bkpt_type_hw;
- case Z_PACKET_WRITE_WP:
- return raw_bkpt_type_write_wp;
- case Z_PACKET_READ_WP:
- return raw_bkpt_type_read_wp;
- case Z_PACKET_ACCESS_WP:
- return raw_bkpt_type_access_wp;
- default:
- gdb_assert_not_reached ("unhandled Z packet type.");
- }
-}
-
-/* Return true if breakpoint TYPE is a GDB breakpoint. */
-
-static int
-is_gdb_breakpoint (enum bkpt_type type)
-{
- return (type == gdb_breakpoint_Z0
- || type == gdb_breakpoint_Z1
- || type == gdb_breakpoint_Z2
- || type == gdb_breakpoint_Z3
- || type == gdb_breakpoint_Z4);
-}
-
-bool
-any_persistent_commands (process_info *proc)
-{
- struct breakpoint *bp;
- struct point_command_list *cl;
-
- for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- {
- if (is_gdb_breakpoint (bp->type))
- {
- struct gdb_breakpoint *gdb_bp = (struct gdb_breakpoint *) bp;
-
- for (cl = gdb_bp->command_list; cl != NULL; cl = cl->next)
- if (cl->persistence)
- return true;
- }
- }
-
- return false;
-}
-
-/* Find low-level breakpoint of type TYPE at address ADDR that is not
- insert-disabled. Returns NULL if not found. */
-
-static struct raw_breakpoint *
-find_enabled_raw_code_breakpoint_at (CORE_ADDR addr, enum raw_bkpt_type type)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if (bp->pc == addr
- && bp->raw_type == type
- && bp->inserted >= 0)
- return bp;
-
- return NULL;
-}
-
-/* Find low-level breakpoint of type TYPE at address ADDR. Returns
- NULL if not found. */
-
-static struct raw_breakpoint *
-find_raw_breakpoint_at (CORE_ADDR addr, enum raw_bkpt_type type, int kind)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if (bp->pc == addr && bp->raw_type == type && bp->kind == kind)
- return bp;
-
- return NULL;
-}
-
-/* See mem-break.h. */
-
-int
-insert_memory_breakpoint (struct raw_breakpoint *bp)
-{
- unsigned char buf[MAX_BREAKPOINT_LEN];
- int err;
-
- /* Note that there can be fast tracepoint jumps installed in the
- same memory range, so to get at the original memory, we need to
- use read_inferior_memory, which masks those out. */
- err = read_inferior_memory (bp->pc, buf, bp_size (bp));
- if (err != 0)
- {
- if (debug_threads)
- debug_printf ("Failed to read shadow memory of"
- " breakpoint at 0x%s (%s).\n",
- paddress (bp->pc), safe_strerror (err));
- }
- else
- {
- memcpy (bp->old_data, buf, bp_size (bp));
-
- err = (*the_target->write_memory) (bp->pc, bp_opcode (bp),
- bp_size (bp));
- if (err != 0)
- {
- if (debug_threads)
- debug_printf ("Failed to insert breakpoint at 0x%s (%s).\n",
- paddress (bp->pc), safe_strerror (err));
- }
- }
- return err != 0 ? -1 : 0;
-}
-
-/* See mem-break.h */
-
-int
-remove_memory_breakpoint (struct raw_breakpoint *bp)
-{
- unsigned char buf[MAX_BREAKPOINT_LEN];
- int err;
-
- /* Since there can be trap breakpoints inserted in the same address
- range, we use `target_write_memory', which takes care of
- layering breakpoints on top of fast tracepoints, and on top of
- the buffer we pass it. This works because the caller has already
- either unlinked the breakpoint or marked it uninserted. Also
- note that we need to pass the current shadow contents, because
- target_write_memory updates any shadow memory with what we pass
- here, and we want that to be a nop. */
- memcpy (buf, bp->old_data, bp_size (bp));
- err = target_write_memory (bp->pc, buf, bp_size (bp));
- if (err != 0)
- {
- if (debug_threads)
- debug_printf ("Failed to uninsert raw breakpoint "
- "at 0x%s (%s) while deleting it.\n",
- paddress (bp->pc), safe_strerror (err));
- }
- return err != 0 ? -1 : 0;
-}
-
-/* Set a RAW breakpoint of type TYPE and kind KIND at WHERE. On
- success, a pointer to the new breakpoint is returned. On failure,
- returns NULL and writes the error code to *ERR. */
-
-static struct raw_breakpoint *
-set_raw_breakpoint_at (enum raw_bkpt_type type, CORE_ADDR where, int kind,
- int *err)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- if (type == raw_bkpt_type_sw || type == raw_bkpt_type_hw)
- {
- bp = find_enabled_raw_code_breakpoint_at (where, type);
- if (bp != NULL && bp->kind != kind)
- {
- /* A different kind than previously seen. The previous
- breakpoint must be gone then. */
- if (debug_threads)
- debug_printf ("Inconsistent breakpoint kind? Was %d, now %d.\n",
- bp->kind, kind);
- bp->inserted = -1;
- bp = NULL;
- }
- }
- else
- bp = find_raw_breakpoint_at (where, type, kind);
-
- gdb::unique_xmalloc_ptr<struct raw_breakpoint> bp_holder;
- if (bp == NULL)
- {
- bp_holder.reset (XCNEW (struct raw_breakpoint));
- bp = bp_holder.get ();
- bp->pc = where;
- bp->kind = kind;
- bp->raw_type = type;
- }
-
- if (!bp->inserted)
- {
- *err = the_target->insert_point (bp->raw_type, bp->pc, bp->kind, bp);
- if (*err != 0)
- {
- if (debug_threads)
- debug_printf ("Failed to insert breakpoint at 0x%s (%d).\n",
- paddress (where), *err);
-
- return NULL;
- }
-
- bp->inserted = 1;
- }
-
- /* If the breakpoint was allocated above, we know we want to keep it
- now. */
- bp_holder.release ();
-
- /* Link the breakpoint in, if this is the first reference. */
- if (++bp->refcount == 1)
- {
- bp->next = proc->raw_breakpoints;
- proc->raw_breakpoints = bp;
- }
- return bp;
-}
-
-/* Notice that breakpoint traps are always installed on top of fast
- tracepoint jumps. This is even if the fast tracepoint is installed
- at a later time compared to when the breakpoint was installed.
- This means that a stopping breakpoint or tracepoint has higher
- "priority". In turn, this allows having fast and slow tracepoints
- (and breakpoints) at the same address behave correctly. */
-
-
-/* A fast tracepoint jump. */
-
-struct fast_tracepoint_jump
-{
- struct fast_tracepoint_jump *next;
-
- /* A reference count. GDB can install more than one fast tracepoint
- at the same address (each with its own action list, for
- example). */
- int refcount;
-
- /* The fast tracepoint's insertion address. There can only be one
- of these for a given PC. */
- CORE_ADDR pc;
-
- /* Non-zero if this fast tracepoint jump is currently inserted in
- the inferior. */
- int inserted;
-
- /* The length of the jump instruction. */
- int length;
-
- /* A poor-man's flexible array member, holding both the jump
- instruction to insert, and a copy of the instruction that would
- be in memory had not been a jump there (the shadow memory of the
- tracepoint jump). */
- unsigned char insn_and_shadow[0];
-};
-
-/* Fast tracepoint FP's jump instruction to insert. */
-#define fast_tracepoint_jump_insn(fp) \
- ((fp)->insn_and_shadow + 0)
-
-/* The shadow memory of fast tracepoint jump FP. */
-#define fast_tracepoint_jump_shadow(fp) \
- ((fp)->insn_and_shadow + (fp)->length)
-
-
-/* Return the fast tracepoint jump set at WHERE. */
-
-static struct fast_tracepoint_jump *
-find_fast_tracepoint_jump_at (CORE_ADDR where)
-{
- struct process_info *proc = current_process ();
- struct fast_tracepoint_jump *jp;
-
- for (jp = proc->fast_tracepoint_jumps; jp != NULL; jp = jp->next)
- if (jp->pc == where)
- return jp;
-
- return NULL;
-}
-
-int
-fast_tracepoint_jump_here (CORE_ADDR where)
-{
- struct fast_tracepoint_jump *jp = find_fast_tracepoint_jump_at (where);
-
- return (jp != NULL);
-}
-
-int
-delete_fast_tracepoint_jump (struct fast_tracepoint_jump *todel)
-{
- struct fast_tracepoint_jump *bp, **bp_link;
- int ret;
- struct process_info *proc = current_process ();
-
- bp = proc->fast_tracepoint_jumps;
- bp_link = &proc->fast_tracepoint_jumps;
-
- while (bp)
- {
- if (bp == todel)
- {
- if (--bp->refcount == 0)
- {
- struct fast_tracepoint_jump *prev_bp_link = *bp_link;
- unsigned char *buf;
-
- /* Unlink it. */
- *bp_link = bp->next;
-
- /* Since there can be breakpoints inserted in the same
- address range, we use `target_write_memory', which
- takes care of layering breakpoints on top of fast
- tracepoints, and on top of the buffer we pass it.
- This works because we've already unlinked the fast
- tracepoint jump above. Also note that we need to
- pass the current shadow contents, because
- target_write_memory updates any shadow memory with
- what we pass here, and we want that to be a nop. */
- buf = (unsigned char *) alloca (bp->length);
- memcpy (buf, fast_tracepoint_jump_shadow (bp), bp->length);
- ret = target_write_memory (bp->pc, buf, bp->length);
- if (ret != 0)
- {
- /* Something went wrong, relink the jump. */
- *bp_link = prev_bp_link;
-
- if (debug_threads)
- debug_printf ("Failed to uninsert fast tracepoint jump "
- "at 0x%s (%s) while deleting it.\n",
- paddress (bp->pc), safe_strerror (ret));
- return ret;
- }
-
- free (bp);
- }
-
- return 0;
- }
- else
- {
- bp_link = &bp->next;
- bp = *bp_link;
- }
- }
-
- warning ("Could not find fast tracepoint jump in list.");
- return ENOENT;
-}
-
-void
-inc_ref_fast_tracepoint_jump (struct fast_tracepoint_jump *jp)
-{
- jp->refcount++;
-}
-
-struct fast_tracepoint_jump *
-set_fast_tracepoint_jump (CORE_ADDR where,
- unsigned char *insn, ULONGEST length)
-{
- struct process_info *proc = current_process ();
- struct fast_tracepoint_jump *jp;
- int err;
- unsigned char *buf;
-
- /* We refcount fast tracepoint jumps. Check if we already know
- about a jump at this address. */
- jp = find_fast_tracepoint_jump_at (where);
- if (jp != NULL)
- {
- jp->refcount++;
- return jp;
- }
-
- /* We don't, so create a new object. Double the length, because the
- flexible array member holds both the jump insn, and the
- shadow. */
- jp = (struct fast_tracepoint_jump *) xcalloc (1, sizeof (*jp) + (length * 2));
- jp->pc = where;
- jp->length = length;
- memcpy (fast_tracepoint_jump_insn (jp), insn, length);
- jp->refcount = 1;
- buf = (unsigned char *) alloca (length);
-
- /* Note that there can be trap breakpoints inserted in the same
- address range. To access the original memory contents, we use
- `read_inferior_memory', which masks out breakpoints. */
- err = read_inferior_memory (where, buf, length);
- if (err != 0)
- {
- if (debug_threads)
- debug_printf ("Failed to read shadow memory of"
- " fast tracepoint at 0x%s (%s).\n",
- paddress (where), safe_strerror (err));
- free (jp);
- return NULL;
- }
- memcpy (fast_tracepoint_jump_shadow (jp), buf, length);
-
- /* Link the jump in. */
- jp->inserted = 1;
- jp->next = proc->fast_tracepoint_jumps;
- proc->fast_tracepoint_jumps = jp;
-
- /* Since there can be trap breakpoints inserted in the same address
- range, we use use `target_write_memory', which takes care of
- layering breakpoints on top of fast tracepoints, on top of the
- buffer we pass it. This works because we've already linked in
- the fast tracepoint jump above. Also note that we need to pass
- the current shadow contents, because target_write_memory
- updates any shadow memory with what we pass here, and we want
- that to be a nop. */
- err = target_write_memory (where, buf, length);
- if (err != 0)
- {
- if (debug_threads)
- debug_printf ("Failed to insert fast tracepoint jump at 0x%s (%s).\n",
- paddress (where), safe_strerror (err));
-
- /* Unlink it. */
- proc->fast_tracepoint_jumps = jp->next;
- free (jp);
-
- return NULL;
- }
-
- return jp;
-}
-
-void
-uninsert_fast_tracepoint_jumps_at (CORE_ADDR pc)
-{
- struct fast_tracepoint_jump *jp;
- int err;
-
- jp = find_fast_tracepoint_jump_at (pc);
- if (jp == NULL)
- {
- /* This can happen when we remove all breakpoints while handling
- a step-over. */
- if (debug_threads)
- debug_printf ("Could not find fast tracepoint jump at 0x%s "
- "in list (uninserting).\n",
- paddress (pc));
- return;
- }
-
- if (jp->inserted)
- {
- unsigned char *buf;
-
- jp->inserted = 0;
-
- /* Since there can be trap breakpoints inserted in the same
- address range, we use use `target_write_memory', which
- takes care of layering breakpoints on top of fast
- tracepoints, and on top of the buffer we pass it. This works
- because we've already marked the fast tracepoint fast
- tracepoint jump uninserted above. Also note that we need to
- pass the current shadow contents, because
- target_write_memory updates any shadow memory with what we
- pass here, and we want that to be a nop. */
- buf = (unsigned char *) alloca (jp->length);
- memcpy (buf, fast_tracepoint_jump_shadow (jp), jp->length);
- err = target_write_memory (jp->pc, buf, jp->length);
- if (err != 0)
- {
- jp->inserted = 1;
-
- if (debug_threads)
- debug_printf ("Failed to uninsert fast tracepoint jump at"
- " 0x%s (%s).\n",
- paddress (pc), safe_strerror (err));
- }
- }
-}
-
-void
-reinsert_fast_tracepoint_jumps_at (CORE_ADDR where)
-{
- struct fast_tracepoint_jump *jp;
- int err;
- unsigned char *buf;
-
- jp = find_fast_tracepoint_jump_at (where);
- if (jp == NULL)
- {
- /* This can happen when we remove breakpoints when a tracepoint
- hit causes a tracing stop, while handling a step-over. */
- if (debug_threads)
- debug_printf ("Could not find fast tracepoint jump at 0x%s "
- "in list (reinserting).\n",
- paddress (where));
- return;
- }
-
- if (jp->inserted)
- error ("Jump already inserted at reinsert time.");
-
- jp->inserted = 1;
-
- /* Since there can be trap breakpoints inserted in the same address
- range, we use `target_write_memory', which takes care of
- layering breakpoints on top of fast tracepoints, and on top of
- the buffer we pass it. This works because we've already marked
- the fast tracepoint jump inserted above. Also note that we need
- to pass the current shadow contents, because
- target_write_memory updates any shadow memory with what we pass
- here, and we want that to be a nop. */
- buf = (unsigned char *) alloca (jp->length);
- memcpy (buf, fast_tracepoint_jump_shadow (jp), jp->length);
- err = target_write_memory (where, buf, jp->length);
- if (err != 0)
- {
- jp->inserted = 0;
-
- if (debug_threads)
- debug_printf ("Failed to reinsert fast tracepoint jump at"
- " 0x%s (%s).\n",
- paddress (where), safe_strerror (err));
- }
-}
-
-/* Set a high-level breakpoint of type TYPE, with low level type
- RAW_TYPE and kind KIND, at WHERE. On success, a pointer to the new
- breakpoint is returned. On failure, returns NULL and writes the
- error code to *ERR. HANDLER is called when the breakpoint is hit.
- HANDLER should return 1 if the breakpoint should be deleted, 0
- otherwise. */
-
-static struct breakpoint *
-set_breakpoint (enum bkpt_type type, enum raw_bkpt_type raw_type,
- CORE_ADDR where, int kind,
- int (*handler) (CORE_ADDR), int *err)
-{
- struct process_info *proc = current_process ();
- struct breakpoint *bp;
- struct raw_breakpoint *raw;
-
- raw = set_raw_breakpoint_at (raw_type, where, kind, err);
-
- if (raw == NULL)
- {
- /* warn? */
- return NULL;
- }
-
- if (is_gdb_breakpoint (type))
- {
- struct gdb_breakpoint *gdb_bp = XCNEW (struct gdb_breakpoint);
-
- bp = (struct breakpoint *) gdb_bp;
- gdb_assert (handler == NULL);
- }
- else if (type == other_breakpoint)
- {
- struct other_breakpoint *other_bp = XCNEW (struct other_breakpoint);
-
- other_bp->handler = handler;
- bp = (struct breakpoint *) other_bp;
- }
- else if (type == single_step_breakpoint)
- {
- struct single_step_breakpoint *ss_bp
- = XCNEW (struct single_step_breakpoint);
-
- bp = (struct breakpoint *) ss_bp;
- }
- else
- gdb_assert_not_reached ("unhandled breakpoint type");
-
- bp->type = type;
- bp->raw = raw;
-
- bp->next = proc->breakpoints;
- proc->breakpoints = bp;
-
- return bp;
-}
-
-/* Set breakpoint of TYPE on address WHERE with handler HANDLER. */
-
-static struct breakpoint *
-set_breakpoint_type_at (enum bkpt_type type, CORE_ADDR where,
- int (*handler) (CORE_ADDR))
-{
- int err_ignored;
- CORE_ADDR placed_address = where;
- int breakpoint_kind = target_breakpoint_kind_from_pc (&placed_address);
-
- return set_breakpoint (type, raw_bkpt_type_sw,
- placed_address, breakpoint_kind, handler,
- &err_ignored);
-}
-
-/* See mem-break.h */
-
-struct breakpoint *
-set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
-{
- return set_breakpoint_type_at (other_breakpoint, where, handler);
-}
-
-
-static int
-delete_raw_breakpoint (struct process_info *proc, struct raw_breakpoint *todel)
-{
- struct raw_breakpoint *bp, **bp_link;
- int ret;
-
- bp = proc->raw_breakpoints;
- bp_link = &proc->raw_breakpoints;
-
- while (bp)
- {
- if (bp == todel)
- {
- if (bp->inserted > 0)
- {
- struct raw_breakpoint *prev_bp_link = *bp_link;
-
- *bp_link = bp->next;
-
- ret = the_target->remove_point (bp->raw_type, bp->pc, bp->kind,
- bp);
- if (ret != 0)
- {
- /* Something went wrong, relink the breakpoint. */
- *bp_link = prev_bp_link;
-
- if (debug_threads)
- debug_printf ("Failed to uninsert raw breakpoint "
- "at 0x%s while deleting it.\n",
- paddress (bp->pc));
- return ret;
- }
- }
- else
- *bp_link = bp->next;
-
- free (bp);
- return 0;
- }
- else
- {
- bp_link = &bp->next;
- bp = *bp_link;
- }
- }
-
- warning ("Could not find raw breakpoint in list.");
- return ENOENT;
-}
-
-static int
-release_breakpoint (struct process_info *proc, struct breakpoint *bp)
-{
- int newrefcount;
- int ret;
-
- newrefcount = bp->raw->refcount - 1;
- if (newrefcount == 0)
- {
- ret = delete_raw_breakpoint (proc, bp->raw);
- if (ret != 0)
- return ret;
- }
- else
- bp->raw->refcount = newrefcount;
-
- free (bp);
-
- return 0;
-}
-
-static int
-delete_breakpoint_1 (struct process_info *proc, struct breakpoint *todel)
-{
- struct breakpoint *bp, **bp_link;
- int err;
-
- bp = proc->breakpoints;
- bp_link = &proc->breakpoints;
-
- while (bp)
- {
- if (bp == todel)
- {
- *bp_link = bp->next;
-
- err = release_breakpoint (proc, bp);
- if (err != 0)
- return err;
-
- bp = *bp_link;
- return 0;
- }
- else
- {
- bp_link = &bp->next;
- bp = *bp_link;
- }
- }
-
- warning ("Could not find breakpoint in list.");
- return ENOENT;
-}
-
-int
-delete_breakpoint (struct breakpoint *todel)
-{
- struct process_info *proc = current_process ();
- return delete_breakpoint_1 (proc, todel);
-}
-
-/* Locate a GDB breakpoint of type Z_TYPE and kind KIND placed at
- address ADDR and return a pointer to its structure. If KIND is -1,
- the breakpoint's kind is ignored. */
-
-static struct gdb_breakpoint *
-find_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind)
-{
- struct process_info *proc = current_process ();
- struct breakpoint *bp;
- enum bkpt_type type = Z_packet_to_bkpt_type (z_type);
-
- for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- if (bp->type == type && bp->raw->pc == addr
- && (kind == -1 || bp->raw->kind == kind))
- return (struct gdb_breakpoint *) bp;
-
- return NULL;
-}
-
-static int
-z_type_supported (char z_type)
-{
- return (z_type >= '0' && z_type <= '4'
- && the_target->supports_z_point_type != NULL
- && the_target->supports_z_point_type (z_type));
-}
-
-/* Create a new GDB breakpoint of type Z_TYPE at ADDR with kind KIND.
- Returns a pointer to the newly created breakpoint on success. On
- failure returns NULL and sets *ERR to either -1 for error, or 1 if
- Z_TYPE breakpoints are not supported on this target. */
-
-static struct gdb_breakpoint *
-set_gdb_breakpoint_1 (char z_type, CORE_ADDR addr, int kind, int *err)
-{
- struct gdb_breakpoint *bp;
- enum bkpt_type type;
- enum raw_bkpt_type raw_type;
-
- /* If we see GDB inserting a second code breakpoint at the same
- address, then either: GDB is updating the breakpoint's conditions
- or commands; or, the first breakpoint must have disappeared due
- to a shared library unload. On targets where the shared
- libraries are handled by userspace, like SVR4, for example,
- GDBserver can't tell if a library was loaded or unloaded. Since
- we refcount raw breakpoints, we must be careful to make sure GDB
- breakpoints never contribute more than one reference. if we
- didn't do this, in case the previous breakpoint is gone due to a
- shared library unload, we'd just increase the refcount of the
- previous breakpoint at this address, but the trap was not planted
- in the inferior anymore, thus the breakpoint would never be hit.
- Note this must be careful to not create a window where
- breakpoints are removed from the target, for non-stop, in case
- the target can poke at memory while the program is running. */
- if (z_type == Z_PACKET_SW_BP
- || z_type == Z_PACKET_HW_BP)
- {
- bp = find_gdb_breakpoint (z_type, addr, -1);
-
- if (bp != NULL)
- {
- if (bp->base.raw->kind != kind)
- {
- /* A different kind than previously seen. The previous
- breakpoint must be gone then. */
- bp->base.raw->inserted = -1;
- delete_breakpoint ((struct breakpoint *) bp);
- bp = NULL;
- }
- else if (z_type == Z_PACKET_SW_BP)
- {
- /* Check if the breakpoint is actually gone from the
- target, due to an solib unload, for example. Might
- as well validate _all_ breakpoints. */
- validate_breakpoints ();
-
- /* Breakpoints that don't pass validation are
- deleted. */
- bp = find_gdb_breakpoint (z_type, addr, -1);
- }
- }
- }
- else
- {
- /* Data breakpoints for the same address but different kind are
- expected. GDB doesn't merge these. The backend gets to do
- that if it wants/can. */
- bp = find_gdb_breakpoint (z_type, addr, kind);
- }
-
- if (bp != NULL)
- {
- /* We already know about this breakpoint, there's nothing else
- to do - GDB's reference is already accounted for. Note that
- whether the breakpoint inserted is left as is - we may be
- stepping over it, for example, in which case we don't want to
- force-reinsert it. */
- return bp;
- }
-
- raw_type = Z_packet_to_raw_bkpt_type (z_type);
- type = Z_packet_to_bkpt_type (z_type);
- return (struct gdb_breakpoint *) set_breakpoint (type, raw_type, addr,
- kind, NULL, err);
-}
-
-static int
-check_gdb_bp_preconditions (char z_type, int *err)
-{
- /* As software/memory breakpoints work by poking at memory, we need
- to prepare to access memory. If that operation fails, we need to
- return error. Seeing an error, if this is the first breakpoint
- of that type that GDB tries to insert, GDB would then assume the
- breakpoint type is supported, but it may actually not be. So we
- need to check whether the type is supported at all before
- preparing to access memory. */
- if (!z_type_supported (z_type))
- {
- *err = 1;
- return 0;
- }
-
- return 1;
-}
-
-/* See mem-break.h. This is a wrapper for set_gdb_breakpoint_1 that
- knows to prepare to access memory for Z0 breakpoints. */
-
-struct gdb_breakpoint *
-set_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind, int *err)
-{
- struct gdb_breakpoint *bp;
-
- if (!check_gdb_bp_preconditions (z_type, err))
- return NULL;
-
- /* If inserting a software/memory breakpoint, need to prepare to
- access memory. */
- if (z_type == Z_PACKET_SW_BP)
- {
- if (prepare_to_access_memory () != 0)
- {
- *err = -1;
- return NULL;
- }
- }
-
- bp = set_gdb_breakpoint_1 (z_type, addr, kind, err);
-
- if (z_type == Z_PACKET_SW_BP)
- done_accessing_memory ();
-
- return bp;
-}
-
-/* Delete a GDB breakpoint of type Z_TYPE and kind KIND previously
- inserted at ADDR with set_gdb_breakpoint_at. Returns 0 on success,
- -1 on error, and 1 if Z_TYPE breakpoints are not supported on this
- target. */
-
-static int
-delete_gdb_breakpoint_1 (char z_type, CORE_ADDR addr, int kind)
-{
- struct gdb_breakpoint *bp;
- int err;
-
- bp = find_gdb_breakpoint (z_type, addr, kind);
- if (bp == NULL)
- return -1;
-
- /* Before deleting the breakpoint, make sure to free its condition
- and command lists. */
- clear_breakpoint_conditions_and_commands (bp);
- err = delete_breakpoint ((struct breakpoint *) bp);
- if (err != 0)
- return -1;
-
- return 0;
-}
-
-/* See mem-break.h. This is a wrapper for delete_gdb_breakpoint that
- knows to prepare to access memory for Z0 breakpoints. */
-
-int
-delete_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind)
-{
- int ret;
-
- if (!check_gdb_bp_preconditions (z_type, &ret))
- return ret;
-
- /* If inserting a software/memory breakpoint, need to prepare to
- access memory. */
- if (z_type == Z_PACKET_SW_BP)
- {
- int err;
-
- err = prepare_to_access_memory ();
- if (err != 0)
- return -1;
- }
-
- ret = delete_gdb_breakpoint_1 (z_type, addr, kind);
-
- if (z_type == Z_PACKET_SW_BP)
- done_accessing_memory ();
-
- return ret;
-}
-
-/* Clear all conditions associated with a breakpoint. */
-
-static void
-clear_breakpoint_conditions (struct gdb_breakpoint *bp)
-{
- struct point_cond_list *cond;
-
- if (bp->cond_list == NULL)
- return;
-
- cond = bp->cond_list;
-
- while (cond != NULL)
- {
- struct point_cond_list *cond_next;
-
- cond_next = cond->next;
- gdb_free_agent_expr (cond->cond);
- free (cond);
- cond = cond_next;
- }
-
- bp->cond_list = NULL;
-}
-
-/* Clear all commands associated with a breakpoint. */
-
-static void
-clear_breakpoint_commands (struct gdb_breakpoint *bp)
-{
- struct point_command_list *cmd;
-
- if (bp->command_list == NULL)
- return;
-
- cmd = bp->command_list;
-
- while (cmd != NULL)
- {
- struct point_command_list *cmd_next;
-
- cmd_next = cmd->next;
- gdb_free_agent_expr (cmd->cmd);
- free (cmd);
- cmd = cmd_next;
- }
-
- bp->command_list = NULL;
-}
-
-void
-clear_breakpoint_conditions_and_commands (struct gdb_breakpoint *bp)
-{
- clear_breakpoint_conditions (bp);
- clear_breakpoint_commands (bp);
-}
-
-/* Add condition CONDITION to GDBserver's breakpoint BP. */
-
-static void
-add_condition_to_breakpoint (struct gdb_breakpoint *bp,
- struct agent_expr *condition)
-{
- struct point_cond_list *new_cond;
-
- /* Create new condition. */
- new_cond = XCNEW (struct point_cond_list);
- new_cond->cond = condition;
-
- /* Add condition to the list. */
- new_cond->next = bp->cond_list;
- bp->cond_list = new_cond;
-}
-
-/* Add a target-side condition CONDITION to a breakpoint. */
-
-int
-add_breakpoint_condition (struct gdb_breakpoint *bp, const char **condition)
-{
- const char *actparm = *condition;
- struct agent_expr *cond;
-
- if (condition == NULL)
- return 1;
-
- if (bp == NULL)
- return 0;
-
- cond = gdb_parse_agent_expr (&actparm);
-
- if (cond == NULL)
- {
- warning ("Condition evaluation failed. Assuming unconditional.");
- return 0;
- }
-
- add_condition_to_breakpoint (bp, cond);
-
- *condition = actparm;
-
- return 1;
-}
-
-/* Evaluate condition (if any) at breakpoint BP. Return 1 if
- true and 0 otherwise. */
-
-static int
-gdb_condition_true_at_breakpoint_z_type (char z_type, CORE_ADDR addr)
-{
- /* Fetch registers for the current inferior. */
- struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1);
- ULONGEST value = 0;
- struct point_cond_list *cl;
- int err = 0;
- struct eval_agent_expr_context ctx;
-
- if (bp == NULL)
- return 0;
-
- /* Check if the breakpoint is unconditional. If it is,
- the condition always evaluates to TRUE. */
- if (bp->cond_list == NULL)
- return 1;
-
- ctx.regcache = get_thread_regcache (current_thread, 1);
- ctx.tframe = NULL;
- ctx.tpoint = NULL;
-
- /* Evaluate each condition in the breakpoint's list of conditions.
- Return true if any of the conditions evaluates to TRUE.
-
- If we failed to evaluate the expression, TRUE is returned. This
- forces GDB to reevaluate the conditions. */
- for (cl = bp->cond_list;
- cl && !value && !err; cl = cl->next)
- {
- /* Evaluate the condition. */
- err = gdb_eval_agent_expr (&ctx, cl->cond, &value);
- }
-
- if (err)
- return 1;
-
- return (value != 0);
-}
-
-int
-gdb_condition_true_at_breakpoint (CORE_ADDR where)
-{
- /* Only check code (software or hardware) breakpoints. */
- return (gdb_condition_true_at_breakpoint_z_type (Z_PACKET_SW_BP, where)
- || gdb_condition_true_at_breakpoint_z_type (Z_PACKET_HW_BP, where));
-}
-
-/* Add commands COMMANDS to GDBserver's breakpoint BP. */
-
-static void
-add_commands_to_breakpoint (struct gdb_breakpoint *bp,
- struct agent_expr *commands, int persist)
-{
- struct point_command_list *new_cmd;
-
- /* Create new command. */
- new_cmd = XCNEW (struct point_command_list);
- new_cmd->cmd = commands;
- new_cmd->persistence = persist;
-
- /* Add commands to the list. */
- new_cmd->next = bp->command_list;
- bp->command_list = new_cmd;
-}
-
-/* Add a target-side command COMMAND to the breakpoint at ADDR. */
-
-int
-add_breakpoint_commands (struct gdb_breakpoint *bp, const char **command,
- int persist)
-{
- const char *actparm = *command;
- struct agent_expr *cmd;
-
- if (command == NULL)
- return 1;
-
- if (bp == NULL)
- return 0;
-
- cmd = gdb_parse_agent_expr (&actparm);
-
- if (cmd == NULL)
- {
- warning ("Command evaluation failed. Disabling.");
- return 0;
- }
-
- add_commands_to_breakpoint (bp, cmd, persist);
-
- *command = actparm;
-
- return 1;
-}
-
-/* Return true if there are no commands to run at this location,
- which likely means we want to report back to GDB. */
-
-static int
-gdb_no_commands_at_breakpoint_z_type (char z_type, CORE_ADDR addr)
-{
- struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1);
-
- if (bp == NULL)
- return 1;
-
- if (debug_threads)
- debug_printf ("at 0x%s, type Z%c, bp command_list is 0x%s\n",
- paddress (addr), z_type,
- phex_nz ((uintptr_t) bp->command_list, 0));
- return (bp->command_list == NULL);
-}
-
-/* Return true if there are no commands to run at this location,
- which likely means we want to report back to GDB. */
-
-int
-gdb_no_commands_at_breakpoint (CORE_ADDR where)
-{
- /* Only check code (software or hardware) breakpoints. */
- return (gdb_no_commands_at_breakpoint_z_type (Z_PACKET_SW_BP, where)
- && gdb_no_commands_at_breakpoint_z_type (Z_PACKET_HW_BP, where));
-}
-
-/* Run a breakpoint's commands. Returns 0 if there was a problem
- running any command, 1 otherwise. */
-
-static int
-run_breakpoint_commands_z_type (char z_type, CORE_ADDR addr)
-{
- /* Fetch registers for the current inferior. */
- struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1);
- ULONGEST value = 0;
- struct point_command_list *cl;
- int err = 0;
- struct eval_agent_expr_context ctx;
-
- if (bp == NULL)
- return 1;
-
- ctx.regcache = get_thread_regcache (current_thread, 1);
- ctx.tframe = NULL;
- ctx.tpoint = NULL;
-
- for (cl = bp->command_list;
- cl && !value && !err; cl = cl->next)
- {
- /* Run the command. */
- err = gdb_eval_agent_expr (&ctx, cl->cmd, &value);
-
- /* If one command has a problem, stop digging the hole deeper. */
- if (err)
- return 0;
- }
-
- return 1;
-}
-
-void
-run_breakpoint_commands (CORE_ADDR where)
-{
- /* Only check code (software or hardware) breakpoints. If one
- command has a problem, stop digging the hole deeper. */
- if (run_breakpoint_commands_z_type (Z_PACKET_SW_BP, where))
- run_breakpoint_commands_z_type (Z_PACKET_HW_BP, where);
-}
-
-/* See mem-break.h. */
-
-int
-gdb_breakpoint_here (CORE_ADDR where)
-{
- /* Only check code (software or hardware) breakpoints. */
- return (find_gdb_breakpoint (Z_PACKET_SW_BP, where, -1) != NULL
- || find_gdb_breakpoint (Z_PACKET_HW_BP, where, -1) != NULL);
-}
-
-void
-set_single_step_breakpoint (CORE_ADDR stop_at, ptid_t ptid)
-{
- struct single_step_breakpoint *bp;
-
- gdb_assert (current_ptid.pid () == ptid.pid ());
-
- bp = (struct single_step_breakpoint *) set_breakpoint_type_at (single_step_breakpoint,
- stop_at, NULL);
- bp->ptid = ptid;
-}
-
-void
-delete_single_step_breakpoints (struct thread_info *thread)
-{
- struct process_info *proc = get_thread_process (thread);
- struct breakpoint *bp, **bp_link;
-
- bp = proc->breakpoints;
- bp_link = &proc->breakpoints;
-
- while (bp)
- {
- if (bp->type == single_step_breakpoint
- && ((struct single_step_breakpoint *) bp)->ptid == ptid_of (thread))
- {
- struct thread_info *saved_thread = current_thread;
-
- current_thread = thread;
- *bp_link = bp->next;
- release_breakpoint (proc, bp);
- bp = *bp_link;
- current_thread = saved_thread;
- }
- else
- {
- bp_link = &bp->next;
- bp = *bp_link;
- }
- }
-}
-
-static void
-uninsert_raw_breakpoint (struct raw_breakpoint *bp)
-{
- if (bp->inserted < 0)
- {
- if (debug_threads)
- debug_printf ("Breakpoint at %s is marked insert-disabled.\n",
- paddress (bp->pc));
- }
- else if (bp->inserted > 0)
- {
- int err;
-
- bp->inserted = 0;
-
- err = the_target->remove_point (bp->raw_type, bp->pc, bp->kind, bp);
- if (err != 0)
- {
- bp->inserted = 1;
-
- if (debug_threads)
- debug_printf ("Failed to uninsert raw breakpoint at 0x%s.\n",
- paddress (bp->pc));
- }
- }
-}
-
-void
-uninsert_breakpoints_at (CORE_ADDR pc)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
- int found = 0;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if ((bp->raw_type == raw_bkpt_type_sw
- || bp->raw_type == raw_bkpt_type_hw)
- && bp->pc == pc)
- {
- found = 1;
-
- if (bp->inserted)
- uninsert_raw_breakpoint (bp);
- }
-
- if (!found)
- {
- /* This can happen when we remove all breakpoints while handling
- a step-over. */
- if (debug_threads)
- debug_printf ("Could not find breakpoint at 0x%s "
- "in list (uninserting).\n",
- paddress (pc));
- }
-}
-
-void
-uninsert_all_breakpoints (void)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if ((bp->raw_type == raw_bkpt_type_sw
- || bp->raw_type == raw_bkpt_type_hw)
- && bp->inserted)
- uninsert_raw_breakpoint (bp);
-}
-
-void
-uninsert_single_step_breakpoints (struct thread_info *thread)
-{
- struct process_info *proc = get_thread_process (thread);
- struct breakpoint *bp;
-
- for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- {
- if (bp->type == single_step_breakpoint
- && ((struct single_step_breakpoint *) bp)->ptid == ptid_of (thread))
- {
- gdb_assert (bp->raw->inserted > 0);
-
- /* Only uninsert the raw breakpoint if it only belongs to a
- reinsert breakpoint. */
- if (bp->raw->refcount == 1)
- {
- struct thread_info *saved_thread = current_thread;
-
- current_thread = thread;
- uninsert_raw_breakpoint (bp->raw);
- current_thread = saved_thread;
- }
- }
- }
-}
-
-static void
-reinsert_raw_breakpoint (struct raw_breakpoint *bp)
-{
- int err;
-
- if (bp->inserted)
- return;
-
- err = the_target->insert_point (bp->raw_type, bp->pc, bp->kind, bp);
- if (err == 0)
- bp->inserted = 1;
- else if (debug_threads)
- debug_printf ("Failed to reinsert breakpoint at 0x%s (%d).\n",
- paddress (bp->pc), err);
-}
-
-void
-reinsert_breakpoints_at (CORE_ADDR pc)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
- int found = 0;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if ((bp->raw_type == raw_bkpt_type_sw
- || bp->raw_type == raw_bkpt_type_hw)
- && bp->pc == pc)
- {
- found = 1;
-
- reinsert_raw_breakpoint (bp);
- }
-
- if (!found)
- {
- /* This can happen when we remove all breakpoints while handling
- a step-over. */
- if (debug_threads)
- debug_printf ("Could not find raw breakpoint at 0x%s "
- "in list (reinserting).\n",
- paddress (pc));
- }
-}
-
-int
-has_single_step_breakpoints (struct thread_info *thread)
-{
- struct process_info *proc = get_thread_process (thread);
- struct breakpoint *bp, **bp_link;
-
- bp = proc->breakpoints;
- bp_link = &proc->breakpoints;
-
- while (bp)
- {
- if (bp->type == single_step_breakpoint
- && ((struct single_step_breakpoint *) bp)->ptid == ptid_of (thread))
- return 1;
- else
- {
- bp_link = &bp->next;
- bp = *bp_link;
- }
- }
-
- return 0;
-}
-
-void
-reinsert_all_breakpoints (void)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if ((bp->raw_type == raw_bkpt_type_sw
- || bp->raw_type == raw_bkpt_type_hw)
- && !bp->inserted)
- reinsert_raw_breakpoint (bp);
-}
-
-void
-reinsert_single_step_breakpoints (struct thread_info *thread)
-{
- struct process_info *proc = get_thread_process (thread);
- struct breakpoint *bp;
-
- for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- {
- if (bp->type == single_step_breakpoint
- && ((struct single_step_breakpoint *) bp)->ptid == ptid_of (thread))
- {
- gdb_assert (bp->raw->inserted > 0);
-
- if (bp->raw->refcount == 1)
- {
- struct thread_info *saved_thread = current_thread;
-
- current_thread = thread;
- reinsert_raw_breakpoint (bp->raw);
- current_thread = saved_thread;
- }
- }
- }
-}
-
-void
-check_breakpoints (CORE_ADDR stop_pc)
-{
- struct process_info *proc = current_process ();
- struct breakpoint *bp, **bp_link;
-
- bp = proc->breakpoints;
- bp_link = &proc->breakpoints;
-
- while (bp)
- {
- struct raw_breakpoint *raw = bp->raw;
-
- if ((raw->raw_type == raw_bkpt_type_sw
- || raw->raw_type == raw_bkpt_type_hw)
- && raw->pc == stop_pc)
- {
- if (!raw->inserted)
- {
- warning ("Hit a removed breakpoint?");
- return;
- }
-
- if (bp->type == other_breakpoint)
- {
- struct other_breakpoint *other_bp
- = (struct other_breakpoint *) bp;
-
- if (other_bp->handler != NULL && (*other_bp->handler) (stop_pc))
- {
- *bp_link = bp->next;
-
- release_breakpoint (proc, bp);
-
- bp = *bp_link;
- continue;
- }
- }
- }
-
- bp_link = &bp->next;
- bp = *bp_link;
- }
-}
-
-int
-breakpoint_here (CORE_ADDR addr)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if ((bp->raw_type == raw_bkpt_type_sw
- || bp->raw_type == raw_bkpt_type_hw)
- && bp->pc == addr)
- return 1;
-
- return 0;
-}
-
-int
-breakpoint_inserted_here (CORE_ADDR addr)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if ((bp->raw_type == raw_bkpt_type_sw
- || bp->raw_type == raw_bkpt_type_hw)
- && bp->pc == addr
- && bp->inserted)
- return 1;
-
- return 0;
-}
-
-/* See mem-break.h. */
-
-int
-software_breakpoint_inserted_here (CORE_ADDR addr)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if (bp->raw_type == raw_bkpt_type_sw
- && bp->pc == addr
- && bp->inserted)
- return 1;
-
- return 0;
-}
-
-/* See mem-break.h. */
-
-int
-hardware_breakpoint_inserted_here (CORE_ADDR addr)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp;
-
- for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
- if (bp->raw_type == raw_bkpt_type_hw
- && bp->pc == addr
- && bp->inserted)
- return 1;
-
- return 0;
-}
-
-/* See mem-break.h. */
-
-int
-single_step_breakpoint_inserted_here (CORE_ADDR addr)
-{
- struct process_info *proc = current_process ();
- struct breakpoint *bp;
-
- for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- if (bp->type == single_step_breakpoint
- && bp->raw->pc == addr
- && bp->raw->inserted)
- return 1;
-
- return 0;
-}
-
-static int
-validate_inserted_breakpoint (struct raw_breakpoint *bp)
-{
- unsigned char *buf;
- int err;
-
- gdb_assert (bp->inserted);
- gdb_assert (bp->raw_type == raw_bkpt_type_sw);
-
- buf = (unsigned char *) alloca (bp_size (bp));
- err = (*the_target->read_memory) (bp->pc, buf, bp_size (bp));
- if (err || memcmp (buf, bp_opcode (bp), bp_size (bp)) != 0)
- {
- /* Tag it as gone. */
- bp->inserted = -1;
- return 0;
- }
-
- return 1;
-}
-
-static void
-delete_disabled_breakpoints (void)
-{
- struct process_info *proc = current_process ();
- struct breakpoint *bp, *next;
-
- for (bp = proc->breakpoints; bp != NULL; bp = next)
- {
- next = bp->next;
- if (bp->raw->inserted < 0)
- {
- /* If single_step_breakpoints become disabled, that means the
- manipulations (insertion and removal) of them are wrong. */
- gdb_assert (bp->type != single_step_breakpoint);
- delete_breakpoint_1 (proc, bp);
- }
- }
-}
-
-/* Check if breakpoints we inserted still appear to be inserted. They
- may disappear due to a shared library unload, and worse, a new
- shared library may be reloaded at the same address as the
- previously unloaded one. If that happens, we should make sure that
- the shadow memory of the old breakpoints isn't used when reading or
- writing memory. */
-
-void
-validate_breakpoints (void)
-{
- struct process_info *proc = current_process ();
- struct breakpoint *bp;
-
- for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- {
- struct raw_breakpoint *raw = bp->raw;
-
- if (raw->raw_type == raw_bkpt_type_sw && raw->inserted > 0)
- validate_inserted_breakpoint (raw);
- }
-
- delete_disabled_breakpoints ();
-}
-
-void
-check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp = proc->raw_breakpoints;
- struct fast_tracepoint_jump *jp = proc->fast_tracepoint_jumps;
- CORE_ADDR mem_end = mem_addr + mem_len;
- int disabled_one = 0;
-
- for (; jp != NULL; jp = jp->next)
- {
- CORE_ADDR bp_end = jp->pc + jp->length;
- CORE_ADDR start, end;
- int copy_offset, copy_len, buf_offset;
-
- gdb_assert (fast_tracepoint_jump_shadow (jp) >= buf + mem_len
- || buf >= fast_tracepoint_jump_shadow (jp) + (jp)->length);
-
- if (mem_addr >= bp_end)
- continue;
- if (jp->pc >= mem_end)
- continue;
-
- start = jp->pc;
- if (mem_addr > start)
- start = mem_addr;
-
- end = bp_end;
- if (end > mem_end)
- end = mem_end;
-
- copy_len = end - start;
- copy_offset = start - jp->pc;
- buf_offset = start - mem_addr;
-
- if (jp->inserted)
- memcpy (buf + buf_offset,
- fast_tracepoint_jump_shadow (jp) + copy_offset,
- copy_len);
- }
-
- for (; bp != NULL; bp = bp->next)
- {
- CORE_ADDR bp_end = bp->pc + bp_size (bp);
- CORE_ADDR start, end;
- int copy_offset, copy_len, buf_offset;
-
- if (bp->raw_type != raw_bkpt_type_sw)
- continue;
-
- gdb_assert (bp->old_data >= buf + mem_len
- || buf >= &bp->old_data[sizeof (bp->old_data)]);
-
- if (mem_addr >= bp_end)
- continue;
- if (bp->pc >= mem_end)
- continue;
-
- start = bp->pc;
- if (mem_addr > start)
- start = mem_addr;
-
- end = bp_end;
- if (end > mem_end)
- end = mem_end;
-
- copy_len = end - start;
- copy_offset = start - bp->pc;
- buf_offset = start - mem_addr;
-
- if (bp->inserted > 0)
- {
- if (validate_inserted_breakpoint (bp))
- memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
- else
- disabled_one = 1;
- }
- }
-
- if (disabled_one)
- delete_disabled_breakpoints ();
-}
-
-void
-check_mem_write (CORE_ADDR mem_addr, unsigned char *buf,
- const unsigned char *myaddr, int mem_len)
-{
- struct process_info *proc = current_process ();
- struct raw_breakpoint *bp = proc->raw_breakpoints;
- struct fast_tracepoint_jump *jp = proc->fast_tracepoint_jumps;
- CORE_ADDR mem_end = mem_addr + mem_len;
- int disabled_one = 0;
-
- /* First fast tracepoint jumps, then breakpoint traps on top. */
-
- for (; jp != NULL; jp = jp->next)
- {
- CORE_ADDR jp_end = jp->pc + jp->length;
- CORE_ADDR start, end;
- int copy_offset, copy_len, buf_offset;
-
- gdb_assert (fast_tracepoint_jump_shadow (jp) >= myaddr + mem_len
- || myaddr >= fast_tracepoint_jump_shadow (jp) + (jp)->length);
- gdb_assert (fast_tracepoint_jump_insn (jp) >= buf + mem_len
- || buf >= fast_tracepoint_jump_insn (jp) + (jp)->length);
-
- if (mem_addr >= jp_end)
- continue;
- if (jp->pc >= mem_end)
- continue;
-
- start = jp->pc;
- if (mem_addr > start)
- start = mem_addr;
-
- end = jp_end;
- if (end > mem_end)
- end = mem_end;
-
- copy_len = end - start;
- copy_offset = start - jp->pc;
- buf_offset = start - mem_addr;
-
- memcpy (fast_tracepoint_jump_shadow (jp) + copy_offset,
- myaddr + buf_offset, copy_len);
- if (jp->inserted)
- memcpy (buf + buf_offset,
- fast_tracepoint_jump_insn (jp) + copy_offset, copy_len);
- }
-
- for (; bp != NULL; bp = bp->next)
- {
- CORE_ADDR bp_end = bp->pc + bp_size (bp);
- CORE_ADDR start, end;
- int copy_offset, copy_len, buf_offset;
-
- if (bp->raw_type != raw_bkpt_type_sw)
- continue;
-
- gdb_assert (bp->old_data >= myaddr + mem_len
- || myaddr >= &bp->old_data[sizeof (bp->old_data)]);
-
- if (mem_addr >= bp_end)
- continue;
- if (bp->pc >= mem_end)
- continue;
-
- start = bp->pc;
- if (mem_addr > start)
- start = mem_addr;
-
- end = bp_end;
- if (end > mem_end)
- end = mem_end;
-
- copy_len = end - start;
- copy_offset = start - bp->pc;
- buf_offset = start - mem_addr;
-
- memcpy (bp->old_data + copy_offset, myaddr + buf_offset, copy_len);
- if (bp->inserted > 0)
- {
- if (validate_inserted_breakpoint (bp))
- memcpy (buf + buf_offset, bp_opcode (bp) + copy_offset, copy_len);
- else
- disabled_one = 1;
- }
- }
-
- if (disabled_one)
- delete_disabled_breakpoints ();
-}
-
-/* Delete all breakpoints, and un-insert them from the inferior. */
-
-void
-delete_all_breakpoints (void)
-{
- struct process_info *proc = current_process ();
-
- while (proc->breakpoints)
- delete_breakpoint_1 (proc, proc->breakpoints);
-}
-
-/* Clear the "inserted" flag in all breakpoints. */
-
-void
-mark_breakpoints_out (struct process_info *proc)
-{
- struct raw_breakpoint *raw_bp;
-
- for (raw_bp = proc->raw_breakpoints; raw_bp != NULL; raw_bp = raw_bp->next)
- raw_bp->inserted = 0;
-}
-
-/* Release all breakpoints, but do not try to un-insert them from the
- inferior. */
-
-void
-free_all_breakpoints (struct process_info *proc)
-{
- mark_breakpoints_out (proc);
-
- /* Note: use PROC explicitly instead of deferring to
- delete_all_breakpoints --- CURRENT_INFERIOR may already have been
- released when we get here. There should be no call to
- current_process from here on. */
- while (proc->breakpoints)
- delete_breakpoint_1 (proc, proc->breakpoints);
-}
-
-/* Clone an agent expression. */
-
-static struct agent_expr *
-clone_agent_expr (const struct agent_expr *src_ax)
-{
- struct agent_expr *ax;
-
- ax = XCNEW (struct agent_expr);
- ax->length = src_ax->length;
- ax->bytes = (unsigned char *) xcalloc (ax->length, 1);
- memcpy (ax->bytes, src_ax->bytes, ax->length);
- return ax;
-}
-
-/* Deep-copy the contents of one breakpoint to another. */
-
-static struct breakpoint *
-clone_one_breakpoint (const struct breakpoint *src, ptid_t ptid)
-{
- struct breakpoint *dest;
- struct raw_breakpoint *dest_raw;
-
- /* Clone the raw breakpoint. */
- dest_raw = XCNEW (struct raw_breakpoint);
- dest_raw->raw_type = src->raw->raw_type;
- dest_raw->refcount = src->raw->refcount;
- dest_raw->pc = src->raw->pc;
- dest_raw->kind = src->raw->kind;
- memcpy (dest_raw->old_data, src->raw->old_data, MAX_BREAKPOINT_LEN);
- dest_raw->inserted = src->raw->inserted;
-
- /* Clone the high-level breakpoint. */
- if (is_gdb_breakpoint (src->type))
- {
- struct gdb_breakpoint *gdb_dest = XCNEW (struct gdb_breakpoint);
- struct point_cond_list *current_cond;
- struct point_cond_list *new_cond;
- struct point_cond_list *cond_tail = NULL;
- struct point_command_list *current_cmd;
- struct point_command_list *new_cmd;
- struct point_command_list *cmd_tail = NULL;
-
- /* Clone the condition list. */
- for (current_cond = ((struct gdb_breakpoint *) src)->cond_list;
- current_cond != NULL;
- current_cond = current_cond->next)
- {
- new_cond = XCNEW (struct point_cond_list);
- new_cond->cond = clone_agent_expr (current_cond->cond);
- APPEND_TO_LIST (&gdb_dest->cond_list, new_cond, cond_tail);
- }
-
- /* Clone the command list. */
- for (current_cmd = ((struct gdb_breakpoint *) src)->command_list;
- current_cmd != NULL;
- current_cmd = current_cmd->next)
- {
- new_cmd = XCNEW (struct point_command_list);
- new_cmd->cmd = clone_agent_expr (current_cmd->cmd);
- new_cmd->persistence = current_cmd->persistence;
- APPEND_TO_LIST (&gdb_dest->command_list, new_cmd, cmd_tail);
- }
-
- dest = (struct breakpoint *) gdb_dest;
- }
- else if (src->type == other_breakpoint)
- {
- struct other_breakpoint *other_dest = XCNEW (struct other_breakpoint);
-
- other_dest->handler = ((struct other_breakpoint *) src)->handler;
- dest = (struct breakpoint *) other_dest;
- }
- else if (src->type == single_step_breakpoint)
- {
- struct single_step_breakpoint *ss_dest
- = XCNEW (struct single_step_breakpoint);
-
- dest = (struct breakpoint *) ss_dest;
- /* Since single-step breakpoint is thread specific, don't copy
- thread id from SRC, use ID instead. */
- ss_dest->ptid = ptid;
- }
- else
- gdb_assert_not_reached ("unhandled breakpoint type");
-
- dest->type = src->type;
- dest->raw = dest_raw;
-
- return dest;
-}
-
-/* See mem-break.h. */
-
-void
-clone_all_breakpoints (struct thread_info *child_thread,
- const struct thread_info *parent_thread)
-{
- const struct breakpoint *bp;
- struct breakpoint *new_bkpt;
- struct breakpoint *bkpt_tail = NULL;
- struct raw_breakpoint *raw_bkpt_tail = NULL;
- struct process_info *child_proc = get_thread_process (child_thread);
- struct process_info *parent_proc = get_thread_process (parent_thread);
- struct breakpoint **new_list = &child_proc->breakpoints;
- struct raw_breakpoint **new_raw_list = &child_proc->raw_breakpoints;
-
- for (bp = parent_proc->breakpoints; bp != NULL; bp = bp->next)
- {
- new_bkpt = clone_one_breakpoint (bp, ptid_of (child_thread));
- APPEND_TO_LIST (new_list, new_bkpt, bkpt_tail);
- APPEND_TO_LIST (new_raw_list, new_bkpt->raw, raw_bkpt_tail);
- }
-}