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