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