OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [tui/] [tui-disasm.c] - Blame information for rev 854

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* 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 "arch-utils.h"
25
#include "symtab.h"
26
#include "breakpoint.h"
27
#include "frame.h"
28
#include "value.h"
29
#include "source.h"
30
#include "disasm.h"
31
#include "gdb_string.h"
32
#include "tui/tui.h"
33
#include "tui/tui-data.h"
34
#include "tui/tui-win.h"
35
#include "tui/tui-layout.h"
36
#include "tui/tui-winsource.h"
37
#include "tui/tui-stack.h"
38
#include "tui/tui-file.h"
39
#include "tui/tui-disasm.h"
40
#include "progspace.h"
41
 
42
#include "gdb_curses.h"
43
 
44
struct tui_asm_line
45
{
46
  CORE_ADDR addr;
47
  char *addr_string;
48
  char *insn;
49
};
50
 
51
/* Function to set the disassembly window's content.
52
   Disassemble count lines starting at pc.
53
   Return address of the count'th instruction after pc.  */
54
static CORE_ADDR
55
tui_disassemble (struct gdbarch *gdbarch, struct tui_asm_line *asm_lines,
56
                 CORE_ADDR pc, int count)
57
{
58
  struct ui_file *gdb_dis_out;
59
 
60
  /* Now init the ui_file structure.  */
61
  gdb_dis_out = tui_sfileopen (256);
62
 
63
  /* Now construct each line.  */
64
  for (; count > 0; count--, asm_lines++)
65
    {
66
      if (asm_lines->addr_string)
67
        xfree (asm_lines->addr_string);
68
      if (asm_lines->insn)
69
        xfree (asm_lines->insn);
70
 
71
      print_address (gdbarch, pc, gdb_dis_out);
72
      asm_lines->addr = pc;
73
      asm_lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
74
 
75
      ui_file_rewind (gdb_dis_out);
76
 
77
      pc = pc + gdb_print_insn (gdbarch, pc, gdb_dis_out, NULL);
78
 
79
      asm_lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
80
 
81
      /* Reset the buffer to empty.  */
82
      ui_file_rewind (gdb_dis_out);
83
    }
84
  ui_file_delete (gdb_dis_out);
85
  return pc;
86
}
87
 
88
/* Find the disassembly address that corresponds to FROM lines above
89
   or below the PC.  Variable sized instructions are taken into
90
   account by the algorithm.  */
91
static CORE_ADDR
92
tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
93
{
94
  CORE_ADDR new_low;
95
  int max_lines;
96
  int i;
97
  struct tui_asm_line *asm_lines;
98
 
99
  max_lines = (from > 0) ? from : - from;
100
  if (max_lines <= 1)
101
     return pc;
102
 
103
  asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
104
                                         * max_lines);
105
  memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
106
 
107
  new_low = pc;
108
  if (from > 0)
109
    {
110
      tui_disassemble (gdbarch, asm_lines, pc, max_lines);
111
      new_low = asm_lines[max_lines - 1].addr;
112
    }
113
  else
114
    {
115
      CORE_ADDR last_addr;
116
      int pos;
117
      struct minimal_symbol *msymbol;
118
 
119
      /* Find backward an address which is a symbol and for which
120
         disassembling from that address will fill completely the
121
         window.  */
122
      pos = max_lines - 1;
123
      do {
124
         new_low -= 1 * max_lines;
125
         msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
126
 
127
         if (msymbol)
128
            new_low = SYMBOL_VALUE_ADDRESS (msymbol);
129
         else
130
            new_low += 1 * max_lines;
131
 
132
         tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
133
         last_addr = asm_lines[pos].addr;
134
      } while (last_addr > pc && msymbol);
135
 
136
      /* Scan forward disassembling one instruction at a time until
137
         the last visible instruction of the window matches the pc.
138
         We keep the disassembled instructions in the 'lines' window
139
         and shift it downward (increasing its addresses).  */
140
      if (last_addr < pc)
141
        do
142
          {
143
            CORE_ADDR next_addr;
144
 
145
            pos++;
146
            if (pos >= max_lines)
147
              pos = 0;
148
 
149
            next_addr = tui_disassemble (gdbarch, &asm_lines[pos],
150
                                         last_addr, 1);
151
 
152
            /* If there are some problems while disassembling exit.  */
153
            if (next_addr <= last_addr)
154
              break;
155
            last_addr = next_addr;
156
          } while (last_addr <= pc);
157
      pos++;
158
      if (pos >= max_lines)
159
         pos = 0;
160
      new_low = asm_lines[pos].addr;
161
    }
