GDB (xrefs)
tui-disasm.c
Go to the documentation of this file.
1 /* Disassembly display.
2 
3  Copyright (C) 1998-2015 Free Software Foundation, Inc.
4 
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
11  the Free Software Foundation; either version 3 of the License, or
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
20  along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "symtab.h"
25 #include "breakpoint.h"
26 #include "frame.h"
27 #include "value.h"
28 #include "source.h"
29 #include "disasm.h"
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"
37 #include "tui/tui-disasm.h"
38 #include "progspace.h"
39 #include "objfiles.h"
40 
41 #include "gdb_curses.h"
42 
43 struct tui_asm_line
44 {
46  char *addr_string;
47  char *insn;
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. */
53 static CORE_ADDR
54 tui_disassemble (struct gdbarch *gdbarch, struct tui_asm_line *asm_lines,
55  CORE_ADDR pc, int count)
56 {
57  struct ui_file *gdb_dis_out;
58 
59  /* Now init the ui_file structure. */
60  gdb_dis_out = tui_sfileopen (256);
61 
62  /* Now construct each line. */
63  for (; count > 0; count--, asm_lines++)
64  {
65  if (asm_lines->addr_string)
66  xfree (asm_lines->addr_string);
67  if (asm_lines->insn)
68  xfree (asm_lines->insn);
69 
70  print_address (gdbarch, pc, gdb_dis_out);
71  asm_lines->addr = pc;
72  asm_lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
73 
74  ui_file_rewind (gdb_dis_out);
75 
76  pc = pc + gdb_print_insn (gdbarch, pc, gdb_dis_out, NULL);
77 
78  asm_lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
79 
80  /* Reset the buffer to empty. */
81  ui_file_rewind (gdb_dis_out);
82  }
83  ui_file_delete (gdb_dis_out);
84  return pc;
85 }
86 
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. */
90 static CORE_ADDR
92 {
93  CORE_ADDR new_low;
94  int max_lines;
95  int i;
96  struct tui_asm_line *asm_lines;
97 
98  max_lines = (from > 0) ? from : - from;
99  if (max_lines <= 1)
100  return pc;
101 
102  asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
103  * max_lines);
104  memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
105 
106  new_low = pc;
107  if (from > 0)
108  {
109  tui_disassemble (gdbarch, asm_lines, pc, max_lines);
110  new_low = asm_lines[max_lines - 1].addr;
111  }
112  else
113  {
114  CORE_ADDR last_addr;
115  int pos;
116  struct bound_minimal_symbol msymbol;
117 
118  /* Find backward an address which is a symbol and for which
119  disassembling from that address will fill completely the
120  window. */
121  pos = max_lines - 1;
122  do {
123  new_low -= 1 * max_lines;
124  msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
125 
126  if (msymbol.minsym)
127  new_low = BMSYMBOL_VALUE_ADDRESS (msymbol);
128  else
129  new_low += 1 * max_lines;
130 
131  tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
132  last_addr = asm_lines[pos].addr;
133  } while (last_addr > pc && msymbol.minsym);
134 
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). */
139  if (last_addr < pc)
140  do
141  {
142  CORE_ADDR next_addr;
143 
144  pos++;
145  if (pos >= max_lines)
146  pos = 0;
147 
148  next_addr = tui_disassemble (gdbarch, &asm_lines[pos],
149  last_addr, 1);
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++;
157  if (pos >= max_lines)
158  pos = 0;
159  new_low = asm_lines[pos].addr;
160  }
161  for (i = 0; i < max_lines; i++)
162  {
163  xfree (asm_lines[i].addr_string);
164  xfree (asm_lines[i].insn);
165  }
166  return new_low;
167 }
168 
169 /* Function to set the disassembly window's content. */
170 enum tui_status
172 {
173  enum tui_status ret = TUI_FAILURE;
174  int i;
175  int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
176  int max_lines;
177  CORE_ADDR cur_pc;
178  struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
179  int tab_len = tui_default_tab_len ();
180  struct tui_asm_line *asm_lines;
181  int insn_pos;
182  int addr_size, max_size;
183  char *line;
184 
185  if (pc == 0)
186  return TUI_FAILURE;
187 
189  if (ret != TUI_SUCCESS)
190  return ret;
191 
192  TUI_DISASM_WIN->detail.source_info.gdbarch = gdbarch;
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;
195  cur_pc = locator->content[0]->which_element.locator.addr;
196 
197  max_lines = TUI_DISASM_WIN->generic.height - 2; /* Account for
198  hilite. */
199 
200  /* Get temporary table that will hold all strings (addr & insn). */
201  asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
202  * max_lines);
203  memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
204 
205  tui_disassemble (gdbarch, asm_lines, pc, max_lines);
206 
207  /* See what is the maximum length of an address and of a line. */
208  addr_size = 0;
209  max_size = 0;
210  for (i = 0; i < max_lines; i++)
211  {
212  size_t len = strlen (asm_lines[i].addr_string);
213 
214  if (len > addr_size)
215  addr_size = len;
216 
217  len = strlen (asm_lines[i].insn) + tab_len;
218  if (len > max_size)
219  max_size = len;
220  }
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 
227  /* Now construct each line. */
228  for (i = 0; i < max_lines; i++)
229  {
230  struct tui_win_element *element;
231  struct tui_source_element *src;
232  int cur_len;
233 
234  element = TUI_DISASM_WIN->generic.content[i];
235  src = &element->which_element.source;
236  strcpy (line, asm_lines[i].addr_string);
237  cur_len = strlen (line);
238 
239  /* Add spaces to make the instructions start on the same
240  column. */
241  while (cur_len < insn_pos)
242  {
243  strcat (line, " ");
244  cur_len++;
245  }
246 
247  strcat (line, asm_lines[i].insn);
248 
249  /* Now copy the line taking the offset into account. */
250  if (strlen (line) > offset)
251  strcpy (src->line, &line[offset]);
252  else
253  src->line[0] = '\0';
254 
256  src->line_or_addr.u.addr = asm_lines[i].addr;
257  src->is_exec_point = asm_lines[i].addr == cur_pc;
258 
259  /* See whether there is a breakpoint installed. */
260  src->has_break = (!src->is_exec_point
262  pc)
263  != no_breakpoint_here);
264 
265  xfree (asm_lines[i].addr_string);
266  xfree (asm_lines[i].insn);
267  }
268  TUI_DISASM_WIN->generic.content_size = i;
269  return TUI_SUCCESS;
270 }
271 
272 
273 /* Function to display the disassembly window with disassembled code. */
274 void
276 {
277  struct symtab *s = find_pc_line_symtab (start_addr);
279  struct tui_line_or_address val;
280 
281  val.loa = LOA_ADDRESS;
282  val.u.addr = start_addr;
284  tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
285 
286  /* If the focus was in the src win, put it in the asm win, if the
287  source view isn't split. */
289  && win_with_focus == TUI_SRC_WIN)
291 
292  return;
293 }
294 
295 
296 /* Function to display the disassembly window. */
297 void
299  CORE_ADDR start_addr)
300 {
301  struct symtab_and_line sal;
302 
303  tui_show_disassem (gdbarch, start_addr);
305  {
306  struct tui_line_or_address val;
307 
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. */
311  sal = find_pc_line (start_addr, 0);
312  val.loa = LOA_LINE;
313  val.u.line_no = sal.line;
314  tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
315  if (sal.symtab)
316  {
319  }
320  else
322  }
323 
324  return;
325 }
326 
327 void
328 tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
329 {
330  struct tui_gen_win_info *locator;
331  struct tui_locator_element *element;
332  struct gdbarch *gdbarch = get_current_arch ();
333  CORE_ADDR addr;
334 
335  locator = tui_locator_win_info_ptr ();
336  element = &locator->content[0]->which_element.locator;
337 
338  if (element->addr == 0)
339  {
340  struct bound_minimal_symbol main_symbol;
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);
345  if (main_symbol.minsym == 0)
346  main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
347  if (main_symbol.minsym == 0)
348  main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
349  if (main_symbol.minsym)
350  addr = BMSYMBOL_VALUE_ADDRESS (main_symbol);
351  else
352  addr = 0;
353  }
354  else /* The target is executing. */
355  {
356  gdbarch = element->gdbarch;
357  addr = element->addr;
358  }
359 
360  *gdbarch_p = gdbarch;
361  *addr_p = addr;
362 }
363 
364 /* Determine what the low address will be to display in the TUI's
365  disassembly window. This may or may not be the same as the low
366  address input. */
367 CORE_ADDR
369  CORE_ADDR low, CORE_ADDR pc)
370 {
371  int pos;
372 
373  /* Determine where to start the disassembly so that the pc is about
374  in the middle of the viewport. */
376  pc = tui_find_disassembly_address (gdbarch, pc, -pos);
377 
378  if (pc < low)
379  pc = low;
380  return pc;
381 }
382 
383 /* Scroll the disassembly forward or backward vertically. */
384 void
386  int num_to_scroll)
387 {
388  if (TUI_DISASM_WIN->generic.content != NULL)
389  {
390  struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
391  CORE_ADDR pc;
392  tui_win_content content;
393  struct tui_line_or_address val;
394  int dir;
395 
396  content = (tui_win_content) TUI_DISASM_WIN->generic.content;
397 
398  pc = content[0]->which_element.source.line_or_addr.u.addr;
399  num_to_scroll++;
400  dir = (scroll_direction == FORWARD_SCROLL)
401  ? num_to_scroll : -num_to_scroll;
402 
403  val.loa = LOA_ADDRESS;
404  val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
406  NULL, val, FALSE);
407  }
408 }
void tui_get_begin_asm_address(struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
Definition: tui-disasm.c:328
tui_win_content content
Definition: tui-data.h:47
char * insn
Definition: tui-disasm.c:47
struct bound_minimal_symbol lookup_minimal_symbol_by_pc_section(CORE_ADDR pc, struct obj_section *section)
Definition: minsyms.c:779
char * tui_file_get_strbuf(struct ui_file *file)
Definition: tui-file.c:190
bfd_vma CORE_ADDR
Definition: common-types.h:41
struct address_space * aspace
Definition: progspace.h:166
void print_address(struct gdbarch *, CORE_ADDR, struct ui_file *)
Definition: printcmd.c:741
void xfree(void *)
Definition: common-utils.c:97
#define BMSYMBOL_VALUE_ADDRESS(symbol)
Definition: symtab.h:393
void ui_file_delete(struct ui_file *file)
Definition: ui-file.c:76
struct tui_line_or_address line_or_addr
Definition: tui-data.h:161
enum breakpoint_here breakpoint_here_p(struct address_space *aspace, CORE_ADDR pc)
Definition: breakpoint.c:4187
void tui_set_win_focus_to(struct tui_win_info *win_info)
Definition: tui-win.c:554
union tui_line_or_address::@171 u
enum tui_line_or_address_kind loa
Definition: tui-data.h:142
void tui_update_locator_fullname(const char *fullname)
Definition: tui-stack.c:347
static CORE_ADDR tui_disassemble(struct gdbarch *gdbarch, struct tui_asm_line *asm_lines, CORE_ADDR pc, int count)
Definition: tui-disasm.c:54
const char * symtab_to_fullname(struct symtab *s)
Definition: source.c:1131
void tui_update_source_window(struct tui_win_info *win_info, struct gdbarch *gdbarch, struct symtab *s, struct tui_line_or_address line_or_addr, int noerror)
Definition: tui-winsource.c:71
int * from
Definition: varobj.h:282
struct tui_locator_element locator
Definition: tui-data.h:226
tui_scroll_direction
Definition: tui-data.h:96
struct symtab_and_line find_pc_line(CORE_ADDR pc, int notcurrent)
Definition: symtab.c:3315
void tui_show_disassem(struct gdbarch *gdbarch, CORE_ADDR start_addr)
Definition: tui-disasm.c:275
void tui_vertical_disassem_scroll(enum tui_scroll_direction scroll_direction, int num_to_scroll)
Definition: tui-disasm.c:385
CORE_ADDR addr
Definition: tui-data.h:199
struct ui_file * tui_sfileopen(int n)
Definition: tui-file.c:101
int gdb_print_insn(struct gdbarch *gdbarch, CORE_ADDR memaddr, struct ui_file *stream, int *branch_delay_insns)
Definition: disasm.c:444
struct tui_win_info * tui_win_with_focus(void)
Definition: tui-data.c:125
struct tui_gen_win_info * tui_locator_win_info_ptr(void)
Definition: tui-data.c:254
tui_status
Definition: tui.h:30
struct gdbarch * get_current_arch(void)
Definition: arch-utils.c:781
CORE_ADDR addr
Definition: tui-disasm.c:45
Definition: symtab.h:925
void tui_add_win_to_layout(enum tui_win_type type)
Definition: tui-layout.c:248
struct gdbarch * gdbarch
Definition: tui-data.h:201
union tui_which_element which_element
Definition: tui-data.h:233
#define TUI_SRC_WIN
Definition: tui-data.h:300
struct tui_win_element ** tui_win_content
Definition: tui-data.h:37
int tui_default_tab_len(void)
Definition: tui-data.c:141
struct minimal_symbol * minsym
Definition: minsyms.h:32
int offset
Definition: agent.c:65
struct symtab_and_line set_current_source_symtab_and_line(const struct symtab_and_line *sal)
Definition: source.c:219
static struct tui_win_info * win_with_focus
Definition: tui-data.c:44
int line
Definition: symtab.h:1570
#define TUI_DISASM_WIN
Definition: tui-data.h:301
void ui_file_rewind(struct ui_file *file)
Definition: ui-file.c:204
struct program_space * current_program_space
Definition: progspace.c:35
static CORE_ADDR tui_find_disassembly_address(struct gdbarch *gdbarch, CORE_ADDR pc, int from)
Definition: tui-disasm.c:91
char * addr_string
Definition: tui-disasm.c:46
void tui_show_disassem_and_update_source(struct gdbarch *gdbarch, CORE_ADDR start_addr)
Definition: tui-disasm.c:298
enum tui_status tui_alloc_source_buffer(struct tui_win_info *win_info)
struct symtab * find_pc_line_symtab(CORE_ADDR pc)
Definition: symtab.c:3328
struct bound_minimal_symbol lookup_minimal_symbol(const char *name, const char *sfile, struct objfile *objf)
Definition: minsyms.c:163
struct tui_source_element source
Definition: tui-data.h:222
enum tui_status tui_set_disassem_content(struct gdbarch *gdbarch, CORE_ADDR pc)
Definition: tui-disasm.c:171
CORE_ADDR addr
Definition: tui-data.h:146
void tui_update_source_window_as_is(struct tui_win_info *win_info, struct gdbarch *gdbarch, struct symtab *s, struct tui_line_or_address line_or_addr, int noerror)
Definition: tui-winsource.c:87
CORE_ADDR tui_get_low_disassembly_address(struct gdbarch *gdbarch, CORE_ADDR low, CORE_ADDR pc)
Definition: tui-disasm.c:368
const ULONGEST const LONGEST len
Definition: target.h:309
enum tui_layout_type tui_current_layout(void)
Definition: tui-data.c:294
int tui_default_win_viewport_height(enum tui_win_type type, enum tui_layout_type layout)
Definition: tui-layout.c:338