]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_disasm.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_disasm.cpp
1 INTERFACE:
2
3 #include "jdb_module.h"
4 #include "l4_types.h"
5 #include "types.h"
6
7 class Space;
8
9 // ------------------------------------------------------------------------
10 INTERFACE [!jdb_disasm]:
11
12 class Jdb_disasm : public Jdb_module
13 {
14 public:
15   static bool avail() { return false; }
16 };
17
18 // ------------------------------------------------------------------------
19 INTERFACE [jdb_disasm]:
20
21 class Jdb_disasm : public Jdb_module
22 {
23 public:
24   Jdb_disasm() FIASCO_INIT;
25   static bool avail() { return true; }
26 private:
27   static char show_intel_syntax;
28   static char show_lines;
29 };
30
31
32 // ------------------------------------------------------------------------
33 IMPLEMENTATION [!jdb_disasm]:
34
35 PUBLIC static
36 Jdb_module::Action_code
37 Jdb_disasm::show(Address, Space *, int, bool = false)
38 {
39   return Jdb_module::NOTHING;
40 }
41
42 PUBLIC static
43 bool
44 Jdb_disasm::show_disasm_line(int, Address &, int, Space *)
45 {
46   return false;
47 }
48
49 // ------------------------------------------------------------------------
50 IMPLEMENTATION [jdb_disasm]:
51
52 #include <cstdio>
53 #include <cstring>
54 #include <cstdarg>
55
56 #include "alloca.h"
57 #include "disasm.h"
58 #include "jdb.h"
59 #include "jdb_bp.h"
60 #include "jdb_input.h"
61 #include "jdb_lines.h"
62 #include "jdb_module.h"
63 #include "jdb_screen.h"
64 #include "jdb_symbol.h"
65 #include "kernel_console.h"
66 #include "keycodes.h"
67 #include "static_init.h"
68 #include "task.h"
69
70 char Jdb_disasm::show_intel_syntax;
71 char Jdb_disasm::show_lines = 2;
72
73 static
74 bool
75 Jdb_disasm::disasm_line(char *buffer, int buflen, Address &addr,
76                         int show_symbols, Space *task)
77 {
78   int len;
79
80   if ((len = disasm_bytes(buffer, buflen, addr, task, show_symbols,
81                           show_intel_syntax, &Jdb::peek_task,
82                           &Jdb_symbol::match_addr_to_symbol)) < 0)
83     {
84       addr += 1;
85       return false;
86     }
87
88   addr += len;
89   return true;
90 }
91
92 static
93 int
94 Jdb_disasm::at_symbol(Address addr, Space *task)
95 {
96   return Jdb_symbol::match_addr_to_symbol(addr, task) != 0;
97 }
98
99 static
100 int
101 Jdb_disasm::at_line(Address addr, Space *task)
102 {
103   return (show_lines &&
104           Jdb_lines::match_addr_to_line(addr, task, 0, 0, show_lines==2));
105 }
106
107 static
108 Address
109 Jdb_disasm::disasm_offset(Address &start, int offset, Space *task)
110 {
111   if (offset>0)
112     {
113       Address addr = start;
114       while (offset--)
115         {
116           if (!disasm_line(0, 0, addr, 0, task))
117             {
118               start = addr + offset;
119               return false;
120             }
121           if (at_symbol(addr, task) && !offset--)
122             break;
123           if (at_line(addr, task) && !offset--)
124             break;
125         }
126       start = addr;
127       return true;
128     }
129
130   while (offset++)
131     {
132       Address addr = start-64, va_start;
133       for (;;)
134         {
135           va_start = addr;
136           if (!disasm_line(0, 0, addr, 0, task))
137             {
138               start += offset-1;
139               return false;
140             }
141           if (addr >= start)
142             break;
143         }
144       start = va_start;
145       if (at_symbol(addr, task) && !offset++)
146         break;
147       if (at_line(addr, task) && !offset++)
148         break;
149     }
150   return true;
151 }
152
153 PUBLIC static
154 bool
155 Jdb_disasm::show_disasm_line(int len, Address &addr,
156                              int show_symbols, Space *task)
157 {
158   int clreol = 0;
159   if (len < 0)
160     {
161       len = -len;
162       clreol = 1;
163     }
164
165   char *line = (char*)alloca(len);
166   if (line && disasm_line(line, len, addr, show_symbols, task))
167     {
168       if (clreol)
169         printf("%.*s\033[K\n", len, line);
170       else
171         printf("%-*s\n", len, line);
172       return true;
173     }
174
175   if (clreol)
176     puts("........\033[K");
177   else
178     printf("........%*s", len-8, "\n");
179   return false;
180 }
181
182 PUBLIC static
183 Jdb_module::Action_code
184 Jdb_disasm::show(Address virt, Space *task, int level, bool do_clear_screen = false)
185 {
186   Address  enter_addr = virt;
187   Space *trans_task = Jdb::translate_task(virt, task);
188
189   for (;;)
190     {
191       if (do_clear_screen)
192         Jdb::clear_screen();
193
194       Jdb::cursor();
195
196       Address addr;
197       Mword   i;
198       for (i=Jdb_screen::height()-1, addr=virt; i>0; i--)
199         {
200           const char *symbol;
201           char str[78], *nl;
202           char stat_str[4] = { "   " };
203
204           Kconsole::console()->getchar_chance();
205
206           if ((symbol = Jdb_symbol::match_addr_to_symbol(addr, trans_task)))
207             {
208               snprintf(str, sizeof(str)-2, "<%s", symbol);
209
210               // cut symbol at newline
211               for (nl=str; *nl!='\0' && *nl!='\n'; nl++)
212                 ;
213               *nl++ = '>';
214               *nl++ = ':';
215               *nl++ = '\0';
216               
217               printf("%s%s\033[m\033[K\n", Jdb::esc_symbol, str);
218               if (!--i)
219                 break;
220             }
221
222           if (show_lines)
223             {
224               if (Jdb_lines::match_addr_to_line(addr, trans_task, str, 
225                                                 sizeof(str)-1, show_lines==2))
226                 {
227                   printf("%s%s\033[m\033[K\n", Jdb::esc_line, str);
228                   if (!--i)
229                     break;
230                 }
231             }
232
233           // show instruction breakpoint
234           if (Mword i = Jdb_bp::instruction_bp_at_addr(addr))
235             {
236               stat_str[0] = '#';
237               stat_str[1] = '0'+i;
238             }
239
240           printf("%s"L4_PTR_FMT"%s%s  ", 
241                  addr == enter_addr ? Jdb::esc_emph : "", addr, stat_str,
242                  addr == enter_addr ? "\033[m" : "");
243           show_disasm_line(
244 #ifdef CONFIG_BIT32
245                            -64,
246 #else
247                            -58,
248 #endif
249                            addr, 1, task);
250         }
251
252       static char const * const line_mode[] = { "", "[Source]", "[Headers]" };
253       static char const * const syntax_mode[] = { "[AT&T]", "[Intel]" };
254       Jdb::printf_statline("dis", "<Space>=lines mode",
255                            "<"L4_PTR_FMT"> task %-3p  %-9s  %-7s",
256                            virt, task, line_mode[(int)show_lines], 
257                            syntax_mode[(int)show_intel_syntax]);
258
259       Jdb::cursor(Jdb_screen::height(), 6);
260       switch (int c = Jdb_core::getchar())
261         {
262         case KEY_CURSOR_LEFT:
263         case 'h':
264           virt -= 1;
265           break;
266         case KEY_CURSOR_RIGHT:
267         case 'l':
268           virt += 1;
269           break;
270         case KEY_CURSOR_DOWN:
271         case 'j':
272           disasm_offset(virt, +1, task);
273           break;
274         case KEY_CURSOR_UP:
275         case 'k':
276           disasm_offset(virt, -1, task);
277           break;
278         case KEY_PAGE_UP:
279         case 'K':
280           disasm_offset(virt, -Jdb_screen::height()+2, task);
281           break;
282         case KEY_PAGE_DOWN:
283         case 'J':
284           disasm_offset(virt, +Jdb_screen::height()-2, task);
285           break;
286         case ' ':
287           show_lines = (show_lines+1) % 3;
288           break;
289         case KEY_TAB:
290           show_intel_syntax ^= 1;
291           break;
292         case KEY_CURSOR_HOME:
293         case 'H':
294           if (level > 0)
295             return GO_BACK;
296           break;
297         case KEY_ESC:
298           Jdb::abort_command();
299           return NOTHING;
300         default:
301           if (Jdb::is_toplevel_cmd(c)) 
302             return NOTHING;
303           break;
304         }
305     }
306   
307   return GO_BACK;
308 }
309
310 PUBLIC
311 Jdb_module::Action_code
312 Jdb_disasm::action(int cmd, void *&args, char const *&fmt, int &next_char)
313 {
314   if (cmd == 0)
315     {
316       Jdb_module::Action_code code;
317
318       code = Jdb_input_task_addr::action(args, fmt, next_char);
319       if (code == Jdb_module::NOTHING
320           && Jdb_input_task_addr::space() != 0)
321         {
322           Address addr  = Jdb_input_task_addr::addr();
323           Space *space = Jdb_input_task_addr::space();
324           if (addr == (Address)-1)
325             addr = Jdb::get_entry_frame(Jdb::current_cpu)->ip();
326           return show(addr, space, 0) ? GO_BACK : NOTHING;
327         }
328
329       return code;
330     }
331
332   return NOTHING;
333 }
334
335 PUBLIC
336 Jdb_module::Cmd const *
337 Jdb_disasm::cmds() const
338 {
339   static Cmd cs[] =
340     {
341         { 0, "u", "u", "%C",
342           "u[t<taskno>]<addr>\tdisassemble bytes of given/current task addr",
343           &Jdb_input_task_addr::first_char }
344     };
345
346   return cs;
347 }
348
349 PUBLIC
350 int
351 Jdb_disasm::num_cmds() const
352 { return 1; }
353
354 IMPLEMENT
355 Jdb_disasm::Jdb_disasm()
356   : Jdb_module("INFO")
357 {}
358
359 static Jdb_disasm jdb_disasm INIT_PRIORITY(JDB_MODULE_INIT_PRIO);