162
  for (i = 0; i < max_lines; i++)
163
    {
164
      xfree (asm_lines[i].addr_string);
165
      xfree (asm_lines[i].insn);
166
    }
167
  return new_low;
168
}
169
 
170
/* Function to set the disassembly window's content.  */
171
enum tui_status
172
tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc)
173
{
174
  enum tui_status ret = TUI_FAILURE;
175
  int i;
176
  int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
177
  int line_width, max_lines;
178
  CORE_ADDR cur_pc;
179
  struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
180
  int tab_len = tui_default_tab_len ();
181
  struct tui_asm_line *asm_lines;
182
  int insn_pos;
183
  int addr_size, max_size;
184
  char *line;
185
 
186
  if (pc == 0)
187
    return TUI_FAILURE;
188
 
189
  ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
190
  if (ret != TUI_SUCCESS)
191
    return ret;
192
 
193
  TUI_DISASM_WIN->detail.source_info.gdbarch = gdbarch;
194
  TUI_DISASM_WIN->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS;
195
  TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr = pc;
196
  cur_pc = (CORE_ADDR)
197
    (((struct tui_win_element *) locator->content[0])->which_element.locator.addr);
198
 
199
  max_lines = TUI_DISASM_WIN->generic.height - 2;       /* Account for
200
                                                           hilite.  */
201
 
202
  /* Get temporary table that will hold all strings (addr & insn).  */
203
  asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
204
                                         * max_lines);
205
  memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
206
 
207
  line_width = TUI_DISASM_WIN->generic.width - 1;
208
 
209
  tui_disassemble (gdbarch, asm_lines, pc, max_lines);
210
 
211
  /* See what is the maximum length of an address and of a line.  */
212
  addr_size = 0;
213
  max_size = 0;
214
  for (i = 0; i < max_lines; i++)
215
    {
216
      size_t len = strlen (asm_lines[i].addr_string);
217
 
218
      if (len > addr_size)
219
        addr_size = len;
220
 
221
      len = strlen (asm_lines[i].insn) + tab_len;
222
      if (len > max_size)
223
        max_size = len;
224
    }
225
  max_size += addr_size + tab_len;
226
 
227
  /* Allocate memory to create each line.  */
228
  line = (char*) alloca (max_size);
229
  insn_pos = (1 + (addr_size / tab_len)) * tab_len;
230
 
231
  /* Now construct each line.  */
232
  for (i = 0; i < max_lines; i++)
233
    {
234
      struct tui_win_element *element;
235
      struct tui_source_element *src;
236
      int cur_len;
237
 
238
      element = (struct tui_win_element *) TUI_DISASM_WIN->generic.content[i];
239
      src = &element->which_element.source;
240
      strcpy (line, asm_lines[i].addr_string);
241
      cur_len = strlen (line);
242
 
243
      /* Add spaces to make the instructions start on the same
244
         column.  */
245
      while (cur_len < insn_pos)
246
        {
247
          strcat (line, " ");
248
          cur_len++;
249
        }
250
 
251
      strcat (line, asm_lines[i].insn);
252
 
253
      /* Now copy the line taking the offset into account.  */
254
      if (strlen (line) > offset)
255
        strcpy (src->line, &line[offset]);
256
      else
257
        src->line[0] = '\0';
258
 
259
      src->line_or_addr.loa = LOA_ADDRESS;
260
      src->line_or_addr.u.addr = asm_lines[i].addr;
261
      src->is_exec_point = asm_lines[i].addr == cur_pc;
262
 
263
      /* See whether there is a breakpoint installed.  */
264
      src->has_break = (!src->is_exec_point
265
                        && breakpoint_here_p (current_program_space->aspace, pc)
266
                        != no_breakpoint_here);
267
 
268
      xfree (asm_lines[i].addr_string);
269
      xfree (asm_lines[i].insn);
270
    }
271
  TUI_DISASM_WIN->generic.content_size = i;
272
  return TUI_SUCCESS;
273
}
274
 
275
 
