]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_kobject.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_kobject.cpp
1 INTERFACE:
2
3 #include "jdb_module.h"
4 #include "jdb_list.h"
5 #include "kobject.h"
6
7 class Kobject;
8 class Jdb_kobject_handler;
9
10 class Jdb_kobject : public Jdb_module
11 {
12 public:
13   Jdb_kobject();
14
15 private:
16   Jdb_kobject_handler *_first;
17   Jdb_kobject_handler **_tail;
18   static void *kobjp;
19 };
20
21
22 class Jdb_kobject_handler
23 {
24   friend class Jdb_kobject;
25
26 public:
27   Jdb_kobject_handler(char const *type) : kobj_type(type) {}
28   char const *kobj_type;
29   virtual bool show_kobject(Kobject_common *o, int level) = 0;
30   virtual int show_kobject_short(char *, int, Kobject_common *) { return 0; }
31   virtual Kobject_common *follow_link(Kobject_common *o) { return o; }
32   virtual ~Jdb_kobject_handler() {}
33   virtual bool invoke(Kobject_common *o, Syscall_frame *f, Utcb *utcb);
34   virtual bool handle_key(Kobject_common *, int /*keycode*/) { return false; }
35   virtual Kobject *parent(Kobject_common *) { return 0; }
36   virtual char const *kobject_type() const { return kobj_type; }
37
38 protected:
39   enum {
40     Op_set_name     = 0,
41     Op_global_id    = 1,
42     Op_kobj_to_id   = 2,
43     Op_query_typeid = 3,
44     Op_switch_log   = 4,
45     Op_get_name     = 5,
46   };
47 private:
48   Jdb_kobject_handler *_next;
49 };
50
51 class Jdb_kobject_extension : public Kobject_dbg::Dbg_extension
52 {
53 public:
54   virtual ~Jdb_kobject_extension() {}
55   virtual char const *type() const = 0;
56 };
57
58 class Jdb_kobject_list : public Jdb_list
59 {
60 public:
61   typedef bool Filter_func(Kobject_common const *);
62
63   struct Mode
64   {
65     char const *name;
66     Filter_func *filter;
67     Mode const *next;
68     static Mode *first;
69
70     Mode(char const *name, Filter_func *filter)
71     : name(name), filter(filter)
72     {
73       // make sure that non-filtered mode is first in the list so that we
74       // get this one displayed initially
75       if (!filter || !first)
76         {
77           next = first;
78           first = this;
79         }
80       else
81         {
82           next = first->next;
83           first->next = this;
84         }
85     }
86   };
87
88   void *get_head() const
89   { return Kobject::from_dbg(Kobject_dbg::_jdb_head.get_unused()); }
90
91 private:
92   Mode const *_current_mode;
93
94   Filter_func *_filter;
95 };
96
97 //--------------------------------------------------------------------------
98 IMPLEMENTATION:
99
100 #include <climits>
101 #include <cstring>
102 #include <cstdio>
103 #include <cstdlib>
104
105 #include "entry_frame.h"
106 #include "jdb.h"
107 #include "jdb_core.h"
108 #include "jdb_module.h"
109 #include "jdb_screen.h"
110 #include "kernel_console.h"
111 #include "kobject.h"
112 #include "keycodes.h"
113 #include "ram_quota.h"
114 #include "simpleio.h"
115 #include "space.h"
116 #include "static_init.h"
117
118 Jdb_kobject_list::Mode *Jdb_kobject_list::Mode::first;
119
120 class Jdb_kobject_id_hdl : public Jdb_kobject_handler
121 {
122 public:
123   Jdb_kobject_id_hdl() : Jdb_kobject_handler(0) {}
124   virtual bool show_kobject(Kobject_common *, int) { return false; }
125   virtual ~Jdb_kobject_id_hdl() {}
126 };
127
128 PUBLIC
129 bool
130 Jdb_kobject_id_hdl::invoke(Kobject_common *o, Syscall_frame *f, Utcb *utcb)
131 {
132   if (   utcb->values[0] != Op_global_id
133       && utcb->values[0] != Op_kobj_to_id)
134     return false;
135
136   if (utcb->values[0] == Op_global_id)
137     utcb->values[0] = o->dbg_info()->dbg_id();
138   else
139     utcb->values[0] = Kobject_dbg::pointer_to_id((void *)utcb->values[1]);
140   f->tag(Kobject_iface::commit_result(0, 1));
141   return true;
142 }
143
144
145 PRIVATE
146 void *
147 Jdb_kobject_list::get_first()
148 {
149   Kobject *f = static_cast<Kobject*>(get_head());
150   while (f && _filter && !_filter(f))
151     f = Kobject::from_dbg(f->dbg_info()->_next);
152   return f;
153 }
154
155
156 PUBLIC explicit
157 Jdb_kobject_list::Jdb_kobject_list(Filter_func *filt)
158 : Jdb_list(), _current_mode(0), _filter(filt)
159 { set_start(get_first()); }
160
161 PUBLIC
162 Jdb_kobject_list::Jdb_kobject_list()
163 : Jdb_list(), _current_mode(Mode::first), _filter(0)
164 {
165   if (_current_mode)
166     _filter = _current_mode->filter;
167
168   set_start(get_first());
169 }
170
171 PUBLIC
172 int
173 Jdb_kobject_list::show_item(char *buffer, int max, void *item) const
174 {
175   return Jdb_kobject::obj_description(buffer, max, false, static_cast<Kobject*>(item));
176 }
177
178 PUBLIC
179 bool
180 Jdb_kobject_list::enter_item(void *item) const
181 {
182   Kobject *o = static_cast<Kobject*>(item);
183   return Jdb_kobject::module()->handle_obj(o, 1);
184 }
185
186 PUBLIC
187 void *
188 Jdb_kobject_list::follow_link(void *item)
189 {
190   Kobject *o = static_cast<Kobject*>(item);
191   Jdb_kobject_handler *h = Jdb_kobject::module()->find_handler(o);
192   if (h)
193     return h->follow_link(o);
194
195   return item;
196 }
197
198 PUBLIC
199 bool
200 Jdb_kobject_list::handle_key(void *item, int keycode)
201 {
202   Kobject *o = static_cast<Kobject*>(item);
203   Jdb_kobject_handler *h = Jdb_kobject::module()->first_global_handler();
204   bool handled = false;
205   while (h)
206     {
207       handled |= h->handle_key(o, keycode);
208       h = h->next_global();
209     }
210
211   h = Jdb_kobject::module()->find_handler(o);
212   if (h)
213     handled |= h->handle_key(o, keycode);
214
215   return handled;
216 }
217
218 PRIVATE inline NOEXPORT
219 Kobject *
220 Jdb_kobject_list::next(Kobject *o)
221 {
222   if (!o)
223     return 0;
224
225   do
226     {
227       o = Kobject::from_dbg(o->dbg_info()->_next);
228     }
229   while (o && _filter && !_filter(o));
230   return o;
231 }
232
233 PRIVATE inline NOEXPORT
234 Kobject *
235 Jdb_kobject_list::prev(Kobject *o)
236 {
237   if (!o)
238     return 0;
239
240   do
241     {
242       o = Kobject::from_dbg(o->dbg_info()->_pref);
243     }
244   while (o && _filter && !_filter(o));
245   return o;
246 }
247
248 PUBLIC
249 int
250 Jdb_kobject_list::seek(int cnt, void **item)
251 {
252   Kobject *c = static_cast<Kobject*>(*item);
253   int i;
254   if (cnt > 0)
255     {
256       for (i = 0; i < cnt; ++i)
257         {
258           Kobject *n = next(c);
259           if (!n)
260             break;
261           c = n;
262         }
263     }
264   else if (cnt < 0)
265     {
266       for (i = 0; i < -cnt; ++i)
267         {
268           Kobject *n = prev(c);
269           if (!n)
270             break;
271           c = n;
272         }
273     }
274   else
275     return 0;
276
277   if (*item != c)
278     {
279       *item = c;
280       return i;
281     }
282
283   return 0;
284 }
285
286 PUBLIC
287 char const *
288 Jdb_kobject_list::show_head() const
289 {
290   return "[Objects]";
291 }
292
293
294 PUBLIC
295 char const *
296 Jdb_kobject_list::get_mode_str() const
297 {
298   if (!_current_mode)
299     return "[Objects]";
300   return _current_mode->name;
301 }
302
303
304
305 PUBLIC
306 void
307 Jdb_kobject_list::next_mode()
308 {
309   if (!_current_mode)
310     return;
311
312   _current_mode = _current_mode->next;
313   if (!_current_mode)
314     _current_mode = Mode::first;
315
316   _filter = _current_mode->filter;
317 }
318
319 /* When the mode changes the current object may get invisible,
320  * get a new visible one */
321 PUBLIC
322 void *
323 Jdb_kobject_list::get_valid(void *o)
324 {
325   if (!_current_mode)
326     return o;
327
328   if (_filter && _filter(static_cast<Kobject*>(o)))
329     return o;
330   return get_first();
331 }
332
333 IMPLEMENT
334 bool
335 Jdb_kobject_handler::invoke(Kobject_common *, Syscall_frame *, Utcb *)
336 { return false; }
337
338 PUBLIC
339 Jdb_kobject_handler *
340 Jdb_kobject_handler::next_global()
341 {
342   Jdb_kobject_handler *h = this->_next;
343   while (h)
344     {
345       if (!h->kobj_type)
346         return h;
347       h = h->_next;
348     }
349   return 0;
350 }
351
352 void *Jdb_kobject::kobjp;
353
354 IMPLEMENT
355 Jdb_kobject::Jdb_kobject()
356   : Jdb_module("INFO"),
357     _first(0),
358     _tail(&_first)
359 {
360 }
361
362
363 PUBLIC
364 void
365 Jdb_kobject::register_handler(Jdb_kobject_handler *h)
366 {
367   h->_next = 0;
368   *_tail = h;
369   _tail = &h->_next;
370 }
371
372 PUBLIC inline
373 Jdb_kobject_handler *
374 Jdb_kobject::first_global_handler() const
375 {
376   if (!_first || !_first->kobj_type)
377     return _first;
378   return _first->next_global();
379 }
380
381 PUBLIC
382 Jdb_kobject_handler *
383 Jdb_kobject::find_handler(Kobject_common *o)
384 {
385   Jdb_kobject_handler *h = _first;
386   while (h)
387     {
388       if (o->kobj_type() == h->kobj_type)
389         return h;
390       h = h->_next;
391     }
392   return 0;
393 }
394
395 PUBLIC
396 bool
397 Jdb_kobject::handle_obj(Kobject *o, int lvl)
398 {
399   Jdb_kobject_handler *h = find_handler(o);
400   if (h)
401     return h->show_kobject(o, lvl);
402
403   return true;
404 }
405
406 PUBLIC static
407 char const *
408 Jdb_kobject::kobject_type(Kobject_common *o)
409 {
410   Jdb_kobject_handler *h = module()->find_handler(o);
411   if (h)
412     return h->kobject_type();
413   return o->kobj_type();
414 }
415
416
417 PUBLIC static
418 int
419 Jdb_kobject::obj_description(char *buffer, int max, bool dense, Kobject_common *o)
420 {
421   int pos = snprintf(buffer, max,
422                      dense ? "%lx %lx [%-*s]" : "%8lx %08lx [%-*s]",
423                      o->dbg_info()->dbg_id(), (Mword)o, 7, kobject_type(o));
424
425   Jdb_kobject_handler *h = Jdb_kobject::module()->first_global_handler();
426   while (h)
427     {
428       pos += h->show_kobject_short(buffer + pos, max-pos, o);
429       h = h->next_global();
430     }
431
432   Jdb_kobject_handler *oh = Jdb_kobject::module()->find_handler(o);
433   if (oh)
434     pos += oh->show_kobject_short(buffer + pos, max-pos, o);
435
436   return pos;
437 }
438
439 PRIVATE static
440 void
441 Jdb_kobject::print_kobj(Kobject *o)
442 {
443   printf("%p [type=%s]", o, o->kobj_type());
444 }
445
446 PUBLIC
447 Jdb_module::Action_code
448 Jdb_kobject::action(int cmd, void *&, char const *&, int &)
449 {
450   if (cmd == 0)
451     {
452       puts("");
453       Kobject *k = Kobject::pointer_to_obj(kobjp);
454       if (!k)
455         printf("Not a kobj.\n");
456       else
457         {
458           if (!handle_obj(k, 0))
459             printf("Kobj w/o handler: ");
460           print_kobj(k);
461           puts("");
462         }
463       return NOTHING;
464     }
465   else if (cmd == 1)
466     {
467       Jdb_kobject_list list;
468       list.do_list();
469     }
470   return NOTHING;
471 }
472
473 PUBLIC
474 Jdb_module::Cmd const *
475 Jdb_kobject::cmds() const
476 {
477   static Cmd cs[] =
478     {
479         { 0, "K", "kobj", "%p", "K<kobj_ptr>\tshow information for kernel object", 
480           &kobjp },
481         { 1, "Q", "listkobj", "", "Q\tshow information for kernel objects", 0 },
482     };
483   return cs;
484 }
485
486 PUBLIC
487 int
488 Jdb_kobject::num_cmds() const
489 { return 2; }
490
491 STATIC_INITIALIZE_P(Jdb_kobject, JDB_MODULE_INIT_PRIO);
492
493 PRIVATE static
494 int
495 Jdb_kobject::fmt_handler(char /*fmt*/, int *size, char const *cmd_str, void *arg)
496 {
497   char buffer[20];
498
499   int pos = 0;
500   int c;
501   Address n;
502
503   *size = sizeof(void*);
504
505   while((c = Jdb_core::cmd_getchar(cmd_str)) != ' ' && c!=KEY_RETURN)
506     {
507       if(c==KEY_ESC)
508         return 3;
509
510       if(c==KEY_BACKSPACE && pos>0)
511         {
512           putstr("\b \b");
513           --pos;
514         }
515
516       if (pos < (int)sizeof(buffer) - 1)
517         {
518           putchar(c);
519           buffer[pos++] = c;
520           buffer[pos] = 0;
521         }
522     }
523
524   void **a = (void**)arg;
525
526   if (!pos)
527     {
528       *a = 0;
529       return 0;
530     }
531
532   char const *num = buffer;
533   if (buffer[0] == 'P')
534     num = buffer + 1;
535
536   n = strtoul(num, 0, 16);
537
538   Kobject *ko;
539
540   if (buffer[0] != 'P')
541     ko = Kobject::id_to_obj(n);
542   else
543     ko = Kobject::pointer_to_obj((void*)n);
544
545   *a = ko;
546
547   return 0;
548 }
549
550 PUBLIC static
551 void
552 Jdb_kobject::init()
553 {
554   module();
555
556   Jdb_core::add_fmt_handler('q', fmt_handler);
557
558 //  static Jdb_handler enter(at_jdb_enter);
559
560   static Jdb_kobject_id_hdl id_hdl;
561   module()->register_handler(&id_hdl);
562 }
563
564 PUBLIC static
565 Jdb_kobject *
566 Jdb_kobject::module()
567 {
568   static Jdb_kobject jdb_kobj_module;
569   return &jdb_kobj_module;
570 }
571
572 // Be robust if this object is invalid
573 PUBLIC static
574 void
575 Jdb_kobject::print_uid(Kobject_common *o, int task_format = 0)
576 {
577   if (!o)
578     {
579       printf("%*.s", task_format, "---");
580       return;
581     }
582
583   if (Kobject_dbg::is_kobj(o))
584     {
585       printf("%*.lx", task_format, o->dbg_info()->dbg_id());
586       return;
587     }
588
589   printf("\033[31;1m%*s%p\033[m", task_format, "???", o);
590   return;
591 }
592
593
594 extern "C" void
595 sys_invoke_debug(Kobject_iface *o, Syscall_frame *f)
596 {
597   if (!o)
598     {
599       f->tag(Kobject_iface::commit_result(-L4_err::EInval));
600       return;
601     }
602
603   Utcb *utcb = current_thread()->utcb().access();
604   //printf("sys_invoke_debug: [%p] -> %p\n", o, f);
605   Jdb_kobject_handler *h = Jdb_kobject::module()->find_handler(o);
606   if (h && h->invoke(o, f, utcb))
607     return;
608
609   h = Jdb_kobject::module()->first_global_handler();
610   while (h)
611     {
612       if (h->invoke(o, f, utcb))
613         return;
614       h = h->next_global();
615     }
616
617   f->tag(Kobject_iface::commit_result(-L4_err::ENosys));
618 }
619
620 PUBLIC
621 template< typename T >
622 static
623 T *
624 Jdb_kobject_extension::find_extension(Kobject_common const *o)
625 {
626   Kobject_dbg::Dbg_extension *ex = o->dbg_info()->_jdb_data;
627   while (ex)
628     {
629       Jdb_kobject_extension *je = static_cast<Jdb_kobject_extension*>(ex);
630       if (je->type() == T::static_type)
631         return static_cast<T*>(je);
632
633       ex = ex->next();
634     }
635
636   return 0;
637 }
638
639 static Jdb_kobject_list::Mode INIT_PRIORITY(JDB_MODULE_INIT_PRIO) all("[ALL]", 0);
640
641