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