Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / tui / tui-disasm.c
CommitLineData
f377b406 1/* Disassembly display.
f33c6cbf 2
88b9d363 3 Copyright (C) 1998-2022 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 30#include "tui/tui.h"
6d7fd9aa 31#include "tui/tui-command.h"
d7b2e967
AC
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"
bfad4537 39#include "tui/tui-source.h"
6c95b8df 40#include "progspace.h"
77e371c0 41#include "objfiles.h"
1df2f9ef 42#include "cli/cli-style.h"
f237f998 43#include "tui/tui-location.h"
c906108c 44
6a83354a 45#include "gdb_curses.h"
96ec9981 46
a61b4f69 47struct tui_asm_line
aec2f747
SC
48{
49 CORE_ADDR addr;
6b915f7d 50 std::string addr_string;
825165c5 51 size_t addr_size;
6b915f7d 52 std::string insn;
aec2f747
SC
53};
54
1df2f9ef
TT
55/* Helper function to find the number of characters in STR, skipping
56 any ANSI escape sequences. */
57static size_t
58len_without_escapes (const std::string &str)
59{
60 size_t len = 0;
61 const char *ptr = str.c_str ();
62 char c;
63
d811a7cf 64 while ((c = *ptr) != '\0')
1df2f9ef
TT
65 {
66 if (c == '\033')
67 {
68 ui_file_style style;
69 size_t n_read;
70 if (style.parse (ptr, &n_read))
71 ptr += n_read;
72 else
73 {
74 /* Shouldn't happen, but just skip the ESC if it somehow
75 does. */
76 ++ptr;
77 }
78 }
79 else
d811a7cf
TV
80 {
81 ++len;
82 ++ptr;
83 }
1df2f9ef
TT
84 }
85 return len;
86}
87
733d0a67
AB
88/* Function to disassemble up to COUNT instructions starting from address
89 PC into the ASM_LINES vector (which will be emptied of any previous
90 contents). Return the address of the COUNT'th instruction after pc.
91 When ADDR_SIZE is non-null then place the maximum size of an address and
92 label into the value pointed to by ADDR_SIZE, and set the addr_size
93 field on each item in ASM_LINES, otherwise the addr_size fields within
94 ASM_LINES are undefined.
95
96 It is worth noting that ASM_LINES might not have COUNT entries when this
97 function returns. If the disassembly is truncated for some other
98 reason, for example, we hit invalid memory, then ASM_LINES can have
99 fewer entries than requested. */
aec2f747 100static CORE_ADDR
6b915f7d
TT
101tui_disassemble (struct gdbarch *gdbarch,
102 std::vector<tui_asm_line> &asm_lines,
733d0a67 103 CORE_ADDR pc, int count,
1df2f9ef 104 size_t *addr_size = nullptr)
aec2f747 105{
1df2f9ef
TT
106 bool term_out = source_styling && gdb_stdout->can_emit_style_escape ();
107 string_file gdb_dis_out (term_out);
aec2f747 108
733d0a67
AB
109 /* Must start with an empty list. */
110 asm_lines.clear ();
111
1cc6d956 112 /* Now construct each line. */
6b915f7d 113 for (int i = 0; i < count; ++i)
aec2f747 114 {
733d0a67
AB
115 tui_asm_line tal;
116 CORE_ADDR orig_pc = pc;
aec2f747 117
733d0a67
AB
118 try
119 {
120 pc = pc + gdb_print_insn (gdbarch, pc, &gdb_dis_out, NULL);
121 }
122 catch (const gdb_exception_error &except)
123 {
124 /* If PC points to an invalid address then we'll catch a
125 MEMORY_ERROR here, this should stop the disassembly, but
126 otherwise is fine. */
127 if (except.error != MEMORY_ERROR)
128 throw;
129 return pc;
130 }
131
132 /* Capture the disassembled instruction. */
133 tal.insn = std::move (gdb_dis_out.string ());
134 gdb_dis_out.clear ();
135
136 /* And capture the address the instruction is at. */
137 tal.addr = orig_pc;
138 print_address (gdbarch, orig_pc, &gdb_dis_out);
139 tal.addr_string = std::move (gdb_dis_out.string ());
d7e74731 140 gdb_dis_out.clear ();
aec2f747 141
1df2f9ef
TT
142 if (addr_size != nullptr)
143 {
144 size_t new_size;
145
146 if (term_out)
733d0a67 147 new_size = len_without_escapes (tal.addr_string);
1df2f9ef 148 else
733d0a67 149 new_size = tal.addr_string.size ();
1df2f9ef 150 *addr_size = std::max (*addr_size, new_size);
733d0a67 151 tal.addr_size = new_size;
1df2f9ef
TT
152 }
153
733d0a67 154 asm_lines.push_back (std::move (tal));
aec2f747 155 }
aec2f747
SC
156 return pc;
157}
158
733d0a67
AB
159/* Look backward from ADDR for an address from which we can start
160 disassembling, this needs to be something we can be reasonably
161 confident will fall on an instruction boundary. We use msymbol
162 addresses, or the start of a section. */
163
164static CORE_ADDR
165tui_find_backward_disassembly_start_address (CORE_ADDR addr)
166{
167 struct bound_minimal_symbol msym, msym_prev;
168
169 msym = lookup_minimal_symbol_by_pc_section (addr - 1, nullptr,
170 lookup_msym_prefer::TEXT,
171 &msym_prev);
172 if (msym.minsym != nullptr)
173 return BMSYMBOL_VALUE_ADDRESS (msym);
174 else if (msym_prev.minsym != nullptr)
175 return BMSYMBOL_VALUE_ADDRESS (msym_prev);
176
177 /* Find the section that ADDR is in, and look for the start of the
178 section. */
179 struct obj_section *section = find_pc_section (addr);
180 if (section != NULL)
0c1bcd23 181 return section->addr ();
733d0a67
AB
182
183 return addr;
184}
185
1cc6d956
MS
186/* Find the disassembly address that corresponds to FROM lines above
187 or below the PC. Variable sized instructions are taken into
188 account by the algorithm. */
aec2f747 189static CORE_ADDR
13274fc3 190tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
aec2f747 191{
d02c80cd 192 CORE_ADDR new_low;
6ba8e26f 193 int max_lines;
aec2f747 194
6ba8e26f 195 max_lines = (from > 0) ? from : - from;
733d0a67 196 if (max_lines == 0)
6b915f7d 197 return pc;
aec2f747 198
733d0a67 199 std::vector<tui_asm_line> asm_lines;
aec2f747 200
6ba8e26f 201 new_low = pc;
aec2f747
SC
202 if (from > 0)
203 {
733d0a67
AB
204 /* Always disassemble 1 extra instruction here, then if the last
205 instruction fails to disassemble we will take the address of the
206 previous instruction that did disassemble as the result. */
207 tui_disassemble (gdbarch, asm_lines, pc, max_lines + 1);
208 new_low = asm_lines.back ().addr;
aec2f747
SC
209 }
210 else
211 {
733d0a67
AB
212 /* In order to disassemble backwards we need to find a suitable
213 address to start disassembling from and then work forward until we
214 re-find the address we're currently at. We can then figure out
215 which address will be at the top of the TUI window after our
216 backward scroll. During our backward disassemble we need to be
217 able to distinguish between the case where the last address we
218 _can_ disassemble is ADDR, and the case where the disassembly
219 just happens to stop at ADDR, for this reason we increase
220 MAX_LINES by one. */
221 max_lines++;
222
223 /* When we disassemble a series of instructions this will hold the
224 address of the last instruction disassembled. */
aec2f747 225 CORE_ADDR last_addr;
733d0a67
AB
226
227 /* And this will hold the address of the next instruction that would
228 have been disassembled. */
229 CORE_ADDR next_addr;
230
231 /* As we search backward if we find an address that looks like a
232 promising starting point then we record it in this structure. If
233 the next address we try is not a suitable starting point then we
234 will fall back to the address held here. */
235 gdb::optional<CORE_ADDR> possible_new_low;
236
237 /* The previous value of NEW_LOW so we know if the new value is
238 different or not. */
239 CORE_ADDR prev_low;
240
241 do
242 {
243 /* Find an address from which we can start disassembling. */
244 prev_low = new_low;
245 new_low = tui_find_backward_disassembly_start_address (new_low);
246
247 /* Disassemble forward. */
248 next_addr = tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
249 last_addr = asm_lines.back ().addr;
250
251 /* If disassembling from the current value of NEW_LOW reached PC
252 (or went past it) then this would do as a starting point if we
253 can't find anything better, so remember it. */
254 if (last_addr >= pc && new_low != prev_low
255 && asm_lines.size () >= max_lines)
256 possible_new_low.emplace (new_low);
257
258 /* Continue searching until we find a value of NEW_LOW from which
259 disassembling MAX_LINES instructions doesn't reach PC. We
260 know this means we can find the required number of previous
261 instructions then. */
262 }
263 while ((last_addr > pc
264 || (last_addr == pc && asm_lines.size () < max_lines))
265 && new_low != prev_low);
266
267 /* If we failed to disassemble the required number of lines then the
268 following walk forward is not going to work, it assumes that
269 ASM_LINES contains exactly MAX_LINES entries. Instead we should
270 consider falling back to a previous possible start address in
271 POSSIBLE_NEW_LOW. */
272 if (asm_lines.size () < max_lines)
273 {
274 if (!possible_new_low.has_value ())
42330a68 275 return new_low;
733d0a67
AB
276
277 /* Take the best possible match we have. */
278 new_low = *possible_new_low;
279 next_addr = tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
280 last_addr = asm_lines.back ().addr;
281 gdb_assert (asm_lines.size () >= max_lines);
282 }
aec2f747 283
1cc6d956 284 /* Scan forward disassembling one instruction at a time until
dda83cd7
SM
285 the last visible instruction of the window matches the pc.
286 We keep the disassembled instructions in the 'lines' window
287 and shift it downward (increasing its addresses). */
733d0a67 288 int pos = max_lines - 1;
aec2f747 289 if (last_addr < pc)
dda83cd7
SM
290 do
291 {
292 pos++;
293 if (pos >= max_lines)
294 pos = 0;
aec2f747 295
733d0a67
AB
296 CORE_ADDR old_next_addr = next_addr;
297 std::vector<tui_asm_line> single_asm_line;
298 next_addr = tui_disassemble (gdbarch, single_asm_line,
299 next_addr, 1);
dda83cd7 300 /* If there are some problems while disassembling exit. */
733d0a67
AB
301 if (next_addr <= old_next_addr)
302 return pc;
303 gdb_assert (single_asm_line.size () == 1);
304 asm_lines[pos] = single_asm_line[0];
305 } while (next_addr <= pc);
aec2f747 306 pos++;
6ba8e26f 307 if (pos >= max_lines)
dda83cd7 308 pos = 0;
4cfcaf21 309 new_low = asm_lines[pos].addr;
733d0a67
AB
310
311 /* When scrolling backward the addresses should move backward, or at
312 the very least stay the same if we are at the first address that
313 can be disassembled. */
314 gdb_assert (new_low <= pc);
aec2f747 315 }
6ba8e26f 316 return new_low;
aec2f747
SC
317}
318
319/* Function to set the disassembly window's content. */
61c33f10 320bool
81c82c4b 321tui_disasm_window::set_contents (struct gdbarch *arch,
9f7540a5 322 const struct symtab_and_line &sal)
c906108c 323{
d02c80cd 324 int i;
9e820dec 325 int max_lines;
aec2f747 326 CORE_ADDR cur_pc;
7806cea7 327 int tab_len = tui_tab_width;
aec2f747 328 int insn_pos;
1df2f9ef 329
9f7540a5 330 CORE_ADDR pc = sal.pc;
aec2f747 331 if (pc == 0)
61c33f10 332 return false;
aec2f747 333
432b5c40
TT
334 m_gdbarch = arch;
335 m_start_line_or_addr.loa = LOA_ADDRESS;
336 m_start_line_or_addr.u.addr = pc;
f237f998 337 cur_pc = tui_location.addr ();
aec2f747 338
0bb65f1e 339 /* Window size, excluding highlight box. */
81c82c4b 340 max_lines = height - 2;
aec2f747
SC
341
342 /* Get temporary table that will hold all strings (addr & insn). */
733d0a67 343 std::vector<tui_asm_line> asm_lines;
1df2f9ef 344 size_t addr_size = 0;
432b5c40 345 tui_disassemble (m_gdbarch, asm_lines, pc, max_lines, &addr_size);
aec2f747 346
f5396833 347 /* Align instructions to the same column. */
aec2f747
SC
348 insn_pos = (1 + (addr_size / tab_len)) * tab_len;
349
1cc6d956 350 /* Now construct each line. */
432b5c40 351 m_content.resize (max_lines);
9e820dec 352 m_max_length = -1;
6ba8e26f 353 for (i = 0; i < max_lines; i++)
aec2f747 354 {
432b5c40 355 tui_source_element *src = &m_content[i];
6b915f7d 356
733d0a67
AB
357 std::string line;
358 CORE_ADDR addr;
359
360 if (i < asm_lines.size ())
361 {
362 line
363 = (asm_lines[i].addr_string
364 + n_spaces (insn_pos - asm_lines[i].addr_size)
365 + asm_lines[i].insn);
366 addr = asm_lines[i].addr;
367 }
368 else
369 {
370 line = "";
371 addr = 0;
372 }
aec2f747 373
1df2f9ef 374 const char *ptr = line.c_str ();
9e820dec
TT
375 int line_len;
376 src->line = tui_copy_source_line (&ptr, &line_len);
377 m_max_length = std::max (m_max_length, line_len);
aec2f747 378
362c05fe 379 src->line_or_addr.loa = LOA_ADDRESS;
733d0a67
AB
380 src->line_or_addr.u.addr = addr;
381 src->is_exec_point = (addr == cur_pc && line.size () > 0);
aec2f747 382 }
61c33f10 383 return true;
aec2f747 384}
c906108c
SS
385
386
13274fc3
UW
387void
388tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
c906108c 389{
957b8b5a 390 struct gdbarch *gdbarch = get_current_arch ();
52469d76 391 CORE_ADDR addr = 0;
c906108c 392
f237f998 393 if (tui_location.addr () == 0)
c906108c 394 {
52469d76
TT
395 if (have_full_symbols () || have_partial_symbols ())
396 {
397 set_default_source_symtab_and_line ();
398 struct symtab_and_line sal = get_current_source_symtab_and_line ();
399
400 if (sal.symtab != nullptr)
401 find_line_pc (sal.symtab, sal.line, &addr);
402 }
403
404 if (addr == 0)
405 {
406 struct bound_minimal_symbol main_symbol
407 = lookup_minimal_symbol (main_name (), nullptr, nullptr);
408 if (main_symbol.minsym != nullptr)
409 addr = BMSYMBOL_VALUE_ADDRESS (main_symbol);
410 }
c906108c 411 }
1cc6d956 412 else /* The target is executing. */
13274fc3 413 {
f237f998
AB
414 gdbarch = tui_location.gdbarch ();
415 addr = tui_location.addr ();
13274fc3 416 }
c906108c 417
13274fc3
UW
418 *gdbarch_p = gdbarch;
419 *addr_p = addr;
65f05602 420}
c906108c 421
77cad3ba 422/* Determine what the low address will be to display in the TUI's
1cc6d956
MS
423 disassembly window. This may or may not be the same as the low
424 address input. */
77cad3ba 425CORE_ADDR
13274fc3
UW
426tui_get_low_disassembly_address (struct gdbarch *gdbarch,
427 CORE_ADDR low, CORE_ADDR pc)
77cad3ba
SC
428{
429 int pos;
430
1cc6d956
MS
431 /* Determine where to start the disassembly so that the pc is about
432 in the middle of the viewport. */
2a3d458b
TT
433 if (TUI_DISASM_WIN != NULL)
434 pos = TUI_DISASM_WIN->height;
6d7fd9aa
TT
435 else if (TUI_CMD_WIN == NULL)
436 pos = tui_term_height () / 2 - 2;
437 else
438 pos = tui_term_height () - TUI_CMD_WIN->height - 2;
439 pos = (pos - 2) / 2;
440
13274fc3 441 pc = tui_find_disassembly_address (gdbarch, pc, -pos);
77cad3ba
SC
442
443 if (pc < low)
444 pc = low;
445 return pc;
446}
447
65f05602 448/* Scroll the disassembly forward or backward vertically. */
c906108c 449void
c3bd716f 450tui_disasm_window::do_scroll_vertical (int num_to_scroll)
c906108c 451{
432b5c40 452 if (!m_content.empty ())
c906108c 453 {
aec2f747 454 CORE_ADDR pc;
c906108c 455
432b5c40 456 pc = m_start_line_or_addr.u.addr;
c906108c 457
9f7540a5
TT
458 symtab_and_line sal {};
459 sal.pspace = current_program_space;
432b5c40
TT
460 sal.pc = tui_find_disassembly_address (m_gdbarch, pc, num_to_scroll);
461 update_source_window_as_is (m_gdbarch, sal);
aec2f747
SC
462 }
463}
c2cd8994
TT
464
465bool
466tui_disasm_window::location_matches_p (struct bp_location *loc, int line_no)
467{
432b5c40
TT
468 return (m_content[line_no].line_or_addr.loa == LOA_ADDRESS
469 && m_content[line_no].line_or_addr.u.addr == loc->address);
c2cd8994 470}
a54700c6 471
088f37dd
TT
472bool
473tui_disasm_window::addr_is_displayed (CORE_ADDR addr) const
474{
432b5c40 475 if (m_content.size () < SCROLL_THRESHOLD)
cbfa8581 476 return false;
088f37dd 477
432b5c40 478 for (size_t i = 0; i < m_content.size () - SCROLL_THRESHOLD; ++i)
088f37dd 479 {
432b5c40
TT
480 if (m_content[i].line_or_addr.loa == LOA_ADDRESS
481 && m_content[i].line_or_addr.u.addr == addr)
cbfa8581 482 return true;
088f37dd
TT
483 }
484
cbfa8581 485 return false;
088f37dd
TT
486}
487
a54700c6 488void
1ae58f0c 489tui_disasm_window::maybe_update (struct frame_info *fi, symtab_and_line sal)
a54700c6
TT
490{
491 CORE_ADDR low;
492
1ae58f0c
TT
493 struct gdbarch *frame_arch = get_frame_arch (fi);
494
495 if (find_pc_partial_function (sal.pc, NULL, &low, NULL) == 0)
a54700c6
TT
496 {
497 /* There is no symbol available for current PC. There is no
498 safe way how to "disassemble backwards". */
1ae58f0c 499 low = sal.pc;
a54700c6
TT
500 }
501 else
1ae58f0c 502 low = tui_get_low_disassembly_address (frame_arch, low, sal.pc);
a54700c6
TT
503
504 struct tui_line_or_address a;
505
506 a.loa = LOA_ADDRESS;
507 a.u.addr = low;
1ae58f0c 508 if (!addr_is_displayed (sal.pc))
9f7540a5
TT
509 {
510 sal.pc = low;
511 update_source_window (frame_arch, sal);
512 }
a54700c6
TT
513 else
514 {
1ae58f0c 515 a.u.addr = sal.pc;
a54700c6
TT
516 set_is_exec_point_at (a);
517 }
518}
432b5c40
TT
519
520void
521tui_disasm_window::display_start_addr (struct gdbarch **gdbarch_p,
522 CORE_ADDR *addr_p)
523{
524 *gdbarch_p = m_gdbarch;
525 *addr_p = m_start_line_or_addr.u.addr;
526}
This page took 2.378857 seconds and 4 git commands to generate.