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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [tui/] [tui-disasm.c] - Blame information for rev 816

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

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

powered by: WebSVN 2.1.0

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