~ubuntu-branches/debian/jessie/gdb/jessie

« back to all changes in this revision

Viewing changes to .pc/tui-no-gdbarch.patch/gdb/tui/tui-disasm.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Jacobowitz
  • Date: 2010-03-20 01:21:29 UTC
  • mfrom: (1.3.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20100320012129-t7h25y8zgr8c2369
Tags: 7.1-1
* New upstream release, including:
  - PIE support (Closes: #346409).
  - C++ improvements, including static_cast<> et al, namespace imports,
    and bug fixes in printing virtual base classes.
  - Multi-program debugging.  One GDB can now debug multiple programs
    at the same time.
  - Python scripting improvements, including gdb.parse_and_eval.
  - Updated MIPS Linux signal frame layout (Closes: #570875).
  - No internal error stepping over _dl_debug_state (Closes: #569551).
* Update to Standards-Version: 3.8.4 (no changes required).
* Include more relevant (and smaller) docs in the gdbserver package
  (Closes: #571132).
* Do not duplicate documentation in gdb64, gdb-source, and libgdb-dev.
* Fix crash when switching into TUI mode (Closes: #568489).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Disassembly display.
 
2
 
 
3
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009,
 
4
   2010 Free Software Foundation, Inc.
 
5
 
 
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
 
12
   the Free Software Foundation; either version 3 of the License, or
 
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
 
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
22
 
 
23
#include "defs.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 "gdb_string.h"
 
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"
 
38
#include "tui/tui-disasm.h"
 
39
#include "progspace.h"
 
40
 
 
41
#include "gdb_curses.h"
 
42
 
 
43
struct tui_asm_line 
 
44
{
 
45
  CORE_ADDR addr;
 
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
 
91
tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
 
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 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)
 
127
            new_low = SYMBOL_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);
 
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
 
171
tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc)
 
172
{
 
173
  enum tui_status ret = TUI_FAILURE;
 
174
  int i;
 
175
  int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
 
176
  int line_width, 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
 
 
188
  ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
 
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 = (CORE_ADDR)
 
196
    (((struct tui_win_element *) locator->content[0])->which_element.locator.addr);
 
197
 
 
198
  max_lines = TUI_DISASM_WIN->generic.height - 2;       /* Account for
 
199
                                                           hilite.  */
 
200
 
 
201
  /* Get temporary table that will hold all strings (addr & insn).  */
 
202
  asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
 
203
                                         * max_lines);
 
204
  memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
 
205
 
 
206
  line_width = TUI_DISASM_WIN->generic.width - 1;
 
207
 
 
208
  tui_disassemble (gdbarch, asm_lines, pc, max_lines);
 
209
 
 
210
  /* See what is the maximum length of an address and of a line.  */
 
211
  addr_size = 0;
 
212
  max_size = 0;
 
213
  for (i = 0; i < max_lines; i++)
 
214
    {
 
215
      size_t len = strlen (asm_lines[i].addr_string);
 
216
      if (len > addr_size)
 
217
        addr_size = len;
 
218
 
 
219
      len = strlen (asm_lines[i].insn) + tab_len;
 
220
      if (len > max_size)
 
221
        max_size = len;
 
222
    }
 
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
 
 
229
  /* Now construct each line.  */
 
230
  for (i = 0; i < max_lines; i++)
 
231
    {
 
232
      struct tui_win_element *element;
 
233
      struct tui_source_element *src;
 
234
      int cur_len;
 
235
 
 
236
      element = (struct tui_win_element *) TUI_DISASM_WIN->generic.content[i];
 
237
      src = &element->which_element.source;
 
238
      strcpy (line, asm_lines[i].addr_string);
 
239
      cur_len = strlen (line);
 
240
 
 
241
      /* Add spaces to make the instructions start on the same
 
242
         column.  */
 
243
      while (cur_len < insn_pos)
 
244
        {
 
245
          strcat (line, " ");
 
246
          cur_len++;
 
247
        }
 
248
 
 
249
      strcat (line, asm_lines[i].insn);
 
250
 
 
251
      /* Now copy the line taking the offset into account.  */
 
252
      if (strlen (line) > offset)
 
253
        strcpy (src->line, &line[offset]);
 
254
      else
 
255
        src->line[0] = '\0';
 
256
 
 
257
      src->line_or_addr.loa = LOA_ADDRESS;
 
258
      src->line_or_addr.u.addr = asm_lines[i].addr;
 
259
      src->is_exec_point = asm_lines[i].addr == cur_pc;
 
260
 
 
261
      /* See whether there is a breakpoint installed.  */
 
262
      src->has_break = (!src->is_exec_point
 
263
                        && breakpoint_here_p (current_program_space->aspace, pc)
 
264
                        != no_breakpoint_here);
 
265
 
 
266
      xfree (asm_lines[i].addr_string);
 
267
      xfree (asm_lines[i].insn);
 
268
    }
 
269
  TUI_DISASM_WIN->generic.content_size = i;
 
270
  return TUI_SUCCESS;
 
271
}
 
272
 
 
273
 
 
274
/* Function to display the disassembly window with disassembled code.  */
 
275
void
 
276
tui_show_disassem (struct gdbarch *gdbarch, CORE_ADDR start_addr)
 
277
{
 
278
  struct symtab *s = find_pc_symtab (start_addr);
 
279
  struct tui_win_info *win_with_focus = tui_win_with_focus ();
 
280
  struct tui_line_or_address val;
 
281
 
 
282
  val.loa = LOA_ADDRESS;
 
283
  val.u.addr = start_addr;
 
284
  tui_add_win_to_layout (DISASSEM_WIN);
 
285
  tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
 
286
 
 
287
  /* If the focus was in the src win, put it in the asm win, if the
 
288
     source view isn't split.  */
 
289
  if (tui_current_layout () != SRC_DISASSEM_COMMAND 
 
290
      && win_with_focus == TUI_SRC_WIN)
 
291
    tui_set_win_focus_to (TUI_DISASM_WIN);
 
292
 
 
293
  return;
 
294
}
 
295
 
 
296
 
 
297
/* Function to display the disassembly window.  */
 
298
void
 
299
tui_show_disassem_and_update_source (struct gdbarch *gdbarch,
 
300
                                     CORE_ADDR start_addr)
 
301
{
 
302
  struct symtab_and_line sal;
 
303
 
 
304
  tui_show_disassem (gdbarch, start_addr);
 
305
  if (tui_current_layout () == SRC_DISASSEM_COMMAND)
 
306
    {
 
307
      struct tui_line_or_address val;
 
308
 
 
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.  */
 
312
      sal = find_pc_line (start_addr, 0);
 
313
      val.loa = LOA_LINE;
 
314
      val.u.line_no = sal.line;
 
315
      tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
 
316
      if (sal.symtab)
 
317
        {
 
318
          set_current_source_symtab_and_line (&sal);
 
319
          tui_update_locator_filename (sal.symtab->filename);
 
320
        }
 
321
      else
 
322
        tui_update_locator_filename ("?");
 
323
    }
 
324
 
 
325
  return;
 
326
}
 
327
 
 
328
void
 
329
tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
 
330
{
 
331
  struct tui_gen_win_info *locator;
 
332
  struct tui_locator_element *element;
 
333
  struct gdbarch *gdbarch = NULL;
 
334
  CORE_ADDR addr;
 
335
 
 
336
  locator = tui_locator_win_info_ptr ();
 
337
  element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
 
338
 
 
339
  if (element->addr == 0)
 
340
    {
 
341
      struct minimal_symbol *main_symbol;
 
342
 
 
343
      /* Find address of the start of program.
 
344
         Note: this should be language specific.  */
 
345
      main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
 
346
      if (main_symbol == 0)
 
347
        main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
 
348
      if (main_symbol == 0)
 
349
        main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
 
350
      if (main_symbol)
 
351
        addr = SYMBOL_VALUE_ADDRESS (main_symbol);
 
352
      else
 
353
        addr = 0;
 
354
    }
 
355
  else                          /* The target is executing.  */
 
356
    {
 
357
      gdbarch = element->gdbarch;
 
358
      addr = element->addr;
 
359
    }
 
360
 
 
361
  *gdbarch_p = gdbarch;
 
362
  *addr_p = addr;
 
363
}
 
364
 
 
365
/* Determine what the low address will be to display in the TUI's
 
366
   disassembly window.  This may or may not be the same as the low
 
367
   address input.  */
 
368
CORE_ADDR
 
369
tui_get_low_disassembly_address (struct gdbarch *gdbarch,
 
370
                                 CORE_ADDR low, CORE_ADDR pc)
 
371
{
 
372
  int pos;
 
373
 
 
374
  /* Determine where to start the disassembly so that the pc is about
 
375
     in the middle of the viewport.  */
 
376
  pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
 
377
  pc = tui_find_disassembly_address (gdbarch, pc, -pos);
 
378
 
 
379
  if (pc < low)
 
380
    pc = low;
 
381
  return pc;
 
382
}
 
383
 
 
384
/* Scroll the disassembly forward or backward vertically.  */
 
385
void
 
386
tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
 
387
                              int num_to_scroll)
 
388
{
 
389
  if (TUI_DISASM_WIN->generic.content != NULL)
 
390
    {
 
391
      struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
 
392
      CORE_ADDR pc;
 
393
      tui_win_content content;
 
394
      struct tui_line_or_address val;
 
395
      int dir;
 
396
 
 
397
      content = (tui_win_content) TUI_DISASM_WIN->generic.content;
 
398
 
 
399
      pc = content[0]->which_element.source.line_or_addr.u.addr;
 
400
      num_to_scroll++;
 
401
      dir = (scroll_direction == FORWARD_SCROLL) ? num_to_scroll : -num_to_scroll;
 
402
 
 
403
      val.loa = LOA_ADDRESS;
 
404
      val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
 
405
      tui_update_source_window_as_is (TUI_DISASM_WIN, gdbarch, NULL, val, FALSE);
 
406
    }
 
407
}