]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_dump.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_dump.cpp
1 INTERFACE:
2
3 #include "types.h"
4 #include "l4_types.h"
5
6 class Space;
7
8
9 IMPLEMENTATION:
10
11 #include <cstdio>
12 #include <cctype>
13
14 #include "config.h"
15 #include "jdb.h"
16 #include "jdb_disasm.h"
17 #include "jdb_table.h"
18 #include "jdb_input.h"
19 #include "jdb_module.h"
20 #include "jdb_screen.h"
21 #include "jdb_symbol.h"
22 #include "kernel_console.h"
23 #include "keycodes.h"
24 #include "simpleio.h"
25 #include "static_init.h"
26 #include "types.h"
27 #include "task.h"
28
29 class Jdb_dump : public Jdb_module, public Jdb_table
30 {
31 public:
32   Jdb_dump() FIASCO_INIT;
33   unsigned long cols() const { return Jdb_screen::cols(); }
34   unsigned long rows() const { return Jdb_screen::rows(); }
35   void draw_entry(unsigned long row, unsigned long col);
36   void print_statline();
37
38 private:
39   enum
40     {
41       B_MODE = 'b',     // byte
42       C_MODE = 'c',     // char
43       D_MODE = 'd',     // word
44     };
45   
46   static const unsigned elb = sizeof(Mword);
47   static char show_adapter_memory;
48   static Address highlight_start, highlight_end;
49
50   int level;
51   Space *task;
52   char dump_type;
53   static Address virt_addr;
54 };
55
56 char    Jdb_dump::show_adapter_memory;
57 Address Jdb_dump::highlight_start;
58 Address Jdb_dump::highlight_end;
59 Address Jdb_dump::virt_addr;
60
61 // if we have the APIC module
62 extern int ignore_invalid_apic_reg_access
63   __attribute__((weak));
64
65 PRIVATE inline
66 Address
67 Jdb_dump::virt(unsigned long row, unsigned long col)
68 {
69   return (col-1) * elb + row * (cols()-1) * elb;
70 }
71
72 PUBLIC
73 unsigned
74 Jdb_dump::col_width(unsigned col) const
75 {
76   if (col == 0)
77     return Jdb_screen::Col_head_size;
78   if (dump_type == C_MODE)
79     return Jdb_screen::Mword_size_cmode;
80   else
81     return Jdb_screen::Mword_size_bmode; 
82 }
83
84 PUBLIC
85 void
86 Jdb_dump::print_statline(unsigned long row, unsigned long col)
87 {
88   Jdb::printf_statline("dump",
89       (dump_type==D_MODE)
90       ? "e=edit u=disasm D=dump <Space>=mode <CR>=goto addr"
91       : "<Space>=mode",
92       task ? "%c<"L4_PTR_FMT"> task %p" : "%c<"L4_PTR_FMT"> physical",
93       dump_type, virt(row,col), task);
94 }
95
96 IMPLEMENT
97 void
98 Jdb_dump::draw_entry(unsigned long row, unsigned long col)
99 {
100   if (col == 0)
101     {
102       printf("%0*lx", col_width(col), row * (cols()-1) * elb);
103       return;
104     }
105
106   Address entry = virt(row, col);
107
108   // prevent apic from getting confused by invalid register accesses
109   if (&ignore_invalid_apic_reg_access)
110     ignore_invalid_apic_reg_access = 1;
111
112   Mword dummy;
113   bool mapped  = Jdb::peek((Mword*)entry, task, dummy);
114   bool ram     = !Jdb::is_adapter_memory(entry, task);
115
116   if (mapped)
117     {
118       if (ram || show_adapter_memory)
119         {
120           Mword mword;
121           Jdb::peek((Mword*)entry, task, mword);
122
123           if (dump_type==D_MODE)
124             {
125               if (mword == 0)
126                 printf("%*lu", Jdb_screen::Mword_size_bmode, mword);
127               else if (mword == (Mword)~0UL)
128                 printf("%*d", Jdb_screen::Mword_size_bmode, -1);
129               else
130                 {
131                   if (highlight_start <= mword && mword <= highlight_end)
132                     printf("%s" L4_PTR_FMT "\033[m", Jdb::esc_emph, mword);
133                   else
134                     printf(L4_PTR_FMT, mword);
135                 }
136             }
137           else if (dump_type==B_MODE)
138             {
139               for (Mword u=0; u<elb; u++)
140                 {
141                   Unsigned8 b = (mword >> (8*u)) & 0xff;
142                   printf("%02x", b);
143                 }
144             }
145           else if (dump_type==C_MODE)
146             {
147               for (Mword u=0; u<elb; u++)
148                 {
149                   Unsigned8 b = (mword >> (8*u)) & 0xff;
150                   putchar(b>=32 && b<=126 ? b : '.');
151                 }
152             }
153         }
154       else // is_adapter_memory
155         {
156           if (dump_type == C_MODE)
157             printf("%.*s", Jdb_screen::Mword_size_cmode, Jdb_screen::Mword_adapter);
158           else
159             printf("%.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_adapter);
160         }
161     }
162   else // !mapped
163     {
164       if (dump_type == C_MODE)
165         printf("%.*s", Jdb_screen::Mword_size_cmode, Jdb_screen::Mword_not_mapped);
166       else
167         printf("%.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_not_mapped);
168     }
169   
170   if (&ignore_invalid_apic_reg_access)
171     ignore_invalid_apic_reg_access = 0;
172 }
173
174 PUBLIC
175 Jdb_module::Action_code
176 Jdb_dump::dump(Address virt, Space *task, int level)
177 { //printf("DU: %p %lx\n", task, virt); Jdb::getchar();
178   int old_l = this->level;
179   this->level = level;
180   this->task = task;
181   dump_type = D_MODE;
182   if (!level)
183     Jdb::clear_screen();
184
185   unsigned long row =  virt / ((cols()-1) * elb);
186   unsigned long col = (virt % ((cols()-1) * elb)) / elb + 1;
187   bool r = show(row, col);
188   this->level = old_l;
189   return r ? EXTRA_INPUT : NOTHING;
190 }
191
192 PUBLIC
193 bool
194 Jdb_dump::edit_entry(unsigned long row, unsigned long col, unsigned cx, unsigned cy)
195 {
196   Address entry = virt(row,col);
197
198   Mword mword;
199   if (!Jdb::peek((Mword*)entry, task, mword))
200     return false;
201
202   putstr(Jdb_screen::Mword_blank);
203   Jdb::printf_statline("dump", "<CR>=commit change",
204                        "edit <"L4_PTR_FMT"> = "L4_PTR_FMT"", entry, mword);
205
206   Jdb::cursor(cy, cx);
207   Mword new_mword;
208   if (Jdb_input::get_mword(&new_mword, sizeof(Mword)*2, 16))
209     Jdb::poke((Mword*)entry, task, new_mword);
210
211   return true; // redraw
212 }
213
214 PUBLIC
215 unsigned
216 Jdb_dump::key_pressed(int c, unsigned long &row, unsigned long &col)
217 {
218   switch (c)
219     {
220     default:
221       return Nothing;
222
223     case KEY_CURSOR_HOME: // return to previous or go home
224       if (level == 0)
225         {
226           Address v = virt(row, col);
227           if (v == 0)
228             return Handled;
229
230           if ((v & ~Config::PAGE_MASK) == 0)
231             row -= Config::PAGE_SIZE / 32;
232           else
233             {
234               col = 1;
235               row = (v & Config::PAGE_MASK) / 32;
236             }
237           return Redraw;
238         }
239       return Back;
240
241     case KEY_CURSOR_END:
242         {
243           Address v = virt(row, col);
244           if ((v & ~Config::PAGE_MASK) >> 2 == 0x3ff)
245             row += Config::PAGE_SIZE / 32;
246           else
247             {
248               col = Jdb_screen::cols() - 1;
249               row = ((v & Config::PAGE_MASK) + Config::PAGE_SIZE - 4) / 32;
250             }
251         }
252       return Redraw;
253
254     case 'D':
255       if (Kconsole::console()->find_console(Console::GZIP))
256         {
257           Address low_addr, high_addr;
258
259           Jdb::cursor(Jdb_screen::height(), 27);
260           putchar('[');
261           Jdb::clear_to_eol();
262
263           if (Jdb_input::get_mword(&low_addr, sizeof(Mword)*2, 16))
264             {
265               putchar('-');
266               if (Jdb_input::get_mword(&high_addr, sizeof(Mword)*2, 16))
267                 {
268                   unsigned l_row = low_addr  / ((cols()-1) * elb);
269                   unsigned l_col = (low_addr % ((cols()-1) * elb)) / elb;
270                   unsigned h_row = high_addr / ((cols()-1) * elb);
271
272                   if (low_addr <= high_addr)
273                     {
274                       Mword lines = h_row - l_row;
275                       if (lines < 1)
276                         lines = 1;
277                       // enable gzip console
278                       Kconsole::console()->
279                         start_exclusive(Console::GZIP);
280                       char old_mode = dump_type;
281                       dump_type = D_MODE;
282                       draw_table(l_row, l_col, lines, cols());
283                       dump_type = old_mode;
284                       Kconsole::console()->
285                         end_exclusive(Console::GZIP);
286                     }
287                 }
288             }
289           return Redraw;
290         }
291       return Handled;
292
293     case ' ': // change viewing mode
294       switch (dump_type)
295         {
296         case D_MODE: dump_type=B_MODE; return Redraw;
297         case B_MODE: dump_type=C_MODE; return Redraw;
298         case C_MODE: dump_type=D_MODE; return Redraw;
299         }
300       break;
301
302     case KEY_TAB:
303       show_adapter_memory = !show_adapter_memory;
304       return Redraw;
305
306     case KEY_RETURN: // goto address under cursor
307       if (level<=7 && dump_type==D_MODE)
308         {
309           Address virt1;
310           if (Jdb::peek((Address*)virt(row,col), task, virt1))
311             {
312               if (!dump(virt1, task, level +1))
313                   return Exit;
314               return Redraw;
315             }
316         }
317       break;
318
319     case 'u': // disassemble using address the cursor points to
320       if (Jdb_disasm::avail() && level<=7 && dump_type == D_MODE)
321         {
322           Address virt1;
323           if (Jdb::peek((Address*)virt(row,col), task, virt1))
324             {
325               Jdb::printf_statline("dump", "<CR>=disassemble here",
326                                    "u[address="L4_PTR_FMT" task=%p] ",
327                                    virt1, task);
328               int c1 = Jdb_core::getchar();
329               if (c1 != KEY_RETURN && c1 != ' ')
330                 {
331                   Jdb::printf_statline("dump", 0, "u");
332                   Jdb::execute_command("u", c1);
333                   return Exit;
334                 }
335
336               return Jdb_disasm::show(virt1, task, level+1, 1)
337                      ? Redraw
338                      : Exit;
339             }
340         }
341       return Handled;
342
343     case 'e': // poke memory
344       if (dump_type == D_MODE)
345         return Edit;
346       break;
347
348     case 'c': // set boundaries for highlighting memory contents
349       if (level <= 7 && dump_type == D_MODE)
350         {
351           Address a;
352           if (Jdb::peek((Address*)virt(row,col), task, a))
353             {
354               const Address pm = 0x100000;
355               highlight_start = (a  > pm)        ? a - pm : 0;
356               highlight_end   = (a <= ~1UL - pm) ? a + pm : ~1UL;
357               return Redraw;
358             }
359         }
360       break;
361
362     case 'r':
363       return Redraw;
364     }
365
366   return Handled;
367
368 }
369
370 PUBLIC
371 Jdb_module::Action_code
372 Jdb_dump::action(int cmd, void *&args, char const *&fmt, int &next_char)
373 {
374   if (cmd == 0)
375     {
376       Jdb_module::Action_code code;
377
378       code = Jdb_input_task_addr::action(args, fmt, next_char);
379       if (code == Jdb_module::NOTHING)
380         {
381           Address addr  = Jdb_input_task_addr::addr();
382           Space *space = Jdb_input_task_addr::space();
383           if (addr == (Address)~0UL)
384             addr = 0;
385
386           return dump(addr, space, 0);
387         }
388
389       if (code != ERROR)
390         return code;
391     }
392
393   return NOTHING;
394 }
395
396 PUBLIC
397 Jdb_module::Cmd const *
398 Jdb_dump::cmds() const
399 {
400   static Cmd cs[] =
401     {
402       { 0, "d", "dump", "%C",
403         "d[t<taskno>|p]<addr>\tdump memory of given/current task at <addr>, or physical",
404         &Jdb_input_task_addr::first_char },
405     };
406   return cs;
407 }
408
409 PUBLIC
410 int
411 Jdb_dump::num_cmds() const
412 {
413   return 1;
414 }
415
416 IMPLEMENT
417 Jdb_dump::Jdb_dump()
418   : Jdb_module("INFO"), dump_type(D_MODE)
419 {}
420
421 static Jdb_dump jdb_dump INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
422
423 int
424 jdb_dump_addr_task(Address addr, Space *task, int level)
425 { return jdb_dump.dump(addr, task, level); }