1 /* Disassembly display.
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
6 Contributed by Hewlett-Packard Company.
8 This file is part of GDB.
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.
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.
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. */
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>
44 #include "breakpoint.h"
51 #include "tuiLayout.h"
52 #include "tuiSourceWin.h"
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. */
67 tui_disassemble (struct tui_asm_line
* lines
, CORE_ADDR pc
, int count
)
69 struct ui_file
*gdb_dis_out
;
70 disassemble_info asm_info
;
72 /* now init the ui_file structure */
73 gdb_dis_out
= tui_sfileopen (256);
75 memcpy (&asm_info
, TARGET_PRINT_INSN_INFO
, sizeof (asm_info
));
76 asm_info
.stream
= gdb_dis_out
;
78 if (TARGET_BYTE_ORDER
== BFD_ENDIAN_BIG
)
79 asm_info
.endian
= BFD_ENDIAN_BIG
;
81 asm_info
.endian
= BFD_ENDIAN_LITTLE
;
83 if (TARGET_ARCHITECTURE
!= NULL
)
84 asm_info
.mach
= TARGET_ARCHITECTURE
->mach
;
86 /* Now construct each line */
87 for (; count
> 0; count
--, lines
++)
89 if (lines
->addr_string
)
90 xfree (lines
->addr_string
);
94 print_address (pc
, gdb_dis_out
);
96 lines
->addr_string
= xstrdup (tui_file_get_strbuf (gdb_dis_out
));
98 ui_file_rewind (gdb_dis_out
);
100 pc
= pc
+ TARGET_PRINT_INSN (pc
, &asm_info
);
102 lines
->insn
= xstrdup (tui_file_get_strbuf (gdb_dis_out
));
104 /* reset the buffer to empty */
105 ui_file_rewind (gdb_dis_out
);
107 ui_file_delete (gdb_dis_out
);
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. */
115 tui_find_disassembly_address (CORE_ADDR pc
, int from
)
117 register CORE_ADDR newLow
;
120 struct tui_asm_line
* lines
;
122 maxLines
= (from
> 0) ? from
: - from
;
126 lines
= (struct tui_asm_line
*) alloca (sizeof (struct tui_asm_line
)
128 memset (lines
, 0, sizeof (struct tui_asm_line
) * maxLines
);
133 tui_disassemble (lines
, pc
, maxLines
);
134 newLow
= lines
[maxLines
- 1].addr
;
140 struct minimal_symbol
* msymbol
;
142 /* Find backward an address which is a symbol
143 and for which disassembling from that address will fill
144 completely the window. */
147 newLow
-= 1 * maxLines
;
148 msymbol
= lookup_minimal_symbol_by_pc_section (newLow
, 0);
151 newLow
= SYMBOL_VALUE_ADDRESS (msymbol
);
153 newLow
+= 1 * maxLines
;
155 tui_disassemble (lines
, newLow
, maxLines
);
156 last_addr
= lines
[pos
].addr
;
157 } while (last_addr
> pc
&& msymbol
);
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
173 next_addr
= tui_disassemble (&lines
[pos
], last_addr
, 1);
175 /* If there are some problems while disassembling exit. */
176 if (next_addr
<= last_addr
)
178 last_addr
= next_addr
;
179 } while (last_addr
<= pc
);
183 newLow
= lines
[pos
].addr
;
185 for (i
= 0; i
< maxLines
; i
++)
187 xfree (lines
[i
].addr_string
);
188 xfree (lines
[i
].insn
);
193 /* Function to set the disassembly window's content. */
195 tuiSetDisassemContent (CORE_ADDR pc
)
197 TuiStatus ret
= TUI_FAILURE
;
199 register int offset
= disassemWin
->detail
.sourceInfo
.horizontalOffset
;
200 register int lineWidth
, maxLines
;
202 TuiGenWinInfoPtr locator
= locatorWinInfoPtr ();
203 int tab_len
= tuiDefaultTabLen ();
204 struct tui_asm_line
* lines
;
206 int addr_size
, max_size
;
212 ret
= tuiAllocSourceBuffer (disassemWin
);
213 if (ret
!= TUI_SUCCESS
)
216 disassemWin
->detail
.sourceInfo
.startLineOrAddr
.addr
= pc
;
218 (((TuiWinElementPtr
) locator
->content
[0])->whichElement
.locator
.addr
);
220 maxLines
= disassemWin
->generic
.height
- 2; /* account for hilite */
222 /* Get temporary table that will hold all strings (addr & insn). */
223 lines
= (struct tui_asm_line
*) alloca (sizeof (struct tui_asm_line
)
225 memset (lines
, 0, sizeof (struct tui_asm_line
) * maxLines
);
227 lineWidth
= disassemWin
->generic
.width
- 1;
229 tui_disassemble (lines
, pc
, maxLines
);
231 /* See what is the maximum length of an address and of a line. */
234 for (i
= 0; i
< maxLines
; i
++)
236 size_t len
= strlen (lines
[i
].addr_string
);
240 len
= strlen (lines
[i
].insn
) + tab_len
;
244 max_size
+= addr_size
+ tab_len
;
246 /* Allocate memory to create each line. */
247 line
= (char*) alloca (max_size
);
248 insn_pos
= (1 + (addr_size
/ tab_len
)) * tab_len
;
250 /* Now construct each line */
251 for (i
= 0; i
< maxLines
; i
++)
253 TuiWinElementPtr element
;
254 TuiSourceElement
* src
;
257 element
= (TuiWinElementPtr
) disassemWin
->generic
.content
[i
];
258 src
= &element
->whichElement
.source
;
259 strcpy (line
, lines
[i
].addr_string
);
260 curLen
= strlen (line
);
262 /* Add spaces to make the instructions start on the same column */
263 while (curLen
< insn_pos
)
269 strcat (line
, lines
[i
].insn
);
271 /* Now copy the line taking the offset into account */
272 if (strlen (line
) > offset
)
273 strcpy (src
->line
, &line
[offset
]);
277 src
->lineOrAddr
.addr
= lines
[i
].addr
;
278 src
->isExecPoint
= lines
[i
].addr
== cur_pc
;
280 /* See whether there is a breakpoint installed. */
281 src
->hasBreak
= (!src
->isExecPoint
282 && breakpoint_here_p (pc
) != no_breakpoint_here
);
284 xfree (lines
[i
].addr_string
);
285 xfree (lines
[i
].insn
);
287 disassemWin
->generic
.contentSize
= i
;
293 ** tuiShowDisassem().
294 ** Function to display the disassembly window with disassembled code.
297 tuiShowDisassem (CORE_ADDR startAddr
)
299 struct symtab
*s
= find_pc_symtab (startAddr
);
300 TuiWinInfoPtr winWithFocus
= tuiWinWithFocus ();
301 TuiLineOrAddress val
;
303 val
.addr
= startAddr
;
304 tuiAddWinToLayout (DISASSEM_WIN
);
305 tuiUpdateSourceWindow (disassemWin
, s
, val
, FALSE
);
307 ** if the focus was in the src win, put it in the asm win, if the
308 ** source view isn't split
310 if (currentLayout () != SRC_DISASSEM_COMMAND
&& winWithFocus
== srcWin
)
311 tuiSetWinFocusTo (disassemWin
);
314 } /* tuiShowDisassem */
318 ** tuiShowDisassemAndUpdateSource().
319 ** Function to display the disassembly window.
322 tuiShowDisassemAndUpdateSource (CORE_ADDR startAddr
)
324 struct symtab_and_line sal
;
326 tuiShowDisassem (startAddr
);
327 if (currentLayout () == SRC_DISASSEM_COMMAND
)
329 TuiLineOrAddress val
;
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
335 sal
= find_pc_line (startAddr
, 0);
336 val
.lineNo
= sal
.line
;
337 tuiUpdateSourceWindow (srcWin
, sal
.symtab
, val
, TRUE
);
340 current_source_symtab
= sal
.symtab
;
341 tuiUpdateLocatorFilename (sal
.symtab
->filename
);
344 tuiUpdateLocatorFilename ("?");
348 } /* tuiShowDisassemAndUpdateSource */
351 ** tuiGetBeginAsmAddress().
354 tuiGetBeginAsmAddress (void)
356 TuiGenWinInfoPtr locator
;
357 TuiLocatorElementPtr element
;
360 locator
= locatorWinInfoPtr ();
361 element
= &((TuiWinElementPtr
) locator
->content
[0])->whichElement
.locator
;
363 if (element
->addr
== 0)
365 struct minimal_symbol
*main_symbol
;
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
);
375 addr
= SYMBOL_VALUE_ADDRESS (main_symbol
);
379 else /* the target is executing */
380 addr
= element
->addr
;
383 } /* tuiGetBeginAsmAddress */
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. */
389 tuiGetLowDisassemblyAddress (CORE_ADDR low
, CORE_ADDR pc
)
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
);
404 ** tuiVerticalDisassemScroll().
405 ** Scroll the disassembly forward or backward vertically
408 tuiVerticalDisassemScroll (TuiScrollDirection scrollDirection
,
411 if (disassemWin
->generic
.content
!= (OpaquePtr
) NULL
)
414 TuiWinContent content
;
416 TuiLineOrAddress val
;
419 content
= (TuiWinContent
) disassemWin
->generic
.content
;
420 if (current_source_symtab
== (struct symtab
*) NULL
)
421 s
= find_pc_symtab (selected_frame
->pc
);
423 s
= current_source_symtab
;
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
;
430 val
.addr
= tui_find_disassembly_address (pc
, dir
);
431 tuiUpdateSourceWindowAsIs (disassemWin
, s
, val
, FALSE
);