GDB (xrefs)
tui-disasm.c
Go to the documentation of this file.
1 /* Disassembly display.
2 
3  Copyright (C) 1998-2018 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  string_file gdb_dis_out;
58 
59  /* Now construct each line. */
60  for (; count > 0; count--, asm_lines++)
61  {
62  if (asm_lines->addr_string)
63  xfree (asm_lines->addr_string);
64  if (asm_lines->insn)
65  xfree (asm_lines->insn);
66 
67  print_address (gdbarch, pc, &gdb_dis_out);
68  asm_lines->addr = pc;
69  asm_lines->addr_string = xstrdup (gdb_dis_out.c_str ());
70 
71  gdb_dis_out.clear ();
72 
73  pc = pc + gdb_print_insn (gdbarch, pc, &gdb_dis_out, NULL);
74 
75  asm_lines->insn = xstrdup (gdb_dis_out.c_str ());
76 
77  /* Reset the buffer to empty. */
78  gdb_dis_out.clear ();
79  }
80  return pc;
81 }
82 
83 /* Find the disassembly address that corresponds to FROM lines above
84  or below the PC. Variable sized instructions are taken into
85  account by the algorithm. */
86 static CORE_ADDR
88 {
89  CORE_ADDR new_low;
90  int max_lines;
91  int i;
92  struct tui_asm_line *asm_lines;
93 
94  max_lines = (from > 0) ? from : - from;
95  if (max_lines <= 1)
96  return pc;
97 
98  asm_lines = XALLOCAVEC (struct tui_asm_line, max_lines);
99  memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
100 
101  new_low = pc;
102  if (from > 0)
103  {
104  tui_disassemble (gdbarch, asm_lines, pc, max_lines);
105  new_low = asm_lines[max_lines - 1].addr;
106  }
107  else
108  {
109  CORE_ADDR last_addr;
110  int pos;
111  struct bound_minimal_symbol msymbol;
112 
113  /* Find backward an address which is a symbol and for which
114  disassembling from that address will fill completely the
115  window. */
116  pos = max_lines - 1;
117  do {
118  new_low -= 1 * max_lines;
119  msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
120 
121  if (msymbol.minsym)
122  new_low = BMSYMBOL_VALUE_ADDRESS (msymbol);
123  else
124  new_low += 1 * max_lines;
125 
126  tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
127  last_addr = asm_lines[pos].addr;
128  } while (last_addr > pc && msymbol.minsym);
129 
130  /* Scan forward disassembling one instruction at a time until
131  the last visible instruction of the window matches the pc.
132  We keep the disassembled instructions in the 'lines' window
133  and shift it downward (increasing its addresses). */
134  if (last_addr < pc)
135  do
136  {
137  CORE_ADDR next_addr;
138 
139  pos++;
140  if (pos >= max_lines)
141  pos = 0;
142 
143  next_addr = tui_disassemble (gdbarch, &asm_lines[pos],
144  last_addr, 1);
145 
146  /* If there are some problems while disassembling exit. */
147  if (next_addr <= last_addr)
148  break;
149  last_addr = next_addr;
150  } while (last_addr <= pc);
151  pos++;
152  if (pos >= max_lines)
153  pos = 0;
154  new_low = asm_lines[pos].addr;
155  }
156  for (i = 0; i < max_lines; i++)
157  {
158  xfree (asm_lines[i].addr_string);
159  xfree (asm_lines[i].insn);
160  }
161  return new_low;
162 }
163 
164 /* Function to set the disassembly window's content. */
165 enum tui_status
167 {
168  enum tui_status ret = TUI_FAILURE;
169  int i;
170  int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
171  int max_lines, line_width;
172  CORE_ADDR cur_pc;
173  struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
174  int tab_len = tui_default_tab_len ();
175  struct tui_asm_line *asm_lines;
176  int insn_pos;
177  int addr_size, insn_size;
178  char *line;
179 
180  if (pc == 0)
181  return TUI_FAILURE;
182 
184  if (ret != TUI_SUCCESS)
185  return ret;
186 
187  TUI_DISASM_WIN->detail.source_info.gdbarch = gdbarch;
188  TUI_DISASM_WIN->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS;
189  TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr = pc;
190  cur_pc = locator->content[0]->which_element.locator.addr;
191 
192  /* Window size, excluding highlight box. */
193  max_lines = TUI_DISASM_WIN->generic.height - 2;
194  line_width = TUI_DISASM_WIN->generic.width - 2;
195 
196  /* Get temporary table that will hold all strings (addr & insn). */
197  asm_lines = XALLOCAVEC (struct tui_asm_line, max_lines);
198  memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
199 
200  tui_disassemble (gdbarch, asm_lines, pc, max_lines);
201 
202  /* Determine maximum address- and instruction lengths. */
203  addr_size = 0;
204  insn_size = 0;
205  for (i = 0; i < max_lines; i++)
206  {
207  size_t len = strlen (asm_lines[i].addr_string);
208 
209  if (len > addr_size)
210  addr_size = len;
211 
212  len = strlen (asm_lines[i].insn);
213  if (len > insn_size)
214  insn_size = len;
215  }
216 
217  /* Align instructions to the same column. */
218  insn_pos = (1 + (addr_size / tab_len)) * tab_len;
219 
220  /* Allocate memory to create each line. */
221  line = (char*) alloca (insn_pos + insn_size + 1);
222 
223  /* Now construct each line. */
224  for (i = 0; i < max_lines; i++)
225  {
226  struct tui_win_element *element;
227  struct tui_source_element *src;
228  int cur_len;
229 
230  element = TUI_DISASM_WIN->generic.content[i];
231  src = &element->which_element.source;
232  strcpy (line, asm_lines[i].addr_string);
233  cur_len = strlen (line);
234  memset (line + cur_len, ' ', insn_pos - cur_len);
235  strcpy (line + insn_pos, asm_lines[i].insn);
236 
237  /* Now copy the line taking the offset into account. */
238  if (strlen (line) > offset)
239  {
240  strncpy (src->line, &line[offset], line_width);
241  src->line[line_width] = '\0';
242  }
243  else
244  src->line[0] = '\0';
245 
247  src->line_or_addr.u.addr = asm_lines[i].addr;
248  src->is_exec_point = asm_lines[i].addr == cur_pc;
249 
250  /* See whether there is a breakpoint installed. */
251  src->has_break = (!src->is_exec_point
253  pc)
254  != no_breakpoint_here);
255 
256  xfree (asm_lines[i].addr_string);
257  xfree (asm_lines[i].insn);
258  }
259  TUI_DISASM_WIN->generic.content_size = i;
260  return TUI_SUCCESS;
261 }
262 
263 
264 /* Function to display the disassembly window with disassembled code. */
265 void
267 {
268  struct symtab *s = find_pc_line_symtab (start_addr);
270  struct tui_line_or_address val;
271 
272  val.loa = LOA_ADDRESS;
273  val.u.addr = start_addr;
276 
277  /* If the focus was in the src win, put it in the asm win, if the
278  source view isn't split. */
282 
283  return;
284 }
285 
286 
287 /* Function to display the disassembly window. */
288 void
290  CORE_ADDR start_addr)
291 {
292  struct symtab_and_line sal;
293 
294  tui_show_disassem (gdbarch, start_addr);
296  {
297  struct tui_line_or_address val;
298 
299  /* Update what is in the source window if it is displayed too,
300  note that it follows what is in the disassembly window and
301  visa-versa. */
302  sal = find_pc_line (start_addr, 0);
303  val.loa = LOA_LINE;
304  val.u.line_no = sal.line;
305  tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
306  if (sal.symtab)
307  {
310  }
311  else
313  }
314 
315  return;
316 }
317 
318 void
319 tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
320 {
321  struct tui_gen_win_info *locator;
322  struct tui_locator_element *element;
323  struct gdbarch *gdbarch = get_current_arch ();
324  CORE_ADDR addr;
325 
326  locator = tui_locator_win_info_ptr ();
327  element = &locator->content[0]->which_element.locator;
328 
329  if (element->addr == 0)
330  {
331  struct bound_minimal_symbol main_symbol;
332 
333  /* Find address of the start of program.
334  Note: this should be language specific. */
335  main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
336  if (main_symbol.minsym == 0)
337  main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
338  if (main_symbol.minsym == 0)
339  main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
340  if (main_symbol.minsym)
341  addr = BMSYMBOL_VALUE_ADDRESS (main_symbol);
342  else
343  addr = 0;
344  }
345  else /* The target is executing. */
346  {
347  gdbarch = element->gdbarch;
348  addr = element->addr;
349  }
350 
351  *gdbarch_p = gdbarch;
352  *addr_p = addr;
353 }
354 
355 /* Determine what the low address will be to display in the TUI's
356  disassembly window. This may or may not be the same as the low
357  address input. */
358 CORE_ADDR
360  CORE_ADDR low, CORE_ADDR pc)
361 {
362  int pos;
363 
364  /* Determine where to start the disassembly so that the pc is about
365  in the middle of the viewport. */
367  pc = tui_find_disassembly_address (gdbarch, pc, -pos);
368 
369  if (pc < low)
370  pc = low;
371  return pc;
372 }
373 
374 /* Scroll the disassembly forward or backward vertically. */
375 void
377  int num_to_scroll)
378 {
379  if (TUI_DISASM_WIN->generic.content != NULL)
380  {
381  struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
382  CORE_ADDR pc;
383  tui_win_content content;
384  struct tui_line_or_address val;
385  int dir;
386 
387  content = (tui_win_content) TUI_DISASM_WIN->generic.content;
388 
389  pc = content[0]->which_element.source.line_or_addr.u.addr;
390  num_to_scroll++;
391  dir = (scroll_direction == FORWARD_SCROLL)
392  ? num_to_scroll : -num_to_scroll;
393 
394  val.loa = LOA_ADDRESS;
395  val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
397  NULL, val, FALSE);
398  }
399 }
void tui_get_begin_asm_address(struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
Definition: tui-disasm.c:319
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:906
enum breakpoint_here breakpoint_here_p(const address_space *aspace, CORE_ADDR pc)
Definition: breakpoint.c:3989
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:706
void xfree(void *)
#define BMSYMBOL_VALUE_ADDRESS(symbol)
Definition: symtab.h:691
struct tui_line_or_address line_or_addr
Definition: tui-data.h:161
void * memset(T *s, int c, size_t n)=delete
void tui_set_win_focus_to(struct tui_win_info *win_info)
Definition: tui-win.c:564
enum tui_line_or_address_kind loa
Definition: tui-data.h:142
void tui_update_locator_fullname(const char *fullname)
Definition: tui-stack.c:344
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
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:3288
void tui_show_disassem(struct gdbarch *gdbarch, CORE_ADDR start_addr)
Definition: tui-disasm.c:266
void tui_vertical_disassem_scroll(enum tui_scroll_direction scroll_direction, int num_to_scroll)
Definition: tui-disasm.c:376
CORE_ADDR addr
Definition: tui-data.h:199
int gdb_print_insn(struct gdbarch *gdbarch, CORE_ADDR memaddr, struct ui_file *stream, int *branch_delay_insns)
Definition: disasm.c:813
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:253
tui_status
Definition: tui.h:30
struct gdbarch * get_current_arch(void)
Definition: arch-utils.c:798
CORE_ADDR addr
Definition: tui-disasm.c:45
void clear()
Definition: ui-file.h:140
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:298
struct tui_win_element ** tui_win_content
Definition: tui-data.h:37
const char * c_str() const
Definition: ui-file.h:137
int tui_default_tab_len(void)
Definition: tui-data.c:141
struct minimal_symbol * minsym
Definition: minsyms.h:34
union tui_line_or_address::@181 u
int offset
Definition: agent.c:65
static struct tui_win_info * win_with_focus
Definition: tui-data.c:44
#define TUI_DISASM_WIN
Definition: tui-data.h:299
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:87
char * addr_string
Definition: tui-disasm.c:46
struct symtab_and_line set_current_source_symtab_and_line(const symtab_and_line &sal)
Definition: source.c:209
void tui_show_disassem_and_update_source(struct gdbarch *gdbarch, CORE_ADDR start_addr)
Definition: tui-disasm.c:289
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:3301
struct bound_minimal_symbol lookup_minimal_symbol(const char *name, const char *sfile, struct objfile *objf)
Definition: minsyms.c:311
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:166
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:359
enum tui_layout_type tui_current_layout(void)
Definition: tui-data.c:293
int tui_default_win_viewport_height(enum tui_win_type type, enum tui_layout_type layout)
Definition: tui-layout.c:338