Remove obsolete TYPE_FLAG_... values
[deliverable/binutils-gdb.git] / gdb / tui / tui-disasm.c
CommitLineData
f377b406 1/* Disassembly display.
f33c6cbf 2
618f726f 3 Copyright (C) 1998-2016 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"
d7b2e967
AC
30#include "tui/tui.h"
31#include "tui/tui-data.h"
32#include "tui/tui-win.h"
33#include "tui/tui-layout.h"
34#include "tui/tui-winsource.h"
35#include "tui/tui-stack.h"
36#include "tui/tui-file.h"
2c0b251b 37#include "tui/tui-disasm.h"
6c95b8df 38#include "progspace.h"
77e371c0 39#include "objfiles.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
8d749320 102 asm_lines = XALLOCAVEC (struct tui_asm_line, max_lines);
4cfcaf21 103 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 104
6ba8e26f 105 new_low = pc;
aec2f747
SC
106 if (from > 0)
107 {
13274fc3 108 tui_disassemble (gdbarch, asm_lines, pc, max_lines);
4cfcaf21 109 new_low = asm_lines[max_lines - 1].addr;
aec2f747
SC
110 }
111 else
112 {
113 CORE_ADDR last_addr;
114 int pos;
77e371c0 115 struct bound_minimal_symbol msymbol;
aec2f747 116
1cc6d956
MS
117 /* Find backward an address which is a symbol and for which
118 disassembling from that address will fill completely the
119 window. */
6ba8e26f 120 pos = max_lines - 1;
aec2f747 121 do {
6ba8e26f 122 new_low -= 1 * max_lines;
77e371c0 123 msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
aec2f747 124
77e371c0
TT
125 if (msymbol.minsym)
126 new_low = BMSYMBOL_VALUE_ADDRESS (msymbol);
aec2f747 127 else
6ba8e26f 128 new_low += 1 * max_lines;
aec2f747 129
13274fc3 130 tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
4cfcaf21 131 last_addr = asm_lines[pos].addr;
77e371c0 132 } while (last_addr > pc && msymbol.minsym);
aec2f747 133
1cc6d956
MS
134 /* Scan forward disassembling one instruction at a time until
135 the last visible instruction of the window matches the pc.
136 We keep the disassembled instructions in the 'lines' window
137 and shift it downward (increasing its addresses). */
aec2f747
SC
138 if (last_addr < pc)
139 do
140 {
141 CORE_ADDR next_addr;
142
143 pos++;
6ba8e26f 144 if (pos >= max_lines)
aec2f747
SC
145 pos = 0;
146
13274fc3
UW
147 next_addr = tui_disassemble (gdbarch, &asm_lines[pos],
148 last_addr, 1);
aec2f747
SC
149
150 /* If there are some problems while disassembling exit. */
151 if (next_addr <= last_addr)
152 break;
153 last_addr = next_addr;
154 } while (last_addr <= pc);
155 pos++;
6ba8e26f 156 if (pos >= max_lines)
aec2f747 157 pos = 0;
4cfcaf21 158 new_low = asm_lines[pos].addr;
aec2f747 159 }
6ba8e26f 160 for (i = 0; i < max_lines; i++)
aec2f747 161 {
4cfcaf21
JB
162 xfree (asm_lines[i].addr_string);
163 xfree (asm_lines[i].insn);
aec2f747 164 }
6ba8e26f 165 return new_low;
aec2f747
SC
166}
167
168/* Function to set the disassembly window's content. */
65f05602 169enum tui_status
13274fc3 170tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc)
c906108c 171{
22940a24 172 enum tui_status ret = TUI_FAILURE;
d02c80cd 173 int i;
6d012f14 174 int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
5799c0b9 175 int max_lines;
aec2f747 176 CORE_ADDR cur_pc;
5b6fe301 177 struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
dd1abb8c 178 int tab_len = tui_default_tab_len ();
5b6fe301 179 struct tui_asm_line *asm_lines;
aec2f747
SC
180 int insn_pos;
181 int addr_size, max_size;
5b6fe301 182 char *line;
aec2f747
SC
183
184 if (pc == 0)
185 return TUI_FAILURE;
186
6d012f14 187 ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
aec2f747
SC
188 if (ret != TUI_SUCCESS)
189 return ret;
190
13274fc3 191 TUI_DISASM_WIN->detail.source_info.gdbarch = gdbarch;
362c05fe
AS
192 TUI_DISASM_WIN->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS;
193 TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr = pc;
63ed8182 194 cur_pc = locator->content[0]->which_element.locator.addr;
aec2f747 195
1cc6d956
MS
196 max_lines = TUI_DISASM_WIN->generic.height - 2; /* Account for
197 hilite. */
aec2f747
SC
198
199 /* Get temporary table that will hold all strings (addr & insn). */
8d749320 200 asm_lines = XALLOCAVEC (struct tui_asm_line, max_lines);
4cfcaf21 201 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 202
13274fc3 203 tui_disassemble (gdbarch, asm_lines, pc, max_lines);
aec2f747
SC
204
205 /* See what is the maximum length of an address and of a line. */
206 addr_size = 0;
207 max_size = 0;
6ba8e26f 208 for (i = 0; i < max_lines; i++)
c906108c 209 {
4cfcaf21 210 size_t len = strlen (asm_lines[i].addr_string);
1c5313c5 211
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
63ed8182 232 element = TUI_DISASM_WIN->generic.content[i];
6d012f14 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
9a2b4c1b
MS
259 && breakpoint_here_p (current_program_space->aspace,
260 pc)
6c95b8df 261 != no_breakpoint_here);
c906108c 262
4cfcaf21
JB
263 xfree (asm_lines[i].addr_string);
264 xfree (asm_lines[i].insn);
aec2f747 265 }
6d012f14 266 TUI_DISASM_WIN->generic.content_size = i;
aec2f747
SC
267 return TUI_SUCCESS;
268}
c906108c
SS
269
270
1cc6d956 271/* Function to display the disassembly window with disassembled code. */
c906108c 272void
13274fc3 273tui_show_disassem (struct gdbarch *gdbarch, CORE_ADDR start_addr)
c906108c 274{
34248c3a 275 struct symtab *s = find_pc_line_symtab (start_addr);
5b6fe301 276 struct tui_win_info *win_with_focus = tui_win_with_focus ();
362c05fe 277 struct tui_line_or_address val;
c906108c 278
362c05fe
AS
279 val.loa = LOA_ADDRESS;
280 val.u.addr = start_addr;
080ce8c0 281 tui_add_win_to_layout (DISASSEM_WIN);
13274fc3 282 tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
ef5eab5a
MS
283
284 /* If the focus was in the src win, put it in the asm win, if the
285 source view isn't split. */
e5908723
MS
286 if (tui_current_layout () != SRC_DISASSEM_COMMAND
287 && win_with_focus == TUI_SRC_WIN)
6d012f14 288 tui_set_win_focus_to (TUI_DISASM_WIN);
c906108c
SS
289
290 return;
65f05602 291}
c906108c
SS
292
293
1cc6d956 294/* Function to display the disassembly window. */
c906108c 295void
13274fc3
UW
296tui_show_disassem_and_update_source (struct gdbarch *gdbarch,
297 CORE_ADDR start_addr)
c906108c
SS
298{
299 struct symtab_and_line sal;
300
13274fc3 301 tui_show_disassem (gdbarch, start_addr);
dd1abb8c 302 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
c906108c 303 {
362c05fe 304 struct tui_line_or_address val;
aec2f747 305
ef5eab5a
MS
306 /* Update what is in the source window if it is displayed too,
307 note that it follows what is in the disassembly window and
308 visa-versa. */
6ba8e26f 309 sal = find_pc_line (start_addr, 0);
362c05fe
AS
310 val.loa = LOA_LINE;
311 val.u.line_no = sal.line;
13274fc3 312 tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
3024f13a
SC
313 if (sal.symtab)
314 {
52575520 315 set_current_source_symtab_and_line (&sal);
56d397a3 316 tui_update_locator_fullname (symtab_to_fullname (sal.symtab));
3024f13a
SC
317 }
318 else
56d397a3 319 tui_update_locator_fullname ("?");
c906108c
SS
320 }
321
322 return;
65f05602 323}
c906108c 324
13274fc3
UW
325void
326tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
c906108c 327{
5b6fe301
MS
328 struct tui_gen_win_info *locator;
329 struct tui_locator_element *element;
957b8b5a 330 struct gdbarch *gdbarch = get_current_arch ();
c774cec6 331 CORE_ADDR addr;
c906108c 332
dd1abb8c 333 locator = tui_locator_win_info_ptr ();
63ed8182 334 element = &locator->content[0]->which_element.locator;
c906108c 335
c774cec6 336 if (element->addr == 0)
c906108c 337 {
3b7344d5 338 struct bound_minimal_symbol main_symbol;
0510ab86
SC
339
340 /* Find address of the start of program.
341 Note: this should be language specific. */
342 main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
3b7344d5 343 if (main_symbol.minsym == 0)
0510ab86 344 main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
3b7344d5 345 if (main_symbol.minsym == 0)
0510ab86 346 main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
3b7344d5 347 if (main_symbol.minsym)
77e371c0 348 addr = BMSYMBOL_VALUE_ADDRESS (main_symbol);
0510ab86
SC
349 else
350 addr = 0;
c906108c 351 }
1cc6d956 352 else /* The target is executing. */
13274fc3
UW
353 {
354 gdbarch = element->gdbarch;
355 addr = element->addr;
356 }
c906108c 357
13274fc3
UW
358 *gdbarch_p = gdbarch;
359 *addr_p = addr;
65f05602 360}
c906108c 361
77cad3ba 362/* Determine what the low address will be to display in the TUI's
1cc6d956
MS
363 disassembly window. This may or may not be the same as the low
364 address input. */
77cad3ba 365CORE_ADDR
13274fc3
UW
366tui_get_low_disassembly_address (struct gdbarch *gdbarch,
367 CORE_ADDR low, CORE_ADDR pc)
77cad3ba
SC
368{
369 int pos;
370
1cc6d956
MS
371 /* Determine where to start the disassembly so that the pc is about
372 in the middle of the viewport. */
080ce8c0 373 pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
13274fc3 374 pc = tui_find_disassembly_address (gdbarch, pc, -pos);
77cad3ba
SC
375
376 if (pc < low)
377 pc = low;
378 return pc;
379}
380
65f05602 381/* Scroll the disassembly forward or backward vertically. */
c906108c 382void
6ba8e26f
AC
383tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
384 int num_to_scroll)
c906108c 385{
6d012f14 386 if (TUI_DISASM_WIN->generic.content != NULL)
c906108c 387 {
13274fc3 388 struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
aec2f747 389 CORE_ADDR pc;
2a8854a7 390 tui_win_content content;
362c05fe 391 struct tui_line_or_address val;
aefc7064 392 int dir;
c906108c 393
6d012f14 394 content = (tui_win_content) TUI_DISASM_WIN->generic.content;
c906108c 395
362c05fe 396 pc = content[0]->which_element.source.line_or_addr.u.addr;
aefc7064 397 num_to_scroll++;
9a2b4c1b
MS
398 dir = (scroll_direction == FORWARD_SCROLL)
399 ? num_to_scroll : -num_to_scroll;
c906108c 400
362c05fe 401 val.loa = LOA_ADDRESS;
13274fc3 402 val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
9a2b4c1b
MS
403 tui_update_source_window_as_is (TUI_DISASM_WIN, gdbarch,
404 NULL, val, FALSE);
aec2f747
SC
405 }
406}
This page took 1.605368 seconds and 4 git commands to generate.