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