Rename common to gdbsupport
[deliverable/binutils-gdb.git] / gdb / tui / tui-disasm.c
CommitLineData
f377b406 1/* Disassembly display.
f33c6cbf 2
42a4f53d 3 Copyright (C) 1998-2019 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 56{
d7e74731 57 string_file gdb_dis_out;
aec2f747 58
1cc6d956 59 /* Now construct each line. */
4cfcaf21 60 for (; count > 0; count--, asm_lines++)
aec2f747 61 {
17568d78
TT
62 xfree (asm_lines->addr_string);
63 xfree (asm_lines->insn);
aec2f747 64
d7e74731 65 print_address (gdbarch, pc, &gdb_dis_out);
4cfcaf21 66 asm_lines->addr = pc;
d7e74731 67 asm_lines->addr_string = xstrdup (gdb_dis_out.c_str ());
aec2f747 68
d7e74731 69 gdb_dis_out.clear ();
aec2f747 70
d7e74731 71 pc = pc + gdb_print_insn (gdbarch, pc, &gdb_dis_out, NULL);
aec2f747 72
d7e74731 73 asm_lines->insn = xstrdup (gdb_dis_out.c_str ());
aec2f747 74
1cc6d956 75 /* Reset the buffer to empty. */
d7e74731 76 gdb_dis_out.clear ();
aec2f747 77 }
aec2f747
SC
78 return pc;
79}
80
1cc6d956
MS
81/* Find the disassembly address that corresponds to FROM lines above
82 or below the PC. Variable sized instructions are taken into
83 account by the algorithm. */
aec2f747 84static CORE_ADDR
13274fc3 85tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
aec2f747 86{
d02c80cd 87 CORE_ADDR new_low;
6ba8e26f 88 int max_lines;
aec2f747 89 int i;
5b6fe301 90 struct tui_asm_line *asm_lines;
aec2f747 91
6ba8e26f
AC
92 max_lines = (from > 0) ? from : - from;
93 if (max_lines <= 1)
aec2f747
SC
94 return pc;
95
8d749320 96 asm_lines = XALLOCAVEC (struct tui_asm_line, max_lines);
4cfcaf21 97 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 98
6ba8e26f 99 new_low = pc;
aec2f747
SC
100 if (from > 0)
101 {
13274fc3 102 tui_disassemble (gdbarch, asm_lines, pc, max_lines);
4cfcaf21 103 new_low = asm_lines[max_lines - 1].addr;
aec2f747
SC
104 }
105 else
106 {
107 CORE_ADDR last_addr;
108 int pos;
77e371c0 109 struct bound_minimal_symbol msymbol;
aec2f747 110
1cc6d956
MS
111 /* Find backward an address which is a symbol and for which
112 disassembling from that address will fill completely the
113 window. */
6ba8e26f 114 pos = max_lines - 1;
aec2f747 115 do {
6ba8e26f 116 new_low -= 1 * max_lines;
77e371c0 117 msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
aec2f747 118
77e371c0
TT
119 if (msymbol.minsym)
120 new_low = BMSYMBOL_VALUE_ADDRESS (msymbol);
aec2f747 121 else
6ba8e26f 122 new_low += 1 * max_lines;
aec2f747 123
13274fc3 124 tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
4cfcaf21 125 last_addr = asm_lines[pos].addr;
77e371c0 126 } while (last_addr > pc && msymbol.minsym);
aec2f747 127
1cc6d956
MS
128 /* Scan forward disassembling one instruction at a time until
129 the last visible instruction of the window matches the pc.
130 We keep the disassembled instructions in the 'lines' window
131 and shift it downward (increasing its addresses). */
aec2f747
SC
132 if (last_addr < pc)
133 do
134 {
135 CORE_ADDR next_addr;
136
137 pos++;
6ba8e26f 138 if (pos >= max_lines)
aec2f747
SC
139 pos = 0;
140
13274fc3
UW
141 next_addr = tui_disassemble (gdbarch, &asm_lines[pos],
142 last_addr, 1);
aec2f747
SC
143
144 /* If there are some problems while disassembling exit. */
145 if (next_addr <= last_addr)
146 break;
147 last_addr = next_addr;
148 } while (last_addr <= pc);
149 pos++;
6ba8e26f 150 if (pos >= max_lines)
aec2f747 151 pos = 0;
4cfcaf21 152 new_low = asm_lines[pos].addr;
aec2f747 153 }
6ba8e26f 154 for (i = 0; i < max_lines; i++)
aec2f747 155 {
4cfcaf21
JB
156 xfree (asm_lines[i].addr_string);
157 xfree (asm_lines[i].insn);
aec2f747 158 }
6ba8e26f 159 return new_low;
aec2f747
SC
160}
161
162/* Function to set the disassembly window's content. */
65f05602 163enum tui_status
13274fc3 164tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc)
c906108c 165{
d02c80cd 166 int i;
e6e41501 167 int offset = TUI_DISASM_WIN->horizontal_offset;
0bb65f1e 168 int max_lines, line_width;
aec2f747 169 CORE_ADDR cur_pc;
3add462f 170 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
7806cea7 171 int tab_len = tui_tab_width;
5b6fe301 172 struct tui_asm_line *asm_lines;
aec2f747 173 int insn_pos;
f5396833 174 int addr_size, insn_size;
5b6fe301 175 char *line;
aec2f747
SC
176
177 if (pc == 0)
178 return TUI_FAILURE;
179
29d2c474 180 tui_alloc_source_buffer (TUI_DISASM_WIN);
aec2f747 181
e6e41501
TT
182 tui_source_window_base *base = TUI_DISASM_WIN;
183 base->gdbarch = gdbarch;
184 base->start_line_or_addr.loa = LOA_ADDRESS;
185 base->start_line_or_addr.u.addr = pc;
3add462f 186 cur_pc = locator->addr;
aec2f747 187
0bb65f1e 188 /* Window size, excluding highlight box. */
cb2ce893
TT
189 max_lines = TUI_DISASM_WIN->height - 2;
190 line_width = TUI_DISASM_WIN->width - 2;
aec2f747
SC
191
192 /* Get temporary table that will hold all strings (addr & insn). */
8d749320 193 asm_lines = XALLOCAVEC (struct tui_asm_line, max_lines);
4cfcaf21 194 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 195
13274fc3 196 tui_disassemble (gdbarch, asm_lines, pc, max_lines);
aec2f747 197
f5396833 198 /* Determine maximum address- and instruction lengths. */
aec2f747 199 addr_size = 0;
f5396833 200 insn_size = 0;
6ba8e26f 201 for (i = 0; i < max_lines; i++)
c906108c 202 {
4cfcaf21 203 size_t len = strlen (asm_lines[i].addr_string);
1c5313c5 204
aec2f747
SC
205 if (len > addr_size)
206 addr_size = len;
c906108c 207
f5396833
AA
208 len = strlen (asm_lines[i].insn);
209 if (len > insn_size)
210 insn_size = len;
c906108c 211 }
aec2f747 212
f5396833 213 /* Align instructions to the same column. */
aec2f747
SC
214 insn_pos = (1 + (addr_size / tab_len)) * tab_len;
215
f5396833
AA
216 /* Allocate memory to create each line. */
217 line = (char*) alloca (insn_pos + insn_size + 1);
218
1cc6d956 219 /* Now construct each line. */
53e7cdba 220 TUI_DISASM_WIN->content.resize (max_lines);
6ba8e26f 221 for (i = 0; i < max_lines; i++)
aec2f747 222 {
6ba8e26f 223 int cur_len;
aec2f747 224
53e7cdba 225 tui_source_element *src = &TUI_DISASM_WIN->content[i];
4cfcaf21 226 strcpy (line, asm_lines[i].addr_string);
6ba8e26f 227 cur_len = strlen (line);
0bb65f1e
AA
228 memset (line + cur_len, ' ', insn_pos - cur_len);
229 strcpy (line + insn_pos, asm_lines[i].insn);
aec2f747 230
1cc6d956 231 /* Now copy the line taking the offset into account. */
53e7cdba 232 xfree (src->line);
aec2f747 233 if (strlen (line) > offset)
53e7cdba 234 src->line = xstrndup (&line[offset], line_width);
aec2f747 235 else
53e7cdba 236 src->line = xstrdup ("");
aec2f747 237
362c05fe
AS
238 src->line_or_addr.loa = LOA_ADDRESS;
239 src->line_or_addr.u.addr = asm_lines[i].addr;
4cfcaf21 240 src->is_exec_point = asm_lines[i].addr == cur_pc;
aec2f747 241
4cfcaf21
JB
242 xfree (asm_lines[i].addr_string);
243 xfree (asm_lines[i].insn);
aec2f747 244 }
aec2f747
SC
245 return TUI_SUCCESS;
246}
c906108c
SS
247
248
1cc6d956 249/* Function to display the disassembly window with disassembled code. */
c906108c 250void
13274fc3 251tui_show_disassem (struct gdbarch *gdbarch, CORE_ADDR start_addr)
c906108c 252{
34248c3a 253 struct symtab *s = find_pc_line_symtab (start_addr);
5b6fe301 254 struct tui_win_info *win_with_focus = tui_win_with_focus ();
362c05fe 255 struct tui_line_or_address val;
c906108c 256
362c05fe
AS
257 val.loa = LOA_ADDRESS;
258 val.u.addr = start_addr;
080ce8c0 259 tui_add_win_to_layout (DISASSEM_WIN);
13274fc3 260 tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
ef5eab5a
MS
261
262 /* If the focus was in the src win, put it in the asm win, if the
263 source view isn't split. */
e5908723
MS
264 if (tui_current_layout () != SRC_DISASSEM_COMMAND
265 && win_with_focus == TUI_SRC_WIN)
6d012f14 266 tui_set_win_focus_to (TUI_DISASM_WIN);
c906108c
SS
267
268 return;
65f05602 269}
c906108c
SS
270
271
1cc6d956 272/* Function to display the disassembly window. */
c906108c 273void
13274fc3
UW
274tui_show_disassem_and_update_source (struct gdbarch *gdbarch,
275 CORE_ADDR start_addr)
c906108c
SS
276{
277 struct symtab_and_line sal;
278
13274fc3 279 tui_show_disassem (gdbarch, start_addr);
dd1abb8c 280 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
c906108c 281 {
362c05fe 282 struct tui_line_or_address val;
aec2f747 283
ef5eab5a
MS
284 /* Update what is in the source window if it is displayed too,
285 note that it follows what is in the disassembly window and
286 visa-versa. */
6ba8e26f 287 sal = find_pc_line (start_addr, 0);
362c05fe
AS
288 val.loa = LOA_LINE;
289 val.u.line_no = sal.line;
13274fc3 290 tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
3024f13a
SC
291 if (sal.symtab)
292 {
51abb421 293 set_current_source_symtab_and_line (sal);
56d397a3 294 tui_update_locator_fullname (symtab_to_fullname (sal.symtab));
3024f13a
SC
295 }
296 else
56d397a3 297 tui_update_locator_fullname ("?");
c906108c
SS
298 }
299
300 return;
65f05602 301}
c906108c 302
13274fc3
UW
303void
304tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
c906108c 305{
3add462f 306 struct tui_locator_window *locator;
957b8b5a 307 struct gdbarch *gdbarch = get_current_arch ();
c774cec6 308 CORE_ADDR addr;
c906108c 309
dd1abb8c 310 locator = tui_locator_win_info_ptr ();
c906108c 311
3add462f 312 if (locator->addr == 0)
c906108c 313 {
3b7344d5 314 struct bound_minimal_symbol main_symbol;
0510ab86
SC
315
316 /* Find address of the start of program.
317 Note: this should be language specific. */
318 main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
3b7344d5 319 if (main_symbol.minsym == 0)
0510ab86 320 main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
3b7344d5 321 if (main_symbol.minsym == 0)
0510ab86 322 main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
3b7344d5 323 if (main_symbol.minsym)
77e371c0 324 addr = BMSYMBOL_VALUE_ADDRESS (main_symbol);
0510ab86
SC
325 else
326 addr = 0;
c906108c 327 }
1cc6d956 328 else /* The target is executing. */
13274fc3 329 {
3add462f
TT
330 gdbarch = locator->gdbarch;
331 addr = locator->addr;
13274fc3 332 }
c906108c 333
13274fc3
UW
334 *gdbarch_p = gdbarch;
335 *addr_p = addr;
65f05602 336}
c906108c 337
77cad3ba 338/* Determine what the low address will be to display in the TUI's
1cc6d956
MS
339 disassembly window. This may or may not be the same as the low
340 address input. */
77cad3ba 341CORE_ADDR
13274fc3
UW
342tui_get_low_disassembly_address (struct gdbarch *gdbarch,
343 CORE_ADDR low, CORE_ADDR pc)
77cad3ba
SC
344{
345 int pos;
346
1cc6d956
MS
347 /* Determine where to start the disassembly so that the pc is about
348 in the middle of the viewport. */
080ce8c0 349 pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
13274fc3 350 pc = tui_find_disassembly_address (gdbarch, pc, -pos);
77cad3ba
SC
351
352 if (pc < low)
353 pc = low;
354 return pc;
355}
356
65f05602 357/* Scroll the disassembly forward or backward vertically. */
c906108c 358void
c3bd716f 359tui_disasm_window::do_scroll_vertical (int num_to_scroll)
c906108c 360{
53e7cdba 361 if (!content.empty ())
c906108c 362 {
aec2f747 363 CORE_ADDR pc;
362c05fe 364 struct tui_line_or_address val;
c906108c 365
53e7cdba 366 pc = content[0].line_or_addr.u.addr;
c3bd716f
TT
367 if (num_to_scroll >= 0)
368 num_to_scroll++;
369 else
370 --num_to_scroll;
c906108c 371
362c05fe 372 val.loa = LOA_ADDRESS;
c3bd716f 373 val.u.addr = tui_find_disassembly_address (gdbarch, pc, num_to_scroll);
f83d391c 374 tui_update_source_window_as_is (this, gdbarch,
9a2b4c1b 375 NULL, val, FALSE);
aec2f747
SC
376 }
377}
This page took 2.01788 seconds and 4 git commands to generate.