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