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