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