* gdb.c++/pr-1210.cc: New file.
[deliverable/binutils-gdb.git] / gdb / tui / tuiDisassem.c
... / ...
CommitLineData
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#include "source.h"
48#include "disasm.h"
49
50#include "tui.h"
51#include "tuiData.h"
52#include "tuiWin.h"
53#include "tuiLayout.h"
54#include "tuiSourceWin.h"
55#include "tuiStack.h"
56#include "tui-file.h"
57
58struct tui_asm_line
59{
60 CORE_ADDR addr;
61 char* addr_string;
62 char* insn;
63};
64
65/* Function to set the disassembly window's content.
66 Disassemble count lines starting at pc.
67 Return address of the count'th instruction after pc. */
68static CORE_ADDR
69tui_disassemble (struct tui_asm_line* lines, CORE_ADDR pc, int count)
70{
71 struct ui_file *gdb_dis_out;
72
73 /* now init the ui_file structure */
74 gdb_dis_out = tui_sfileopen (256);
75
76 /* Now construct each line */
77 for (; count > 0; count--, lines++)
78 {
79 if (lines->addr_string)
80 xfree (lines->addr_string);
81 if (lines->insn)
82 xfree (lines->insn);
83
84 print_address (pc, gdb_dis_out);
85 lines->addr = pc;
86 lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
87
88 ui_file_rewind (gdb_dis_out);
89
90 pc = pc + gdb_print_insn (pc, gdb_dis_out);
91
92 lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
93
94 /* reset the buffer to empty */
95 ui_file_rewind (gdb_dis_out);
96 }
97 ui_file_delete (gdb_dis_out);
98 return pc;
99}
100
101/* Find the disassembly address that corresponds to FROM lines
102 above or below the PC. Variable sized instructions are taken
103 into account by the algorithm. */
104static CORE_ADDR
105tui_find_disassembly_address (CORE_ADDR pc, int from)
106{
107 register CORE_ADDR newLow;
108 int maxLines;
109 int i;
110 struct tui_asm_line* lines;
111
112 maxLines = (from > 0) ? from : - from;
113 if (maxLines <= 1)
114 return pc;
115
116 lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
117 * maxLines);
118 memset (lines, 0, sizeof (struct tui_asm_line) * maxLines);
119
120 newLow = pc;
121 if (from > 0)
122 {
123 tui_disassemble (lines, pc, maxLines);
124 newLow = lines[maxLines - 1].addr;
125 }
126 else
127 {
128 CORE_ADDR last_addr;
129 int pos;
130 struct minimal_symbol* msymbol;
131
132 /* Find backward an address which is a symbol
133 and for which disassembling from that address will fill
134 completely the window. */
135 pos = maxLines - 1;
136 do {
137 newLow -= 1 * maxLines;
138 msymbol = lookup_minimal_symbol_by_pc_section (newLow, 0);
139
140 if (msymbol)
141 newLow = SYMBOL_VALUE_ADDRESS (msymbol);
142 else
143 newLow += 1 * maxLines;
144
145 tui_disassemble (lines, newLow, maxLines);
146 last_addr = lines[pos].addr;
147 } while (last_addr > pc && msymbol);
148
149 /* Scan forward disassembling one instruction at a time
150 until the last visible instruction of the window
151 matches the pc. We keep the disassembled instructions
152 in the 'lines' window and shift it downward (increasing
153 its addresses). */
154 if (last_addr < pc)
155 do
156 {
157 CORE_ADDR next_addr;
158
159 pos++;
160 if (pos >= maxLines)
161 pos = 0;
162
163 next_addr = tui_disassemble (&lines[pos], last_addr, 1);
164
165 /* If there are some problems while disassembling exit. */
166 if (next_addr <= last_addr)
167 break;
168 last_addr = next_addr;
169 } while (last_addr <= pc);
170 pos++;
171 if (pos >= maxLines)
172 pos = 0;
173 newLow = lines[pos].addr;
174 }
175 for (i = 0; i < maxLines; i++)
176 {
177 xfree (lines[i].addr_string);
178 xfree (lines[i].insn);
179 }
180 return newLow;
181}
182
183/* Function to set the disassembly window's content. */
184TuiStatus
185tuiSetDisassemContent (CORE_ADDR pc)
186{
187 TuiStatus ret = TUI_FAILURE;
188 register int i;
189 register int offset = disassemWin->detail.sourceInfo.horizontalOffset;
190 register int lineWidth, maxLines;
191 CORE_ADDR cur_pc;
192 TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
193 int tab_len = tuiDefaultTabLen ();
194 struct tui_asm_line* lines;
195 int insn_pos;
196 int addr_size, max_size;
197 char* line;
198
199 if (pc == 0)
200 return TUI_FAILURE;
201
202 ret = tuiAllocSourceBuffer (disassemWin);
203 if (ret != TUI_SUCCESS)
204 return ret;
205
206 disassemWin->detail.sourceInfo.startLineOrAddr.addr = pc;
207 cur_pc = (CORE_ADDR)
208 (((TuiWinElementPtr) locator->content[0])->whichElement.locator.addr);
209
210 maxLines = disassemWin->generic.height - 2; /* account for hilite */
211
212 /* Get temporary table that will hold all strings (addr & insn). */
213 lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
214 * maxLines);
215 memset (lines, 0, sizeof (struct tui_asm_line) * maxLines);
216
217 lineWidth = disassemWin->generic.width - 1;
218
219 tui_disassemble (lines, pc, maxLines);
220
221 /* See what is the maximum length of an address and of a line. */
222 addr_size = 0;
223 max_size = 0;
224 for (i = 0; i < maxLines; i++)
225 {
226 size_t len = strlen (lines[i].addr_string);
227 if (len > addr_size)
228 addr_size = len;
229
230 len = strlen (lines[i].insn) + tab_len;
231 if (len > max_size)
232 max_size = len;
233 }
234 max_size += addr_size + tab_len;
235
236 /* Allocate memory to create each line. */
237 line = (char*) alloca (max_size);
238 insn_pos = (1 + (addr_size / tab_len)) * tab_len;
239
240 /* Now construct each line */
241 for (i = 0; i < maxLines; i++)
242 {
243 TuiWinElementPtr element;
244 TuiSourceElement* src;
245 int curLen;
246
247 element = (TuiWinElementPtr) disassemWin->generic.content[i];
248 src = &element->whichElement.source;
249 strcpy (line, lines[i].addr_string);
250 curLen = strlen (line);
251
252 /* Add spaces to make the instructions start on the same column */
253 while (curLen < insn_pos)
254 {
255 strcat (line, " ");
256 curLen++;
257 }
258
259 strcat (line, lines[i].insn);
260
261 /* Now copy the line taking the offset into account */
262 if (strlen (line) > offset)
263 strcpy (src->line, &line[offset]);
264 else
265 src->line[0] = '\0';
266
267 src->lineOrAddr.addr = lines[i].addr;
268 src->isExecPoint = lines[i].addr == cur_pc;
269
270 /* See whether there is a breakpoint installed. */
271 src->hasBreak = (!src->isExecPoint
272 && breakpoint_here_p (pc) != no_breakpoint_here);
273
274 xfree (lines[i].addr_string);
275 xfree (lines[i].insn);
276 }
277 disassemWin->generic.contentSize = i;
278 return TUI_SUCCESS;
279}
280
281
282/*
283 ** tuiShowDisassem().
284 ** Function to display the disassembly window with disassembled code.
285 */
286void
287tuiShowDisassem (CORE_ADDR startAddr)
288{
289 struct symtab *s = find_pc_symtab (startAddr);
290 TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
291 TuiLineOrAddress val;
292
293 val.addr = startAddr;
294 tuiAddWinToLayout (DISASSEM_WIN);
295 tuiUpdateSourceWindow (disassemWin, s, val, FALSE);
296 /*
297 ** if the focus was in the src win, put it in the asm win, if the
298 ** source view isn't split
299 */
300 if (currentLayout () != SRC_DISASSEM_COMMAND && winWithFocus == srcWin)
301 tuiSetWinFocusTo (disassemWin);
302
303 return;
304} /* tuiShowDisassem */
305
306
307/*
308 ** tuiShowDisassemAndUpdateSource().
309 ** Function to display the disassembly window.
310 */
311void
312tuiShowDisassemAndUpdateSource (CORE_ADDR startAddr)
313{
314 struct symtab_and_line sal;
315
316 tuiShowDisassem (startAddr);
317 if (currentLayout () == SRC_DISASSEM_COMMAND)
318 {
319 TuiLineOrAddress val;
320
321 /*
322 ** Update what is in the source window if it is displayed too,
323 ** note that it follows what is in the disassembly window and visa-versa
324 */
325 sal = find_pc_line (startAddr, 0);
326 val.lineNo = sal.line;
327 tuiUpdateSourceWindow (srcWin, sal.symtab, val, TRUE);
328 if (sal.symtab)
329 {
330 set_current_source_symtab_and_line (&sal);
331 tuiUpdateLocatorFilename (sal.symtab->filename);
332 }
333 else
334 tuiUpdateLocatorFilename ("?");
335 }
336
337 return;
338} /* tuiShowDisassemAndUpdateSource */
339
340/*
341 ** tuiGetBeginAsmAddress().
342 */
343CORE_ADDR
344tuiGetBeginAsmAddress (void)
345{
346 TuiGenWinInfoPtr locator;
347 TuiLocatorElementPtr element;
348 CORE_ADDR addr;
349
350 locator = locatorWinInfoPtr ();
351 element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator;
352
353 if (element->addr == 0)
354 {
355 struct minimal_symbol *main_symbol;
356
357 /* Find address of the start of program.
358 Note: this should be language specific. */
359 main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
360 if (main_symbol == 0)
361 main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
362 if (main_symbol == 0)
363 main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
364 if (main_symbol)
365 addr = SYMBOL_VALUE_ADDRESS (main_symbol);
366 else
367 addr = 0;
368 }
369 else /* the target is executing */
370 addr = element->addr;
371
372 return addr;
373} /* tuiGetBeginAsmAddress */
374
375/* Determine what the low address will be to display in the TUI's
376 disassembly window. This may or may not be the same as the
377 low address input. */
378CORE_ADDR
379tuiGetLowDisassemblyAddress (CORE_ADDR low, CORE_ADDR pc)
380{
381 int pos;
382
383 /* Determine where to start the disassembly so that the pc is about in the
384 middle of the viewport. */
385 pos = tuiDefaultWinViewportHeight (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
386 pc = tui_find_disassembly_address (pc, -pos);
387
388 if (pc < low)
389 pc = low;
390 return pc;
391}
392
393/*
394 ** tuiVerticalDisassemScroll().
395 ** Scroll the disassembly forward or backward vertically
396 */
397void
398tuiVerticalDisassemScroll (TuiScrollDirection scrollDirection,
399 int numToScroll)
400{
401 if (disassemWin->generic.content != (OpaquePtr) NULL)
402 {
403 CORE_ADDR pc;
404 TuiWinContent content;
405 struct symtab *s;
406 TuiLineOrAddress val;
407 int maxLines, dir;
408 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
409
410 content = (TuiWinContent) disassemWin->generic.content;
411 if (cursal.symtab == (struct symtab *) NULL)
412 s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
413 else
414 s = cursal.symtab;
415
416 /* account for hilite */
417 maxLines = disassemWin->generic.height - 2;
418 pc = content[0]->whichElement.source.lineOrAddr.addr;
419 dir = (scrollDirection == FORWARD_SCROLL) ? maxLines : - maxLines;
420
421 val.addr = tui_find_disassembly_address (pc, dir);
422 tuiUpdateSourceWindowAsIs (disassemWin, s, val, FALSE);
423 }
424}
This page took 0.024083 seconds and 4 git commands to generate.