3 Copyright 2000, 2001, 2002 Red Hat, Inc.
5 This file is part of RDA, the Red Hat Debug Agent (and library).
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Alternative licenses for RDA may be arranged by contacting Red Hat,
30 #if TIME_WITH_SYS_TIME
40 #include "gdbserv-target.h"
41 #include "gdbserv-utils.h"
43 #include "demo-target.h"
46 /* This is a sample gdbserv target that demonstrates use of the RDA library
47 routines. It acts to gdb like a strange generic remote target. */
51 static void demo_process_rcmd (struct gdbserv* serv, const char* cmd, int sizeof_cmd);
52 /* process_set_args */
54 static int demo_process_set_regs (struct gdbserv *serv);
55 static void demo_process_get_regs (struct gdbserv* serv);
59 /* expedited_reg_nr */
63 static long demo_get_mem (struct gdbserv* serv, struct gdbserv_reg* addr, void* data, long len);
64 static long demo_set_thread_mem (struct gdbserv *serv,
65 struct gdbserv_thread *thread,
66 struct gdbserv_reg *addr,
67 void *data, long len);
68 static void demo_process_set_pc (struct gdbserv *gdbserv,
69 const struct gdbserv_reg *pc);
71 static void demo_flush_i_cache (struct gdbserv* serv);
72 static unsigned long demo_compute_signal (struct gdbserv* serv, unsigned long);
73 static unsigned long demo_get_trap_number (struct gdbserv* serv);
74 static void demo_exit_program (struct gdbserv* serv);
75 static void demo_break_program (struct gdbserv* serv);
76 static int demo_reset_program (struct gdbserv* serv);
77 static void demo_restart_program (struct gdbserv* serv);
78 static void demo_singlestep_program (struct gdbserv* serv);
79 static void demo_cyclestep_program (struct gdbserv* serv);
80 static void demo_sigkill_program (struct gdbserv* serv);
81 static void demo_continue_thread (struct gdbserv *serv,
82 struct gdbserv_thread *thread,
83 const struct gdbserv_reg *sigval);
84 /* remove_breakpoint */
87 static void demo_detach (struct gdbserv* serv, struct gdbserv_target* target);
93 /* Signal a request to terminate main loop. */
96 /* Simple minded event handler to dispatch break events after an
100 dispatch_break (struct gdbserv *gdbserv,
101 struct gdbserv_thread *thread,
104 /* THREAD is probably NULL. Since we don't know what thread we
105 "stopped" in, we'll let the RDA library figure it out. */
106 gdbserv_fromtarget_thread_break (gdbserv, thread, GDBSERV_SIGTRAP);
110 sched_break (struct gdbserv *serv, long timeout)
112 static struct gdbsched *break_event = NULL;
114 assert (timeout >= 0);
115 /* Re-schedule the event being careful to not zap the ``NULL''
117 if (break_event != NULL)
118 gdbsched_deschedule (break_event, NULL, NULL, NULL, NULL, NULL);
119 /* If the timeout is ZERO don't use time() to compute the time that
120 the event should be scheduled. Instead, force it to NOW. There
121 could easily be a skew between the time() call below and the
122 event loops current time. That in turn can cause ``NOW'' to be
123 scheduled in a second or more.... */
127 sched_time = time (NULL) + timeout;
128 break_event = gdbsched_schedule (sched_time, dispatch_break,
133 /* Track sole connection to a remote gdb client. */
134 static struct gdbserv* sole_connection = NULL;
136 struct gdbserv_target *
137 demo_target (struct gdbserv *serv, void *context)
139 static struct gdbserv_target *target = NULL;
141 if (sole_connection != NULL)
143 fprintf (stderr, "Rejected duplicate connection.\n");
147 fprintf (stderr, "Accepted gdb connection.\n");
148 sole_connection = serv;
151 target = malloc (sizeof (struct gdbserv_target));
152 memset (target, sizeof (*target), 0);
154 /* Callback structure for function pointers that handle processed
155 control packets. See gdbserv-target.h for docs on the individual
158 target->process_get_gen = NULL;
159 target->process_set_gen = NULL;
160 target->process_rcmd = demo_process_rcmd;
161 target->process_set_args = NULL;
162 target->process_set_reg = NULL;
163 target->process_get_reg = NULL;
164 target->process_set_regs = demo_process_set_regs /* <deprecated?> */;
165 target->process_get_regs = demo_process_get_regs /* (deprecated) */;
166 target->input_reg = NULL;
167 target->output_reg = NULL;
168 target->gg_reg_nr = NULL;
169 target->expedited_reg_nr = NULL;
170 target->sizeof_reg = NULL;
171 target->set_reg = NULL;
172 target->get_reg = NULL;
173 target->get_mem = demo_get_mem;
174 target->set_thread_mem = demo_set_thread_mem;
175 target->process_set_pc = demo_process_set_pc;
176 target->flush_i_cache = demo_flush_i_cache;
177 target->process_signal = NULL;
178 target->compute_signal = demo_compute_signal;
179 target->get_trap_number = demo_get_trap_number;
180 target->exit_program = demo_exit_program;
181 target->break_program = demo_break_program;
182 target->reset_program = demo_reset_program;
183 target->restart_program = demo_restart_program;
184 target->singlestep_program = demo_singlestep_program;
185 target->cyclestep_program = demo_cyclestep_program;
186 target->sigkill_program = demo_sigkill_program;
187 target->continue_thread = demo_continue_thread;
188 target->remove_breakpoint = NULL;
189 target->set_breakpoint = NULL;
190 target->process_target_packet = NULL;
191 target->detach = demo_detach;
193 /* DATA can be assigned any value. That value is accessible via
194 gdbserv_target_data(). This example just happens to use
196 target->data = context;
201 /* This function is called from gdbloop_poll when a new incoming
202 connection is attempted. It may return NULL if the new connection
203 is to be refused, or a gdbserv_target vector if the connection is
204 accepted. The helper function do_fromtarget_ready() is to notify
205 the server that the target has finished initializing and is ready
209 do_fromtarget_ready (struct gdbserv *gdbserv,
210 struct gdbserv_thread *ignore2,
213 gdbserv_fromtarget (gdbserv, NULL, GDBSERV_FROMTARGET_STOPPED, NULL, 0);
216 struct gdbserv_target *
217 demo_attach (struct gdbserv *serv, void *context)
219 struct gdbserv_target *target = demo_target (serv, context);
222 /* Take the target out of reset. */
223 gdbsched_schedule (0, do_fromtarget_ready, serv, NULL, NULL);
229 demo_detach (struct gdbserv* serv, struct gdbserv_target* target)
231 assert (serv == sole_connection);
233 fprintf (stderr, "Detached.\n");
234 sole_connection = NULL;
236 /* Quit out of main loop for this demo. In general, this is not necessary, as the
237 next incoming connection could again be handled by demo_attach() above. */
244 demo_get_trap_number (struct gdbserv* serv)
246 /* Return a target-dependent trap number. */
252 demo_compute_signal (struct gdbserv* serv, unsigned long tgtsig)
254 assert (tgtsig == 0); /* comes from get_trap_number above */
255 /* Return standard signal number */
256 return GDBSERV_SIGTRAP;
261 demo_process_rcmd (struct gdbserv* serv, const char* cmd, int sizeof_cmd)
263 gdbserv_output_bytes (serv, cmd, sizeof_cmd);
270 * (including a primitive register cache)
273 static struct target_regs { /* register cache */
279 demo_process_get_regs (struct gdbserv* serv)
283 for (i=0; i<180; i++) /* 180 bytes < gdb's PBUFSIZ/2 */
284 gdbserv_output_byte (serv, target_regs.buf[i]);
288 demo_process_set_regs (struct gdbserv *serv)
290 gdbserv_input_bytes (serv, &target_regs.buf[0], sizeof (target_regs.buf));
295 demo_exit_program (struct gdbserv* serv)
297 gdbserv_fromtarget_exit (serv, GDBSERV_SIGQUIT);
301 demo_break_program (struct gdbserv* serv)
303 fprintf (stderr, "<BREAK>\n");
304 /* Enqueue a break response NOW */
305 sched_break (serv, 0);
309 demo_reset_program (struct gdbserv* serv)
311 gdbserv_fromtarget_reset (serv);
316 demo_restart_program (struct gdbserv* serv)
318 sched_break (serv, 1);
323 demo_singlestep_program (struct gdbserv* serv)
325 sched_break (serv, 2);
329 demo_cyclestep_program (struct gdbserv* serv)
331 sched_break (serv, 1);
335 demo_sigkill_program (struct gdbserv* serv)
337 gdbserv_fromtarget_exit (serv, GDBSERV_SIGKILL);
341 demo_continue_thread (struct gdbserv *serv,
342 struct gdbserv_thread *thread,
343 const struct gdbserv_reg *sigval)
345 fprintf (stderr, "Resumed fictional target program - send break from gdb or wait a while.\n");
346 /* Enqueue a break response */
347 sched_break (serv, 10);
355 * (including a primitive memory cache)
358 static struct target_mem { /* memory cache */
365 demo_get_mem (struct gdbserv* serv,
366 struct gdbserv_reg* addr,
371 unsigned char *d = data;
372 unsigned long request_base;
374 gdbserv_reg_to_ulong (serv, addr, &request_base);
376 for (n=0; n<len; n++)
378 if (request_base + n >= target_mem.base &&
379 request_base + n < target_mem.base + target_mem.len)
380 *d++ = target_mem.buf[request_base + n - target_mem.base];
388 #define ALLOC_UNIT 0x1000
389 #define alloc_roundup(LEN) ((((LEN)+ALLOC_UNIT-1) / ALLOC_UNIT) * ALLOC_UNIT)
393 demo_set_thread_mem (struct gdbserv *serv,
394 struct gdbserv_thread *thread,
395 struct gdbserv_reg *addr,
399 unsigned long request_base;
401 gdbserv_reg_to_ulong (serv, addr, &request_base);
402 if (target_mem.len == 0)
404 target_mem.len = alloc_roundup (len);
405 target_mem.buf = malloc (target_mem.len);
406 target_mem.base = request_base;
410 if (request_base < target_mem.base)
412 unsigned long oldlen = target_mem.len;
413 unsigned long movlen = target_mem.base - request_base;
415 target_mem.len += alloc_roundup (target_mem.base - request_base);
416 target_mem.base = request_base;
417 target_mem.buf = realloc (target_mem.buf, target_mem.len);
418 memmove (target_mem.buf + movlen, target_mem.buf, oldlen);
420 if (request_base + len >
421 target_mem.base + target_mem.len)
423 target_mem.len += alloc_roundup ((request_base + len) -
424 (target_mem.base + target_mem.len));
425 target_mem.buf = realloc (target_mem.buf, target_mem.len);
429 if (target_mem.buf == NULL)
432 memcpy (target_mem.buf + (request_base - target_mem.base),
440 demo_process_set_pc (struct gdbserv *gdbserv, const struct gdbserv_reg *pc)
443 gdbserv_reg_to_ulong (gdbserv, pc, &addr);
444 fprintf (stderr, "demo target pc set to 0x%lx\n", addr);
449 demo_flush_i_cache (struct gdbserv* serv)