* disasm.h (gdb_disassembly): Add GDBARCH parameter.
[deliverable/binutils-gdb.git] / gdb / tui / tui-disasm.c
CommitLineData
f377b406 1/* Disassembly display.
f33c6cbf 2
0fb0cc75 3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009
6aba47ca 4 Free Software Foundation, Inc.
f33c6cbf 5
f377b406
SC
6 Contributed by Hewlett-Packard Company.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
a9762ec7 12 the Free Software Foundation; either version 3 of the License, or
f377b406
SC
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
a9762ec7 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
22
23#include "defs.h"
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"
6d012f14 30#include "gdb_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"
c906108c 39
6a83354a 40#include "gdb_curses.h"
96ec9981 41
aec2f747
SC
42struct tui_asm_line
43{
44 CORE_ADDR addr;
5b6fe301
MS
45 char *addr_string;
46 char *insn;
aec2f747
SC
47};
48
49/* Function to set the disassembly window's content.
50 Disassemble count lines starting at pc.
51 Return address of the count'th instruction after pc. */
52static CORE_ADDR
13274fc3 53tui_disassemble (struct gdbarch *gdbarch, struct tui_asm_line *asm_lines,
08ef48c5 54 CORE_ADDR pc, int count)
aec2f747
SC
55{
56 struct ui_file *gdb_dis_out;
c906108c 57
1cc6d956 58 /* Now init the ui_file structure. */
aec2f747
SC
59 gdb_dis_out = tui_sfileopen (256);
60
1cc6d956 61 /* Now construct each line. */
4cfcaf21 62 for (; count > 0; count--, asm_lines++)
aec2f747 63 {
4cfcaf21
JB
64 if (asm_lines->addr_string)
65 xfree (asm_lines->addr_string);
66 if (asm_lines->insn)
67 xfree (asm_lines->insn);
aec2f747
SC
68
69 print_address (pc, gdb_dis_out);
4cfcaf21
JB
70 asm_lines->addr = pc;
71 asm_lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
aec2f747
SC
72
73 ui_file_rewind (gdb_dis_out);
74
13274fc3 75 pc = pc + gdb_print_insn (gdbarch, pc, gdb_dis_out, NULL);
aec2f747 76
4cfcaf21 77 asm_lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
aec2f747 78
1cc6d956 79 /* Reset the buffer to empty. */
aec2f747
SC
80 ui_file_rewind (gdb_dis_out);
81 }
82 ui_file_delete (gdb_dis_out);
83 return pc;
84}
85
1cc6d956
MS
86/* Find the disassembly address that corresponds to FROM lines above
87 or below the PC. Variable sized instructions are taken into
88 account by the algorithm. */
aec2f747 89static CORE_ADDR
13274fc3 90tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
aec2f747 91{
d02c80cd 92 CORE_ADDR new_low;
6ba8e26f 93 int max_lines;
aec2f747 94 int i;
5b6fe301 95 struct tui_asm_line *asm_lines;
aec2f747 96
6ba8e26f
AC
97 max_lines = (from > 0) ? from : - from;
98 if (max_lines <= 1)
aec2f747
SC
99 return pc;
100
4cfcaf21 101 asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
6ba8e26f 102 * max_lines);
4cfcaf21 103 memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
aec2f747 104
6ba8e26f 105 new_low = pc;
aec2f747
SC
106 if (from > 0)
107 {
13274fc3 108 tui_disassemble (gdbarch, asm_lines, pc, max_lines);
4cfcaf21 109 new_low = asm_lines[max_lines - 1].addr;
aec2f747
SC
110 }
111 else
112 {
113 CORE_ADDR last_addr;
114 int pos;
5b6fe301 115 struct minimal_symbol *msymbol;
aec2f747 116
1cc6d956
MS
117 /* Find backward an address which is a symbol and for which
118 disassembling from that address will fill completely the
119 window. */
6ba8e26f 120 pos = max_lines - 1;
aec2f747 121 do {
6ba8e26f
AC
122 new_low -= 1 * max_lines;
123 msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
aec2f747
SC
124
125 if (msymbol)
6ba8e26f 126 new_low = SYMBOL_VALUE_ADDRESS (msymbol);
aec2f747 127 else
6ba8e26f 128 new_low += 1 * max_lines;
aec2f747 129
13274fc3 130 tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
4cfcaf21 131 last_addr = asm_lines[pos].addr;
aec2f747
SC
132 } while (last_addr > pc && msymbol);
133
1cc6d956
MS
134 /* Scan forward disassembling one instruction at a time until
135 the last visible instruction of the window matches the pc.
136 We keep the disassembled instructions in the 'lines' window
137 and shift it downward (increasing its addresses). */
aec2f747
SC
138 if (last_addr < pc)
139 do
140 {
141 CORE_ADDR next_addr;
142
143 pos++;
6ba8e26f 144 if (pos >= max_lines)
aec2f747
SC
145 pos = 0;
146
13274fc3
UW
147 next_addr = tui_disassemble (gdbarch, &asm_lines[pos],
148 last_addr, 1);
aec2f747
SC
149
150 /* If there are some problems while disassembling exit. */
151 if (next_addr <= last_addr)
152 break;
153 last_addr = next_addr;
154 } while (last_addr <= pc);
155 pos++;
6ba8e26f 156 if (pos >= max_lines)
aec2f747 157 pos = 0;
4cfcaf21 158 new_low = asm_lines[pos].addr;
aec2f747 159 }
6ba8e26f 160 for (i = 0; i < max_lines; i++)
aec2f747 161 {
4cfcaf21
JB
162 xfree (asm_lines[i].addr_string);
163 xfree (asm_lines[i].insn);
aec2f747 164 }
6ba8e26f 165 return new_low;
aec2f747
SC
166}
167
168/* Function to set the disassembly window's content. */
65f05602 169enum tui_status
13274fc3 170tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc)
c906108c 171{
22940a24 172 enum tui_status ret = TUI_FAILURE;
d02c80cd 173 int i;
6d012f14 174 int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
d02c80cd 175 int line_width, max_lines;
aec2f747 176 CORE_ADDR cur_pc;
5b6fe301 177 struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
dd1abb8c 178 int tab_len = tui_default_tab_len ();
5b6fe301 179 struct tui_asm_line *asm_lines;
aec2f747
SC
180 int insn_pos;
181 int addr_size, max_size;
5b6fe301 182 char *line;
aec2f747
SC
183
184 if (pc == 0)
185 return TUI_FAILURE;
186
6d012f14 187 ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
aec2f747
SC
188 if (ret != TUI_SUCCESS)
189 return ret;
190
13274fc3 191 TUI_DISASM_WIN->detail.source_info.gdbarch = gdbarch;
362c05fe
AS
192 TUI_DISASM_WIN->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS;
193 TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr = pc;
aec2f747 194 cur_pc = (CORE_ADDR)
6d012f14 195 (((struct tui_win_element *) 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
6ba8e26f 205 line_width = TUI_DISASM_WIN->generic.width - 1;
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);
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
aec2f747 262 && breakpoint_here_p (pc) != no_breakpoint_here);
c906108c 263
4cfcaf21
JB
264 xfree (asm_lines[i].addr_string);
265 xfree (asm_lines[i].insn);
aec2f747 266 }
6d012f14 267 TUI_DISASM_WIN->generic.content_size = i;
aec2f747
SC
268 return TUI_SUCCESS;
269}
c906108c
SS
270
271
1cc6d956 272/* Function to display the disassembly window with disassembled code. */
c906108c 273void
13274fc3 274tui_show_disassem (struct gdbarch *gdbarch, CORE_ADDR start_addr)
c906108c 275{
6ba8e26f 276 struct symtab *s = find_pc_symtab (start_addr);
5b6fe301 277 struct tui_win_info *win_with_focus = tui_win_with_focus ();
362c05fe 278 struct tui_line_or_address val;
c906108c 279
362c05fe
AS
280 val.loa = LOA_ADDRESS;
281 val.u.addr = start_addr;
080ce8c0 282 tui_add_win_to_layout (DISASSEM_WIN);
13274fc3 283 tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
ef5eab5a
MS
284
285 /* If the focus was in the src win, put it in the asm win, if the
286 source view isn't split. */
e5908723
MS
287 if (tui_current_layout () != SRC_DISASSEM_COMMAND
288 && win_with_focus == TUI_SRC_WIN)
6d012f14 289 tui_set_win_focus_to (TUI_DISASM_WIN);
c906108c
SS
290
291 return;
65f05602 292}
c906108c
SS
293
294
1cc6d956 295/* Function to display the disassembly window. */
c906108c 296void
13274fc3
UW
297tui_show_disassem_and_update_source (struct gdbarch *gdbarch,
298 CORE_ADDR start_addr)
c906108c
SS
299{
300 struct symtab_and_line sal;
301
13274fc3 302 tui_show_disassem (gdbarch, start_addr);
dd1abb8c 303 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
c906108c 304 {
362c05fe 305 struct tui_line_or_address val;
aec2f747 306
ef5eab5a
MS
307 /* Update what is in the source window if it is displayed too,
308 note that it follows what is in the disassembly window and
309 visa-versa. */
6ba8e26f 310 sal = find_pc_line (start_addr, 0);
362c05fe
AS
311 val.loa = LOA_LINE;
312 val.u.line_no = sal.line;
13274fc3 313 tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
3024f13a
SC
314 if (sal.symtab)
315 {
52575520 316 set_current_source_symtab_and_line (&sal);
47d3492a 317 tui_update_locator_filename (sal.symtab->filename);
3024f13a
SC
318 }
319 else
47d3492a 320 tui_update_locator_filename ("?");
c906108c
SS
321 }
322
323 return;
65f05602 324}
c906108c 325
13274fc3
UW
326void
327tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
c906108c 328{
5b6fe301
MS
329 struct tui_gen_win_info *locator;
330 struct tui_locator_element *element;
13274fc3 331 struct gdbarch *gdbarch = NULL;
c774cec6 332 CORE_ADDR addr;
c906108c 333
dd1abb8c 334 locator = tui_locator_win_info_ptr ();
6d012f14 335 element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
c906108c 336
c774cec6 337 if (element->addr == 0)
c906108c 338 {
0510ab86
SC
339 struct minimal_symbol *main_symbol;
340
341 /* Find address of the start of program.
342 Note: this should be language specific. */
343 main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
344 if (main_symbol == 0)
345 main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
346 if (main_symbol == 0)
347 main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
348 if (main_symbol)
349 addr = SYMBOL_VALUE_ADDRESS (main_symbol);
350 else
351 addr = 0;
c906108c 352 }
1cc6d956 353 else /* The target is executing. */
13274fc3
UW
354 {
355 gdbarch = element->gdbarch;
356 addr = element->addr;
357 }
c906108c 358
13274fc3
UW
359 *gdbarch_p = gdbarch;
360 *addr_p = addr;
65f05602 361}
c906108c 362
77cad3ba 363/* Determine what the low address will be to display in the TUI's
1cc6d956
MS
364 disassembly window. This may or may not be the same as the low
365 address input. */
77cad3ba 366CORE_ADDR
13274fc3
UW
367tui_get_low_disassembly_address (struct gdbarch *gdbarch,
368 CORE_ADDR low, CORE_ADDR pc)
77cad3ba
SC
369{
370 int pos;
371
1cc6d956
MS
372 /* Determine where to start the disassembly so that the pc is about
373 in the middle of the viewport. */
080ce8c0 374 pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
13274fc3 375 pc = tui_find_disassembly_address (gdbarch, pc, -pos);
77cad3ba
SC
376
377 if (pc < low)
378 pc = low;
379 return pc;
380}
381
65f05602 382/* Scroll the disassembly forward or backward vertically. */
c906108c 383void
6ba8e26f
AC
384tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
385 int num_to_scroll)
c906108c 386{
6d012f14 387 if (TUI_DISASM_WIN->generic.content != NULL)
c906108c 388 {
13274fc3 389 struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
aec2f747 390 CORE_ADDR pc;
2a8854a7 391 tui_win_content content;
362c05fe 392 struct tui_line_or_address val;
aefc7064 393 int dir;
c906108c 394
6d012f14 395 content = (tui_win_content) TUI_DISASM_WIN->generic.content;
c906108c 396
362c05fe 397 pc = content[0]->which_element.source.line_or_addr.u.addr;
aefc7064
PA
398 num_to_scroll++;
399 dir = (scroll_direction == FORWARD_SCROLL) ? num_to_scroll : -num_to_scroll;
c906108c 400
362c05fe 401 val.loa = LOA_ADDRESS;
13274fc3
UW
402 val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
403 tui_update_source_window_as_is (TUI_DISASM_WIN, gdbarch, NULL, val, FALSE);
aec2f747
SC
404 }
405}
This page took 1.062434 seconds and 4 git commands to generate.