]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_tbuf_output.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_tbuf_output.cpp
1 INTERFACE:
2
3 #include "initcalls.h"
4 #include "l4_types.h"
5 #include "thread.h"
6
7 class Tb_entry;
8
9 class Jdb_tbuf_output
10 {
11 private:
12   typedef unsigned (Format_entry_fn)(Tb_entry *tb, const char *tidstr,
13                                      unsigned tidlen, char *buf, int maxlen);
14   static Format_entry_fn *_format_entry_fn[];
15   static bool show_names;
16 };
17
18 IMPLEMENTATION:
19
20 #include <cassert>
21 #include <cstdlib>
22 #include <cstdio>
23 #include <cstring>
24
25 #include "config.h"
26 #include "initcalls.h"
27 #include "jdb.h"
28 #include "jdb_kobject_names.h"
29 #include "jdb_regex.h"
30 #include "jdb_symbol.h"
31 #include "jdb_tbuf.h"
32 #include "kdb_ke.h"
33 #include "kernel_console.h"
34 #include "l4_types.h"
35 #include "processor.h"
36 #include "static_init.h"
37 #include "tb_entry.h"
38 #include "terminate.h"
39 #include "watchdog.h"
40
41
42 Jdb_tbuf_output::Format_entry_fn *Jdb_tbuf_output::_format_entry_fn[Tbuf_max];
43 bool Jdb_tbuf_output::show_names;
44
45 static void
46 console_log_entry(Tb_entry *e, const char *)
47 {
48   static char log_message[80];
49
50   // disable all interrupts to stop other threads
51   Watchdog::disable();
52   Proc::Status s = Proc::cli_save();
53
54   Jdb_tbuf_output::print_entry(e, log_message, sizeof(log_message));
55   printf("%s\n", log_message);
56
57   // do not use getchar here because we ran cli'd
58   // and getchar may do halt
59   int c;
60   Jdb::enter_getchar();
61   while ((c=Kconsole::console()->getchar(false)) == -1)
62     Proc::pause();
63   Jdb::leave_getchar();
64   if (c == 'i')
65     kdb_ke("LOG");
66   if (c == '^')
67     terminate(1);
68
69   // enable interrupts we previously disabled
70   Proc::sti_restore(s);
71   Watchdog::enable();
72 }
73
74 PRIVATE static
75 unsigned
76 Jdb_tbuf_output::dummy_format_entry (Tb_entry *tb, const char *, unsigned,
77                                      char *buf, int maxlen)
78 {
79   int len = snprintf(buf, maxlen,
80       " << no format_entry_fn for type %d registered >>", tb->type());
81   return len >= maxlen ? maxlen-1 : len;
82 }
83
84 STATIC_INITIALIZE(Jdb_tbuf_output);
85
86 PUBLIC static
87 void FIASCO_INIT
88 Jdb_tbuf_output::init()
89 {
90   unsigned i;
91
92   Jdb_tbuf::direct_log_entry = &console_log_entry;
93   for (i=0; i<sizeof(_format_entry_fn)/sizeof(_format_entry_fn[0]); i++)
94     if (!_format_entry_fn[i])
95       _format_entry_fn[i] = dummy_format_entry;
96 }
97
98 PUBLIC static
99 void
100 Jdb_tbuf_output::register_ff(Unsigned8 type, Format_entry_fn format_entry_fn)
101 {
102   assert(type < Tbuf_max);
103
104   if (   (_format_entry_fn[type] != 0)
105       && (_format_entry_fn[type] != dummy_format_entry))
106     panic("format entry function for type %d already registered", type);
107
108   _format_entry_fn[type] = format_entry_fn;
109 }
110
111 // return thread+ip of entry <e_nr>
112 PUBLIC static
113 int
114 Jdb_tbuf_output::thread_ip(int e_nr, Thread const **th, Mword *ip)
115 {
116   Tb_entry *e = Jdb_tbuf::lookup(e_nr);
117
118   if (!e)
119     return false;
120
121   *th = static_cast<Thread const *>(e->ctx());
122
123   *ip = e->ip();
124
125   return true;
126 }
127
128 PUBLIC static
129 void
130 Jdb_tbuf_output::toggle_names()
131 {
132   show_names = !show_names;
133 }
134
135 static
136 unsigned
137 formatter_default(Tb_entry *tb, const char *tidstr, unsigned tidlen,
138                  char *buf, int maxlen)
139 {
140   if (tb->type() < Tbuf_dynentries)
141     return 0;
142
143   int idx = tb->type()-Tbuf_dynentries;
144
145   Tb_entry_formatter *fmt = _log_table[idx].fmt;
146   char const *sc = _log_table[idx].name;
147   sc += strlen(sc) + 1;
148
149   unsigned l = snprintf(buf, maxlen, "%-3s: %-*s ", sc, tidlen, tidstr);
150   buf += l;
151   maxlen -= l;
152
153   if (!fmt)
154     {
155       Tb_entry_ke_reg *e = static_cast<Tb_entry_ke_reg*>(tb);
156       char ip_buf[32];
157       snprintf(ip_buf, sizeof(ip_buf), " @ " L4_PTR_FMT, e->ip());
158       snprintf(buf, maxlen, "\"%s\" "
159                L4_PTR_FMT " " L4_PTR_FMT " " L4_PTR_FMT "%s",
160                e->msg(), e->val1(), e->val2(), e->val3(),
161                e->ip() ? ip_buf : "");
162
163       return maxlen;
164     }
165
166   return fmt(tb, maxlen, buf);
167 }
168
169 PUBLIC static
170 void
171 Jdb_tbuf_output::print_entry(int e_nr, char *buf, int maxlen)
172 {
173   Tb_entry *tb = Jdb_tbuf::lookup(e_nr);
174
175   if (tb)
176     print_entry(tb, buf, maxlen);
177 }
178
179 PUBLIC static
180 void
181 Jdb_tbuf_output::print_entry(Tb_entry *tb, char *buf, int maxlen)
182 {
183   assert(tb->type() < Tbuf_max);
184
185   char tidstr[32];
186   Thread const *t = static_cast<Thread const *>(tb->ctx());
187
188   if (!t || !Kobject_dbg::is_kobj(t))
189     strcpy(tidstr, "????");
190   else
191     {
192       Jdb_kobject_name *ex
193         = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(t);
194       if (show_names && ex)
195         snprintf(tidstr, sizeof(tidstr), "%04lx %-*.*s", t->dbg_info()->dbg_id(), ex->max_len(), ex->max_len(), ex->name());
196       else
197         snprintf(tidstr, sizeof(tidstr), "%04lx", t->dbg_info()->dbg_id());
198     }
199
200   if (Config::Max_num_cpus > 1)
201     {
202       snprintf(buf, maxlen, Config::Max_num_cpus > 16 ? "%02d " : "%d ", tb->cpu());
203       buf    += 2 + (Config::Max_num_cpus > 16);
204       maxlen -= 2 + (Config::Max_num_cpus > 16);
205     }
206
207   unsigned len;
208
209   if (tb->type() >= Tbuf_dynentries)
210     len = formatter_default(tb, tidstr, show_names ? 21 : 4, buf, maxlen);
211   else
212     len = _format_entry_fn[tb->type()](tb, tidstr,
213                                        show_names ? 21 : 4, buf, maxlen);
214
215   // terminate string
216   buf += maxlen-len;
217   while (len--)
218     *buf++ = ' ';
219   buf[-1] = '\0';
220 }
221
222 PUBLIC static
223 bool
224 Jdb_tbuf_output::set_filter(const char *filter_str, Mword *entries)
225 {
226   if (*filter_str && Jdb_regex::avail() && !Jdb_regex::start(filter_str))
227     return false;
228
229   if (!*filter_str)
230     {
231       for (Mword n=0; n<Jdb_tbuf::unfiltered_entries(); n++)
232         Jdb_tbuf::unfiltered_lookup(n)->unhide();
233
234       Jdb_tbuf::disable_filter();
235       if (entries)
236         *entries = Jdb_tbuf::unfiltered_entries();
237       return true;
238     }
239
240   Mword cnt = 0;
241
242   for (Mword n=0; n<Jdb_tbuf::unfiltered_entries(); n++)
243     {
244       Tb_entry *e = Jdb_tbuf::unfiltered_lookup(n);
245       char s[80];
246
247       print_entry(e, s, sizeof(s));
248       if (Jdb_regex::avail())
249         {
250           if (Jdb_regex::find(s, 0, 0))
251             {
252               e->unhide();
253               cnt++;
254               continue;
255             }
256         }
257       else
258         {
259           if (strstr(s, filter_str))
260             {
261               e->unhide();
262               cnt++;
263               continue;
264             }
265         }
266       e->hide();
267     }
268
269   if (entries)
270     *entries = cnt;
271   Jdb_tbuf::enable_filter();
272   return true;
273 }