daily update
[deliverable/binutils-gdb.git] / gdb / tui / tuiDisassem.c
1 /* Disassembly display.
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
6 Contributed by Hewlett-Packard Company.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
24
25 /* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
26 "defs.h" should be included first. Unfortunatly some systems
27 (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
28 and they clash with "bfd.h"'s definiton of true/false. The correct
29 fix is to remove true/false from "bfd.h", however, until that
30 happens, hack around it by including "config.h" and <curses.h>
31 first. */
32
33 #include "config.h"
34 #ifdef HAVE_NCURSES_H
35 #include <ncurses.h>
36 #else
37 #ifdef HAVE_CURSES_H
38 #include <curses.h>
39 #endif
40 #endif
41
42 #include "defs.h"
43 #include "symtab.h"
44 #include "breakpoint.h"
45 #include "frame.h"
46 #include "value.h"
47
48 #include "tui.h"
49 #include "tuiData.h"
50 #include "tuiWin.h"
51 #include "tuiLayout.h"
52 #include "tuiSourceWin.h"
53 #include "tuiStack.h"
54 #include "tui-file.h"
55
56 struct tui_asm_line
57 {
58 CORE_ADDR addr;
59 char* addr_string;
60 char* insn;
61 };
62
63 /* Function to set the disassembly window's content.
64 Disassemble count lines starting at pc.
65 Return address of the count'th instruction after pc. */
66 static CORE_ADDR
67 tui_disassemble (struct tui_asm_line* lines, CORE_ADDR pc, int count)
68 {
69 struct ui_file *gdb_dis_out;
70 disassemble_info asm_info;
71
72 /* now init the ui_file structure */
73 gdb_dis_out = tui_sfileopen (256);
74
75 memcpy (&asm_info, TARGET_PRINT_INSN_INFO, sizeof (asm_info));
76 asm_info.stream = gdb_dis_out;
77
78 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
79 asm_info.endian = BFD_ENDIAN_BIG;
80 else
81 asm_info.endian = BFD_ENDIAN_LITTLE;
82
83 if (TARGET_ARCHITECTURE != NULL)
84 asm_info.mach = TARGET_ARCHITECTURE->mach;
85
86 /* Now construct each line */
87 for (; count > 0; count--, lines++)
88 {
89 if (lines->addr_string)
90 xfree (lines->addr_string);
91 if (lines->insn)
92 xfree (lines->insn);
93
94 print_address (pc, gdb_dis_out);
95 lines->addr = pc;
96 lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
97
98 ui_file_rewind (gdb_dis_out);
99
100 pc = pc + TARGET_PRINT_INSN (pc, &asm_info);
101
102 lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
103
104 /* reset the buffer to empty */
105 ui_file_rewind (gdb_dis_out);
106 }
107 ui_file_delete (gdb_dis_out);
108 return pc;
109 }
110
111 /* Find the disassembly address that corresponds to FROM lines
112 above or below the PC. Variable sized instructions are taken
113 into account by the algorithm. */
114 static CORE_ADDR
115 tui_find_disassembly_address (CORE_ADDR pc, int from)
116 {
117 register CORE_ADDR newLow;
118 int maxLines;
119 int i;
120 struct tui_asm_line* lines;
121
122 maxLines = (from > 0) ? from : - from;
123 if (maxLines <= 1)
124 return pc;
125
126 lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
127 * maxLines);
128 memset (lines, 0, sizeof (struct tui_asm_line) * maxLines);
129
130 newLow = pc;
131 if (from > 0)
132 {
133 tui_disassemble (lines, pc, maxLines);
134 newLow = lines[maxLines - 1].addr;
135 }
136 else
137 {
138 CORE_ADDR last_addr;
139 int pos;
140 struct minimal_symbol* msymbol;
141
142 /* Find backward an address which is a symbol
143 and for which disassembling from that address will fill
144 completely the window. */
145 pos = maxLines - 1;
146 do {
147 newLow -= 1 * maxLines;
148 msymbol = lookup_minimal_symbol_by_pc_section (newLow, 0);
149
150 if (msymbol)
151 newLow = SYMBOL_VALUE_ADDRESS (msymbol);
152 else
153 newLow += 1 * maxLines;
154
155 tui_disassemble (lines, newLow, maxLines);
156 last_addr = lines[pos].addr;
157 } while (last_addr > pc && msymbol);
158
159 /* Scan forward disassembling one instruction at a time
160 until the last visible instruction of the window
161 matches the pc. We keep the disassembled instructions
162 in the 'lines' window and shift it downward (increasing
163 its addresses). */
164 if (last_addr < pc)
165 do
166 {
167 CORE_ADDR next_addr;
168
169 pos++;
170 if (pos >= maxLines)
171 pos = 0;
172
173 next_addr = tui_disassemble (&lines[pos], last_addr, 1);
174
175 /* If there are some problems while disassembling exit. */
176 if (next_addr <= last_addr)
177 break;
178 last_addr = next_addr;
179 } while (last_addr <= pc);
180 pos++;
181 if (pos >= maxLines)
182 pos = 0;
183 newLow = lines[pos].addr;
184 }
185 for (i = 0; i < maxLines; i++)
186 {
187 xfree (lines[i].addr_string);
188 xfree (lines[i].insn);
189 }
190 return newLow;
191 }
192
193 /* Function to set the disassembly window's content. */
194 TuiStatus
195 tuiSetDisassemContent (CORE_ADDR pc)
196 {
197 TuiStatus ret = TUI_FAILURE;
198 register int i;
199 register int offset = disassemWin->detail.sourceInfo.horizontalOffset;
200 register int lineWidth, maxLines;
201 CORE_ADDR cur_pc;
202 TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
203 int tab_len = tuiDefaultTabLen ();
204 struct tui_asm_line* lines;
205 int insn_pos;
206 int addr_size, max_size;
207 char* line;
208
209 if (pc == 0)
210 return TUI_FAILURE;
211
212 ret = tuiAllocSourceBuffer (disassemWin);
213 if (ret != TUI_SUCCESS)
214 return ret;
215
216 disassemWin->detail.sourceInfo.startLineOrAddr.addr = pc;
217 cur_pc = (CORE_ADDR)
218 (((TuiWinElementPtr) locator->content[0])->whichElement.locator.addr);
219
220 maxLines = disassemWin->generic.height - 2; /* account for hilite */
221
222 /* Get temporary table that will hold all strings (addr & insn). */
223 lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
224 * maxLines);
225 memset (lines, 0, sizeof (struct tui_asm_line) * maxLines);
226
227 lineWidth = disassemWin->generic.width - 1;
228
229 tui_disassemble (lines, pc, maxLines);
230
231 /* See what is the maximum length of an address and of a line. */
232 addr_size = 0;
233 max_size = 0;
234 for (i = 0; i < maxLines; i++)
235 {
236 size_t len = strlen (lines[i].addr_string);
237 if (len > addr_size)
238 addr_size = len;
239
240 len = strlen (lines[i].insn) + tab_len;
241 if (len > max_size)
242 max_size = len;
243 }
244 max_size += addr_size + tab_len;
245
246 /* Allocate memory to create each line. */
247 line = (char*) alloca (max_size);
248 insn_pos = (1 + (addr_size / tab_len)) * tab_len;
249
250 /* Now construct each line */
251 for (i = 0; i < maxLines; i++)
252 {
253 TuiWinElementPtr element;
254 TuiSourceElement* src;
255 int curLen;
256
257 element = (TuiWinElementPtr) disassemWin->generic.content[i];
258 src = &element->whichElement.source;
259 strcpy (line, lines[i].addr_string);
260 curLen = strlen (line);
261
262 /* Add spaces to make the instructions start on the same column */
263 while (curLen < insn_pos)
264 {
265 strcat (line, " ");
266 curLen++;
267 }
268
269 strcat (line, lines[i].insn);
270
271 /* Now copy the line taking the offset into account */
272 if (strlen (line) > offset)
273 strcpy (src->line, &line[offset]);
274 else
275 src->line[0] = '\0';
276
277 src->lineOrAddr.addr = lines[i].addr;
278 src->isExecPoint = lines[i].addr == cur_pc;
279
280 /* See whether there is a breakpoint installed. */
281 src->hasBreak = (!src->isExecPoint
282 && breakpoint_here_p (pc) != no_breakpoint_here);
283
284 xfree (lines[i].addr_string);
285 xfree (lines[i].insn);
286 }
287 disassemWin->generic.contentSize = i;
288 return TUI_SUCCESS;
289 }
290
291
292 /*
293 ** tuiShowDisassem().
294 ** Function to display the disassembly window with disassembled code.
295 */
296 void
297 tuiShowDisassem (CORE_ADDR startAddr)
298 {
299 struct symtab *s = find_pc_symtab (startAddr);
300 TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
301 TuiLineOrAddress val;
302
303 val.addr = startAddr;
304 tuiAddWinToLayout (DISASSEM_WIN);
305 tuiUpdateSourceWindow (disassemWin, s, val, FALSE);
306 /*
307 ** if the focus was in the src win, put it in the asm win, if the
308 ** source view isn't split
309 */
310 if (currentLayout () != SRC_DISASSEM_COMMAND && winWithFocus == srcWin)
311 tuiSetWinFocusTo (disassemWin);
312
313 return;
314 } /* tuiShowDisassem */
315
316
317 /*
318 ** tuiShowDisassemAndUpdateSource().
319 ** Function to display the disassembly window.
320 */
321 void
322 tuiShowDisassemAndUpdateSource (CORE_ADDR startAddr)
323 {
324 struct symtab_and_line sal;
325
326 tuiShowDisassem (startAddr);
327 if (currentLayout () == SRC_DISASSEM_COMMAND)
328 {
329 TuiLineOrAddress val;
330
331 /*
332 ** Update what is in the source window if it is displayed too,
333 ** note that it follows what is in the disassembly window and visa-versa
334 */
335 sal = find_pc_line (startAddr, 0);
336 val.lineNo = sal.line;
337 tuiUpdateSourceWindow (srcWin, sal.symtab, val, TRUE);
338 if (sal.symtab)
339 {
340 current_source_symtab = sal.symtab;
341 tuiUpdateLocatorFilename (sal.symtab->filename);
342 }
343 else
344 tuiUpdateLocatorFilename ("?");
345 }
346
347 return;
348 } /* tuiShowDisassemAndUpdateSource */
349
350 /*
351 ** tuiGetBeginAsmAddress().
352 */
353 CORE_ADDR
354 tuiGetBeginAsmAddress (void)
355 {
356 TuiGenWinInfoPtr locator;
357 TuiLocatorElementPtr element;
358 CORE_ADDR addr;
359
360 locator = locatorWinInfoPtr ();
361 element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator;
362
363 if (element->addr == 0)
364 {
365 struct minimal_symbol *main_symbol;
366
367 /* Find address of the start of program.
368 Note: this should be language specific. */
369 main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
370 if (main_symbol == 0)
371 main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
372 if (main_symbol == 0)
373 main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
374 if (main_symbol)
375 addr = SYMBOL_VALUE_ADDRESS (main_symbol);
376 else
377 addr = 0;
378 }
379 else /* the target is executing */
380 addr = element->addr;
381
382 return addr;
383 } /* tuiGetBeginAsmAddress */
384
385 /* Determine what the low address will be to display in the TUI's
386 disassembly window. This may or may not be the same as the
387 low address input. */
388 CORE_ADDR
389 tuiGetLowDisassemblyAddress (CORE_ADDR low, CORE_ADDR pc)
390 {
391 int pos;
392
393 /* Determine where to start the disassembly so that the pc is about in the
394 middle of the viewport. */
395 pos = tuiDefaultWinViewportHeight (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
396 pc = tui_find_disassembly_address (pc, -pos);
397
398 if (pc < low)
399 pc = low;
400 return pc;
401 }
402
403 /*
404 ** tuiVerticalDisassemScroll().
405 ** Scroll the disassembly forward or backward vertically
406 */
407 void
408 tuiVerticalDisassemScroll (TuiScrollDirection scrollDirection,
409 int numToScroll)
410 {
411 if (disassemWin->generic.content != (OpaquePtr) NULL)
412 {
413 CORE_ADDR pc;
414 TuiWinContent content;
415 struct symtab *s;
416 TuiLineOrAddress val;
417 int maxLines, dir;
418
419 content = (TuiWinContent) disassemWin->generic.content;
420 if (current_source_symtab == (struct symtab *) NULL)
421 s = find_pc_symtab (selected_frame->pc);
422 else
423 s = current_source_symtab;
424
425 /* account for hilite */
426 maxLines = disassemWin->generic.height - 2;
427 pc = content[0]->whichElement.source.lineOrAddr.addr;
428 dir = (scrollDirection == FORWARD_SCROLL) ? maxLines : - maxLines;
429
430 val.addr = tui_find_disassembly_address (pc, dir);
431 tuiUpdateSourceWindowAsIs (disassemWin, s, val, FALSE);
432 }
433 }
This page took 0.038536 seconds and 5 git commands to generate.