daily update
[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"
c906108c
SS
47
48#include "tui.h"
49#include "tuiData.h"
a8080b7f 50#include "tuiWin.h"
c906108c
SS
51#include "tuiLayout.h"
52#include "tuiSourceWin.h"
53#include "tuiStack.h"
a8080b7f 54#include "tui-file.h"
c906108c 55
aec2f747
SC
56struct 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. */
66static CORE_ADDR
67tui_disassemble (struct tui_asm_line* lines, CORE_ADDR pc, int count)
68{
69 struct ui_file *gdb_dis_out;
70 disassemble_info asm_info;
c906108c 71
aec2f747
SC
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. */
114static CORE_ADDR
115tui_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. */
c906108c 194TuiStatus
aec2f747 195tuiSetDisassemContent (CORE_ADDR pc)
c906108c
SS
196{
197 TuiStatus ret = TUI_FAILURE;
aec2f747
SC
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++)
c906108c 235 {
aec2f747
SC
236 size_t len = strlen (lines[i].addr_string);
237 if (len > addr_size)
238 addr_size = len;
c906108c 239
aec2f747
SC
240 len = strlen (lines[i].insn) + tab_len;
241 if (len > max_size)
242 max_size = len;
c906108c 243 }
aec2f747
SC
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);
c906108c 283
aec2f747
SC
284 xfree (lines[i].addr_string);
285 xfree (lines[i].insn);
286 }
287 disassemWin->generic.contentSize = i;
288 return TUI_SUCCESS;
289}
c906108c
SS
290
291
292/*
c5aa993b
JM
293 ** tuiShowDisassem().
294 ** Function to display the disassembly window with disassembled code.
295 */
c906108c 296void
c774cec6 297tuiShowDisassem (CORE_ADDR startAddr)
c906108c 298{
c774cec6 299 struct symtab *s = find_pc_symtab (startAddr);
c906108c 300 TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
a4b99e53 301 TuiLineOrAddress val;
c906108c 302
a4b99e53 303 val.addr = startAddr;
c906108c 304 tuiAddWinToLayout (DISASSEM_WIN);
a4b99e53 305 tuiUpdateSourceWindow (disassemWin, s, val, FALSE);
c906108c 306 /*
c5aa993b
JM
307 ** if the focus was in the src win, put it in the asm win, if the
308 ** source view isn't split
309 */
c906108c
SS
310 if (currentLayout () != SRC_DISASSEM_COMMAND && winWithFocus == srcWin)
311 tuiSetWinFocusTo (disassemWin);
312
313 return;
314} /* tuiShowDisassem */
315
316
317/*
c5aa993b
JM
318 ** tuiShowDisassemAndUpdateSource().
319 ** Function to display the disassembly window.
320 */
c906108c 321void
c774cec6 322tuiShowDisassemAndUpdateSource (CORE_ADDR startAddr)
c906108c
SS
323{
324 struct symtab_and_line sal;
325
326 tuiShowDisassem (startAddr);
327 if (currentLayout () == SRC_DISASSEM_COMMAND)
328 {
a4b99e53 329 TuiLineOrAddress val;
aec2f747 330
c906108c 331 /*
c5aa993b
JM
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 */
c774cec6 335 sal = find_pc_line (startAddr, 0);
a4b99e53
SC
336 val.lineNo = sal.line;
337 tuiUpdateSourceWindow (srcWin, sal.symtab, val, TRUE);
3024f13a
SC
338 if (sal.symtab)
339 {
340 current_source_symtab = sal.symtab;
341 tuiUpdateLocatorFilename (sal.symtab->filename);
342 }
343 else
344 tuiUpdateLocatorFilename ("?");
c906108c
SS
345 }
346
347 return;
348} /* tuiShowDisassemAndUpdateSource */
349
c906108c 350/*
c5aa993b
JM
351 ** tuiGetBeginAsmAddress().
352 */
c774cec6 353CORE_ADDR
c906108c 354tuiGetBeginAsmAddress (void)
c906108c
SS
355{
356 TuiGenWinInfoPtr locator;
357 TuiLocatorElementPtr element;
c774cec6 358 CORE_ADDR addr;
c906108c
SS
359
360 locator = locatorWinInfoPtr ();
361 element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator;
362
c774cec6 363 if (element->addr == 0)
c906108c 364 {
0510ab86
SC
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;
c906108c
SS
378 }
379 else /* the target is executing */
380 addr = element->addr;
381
382 return addr;
aec2f747 383} /* tuiGetBeginAsmAddress */
c906108c 384
77cad3ba
SC
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. */
388CORE_ADDR
389tuiGetLowDisassemblyAddress (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
c906108c 403/*
c5aa993b
JM
404 ** tuiVerticalDisassemScroll().
405 ** Scroll the disassembly forward or backward vertically
406 */
c906108c 407void
eca6576c
SC
408tuiVerticalDisassemScroll (TuiScrollDirection scrollDirection,
409 int numToScroll)
c906108c
SS
410{
411 if (disassemWin->generic.content != (OpaquePtr) NULL)
412 {
aec2f747 413 CORE_ADDR pc;
c906108c
SS
414 TuiWinContent content;
415 struct symtab *s;
aec2f747
SC
416 TuiLineOrAddress val;
417 int maxLines, dir;
c906108c
SS
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
aec2f747
SC
425 /* account for hilite */
426 maxLines = disassemWin->generic.height - 2;
c906108c 427 pc = content[0]->whichElement.source.lineOrAddr.addr;
aec2f747 428 dir = (scrollDirection == FORWARD_SCROLL) ? maxLines : - maxLines;
c906108c 429
aec2f747
SC
430 val.addr = tui_find_disassembly_address (pc, dir);
431 tuiUpdateSourceWindowAsIs (disassemWin, s, val, FALSE);
432 }
433}
This page took 0.283685 seconds and 4 git commands to generate.