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