OSDN Git Service

2004-07-09 Michael Snyder <msnyder@redhat.com>
[pf3gnuchains/pf3gnuchains3x.git] / rda / samples / demo-target.c
1 /* demo-target.c
2
3    Copyright 2000, 2001, 2002 Red Hat, Inc.
4
5    This file is part of RDA, the Red Hat Debug Agent (and library).
6
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.
11
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.
16
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.
21    
22    Alternative licenses for RDA may be arranged by contacting Red Hat,
23    Inc.  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <assert.h>
29 #include <stdlib.h>
30 #if TIME_WITH_SYS_TIME
31 #include <sys/time.h>
32 #include <time.h>
33 #elif HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #else
36 #include <time.h>
37 #endif
38
39 #include "gdbserv.h" 
40 #include "gdbserv-target.h" 
41 #include "gdbserv-utils.h"
42
43 #include "demo-target.h"
44 #include "gdbsched.h"
45
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. */
48
49  /* process_get_gen */
50  /* process_set_gen */
51 static void demo_process_rcmd (struct gdbserv* serv, const char* cmd, int sizeof_cmd);
52  /* process_set_args */
53  /* process_set_reg */
54 static int  demo_process_set_regs (struct gdbserv *serv);
55 static void demo_process_get_regs (struct gdbserv* serv);
56  /* input_reg */
57  /* output_reg */
58  /* gg_reg_nr */
59  /* expedited_reg_nr */
60  /* sizeof_reg */
61  /* set_reg */
62  /* get_reg */
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);
70  /* process_signal */
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 */
85  /* set_breakpoint */
86  /* process_target */
87 static void demo_detach (struct gdbserv* serv, struct gdbserv_target* target);
88
89
90
91
92
93 /* Signal a request to terminate main loop. */
94 int demo_quit_p = 0;
95
96 /* Simple minded event handler to dispatch break events after an
97    arbitrary time. */
98
99 static void
100 dispatch_break (struct gdbserv *gdbserv,
101                 struct gdbserv_thread *thread,
102                 void *context)
103 {
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);
107 }
108
109 static void
110 sched_break (struct gdbserv *serv, long timeout)
111 {
112   static struct gdbsched *break_event = NULL;
113   long sched_time;
114   assert (timeout >= 0);
115   /* Re-schedule the event being careful to not zap the ``NULL''
116      event. */
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.... */
124   if (timeout == 0)
125     sched_time = 0;
126   else
127     sched_time = time (NULL) + timeout;
128   break_event = gdbsched_schedule (sched_time, dispatch_break,
129                                    serv, NULL, NULL);
130 }
131
132
133 /* Track sole connection to a remote gdb client. */
134 static struct gdbserv* sole_connection = NULL;
135
136 struct gdbserv_target *
137 demo_target (struct gdbserv *serv, void *context)
138 {
139   static struct gdbserv_target *target = NULL;
140
141   if (sole_connection != NULL)
142     {
143       fprintf (stderr, "Rejected duplicate connection.\n");
144       return NULL;
145     }
146
147   fprintf (stderr, "Accepted gdb connection.\n");
148   sole_connection = serv;
149
150   if (target == NULL)
151     target = malloc (sizeof (struct gdbserv_target));
152   memset (target, sizeof (*target), 0);
153
154   /* Callback structure for function pointers that handle processed
155      control packets.  See gdbserv-target.h for docs on the individual
156      functions. */
157
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;
192
193   /* DATA can be assigned any value.  That value is accessible via
194      gdbserv_target_data().  This example just happens to use
195      CONTEXT. */
196   target->data = context;
197
198   return target;
199 }
200
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
206    to talk to GDB.  */
207
208 static void
209 do_fromtarget_ready (struct gdbserv *gdbserv,
210                      struct gdbserv_thread *ignore2,
211                      void *ignore3)
212 {
213   gdbserv_fromtarget (gdbserv, NULL, GDBSERV_FROMTARGET_STOPPED, NULL, 0);
214 }
215
216 struct gdbserv_target * 
217 demo_attach (struct gdbserv *serv, void *context)
218 {
219   struct gdbserv_target *target = demo_target (serv, context);
220   if (target == NULL)
221     return NULL;
222   /* Take the target out of reset. */
223   gdbsched_schedule (0, do_fromtarget_ready, serv, NULL, NULL);
224   return target;
225 }
226
227
228 void
229 demo_detach (struct gdbserv* serv, struct gdbserv_target* target)
230 {
231   assert (serv == sole_connection);
232
233   fprintf (stderr, "Detached.\n");
234   sole_connection = NULL;
235
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. */
238   demo_quit_p = 1;
239 }
240
241
242
243 unsigned long
244 demo_get_trap_number (struct gdbserv* serv)
245 {
246   /* Return a target-dependent trap number. */
247   return 0;
248 }
249
250
251 unsigned long
252 demo_compute_signal (struct gdbserv* serv, unsigned long tgtsig)
253 {
254   assert (tgtsig == 0); /* comes from get_trap_number above */
255   /* Return standard signal number */
256   return GDBSERV_SIGTRAP;
257 }
258
259
260 void
261 demo_process_rcmd (struct gdbserv* serv, const char* cmd, int sizeof_cmd)
262 {
263   gdbserv_output_bytes (serv, cmd, sizeof_cmd);
264 }
265
266
267 /*
268  * Get/Set Registers
269  * 
270  * (including a primitive register cache) 
271  */
272
273 static struct target_regs {     /* register cache */
274   unsigned int len;
275   char buf[180];
276 } target_regs;
277
278 static void 
279 demo_process_get_regs (struct gdbserv* serv)
280 {
281   int i;
282
283   for (i=0; i<180; i++) /* 180 bytes < gdb's PBUFSIZ/2 */
284     gdbserv_output_byte (serv, target_regs.buf[i]);
285 }
286
287 static int 
288 demo_process_set_regs (struct gdbserv *serv)
289 {
290   gdbserv_input_bytes (serv, &target_regs.buf[0], sizeof (target_regs.buf));
291   return 0;
292 }
293
294 void
295 demo_exit_program (struct gdbserv* serv)
296 {
297   gdbserv_fromtarget_exit (serv, GDBSERV_SIGQUIT);
298 }
299
300 void
301 demo_break_program (struct gdbserv* serv)
302 {
303   fprintf (stderr, "<BREAK>\n");
304   /* Enqueue a break response NOW */
305   sched_break (serv, 0);
306 }
307
308 int
309 demo_reset_program (struct gdbserv* serv)
310 {
311   gdbserv_fromtarget_reset (serv);
312   return 0;
313 }
314
315 void
316 demo_restart_program (struct gdbserv* serv)
317 {
318   sched_break (serv, 1);
319 }
320
321
322 void
323 demo_singlestep_program (struct gdbserv* serv)
324 {
325   sched_break (serv, 2);
326 }
327
328 void
329 demo_cyclestep_program (struct gdbserv* serv)
330 {
331   sched_break (serv, 1);
332 }
333
334 void
335 demo_sigkill_program (struct gdbserv* serv)
336 {
337   gdbserv_fromtarget_exit (serv, GDBSERV_SIGKILL);
338 }
339
340 void
341 demo_continue_thread (struct gdbserv *serv,
342                       struct gdbserv_thread *thread,
343                       const struct gdbserv_reg *sigval)
344 {
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);
348 }
349
350
351
352 /*
353  * Get/Set memory
354  *
355  * (including a primitive memory cache)
356  */
357
358 static struct target_mem {      /* memory cache */
359   unsigned long base;
360   unsigned long len;
361   unsigned char *buf;
362 } target_mem;
363
364 static long
365 demo_get_mem (struct gdbserv* serv, 
366               struct gdbserv_reg* addr, 
367               void* data, 
368               long len)
369 {
370   long n;
371   unsigned char *d = data;
372   unsigned long request_base;
373
374   gdbserv_reg_to_ulong (serv, addr, &request_base);
375
376   for (n=0; n<len; n++)
377     {
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];
381       else
382         *d++ = 0;
383     }
384
385   return n;
386 }
387
388 #define ALLOC_UNIT  0x1000
389 #define alloc_roundup(LEN) ((((LEN)+ALLOC_UNIT-1) / ALLOC_UNIT) * ALLOC_UNIT)
390   
391
392 static long
393 demo_set_thread_mem (struct gdbserv *serv, 
394                      struct gdbserv_thread *thread,
395                      struct gdbserv_reg *addr, 
396                      void *data, 
397                      long len)
398 {
399   unsigned long request_base;
400
401   gdbserv_reg_to_ulong (serv, addr, &request_base);
402   if (target_mem.len == 0)
403     {
404       target_mem.len  = alloc_roundup (len);
405       target_mem.buf  = malloc (target_mem.len);
406       target_mem.base = request_base;
407     }
408   else
409     {
410       if (request_base < target_mem.base)
411         {
412           unsigned long oldlen = target_mem.len;
413           unsigned long movlen = target_mem.base - request_base;
414
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);
419         }
420       if (request_base + len > 
421           target_mem.base + target_mem.len)
422         {
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);
426         }
427     }
428
429   if (target_mem.buf == NULL)
430     return 0;
431
432   memcpy (target_mem.buf + (request_base - target_mem.base), 
433           data, 
434           len);
435   return  len;
436 }
437
438
439 void
440 demo_process_set_pc (struct gdbserv *gdbserv, const struct gdbserv_reg *pc)
441 {
442   unsigned long addr;
443   gdbserv_reg_to_ulong (gdbserv, pc, &addr);
444   fprintf (stderr, "demo target pc set to 0x%lx\n", addr);
445 }
446
447
448 void
449 demo_flush_i_cache (struct gdbserv* serv)
450 {
451 }