make MSYMBOL_VALUE_ADDRESS an rvalue
[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"
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;
5b6fe301 116 struct 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;
7cbd4a93 124 msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0).minsym;
aec2f747
SC
125
126 if (msymbol)
efd66ac6 127 new_low = MSYMBOL_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;
aec2f747
SC
133 } while (last_addr > pc && msymbol);
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;
9a2b4c1b
MS
195 cur_pc = (CORE_ADDR) (((struct tui_win_element *)
196 locator->content[0])->which_element.locator.addr);
aec2f747 197
1cc6d956
MS
198 max_lines = TUI_DISASM_WIN->generic.height - 2; /* Account for
199 hilite. */
aec2f747
SC
200
201 /* Get temporary table that will hold all strings (addr & insn). */
4cfcaf21 202 asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
6ba8e26f 203 * max_lines);
4cfcaf21 204 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 205
13274fc3 206 tui_disassemble (gdbarch, asm_lines, pc, max_lines);
aec2f747
SC
207
208 /* See what is the maximum length of an address and of a line. */
209 addr_size = 0;
210 max_size = 0;
6ba8e26f 211 for (i = 0; i < max_lines; i++)
c906108c 212 {
4cfcaf21 213 size_t len = strlen (asm_lines[i].addr_string);
1c5313c5 214
aec2f747
SC
215 if (len > addr_size)
216 addr_size = len;
c906108c 217
4cfcaf21 218 len = strlen (asm_lines[i].insn) + tab_len;
aec2f747
SC
219 if (len > max_size)
220 max_size = len;
c906108c 221 }
aec2f747
SC
222 max_size += addr_size + tab_len;
223
224 /* Allocate memory to create each line. */
225 line = (char*) alloca (max_size);
226 insn_pos = (1 + (addr_size / tab_len)) * tab_len;
227
1cc6d956 228 /* Now construct each line. */
6ba8e26f 229 for (i = 0; i < max_lines; i++)
aec2f747 230 {
5b6fe301
MS
231 struct tui_win_element *element;
232 struct tui_source_element *src;
6ba8e26f 233 int cur_len;
aec2f747 234
6d012f14
AC
235 element = (struct tui_win_element *) TUI_DISASM_WIN->generic.content[i];
236 src = &element->which_element.source;
4cfcaf21 237 strcpy (line, asm_lines[i].addr_string);
6ba8e26f 238 cur_len = strlen (line);
aec2f747 239
1cc6d956
MS
240 /* Add spaces to make the instructions start on the same
241 column. */
6ba8e26f 242 while (cur_len < insn_pos)
aec2f747
SC
243 {
244 strcat (line, " ");
6ba8e26f 245 cur_len++;
aec2f747
SC
246 }
247
4cfcaf21 248 strcat (line, asm_lines[i].insn);
aec2f747 249
1cc6d956 250 /* Now copy the line taking the offset into account. */
aec2f747
SC
251 if (strlen (line) > offset)
252 strcpy (src->line, &line[offset]);
253 else
254 src->line[0] = '\0';
255
362c05fe
AS
256 src->line_or_addr.loa = LOA_ADDRESS;
257 src->line_or_addr.u.addr = asm_lines[i].addr;
4cfcaf21 258 src->is_exec_point = asm_lines[i].addr == cur_pc;
aec2f747
SC
259
260 /* See whether there is a breakpoint installed. */
6d012f14 261 src->has_break = (!src->is_exec_point
9a2b4c1b
MS
262 && breakpoint_here_p (current_program_space->aspace,
263 pc)
6c95b8df 264 != no_breakpoint_here);
c906108c 265
4cfcaf21
JB
266 xfree (asm_lines[i].addr_string);
267 xfree (asm_lines[i].insn);
aec2f747 268 }
6d012f14 269 TUI_DISASM_WIN->generic.content_size = i;
aec2f747
SC
270 return TUI_SUCCESS;
271}
c906108c
SS
272
273
1cc6d956 274/* Function to display the disassembly window with disassembled code. */
c906108c 275void
13274fc3 276tui_show_disassem (struct gdbarch *gdbarch, CORE_ADDR start_addr)
c906108c 277{
6ba8e26f 278 struct symtab *s = find_pc_symtab (start_addr);
5b6fe301 279 struct tui_win_info *win_with_focus = tui_win_with_focus ();
362c05fe 280 struct tui_line_or_address val;
c906108c 281
362c05fe
AS
282 val.loa = LOA_ADDRESS;
283 val.u.addr = start_addr;
080ce8c0 284 tui_add_win_to_layout (DISASSEM_WIN);
13274fc3 285 tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
ef5eab5a
MS
286
287 /* If the focus was in the src win, put it in the asm win, if the
288 source view isn't split. */
e5908723
MS
289 if (tui_current_layout () != SRC_DISASSEM_COMMAND
290 && win_with_focus == TUI_SRC_WIN)
6d012f14 291 tui_set_win_focus_to (TUI_DISASM_WIN);
c906108c
SS
292
293 return;
65f05602 294}
c906108c
SS
295
296
1cc6d956 297/* Function to display the disassembly window. */
c906108c 298void
13274fc3
UW
299tui_show_disassem_and_update_source (struct gdbarch *gdbarch,
300 CORE_ADDR start_addr)
c906108c
SS
301{
302 struct symtab_and_line sal;
303
13274fc3 304 tui_show_disassem (gdbarch, start_addr);
dd1abb8c 305 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
c906108c 306 {
362c05fe 307 struct tui_line_or_address val;
aec2f747 308
ef5eab5a
MS
309 /* Update what is in the source window if it is displayed too,
310 note that it follows what is in the disassembly window and
311 visa-versa. */
6ba8e26f 312 sal = find_pc_line (start_addr, 0);
362c05fe
AS
313 val.loa = LOA_LINE;
314 val.u.line_no = sal.line;
13274fc3 315 tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
3024f13a
SC
316 if (sal.symtab)
317 {
52575520 318 set_current_source_symtab_and_line (&sal);
56d397a3 319 tui_update_locator_fullname (symtab_to_fullname (sal.symtab));
3024f13a
SC
320 }
321 else
56d397a3 322 tui_update_locator_fullname ("?");
c906108c
SS
323 }
324
325 return;
65f05602 326}
c906108c 327
13274fc3
UW
328void
329tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
c906108c 330{
5b6fe301
MS
331 struct tui_gen_win_info *locator;
332 struct tui_locator_element *element;
957b8b5a 333 struct gdbarch *gdbarch = get_current_arch ();
c774cec6 334 CORE_ADDR addr;
c906108c 335
dd1abb8c 336 locator = tui_locator_win_info_ptr ();
9a2b4c1b
MS
337 element = &((struct tui_win_element *)
338 locator->content[0])->which_element.locator;
c906108c 339
c774cec6 340 if (element->addr == 0)
c906108c 341 {
0510ab86
SC
342 struct minimal_symbol *main_symbol;
343
344 /* Find address of the start of program.
345 Note: this should be language specific. */
346 main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
347 if (main_symbol == 0)
348 main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
349 if (main_symbol == 0)
350 main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
351 if (main_symbol)
efd66ac6 352 addr = MSYMBOL_VALUE_ADDRESS (main_symbol);
0510ab86
SC
353 else
354 addr = 0;
c906108c 355 }
1cc6d956 356 else /* The target is executing. */
13274fc3
UW
357 {
358 gdbarch = element->gdbarch;
359 addr = element->addr;
360 }
c906108c 361
13274fc3
UW
362 *gdbarch_p = gdbarch;
363 *addr_p = addr;
65f05602 364}
c906108c 365
77cad3ba 366/* Determine what the low address will be to display in the TUI's
1cc6d956
MS
367 disassembly window. This may or may not be the same as the low
368 address input. */
77cad3ba 369CORE_ADDR
13274fc3
UW
370tui_get_low_disassembly_address (struct gdbarch *gdbarch,
371 CORE_ADDR low, CORE_ADDR pc)
77cad3ba
SC
372{
373 int pos;
374
1cc6d956
MS
375 /* Determine where to start the disassembly so that the pc is about
376 in the middle of the viewport. */
080ce8c0 377 pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
13274fc3 378 pc = tui_find_disassembly_address (gdbarch, pc, -pos);
77cad3ba
SC
379
380 if (pc < low)
381 pc = low;
382 return pc;
383}
384
65f05602 385/* Scroll the disassembly forward or backward vertically. */
c906108c 386void
6ba8e26f
AC
387tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
388 int num_to_scroll)
c906108c 389{
6d012f14 390 if (TUI_DISASM_WIN->generic.content != NULL)
c906108c 391 {
13274fc3 392 struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
aec2f747 393 CORE_ADDR pc;
2a8854a7 394 tui_win_content content;
362c05fe 395 struct tui_line_or_address val;
aefc7064 396 int dir;
c906108c 397
6d012f14 398 content = (tui_win_content) TUI_DISASM_WIN->generic.content;
c906108c 399
362c05fe 400 pc = content[0]->which_element.source.line_or_addr.u.addr;
aefc7064 401 num_to_scroll++;
9a2b4c1b
MS
402 dir = (scroll_direction == FORWARD_SCROLL)
403 ? num_to_scroll : -num_to_scroll;
c906108c 404
362c05fe 405 val.loa = LOA_ADDRESS;
13274fc3 406 val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
9a2b4c1b
MS
407 tui_update_source_window_as_is (TUI_DISASM_WIN, gdbarch,
408 NULL, val, FALSE);
aec2f747
SC
409 }
410}
This page took 1.40953 seconds and 4 git commands to generate.