]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tui/tui-disasm.c
Switch the license of all .c files to GPLv3.
[thirdparty/binutils-gdb.git] / gdb / tui / tui-disasm.c
CommitLineData
f377b406 1/* Disassembly display.
f33c6cbf 2
6aba47ca
DJ
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007
4 Free Software Foundation, Inc.
f33c6cbf 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
a9762ec7 12 the Free Software Foundation; either version 3 of the License, or
f377b406
SC
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
a9762ec7 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
22
23#include "defs.h"
24#include "symtab.h"
25#include "breakpoint.h"
26#include "frame.h"
fd0407d6 27#include "value.h"
52575520 28#include "source.h"
f70a7d61 29#include "disasm.h"
6d012f14 30#include "gdb_string.h"
d7b2e967
AC
31#include "tui/tui.h"
32#include "tui/tui-data.h"
33#include "tui/tui-win.h"
34#include "tui/tui-layout.h"
35#include "tui/tui-winsource.h"
36#include "tui/tui-stack.h"
37#include "tui/tui-file.h"
c906108c 38
6a83354a 39#include "gdb_curses.h"
96ec9981 40
aec2f747
SC
41struct tui_asm_line
42{
43 CORE_ADDR addr;
5b6fe301
MS
44 char *addr_string;
45 char *insn;
aec2f747
SC
46};
47
48/* Function to set the disassembly window's content.
49 Disassemble count lines starting at pc.
50 Return address of the count'th instruction after pc. */
51static CORE_ADDR
08ef48c5
MS
52tui_disassemble (struct tui_asm_line *asm_lines,
53 CORE_ADDR pc, int count)
aec2f747
SC
54{
55 struct ui_file *gdb_dis_out;
c906108c 56
1cc6d956 57 /* Now init the ui_file structure. */
aec2f747
SC
58 gdb_dis_out = tui_sfileopen (256);
59
1cc6d956 60 /* Now construct each line. */
4cfcaf21 61 for (; count > 0; count--, asm_lines++)
aec2f747 62 {
4cfcaf21
JB
63 if (asm_lines->addr_string)
64 xfree (asm_lines->addr_string);
65 if (asm_lines->insn)
66 xfree (asm_lines->insn);
aec2f747
SC
67
68 print_address (pc, gdb_dis_out);
4cfcaf21
JB
69 asm_lines->addr = pc;
70 asm_lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
aec2f747
SC
71
72 ui_file_rewind (gdb_dis_out);
73
a4642986 74 pc = pc + gdb_print_insn (pc, gdb_dis_out, NULL);
aec2f747 75
4cfcaf21 76 asm_lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
aec2f747 77
1cc6d956 78 /* Reset the buffer to empty. */
aec2f747
SC
79 ui_file_rewind (gdb_dis_out);
80 }
81 ui_file_delete (gdb_dis_out);
82 return pc;
83}
84
1cc6d956
MS
85/* Find the disassembly address that corresponds to FROM lines above
86 or below the PC. Variable sized instructions are taken into
87 account by the algorithm. */
aec2f747
SC
88static CORE_ADDR
89tui_find_disassembly_address (CORE_ADDR pc, int from)
90{
d02c80cd 91 CORE_ADDR new_low;
6ba8e26f 92 int max_lines;
aec2f747 93 int i;
5b6fe301 94 struct tui_asm_line *asm_lines;
aec2f747 95
6ba8e26f
AC
96 max_lines = (from > 0) ? from : - from;
97 if (max_lines <= 1)
aec2f747
SC
98 return pc;
99
4cfcaf21 100 asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
6ba8e26f 101 * max_lines);
4cfcaf21 102 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 103
6ba8e26f 104 new_low = pc;
aec2f747
SC
105 if (from > 0)
106 {
4cfcaf21
JB
107 tui_disassemble (asm_lines, pc, max_lines);
108 new_low = asm_lines[max_lines - 1].addr;
aec2f747
SC
109 }
110 else
111 {
112 CORE_ADDR last_addr;
113 int pos;
5b6fe301 114 struct minimal_symbol *msymbol;
aec2f747 115
1cc6d956
MS
116 /* Find backward an address which is a symbol and for which
117 disassembling from that address will fill completely the
118 window. */
6ba8e26f 119 pos = max_lines - 1;
aec2f747 120 do {
6ba8e26f
AC
121 new_low -= 1 * max_lines;
122 msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
aec2f747
SC
123
124 if (msymbol)
6ba8e26f 125 new_low = SYMBOL_VALUE_ADDRESS (msymbol);
aec2f747 126 else
6ba8e26f 127 new_low += 1 * max_lines;
aec2f747 128
4cfcaf21
JB
129 tui_disassemble (asm_lines, new_low, max_lines);
130 last_addr = asm_lines[pos].addr;
aec2f747
SC
131 } while (last_addr > pc && msymbol);
132
1cc6d956
MS
133 /* Scan forward disassembling one instruction at a time until
134 the last visible instruction of the window matches the pc.
135 We keep the disassembled instructions in the 'lines' window
136 and shift it downward (increasing its addresses). */
aec2f747
SC
137 if (last_addr < pc)
138 do
139 {
140 CORE_ADDR next_addr;
141
142 pos++;
6ba8e26f 143 if (pos >= max_lines)
aec2f747
SC
144 pos = 0;
145
4cfcaf21 146 next_addr = tui_disassemble (&asm_lines[pos], last_addr, 1);
aec2f747
SC
147
148 /* If there are some problems while disassembling exit. */
149 if (next_addr <= last_addr)
150 break;
151 last_addr = next_addr;
152 } while (last_addr <= pc);
153 pos++;
6ba8e26f 154 if (pos >= max_lines)
aec2f747 155 pos = 0;
4cfcaf21 156 new_low = asm_lines[pos].addr;
aec2f747 157 }
6ba8e26f 158 for (i = 0; i < max_lines; i++)
aec2f747 159 {
4cfcaf21
JB
160 xfree (asm_lines[i].addr_string);
161 xfree (asm_lines[i].insn);
aec2f747 162 }
6ba8e26f 163 return new_low;
aec2f747
SC
164}
165
166/* Function to set the disassembly window's content. */
65f05602
AC
167enum tui_status
168tui_set_disassem_content (CORE_ADDR pc)
c906108c 169{
22940a24 170 enum tui_status ret = TUI_FAILURE;
d02c80cd 171 int i;
6d012f14 172 int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
d02c80cd 173 int line_width, max_lines;
aec2f747 174 CORE_ADDR cur_pc;
5b6fe301 175 struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
dd1abb8c 176 int tab_len = tui_default_tab_len ();
5b6fe301 177 struct tui_asm_line *asm_lines;
aec2f747
SC
178 int insn_pos;
179 int addr_size, max_size;
5b6fe301 180 char *line;
aec2f747
SC
181
182 if (pc == 0)
183 return TUI_FAILURE;
184
6d012f14 185 ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
aec2f747
SC
186 if (ret != TUI_SUCCESS)
187 return ret;
188
362c05fe
AS
189 TUI_DISASM_WIN->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS;
190 TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr = pc;
aec2f747 191 cur_pc = (CORE_ADDR)
6d012f14 192 (((struct tui_win_element *) locator->content[0])->which_element.locator.addr);
aec2f747 193
1cc6d956
MS
194 max_lines = TUI_DISASM_WIN->generic.height - 2; /* Account for
195 hilite. */
aec2f747
SC
196
197 /* Get temporary table that will hold all strings (addr & insn). */
4cfcaf21 198 asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
6ba8e26f 199 * max_lines);
4cfcaf21 200 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 201
6ba8e26f 202 line_width = TUI_DISASM_WIN->generic.width - 1;
aec2f747 203
4cfcaf21 204 tui_disassemble (asm_lines, pc, max_lines);
aec2f747
SC
205
206 /* See what is the maximum length of an address and of a line. */
207 addr_size = 0;
208 max_size = 0;
6ba8e26f 209 for (i = 0; i < max_lines; i++)
c906108c 210 {
4cfcaf21 211 size_t len = strlen (asm_lines[i].addr_string);
aec2f747
SC
212 if (len > addr_size)
213 addr_size = len;
c906108c 214
4cfcaf21 215 len = strlen (asm_lines[i].insn) + tab_len;
aec2f747
SC
216 if (len > max_size)
217 max_size = len;
c906108c 218 }
aec2f747
SC
219 max_size += addr_size + tab_len;
220
221 /* Allocate memory to create each line. */
222 line = (char*) alloca (max_size);
223 insn_pos = (1 + (addr_size / tab_len)) * tab_len;
224
1cc6d956 225 /* Now construct each line. */
6ba8e26f 226 for (i = 0; i < max_lines; i++)
aec2f747 227 {
5b6fe301
MS
228 struct tui_win_element *element;
229 struct tui_source_element *src;
6ba8e26f 230 int cur_len;
aec2f747 231
6d012f14
AC
232 element = (struct tui_win_element *) TUI_DISASM_WIN->generic.content[i];
233 src = &element->which_element.source;
4cfcaf21 234 strcpy (line, asm_lines[i].addr_string);
6ba8e26f 235 cur_len = strlen (line);
aec2f747 236
1cc6d956
MS
237 /* Add spaces to make the instructions start on the same
238 column. */
6ba8e26f 239 while (cur_len < insn_pos)
aec2f747
SC
240 {
241 strcat (line, " ");
6ba8e26f 242 cur_len++;
aec2f747
SC
243 }
244
4cfcaf21 245 strcat (line, asm_lines[i].insn);
aec2f747 246
1cc6d956 247 /* Now copy the line taking the offset into account. */
aec2f747
SC
248 if (strlen (line) > offset)
249 strcpy (src->line, &line[offset]);
250 else
251 src->line[0] = '\0';
252
362c05fe
AS
253 src->line_or_addr.loa = LOA_ADDRESS;
254 src->line_or_addr.u.addr = asm_lines[i].addr;
4cfcaf21 255 src->is_exec_point = asm_lines[i].addr == cur_pc;
aec2f747
SC
256
257 /* See whether there is a breakpoint installed. */
6d012f14 258 src->has_break = (!src->is_exec_point
aec2f747 259 && breakpoint_here_p (pc) != no_breakpoint_here);
c906108c 260
4cfcaf21
JB
261 xfree (asm_lines[i].addr_string);
262 xfree (asm_lines[i].insn);
aec2f747 263 }
6d012f14 264 TUI_DISASM_WIN->generic.content_size = i;
aec2f747
SC
265 return TUI_SUCCESS;
266}
c906108c
SS
267
268
1cc6d956 269/* Function to display the disassembly window with disassembled code. */
c906108c 270void
6ba8e26f 271tui_show_disassem (CORE_ADDR start_addr)
c906108c 272{
6ba8e26f 273 struct symtab *s = find_pc_symtab (start_addr);
5b6fe301 274 struct tui_win_info *win_with_focus = tui_win_with_focus ();
362c05fe 275 struct tui_line_or_address val;
c906108c 276
362c05fe
AS
277 val.loa = LOA_ADDRESS;
278 val.u.addr = start_addr;
080ce8c0 279 tui_add_win_to_layout (DISASSEM_WIN);
6d012f14 280 tui_update_source_window (TUI_DISASM_WIN, s, val, FALSE);
ef5eab5a
MS
281
282 /* If the focus was in the src win, put it in the asm win, if the
283 source view isn't split. */
e5908723
MS
284 if (tui_current_layout () != SRC_DISASSEM_COMMAND
285 && win_with_focus == TUI_SRC_WIN)
6d012f14 286 tui_set_win_focus_to (TUI_DISASM_WIN);
c906108c
SS
287
288 return;
65f05602 289}
c906108c
SS
290
291
1cc6d956 292/* Function to display the disassembly window. */
c906108c 293void
6ba8e26f 294tui_show_disassem_and_update_source (CORE_ADDR start_addr)
c906108c
SS
295{
296 struct symtab_and_line sal;
297
6ba8e26f 298 tui_show_disassem (start_addr);
dd1abb8c 299 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
c906108c 300 {
362c05fe 301 struct tui_line_or_address val;
aec2f747 302
ef5eab5a
MS
303 /* Update what is in the source window if it is displayed too,
304 note that it follows what is in the disassembly window and
305 visa-versa. */
6ba8e26f 306 sal = find_pc_line (start_addr, 0);
362c05fe
AS
307 val.loa = LOA_LINE;
308 val.u.line_no = sal.line;
6d012f14 309 tui_update_source_window (TUI_SRC_WIN, sal.symtab, val, TRUE);
3024f13a
SC
310 if (sal.symtab)
311 {
52575520 312 set_current_source_symtab_and_line (&sal);
47d3492a 313 tui_update_locator_filename (sal.symtab->filename);
3024f13a
SC
314 }
315 else
47d3492a 316 tui_update_locator_filename ("?");
c906108c
SS
317 }
318
319 return;
65f05602 320}
c906108c 321
c774cec6 322CORE_ADDR
65f05602 323tui_get_begin_asm_address (void)
c906108c 324{
5b6fe301
MS
325 struct tui_gen_win_info *locator;
326 struct tui_locator_element *element;
c774cec6 327 CORE_ADDR addr;
c906108c 328
dd1abb8c 329 locator = tui_locator_win_info_ptr ();
6d012f14 330 element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
c906108c 331
c774cec6 332 if (element->addr == 0)
c906108c 333 {
0510ab86
SC
334 struct minimal_symbol *main_symbol;
335
336 /* Find address of the start of program.
337 Note: this should be language specific. */
338 main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
339 if (main_symbol == 0)
340 main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
341 if (main_symbol == 0)
342 main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
343 if (main_symbol)
344 addr = SYMBOL_VALUE_ADDRESS (main_symbol);
345 else
346 addr = 0;
c906108c 347 }
1cc6d956 348 else /* The target is executing. */
c906108c
SS
349 addr = element->addr;
350
351 return addr;
65f05602 352}
c906108c 353
77cad3ba 354/* Determine what the low address will be to display in the TUI's
1cc6d956
MS
355 disassembly window. This may or may not be the same as the low
356 address input. */
77cad3ba 357CORE_ADDR
08ef48c5
MS
358tui_get_low_disassembly_address (CORE_ADDR low,
359 CORE_ADDR pc)
77cad3ba
SC
360{
361 int pos;
362
1cc6d956
MS
363 /* Determine where to start the disassembly so that the pc is about
364 in the middle of the viewport. */
080ce8c0 365 pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
77cad3ba
SC
366 pc = tui_find_disassembly_address (pc, -pos);
367
368 if (pc < low)
369 pc = low;
370 return pc;
371}
372
65f05602 373/* Scroll the disassembly forward or backward vertically. */
c906108c 374void
6ba8e26f
AC
375tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
376 int num_to_scroll)
c906108c 377{
6d012f14 378 if (TUI_DISASM_WIN->generic.content != NULL)
c906108c 379 {
aec2f747 380 CORE_ADDR pc;
2a8854a7 381 tui_win_content content;
c906108c 382 struct symtab *s;
362c05fe 383 struct tui_line_or_address val;
6ba8e26f 384 int max_lines, dir;
52575520 385 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
c906108c 386
6d012f14 387 content = (tui_win_content) TUI_DISASM_WIN->generic.content;
52575520 388 if (cursal.symtab == (struct symtab *) NULL)
206415a3 389 s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
c906108c 390 else
52575520 391 s = cursal.symtab;
c906108c 392
1cc6d956 393 /* Account for hilite. */
6ba8e26f 394 max_lines = TUI_DISASM_WIN->generic.height - 2;
362c05fe 395 pc = content[0]->which_element.source.line_or_addr.u.addr;
6ba8e26f 396 dir = (scroll_direction == FORWARD_SCROLL) ? max_lines : - max_lines;
c906108c 397
362c05fe
AS
398 val.loa = LOA_ADDRESS;
399 val.u.addr = tui_find_disassembly_address (pc, dir);
6d012f14 400 tui_update_source_window_as_is (TUI_DISASM_WIN, s, val, FALSE);
aec2f747
SC
401 }
402}