276
/* Function to display the disassembly window with disassembled code.  */
277
void
278
tui_show_disassem (struct gdbarch *gdbarch, CORE_ADDR start_addr)
279
{
280
  struct symtab *s = find_pc_symtab (start_addr);
281
  struct tui_win_info *win_with_focus = tui_win_with_focus ();
282
  struct tui_line_or_address val;
283
 
284
  val.loa = LOA_ADDRESS;
285
  val.u.addr = start_addr;
286
  tui_add_win_to_layout (DISASSEM_WIN);
287
  tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
288
 
289
  /* If the focus was in the src win, put it in the asm win, if the
290
     source view isn't split.  */
291
  if (tui_current_layout () != SRC_DISASSEM_COMMAND
292
      && win_with_focus == TUI_SRC_WIN)
293
    tui_set_win_focus_to (TUI_DISASM_WIN);
294
 
295
  return;
296
}
297
 
298
 
299
/* Function to display the disassembly window.  */
300
void
301
tui_show_disassem_and_update_source (struct gdbarch *gdbarch,
302
                                     CORE_ADDR start_addr)
303
{
304
  struct symtab_and_line sal;
305
 
306
  tui_show_disassem (gdbarch, start_addr);
307
  if (tui_current_layout () == SRC_DISASSEM_COMMAND)
308
    {
309
      struct tui_line_or_address val;
310
 
311
      /* Update what is in the source window if it is displayed too,
312
         note that it follows what is in the disassembly window and
313
         visa-versa.  */
314
      sal = find_pc_line (start_addr, 0);
315
      val.loa = LOA_LINE;
316
      val.u.line_no = sal.line;
317
      tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
318
      if (sal.symtab)
319
        {
320
          set_current_source_symtab_and_line (&sal);
321
          tui_update_locator_filename (sal.symtab->filename);
322
        }
323
      else
324
        tui_update_locator_filename ("?");
325
    }
326
 
327
  return;
328
}
329
 
330
void
331
tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
332
{
333
  struct tui_gen_win_info *locator;
334
  struct tui_locator_element *element;
335
  struct gdbarch *gdbarch = get_current_arch ();
336
  CORE_ADDR addr;
337
 
338
  locator = tui_locator_win_info_ptr ();
339
  element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
340
 
341
  if (element->addr == 0)
342
    {
343
      struct minimal_symbol *main_symbol;
344
 
345
      /* Find address of the start of program.
346
         Note: this should be language specific.  */
347
      main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
348
      if (main_symbol == 0)
349
        main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
350
      if (main_symbol == 0)
351
        main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
352
      if (main_symbol)
353
        addr = SYMBOL_VALUE_ADDRESS (main_symbol);
354
      else
355
        addr = 0;
356
    }
357
  else                          /* The target is executing.  */
358
    {
359
      gdbarch = element->gdbarch;
360
      addr = element->addr;
361
    }
362
 
363
  *gdbarch_p = gdbarch;
364
  *addr_p = addr;
365
}
366
 
367
/* Determine what the low address will be to display in the TUI's
368
   disassembly window.  This may or may not be the same as the low
369
   address input.  */
370
CORE_ADDR
371
tui_get_low_disassembly_address (struct gdbarch *gdbarch,
372
                                 CORE_ADDR low, CORE_ADDR pc)
373
{
374
  int pos;
375
 
376
  /* Determine where to start the disassembly so that the pc is about
377
     in the middle of the viewport.  */
378
  pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
379
  pc = tui_find_disassembly_address (gdbarch, pc, -pos);
380
 
381
  if (pc < low)
382
    pc = low;
383
  return pc;
384
}
385
 
386
/* Scroll the disassembly forward or backward vertically.  */
387
void
388
tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
389
                              int num_to_scroll)
390
{
391
  if (TUI_DISASM_WIN->generic.content != NULL)
392
    {
393
      struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
394
      CORE_ADDR pc;
395
      tui_win_content content;
396
      struct tui_line_or_address val;
397
      int dir;
398
 
399
      content = (tui_win_content) TUI_DISASM_WIN->generic.content;
400
 
401
      pc = content[0]->which_element.source.line_or_addr.u.addr;
402
      num_to_scroll++;
403
      dir = (scroll_direction == FORWARD_SCROLL) ? num_to_scroll : -num_to_scroll;
404
 
405
      val.loa = LOA_ADDRESS;
406
      val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
407
      tui_update_source_window_as_is (TUI_DISASM_WIN, gdbarch, NULL, val, FALSE);
408
    }
409
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.