* gdb.c++/pr-1210.cc: New file.
[deliverable/binutils-gdb.git] / gdb / tui / tuiDisassem.c
CommitLineData
f377b406 1/* Disassembly display.
f33c6cbf
AC
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
f377b406
SC
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. */
c906108c 24
f33c6cbf
AC
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
4e8f7a8b
DJ
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
c906108c
SS
42#include "defs.h"
43#include "symtab.h"
44#include "breakpoint.h"
45#include "frame.h"
fd0407d6 46#include "value.h"
52575520 47#include "source.h"
f70a7d61 48#include "disasm.h"
c906108c
SS
49
50#include "tui.h"
51#include "tuiData.h"
a8080b7f 52#include "tuiWin.h"
c906108c
SS
53#include "tuiLayout.h"
54#include "tuiSourceWin.h"
55#include "tuiStack.h"
a8080b7f 56#include "tui-file.h"
c906108c 57
aec2f747
SC
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;
c906108c 72
aec2f747
SC
73 /* now init the ui_file structure */
74 gdb_dis_out = tui_sfileopen (256);
75
aec2f747
SC
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
92bf2b80 90 pc = pc + gdb_print_insn (pc, gdb_dis_out);
aec2f747
SC
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. */
c906108c 184TuiStatus
aec2f747 185tuiSetDisassemContent (CORE_ADDR pc)
c906108c
SS
186{
187 TuiStatus ret = TUI_FAILURE;
aec2f747
SC
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++)
c906108c 225 {
aec2f747
SC
226 size_t len = strlen (lines[i].addr_string);
227 if (len > addr_size)
228 addr_size = len;
c906108c 229
aec2f747
SC
230 len = strlen (lines[i].insn) + tab_len;
231 if (len > max_size)
232 max_size = len;
c906108c 233 }
aec2f747
SC
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);
c906108c 273
aec2f747
SC
274 xfree (lines[i].addr_string);
275 xfree (lines[i].insn);
276 }
277 disassemWin->generic.contentSize = i;
278 return TUI_SUCCESS;
279}
c906108c
SS
280
281
282/*
c5aa993b
JM
283 ** tuiShowDisassem().
284 ** Function to display the disassembly window with disassembled code.
285 */
c906108c 286void
c774cec6 287tuiShowDisassem (CORE_ADDR startAddr)
c906108c 288{
c774cec6 289 struct symtab *s = find_pc_symtab (startAddr);
c906108c 290 TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
a4b99e53 291 TuiLineOrAddress val;
c906108c 292
a4b99e53 293 val.addr = startAddr;
c906108c 294 tuiAddWinToLayout (DISASSEM_WIN);
a4b99e53 295 tuiUpdateSourceWindow (disassemWin, s, val, FALSE);
c906108c 296 /*
c5aa993b
JM
297 ** if the focus was in the src win, put it in the asm win, if the
298 ** source view isn't split
299 */
c906108c
SS
300 if (currentLayout () != SRC_DISASSEM_COMMAND && winWithFocus == srcWin)
301 tuiSetWinFocusTo (disassemWin);
302
303 return;
304} /* tuiShowDisassem */
305
306
307/*
c5aa993b
JM
308 ** tuiShowDisassemAndUpdateSource().
309 ** Function to display the disassembly window.
310 */
c906108c 311void
c774cec6 312tuiShowDisassemAndUpdateSource (CORE_ADDR startAddr)
c906108c
SS
313{
314 struct symtab_and_line sal;
315
316 tuiShowDisassem (startAddr);
317 if (currentLayout () == SRC_DISASSEM_COMMAND)
318 {
a4b99e53 319 TuiLineOrAddress val;
aec2f747 320
c906108c 321 /*
c5aa993b
JM
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 */
c774cec6 325 sal = find_pc_line (startAddr, 0);
a4b99e53
SC
326 val.lineNo = sal.line;
327 tuiUpdateSourceWindow (srcWin, sal.symtab, val, TRUE);
3024f13a
SC
328 if (sal.symtab)
329 {
52575520 330 set_current_source_symtab_and_line (&sal);
3024f13a
SC
331 tuiUpdateLocatorFilename (sal.symtab->filename);
332 }
333 else
334 tuiUpdateLocatorFilename ("?");
c906108c
SS
335 }
336
337 return;
338} /* tuiShowDisassemAndUpdateSource */
339
c906108c 340/*
c5aa993b
JM
341 ** tuiGetBeginAsmAddress().
342 */
c774cec6 343CORE_ADDR
c906108c 344tuiGetBeginAsmAddress (void)
c906108c
SS
345{
346 TuiGenWinInfoPtr locator;
347 TuiLocatorElementPtr element;
c774cec6 348 CORE_ADDR addr;
c906108c
SS
349
350 locator = locatorWinInfoPtr ();
351 element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator;
352
c774cec6 353 if (element->addr == 0)
c906108c 354 {
0510ab86
SC
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;
c906108c
SS
368 }
369 else /* the target is executing */
370 addr = element->addr;
371
372 return addr;
aec2f747 373} /* tuiGetBeginAsmAddress */
c906108c 374
77cad3ba
SC
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
c906108c 393/*
c5aa993b
JM
394 ** tuiVerticalDisassemScroll().
395 ** Scroll the disassembly forward or backward vertically
396 */
c906108c 397void
eca6576c
SC
398tuiVerticalDisassemScroll (TuiScrollDirection scrollDirection,
399 int numToScroll)
c906108c
SS
400{
401 if (disassemWin->generic.content != (OpaquePtr) NULL)
402 {
aec2f747 403 CORE_ADDR pc;
c906108c
SS
404 TuiWinContent content;
405 struct symtab *s;
aec2f747
SC
406 TuiLineOrAddress val;
407 int maxLines, dir;
52575520 408 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
c906108c
SS
409
410 content = (TuiWinContent) disassemWin->generic.content;
52575520 411 if (cursal.symtab == (struct symtab *) NULL)
f70a7d61 412 s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
c906108c 413 else
52575520 414 s = cursal.symtab;
c906108c 415
aec2f747
SC
416 /* account for hilite */
417 maxLines = disassemWin->generic.height - 2;
c906108c 418 pc = content[0]->whichElement.source.lineOrAddr.addr;
aec2f747 419 dir = (scrollDirection == FORWARD_SCROLL) ? maxLines : - maxLines;
c906108c 420
aec2f747
SC
421 val.addr = tui_find_disassembly_address (pc, dir);
422 tuiUpdateSourceWindowAsIs (disassemWin, s, val, FALSE);
423 }
424}
This page took 0.352153 seconds and 4 git commands to generate.