From: Hui Zhu on
This patch add a new target empty which level is same with corelow
target. It can save the memory and reg operation command's value and
send it to GDB as the inferior's value.
"target empty" to use this target.

2010-02-22 Hui Zhu <teawater(a)gmail.com>

* Makefile.in (SFILES): Add empty.c.
(COMMON_OBS): Add empty.o
* empty.c: New file.
---
Makefile.in | 3
empty.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 298 insertions(+), 1 deletion(-)

--- a/Makefile.in
+++ b/Makefile.in
@@ -688,6 +688,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
record.c gcore.c \
jit.c \
xml-syscall.c \
+ empty.c

LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c

@@ -839,7 +840,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
prologue-value.o memory-map.o xml-support.o xml-syscall.o \
target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
inferior.o osdata.o gdb_usleep.o record.o gcore.o \
- jit.o progspace.o
+ jit.o progspace.o empty.o

# Definitions for the syscall's XML files and dir
XML_SYSCALLS_DIR = syscalls/
--- /dev/null
+++ b/empty.c
@@ -0,0 +1,296 @@
+/* Empty target for GDB, the GNU debugger.
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ 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 "defs.h"
+#include "gdbcmd.h"
+#include "regcache.h"
+#include "gdbthread.h"
+#include "event-top.h"
+#include "exceptions.h"
+#include "completer.h"
+#include "arch-utils.h"
+#include "gdbcore.h"
+#include "exec.h"
+#include "record.h"
+#include "elf-bfd.h"
+#include "gcore.h"
+
+#define EMPTY_PID 1
+
+static struct target_ops empty_ops;
+
+static gdb_byte *empty_regbuf = NULL;
+
+struct empty_mem_list_s
+{
+ struct empty_mem_list_s *prev;
+ struct empty_mem_list_s *next;
+ ULONGEST begin;
+ ULONGEST end;
+ gdb_byte *buf;
+};
+
+static struct empty_mem_list_s *empty_mem_list = NULL;
+
+static void
+empty_open (char *arg, int from_tty)
+{
+ int regnum = gdbarch_num_regs (get_current_arch ());
+
+ empty_regbuf = xzalloc (MAX_REGISTER_SIZE * regnum);
+
+ push_target (&empty_ops);
+
+ inferior_ptid = pid_to_ptid (EMPTY_PID);
+ inferior_appeared (current_inferior (), EMPTY_PID);
+ add_thread_silent (inferior_ptid);
+}
+
+static void
+empty_close (int quitting)
+{
+ struct empty_mem_list_s *mlp;
+
+ for (mlp = empty_mem_list; mlp;)
+ {
+ struct empty_mem_list_s *tmp = mlp;
+
+ mlp = mlp->next;
+ xfree (tmp->buf);
+ xfree (tmp);
+ }
+
+ if (empty_regbuf)
+ {
+ xfree (empty_regbuf);
+ empty_regbuf = NULL;
+ }
+}
+
+static void
+empty_kill (struct target_ops *ops)
+{
+ unpush_target (ops);
+}
+
+static void
+empty_fetch_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
+{
+ if (regno < 0)
+ {
+ int num = gdbarch_num_regs (get_regcache_arch (regcache));
+ int i;
+
+ for (i = 0; i < num; i ++)
+ regcache_raw_supply (regcache, i,
+ empty_regbuf + MAX_REGISTER_SIZE * i);
+ }
+ else
+ regcache_raw_supply (regcache, regno,
+ empty_regbuf + MAX_REGISTER_SIZE * regno);
+}
+
+static void
+empty_prepare_to_store (struct regcache *regcache)
+{
+}
+
+static void
+empty_store_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
+{
+ regcache_raw_collect (regcache, regno,
+ empty_regbuf + MAX_REGISTER_SIZE * regno);
+}
+
+static LONGEST
+empty_xfer_partial (struct target_ops *ops, enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset,
+ LONGEST len)
+{
+ struct empty_mem_list_s *mlp;
+
+ if (ops->beneath != NULL)
+ {
+ if (ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+ readbuf, writebuf, offset, len) == len)
+ return len;
+ }
+
+ if (readbuf)
+ {
+ memset (readbuf, 0, len);
+
+ for (mlp = empty_mem_list; mlp; mlp = mlp->next)
+ {
+ ULONGEST wbegin = 0;
+ ULONGEST wend = 0;
+
+ if (mlp->begin >= offset && mlp->begin <= offset + len)
+ {
+ wbegin = offset;
+
+ if (mlp->end > offset + len)
+ wend = offset + len;
+ else
+ wend = mlp->end;
+ }
+ else if (mlp->end >= offset && mlp->end <= offset + len)
+ {
+ wend = offset + len;
+
+ if (mlp->begin > offset)
+ wbegin = mlp->begin;
+ else
+ wbegin = offset;
+ }
+ else if (mlp->begin < offset && mlp->end > offset +len)
+ {
+ wbegin = offset;
+ wend = offset + len;
+ }
+
+ if (wbegin != wend)
+ memcpy (readbuf + wbegin - offset,
+ mlp->buf + wbegin - mlp->begin, wend - wbegin);
+ }
+ }
+ else
+ {
+ struct empty_mem_list_s *mlp_new = NULL;
+ struct empty_mem_list_s *mlp_head = NULL, *mlp_tail = NULL;
+ struct empty_mem_list_s *mlp_bodycore = NULL;
+ struct empty_mem_list_s *mlp_bodyhead = NULL, *mlp_bodytail = NULL;
+ ULONGEST begin = offset, end = offset +len;
+ gdb_byte *buf;
+
+ /* Get mlp_head, mlp_tail, mlp_bodyhead, mlp_bodytail, begin, end. */
+ for (mlp = empty_mem_list; mlp; mlp = mlp->next)
+ {
+ if (mlp->end < begin)
+ mlp_head = mlp;
+ else if (begin >= mlp->begin && end <= mlp->end)
+ {
+ mlp_bodycore = mlp;
+ break;
+ }
+ else if ((mlp->begin >= begin && mlp->begin <= end)
+ || (mlp->end >= begin && mlp->end <= end)
+ || (mlp->begin < begin && mlp->end > end))
+ {
+ if (mlp_bodyhead)
+ mlp_bodytail = mlp;
+ else
+ {
+ mlp_bodyhead = mlp;
+ mlp_bodytail = mlp;
+ }
+ if (mlp->begin < begin)
+ begin = mlp->begin;
+ if (mlp->begin > end)
+ end = mlp->end;
+ }
+ else if (end < mlp->begin)
+ {
+ mlp_tail = mlp;
+ break;
+ }
+ }
+
+ if (mlp_bodycore)
+ {
+ memcpy (mlp_bodycore->buf + begin - mlp_bodycore->begin, writebuf, len);
+ }
+ else
+ {
+ mlp_new = xmalloc (sizeof (struct empty_mem_list_s));
+ mlp_new->begin = begin;
+ mlp_new->end = end;
+ mlp_new->buf = xzalloc (end - begin);
+
+ /* Write the mlp_body value to mlp_new and release mlp_body. */
+ for (mlp = mlp_bodyhead; mlp && mlp->prev != mlp_bodytail;)
+ {
+ struct empty_mem_list_s *tmp = mlp;
+
+ mlp = mlp->next;
+ memcpy (mlp_new->buf + tmp->begin - begin, tmp->buf, tmp->end - tmp->begin);
+ xfree (tmp->buf);
+ xfree (tmp);
+ }
+
+ /* Write the new value to mlp_new. */
+ memcpy (mlp_new->buf + offset - begin, writebuf, len);
+
+ /* Add mlp_new to list. */
+ mlp_new->prev = mlp_head;
+ mlp_new->next = mlp_tail;
+ if (mlp_head)
+ mlp_head->next = mlp_new;
+ if (mlp_tail)
+ mlp_tail->prev = mlp_new;
+ if (!mlp_new->prev)
+ empty_mem_list = mlp_new;
+ }
+
+ reinit_frame_cache ();
+ }
+
+ return len;
+}
+
+static int
+ignore (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
+{
+ return 0;
+}
+
+static void
+init_empty_ops (void)
+{
+ empty_ops.to_shortname = "empty";
+ empty_ops.to_longname = "Empty target";
+ empty_ops.to_doc = "Empty target";
+ empty_ops.to_open = empty_open;
+ empty_ops.to_close = empty_close;
+ empty_ops.to_attach = find_default_attach;
+ empty_ops.to_kill = empty_kill;
+ empty_ops.to_fetch_registers = empty_fetch_registers;
+ empty_ops.to_prepare_to_store = empty_prepare_to_store;
+ empty_ops.to_store_registers = empty_store_registers;
+ empty_ops.to_xfer_partial = empty_xfer_partial;
+ empty_ops.to_insert_breakpoint = ignore;
+ empty_ops.to_remove_breakpoint = ignore;
+ empty_ops.to_create_inferior = find_default_create_inferior;
+ empty_ops.to_stratum = core_stratum;
+ empty_ops.to_has_execution = default_child_has_execution;
+ empty_ops.to_has_memory = default_child_has_memory;
+ empty_ops.to_has_stack = default_child_has_stack;
+ empty_ops.to_has_registers = default_child_has_registers;
+ empty_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_empty (void)
+{
+ init_empty_ops ();
+ add_target (&empty_ops);
+}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/