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