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