OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [disasm.c] - Blame information for rev 252

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

Line No. Rev Author Line
1 227 jeremybenn
/* Disassemble support for GDB.
2
 
3
   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#include "defs.h"
22
#include "target.h"
23
#include "value.h"
24
#include "ui-out.h"
25
#include "gdb_string.h"
26
#include "disasm.h"
27
#include "gdbcore.h"
28
#include "dis-asm.h"
29
 
30
/* Disassemble functions.
31
   FIXME: We should get rid of all the duplicate code in gdb that does
32
   the same thing: disassemble_command() and the gdbtk variation. */
33
 
34
/* This Structure is used to store line number information.
35
   We need a different sort of line table from the normal one cuz we can't
36
   depend upon implicit line-end pc's for lines to do the
37
   reordering in this function.  */
38
 
39
struct dis_line_entry
40
{
41
  int line;
42
  CORE_ADDR start_pc;
43
  CORE_ADDR end_pc;
44
};
45
 
46
/* Like target_read_memory, but slightly different parameters.  */
47
static int
48
dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
49
                     struct disassemble_info *info)
50
{
51
  return target_read_memory (memaddr, myaddr, len);
52
}
53
 
54
/* Like memory_error with slightly different parameters.  */
55
static void
56
dis_asm_memory_error (int status, bfd_vma memaddr,
57
                      struct disassemble_info *info)
58
{
59
  memory_error (status, memaddr);
60
}
61
 
62
/* Like print_address with slightly different parameters.  */
63
static void
64
dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
65
{
66
  struct gdbarch *gdbarch = info->application_data;
67
  print_address (gdbarch, addr, info->stream);
68
}
69
 
70
static int
71
compare_lines (const void *mle1p, const void *mle2p)
72
{
73
  struct dis_line_entry *mle1, *mle2;
74
  int val;
75
 
76
  mle1 = (struct dis_line_entry *) mle1p;
77
  mle2 = (struct dis_line_entry *) mle2p;
78
 
79
  val = mle1->line - mle2->line;
80
 
81
  if (val != 0)
82
    return val;
83
 
84
  return mle1->start_pc - mle2->start_pc;
85
}
86
 
87
static int
88
dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
89
            struct disassemble_info * di,
90
            CORE_ADDR low, CORE_ADDR high,
91
            int how_many, int flags, struct ui_stream *stb)
92
{
93
  int num_displayed = 0;
94
  CORE_ADDR pc;
95
 
96
  /* parts of the symbolic representation of the address */
97
  int unmapped;
98
  int offset;
99
  int line;
100
  struct cleanup *ui_out_chain;
101
 
102
  for (pc = low; pc < high;)
103
    {
104
      char *filename = NULL;
105
      char *name = NULL;
106
 
107
      QUIT;
108
      if (how_many >= 0)
109
        {
110
          if (num_displayed >= how_many)
111
            break;
112
          else
113
            num_displayed++;
114
        }
115
      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
116
      ui_out_text (uiout, pc_prefix (pc));
117
      ui_out_field_core_addr (uiout, "address", gdbarch, pc);
118
 
119
      if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
120
                                   &line, &unmapped))
121
        {
122
          /* We don't care now about line, filename and
123
             unmapped. But we might in the future. */
124
          ui_out_text (uiout, " <");
125
          if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
126
            ui_out_field_string (uiout, "func-name", name);
127
          ui_out_text (uiout, "+");
128
          ui_out_field_int (uiout, "offset", offset);
129
          ui_out_text (uiout, ">:\t");
130
        }
131
      else
132
        ui_out_text (uiout, ":\t");
133
 
134
      if (filename != NULL)
135
        xfree (filename);
136
      if (name != NULL)
137
        xfree (name);
138
 
139
      ui_file_rewind (stb->stream);
140
      if (flags & DISASSEMBLY_RAW_INSN)
141
        {
142
          CORE_ADDR old_pc = pc;
143
          bfd_byte data;
144
          int status;
145
          pc += gdbarch_print_insn (gdbarch, pc, di);
146
          for (;old_pc < pc; old_pc++)
147
            {
148
              status = (*di->read_memory_func) (old_pc, &data, 1, di);
149
              if (status != 0)
150
                (*di->memory_error_func) (status, old_pc, di);
151
              ui_out_message (uiout, 0, " %02x", (unsigned)data);
152
            }
153
          ui_out_text (uiout, "\t");
154
        }
155
      else
156
        pc += gdbarch_print_insn (gdbarch, pc, di);
157
      ui_out_field_stream (uiout, "inst", stb);
158
      ui_file_rewind (stb->stream);
159
      do_cleanups (ui_out_chain);
160
      ui_out_text (uiout, "\n");
161
    }
162
  return num_displayed;
163
}
164
 
165
/* The idea here is to present a source-O-centric view of a
166
   function to the user.  This means that things are presented
167
   in source order, with (possibly) out of order assembly
168
   immediately following.  */
169
static void
170
do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
171
                              struct disassemble_info *di, int nlines,
172
                              struct linetable_entry *le,
173
                              CORE_ADDR low, CORE_ADDR high,
174
                              struct symtab *symtab,
175
                              int how_many, int flags, struct ui_stream *stb)
176
{
177
  int newlines = 0;
178
  struct dis_line_entry *mle;
179
  struct symtab_and_line sal;
180
  int i;
181
  int out_of_order = 0;
182
  int next_line = 0;
183
  CORE_ADDR pc;
184
  int num_displayed = 0;
185
  struct cleanup *ui_out_chain;
186
  struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
187
  struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
188
 
189
  mle = (struct dis_line_entry *) alloca (nlines
190
                                          * sizeof (struct dis_line_entry));
191
 
192
  /* Copy linetable entries for this function into our data
193
     structure, creating end_pc's and setting out_of_order as
194
     appropriate.  */
195
 
196
  /* First, skip all the preceding functions.  */
197
 
198
  for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
199
 
200
  /* Now, copy all entries before the end of this function.  */
201
 
202
  for (; i < nlines - 1 && le[i].pc < high; i++)
203
    {
204
      if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
205
        continue;               /* Ignore duplicates */
206
 
207
      /* Skip any end-of-function markers.  */
208
      if (le[i].line == 0)
209
        continue;
210
 
211
      mle[newlines].line = le[i].line;
212
      if (le[i].line > le[i + 1].line)
213
        out_of_order = 1;
214
      mle[newlines].start_pc = le[i].pc;
215
      mle[newlines].end_pc = le[i + 1].pc;
216
      newlines++;
217
    }
218
 
219
  /* If we're on the last line, and it's part of the function,
220
     then we need to get the end pc in a special way.  */
221
 
222
  if (i == nlines - 1 && le[i].pc < high)
223
    {
224
      mle[newlines].line = le[i].line;
225
      mle[newlines].start_pc = le[i].pc;
226
      sal = find_pc_line (le[i].pc, 0);
227
      mle[newlines].end_pc = sal.end;
228
      newlines++;
229
    }
230
 
231
  /* Now, sort mle by line #s (and, then by addresses within
232
     lines). */
233
 
234
  if (out_of_order)
235
    qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
236
 
237
  /* Now, for each line entry, emit the specified lines (unless
238
     they have been emitted before), followed by the assembly code
239
     for that line.  */
240
 
241
  ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
242
 
243
  for (i = 0; i < newlines; i++)
244
    {
245
      /* Print out everything from next_line to the current line.  */
246
      if (mle[i].line >= next_line)
247
        {
248
          if (next_line != 0)
249
            {
250
              /* Just one line to print. */
251
              if (next_line == mle[i].line)
252
                {
253
                  ui_out_tuple_chain
254
                    = make_cleanup_ui_out_tuple_begin_end (uiout,
255
                                                           "src_and_asm_line");
256
                  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
257
                }
258
              else
259
                {
260
                  /* Several source lines w/o asm instructions associated. */
261
                  for (; next_line < mle[i].line; next_line++)
262
                    {
263
                      struct cleanup *ui_out_list_chain_line;
264
                      struct cleanup *ui_out_tuple_chain_line;
265
 
266
                      ui_out_tuple_chain_line
267
                        = make_cleanup_ui_out_tuple_begin_end (uiout,
268
                                                               "src_and_asm_line");
269
                      print_source_lines (symtab, next_line, next_line + 1,
270
                                          0);
271
                      ui_out_list_chain_line
272
                        = make_cleanup_ui_out_list_begin_end (uiout,
273
                                                              "line_asm_insn");
274
                      do_cleanups (ui_out_list_chain_line);
275
                      do_cleanups (ui_out_tuple_chain_line);
276
                    }
277
                  /* Print the last line and leave list open for
278
                     asm instructions to be added. */
279
                  ui_out_tuple_chain
280
                    = make_cleanup_ui_out_tuple_begin_end (uiout,
281
                                                           "src_and_asm_line");
282
                  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
283
                }
284
            }
285
          else
286
            {
287
              ui_out_tuple_chain
288
                = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
289
              print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
290
            }
291
 
292
          next_line = mle[i].line + 1;
293
          ui_out_list_chain
294
            = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
295
        }
296
 
297
      num_displayed += dump_insns (gdbarch, uiout, di,
298
                                   mle[i].start_pc, mle[i].end_pc,
299
                                   how_many, flags, stb);
300
 
301
      /* When we've reached the end of the mle array, or we've seen the last
302
         assembly range for this source line, close out the list/tuple.  */
303
      if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
304
        {
305
          do_cleanups (ui_out_list_chain);
306
          do_cleanups (ui_out_tuple_chain);
307
          ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
308
          ui_out_list_chain = make_cleanup (null_cleanup, 0);
309
          ui_out_text (uiout, "\n");
310
        }
311
      if (how_many >= 0 && num_displayed >= how_many)
312
        break;
313
    }
314
  do_cleanups (ui_out_chain);
315
}
316
 
317
 
318
static void
319
do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
320
                  struct disassemble_info * di,
321
                  CORE_ADDR low, CORE_ADDR high,
322
                  int how_many, int flags, struct ui_stream *stb)
323
{
324
  int num_displayed = 0;
325
  struct cleanup *ui_out_chain;
326
 
327
  ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
328
 
329
  num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
330
                              flags, stb);
331
 
332
  do_cleanups (ui_out_chain);
333
}
334
 
335
/* Initialize the disassemble info struct ready for the specified
336
   stream.  */
337
 
338
static int ATTR_FORMAT (printf, 2, 3)
339
fprintf_disasm (void *stream, const char *format, ...)
340
{
341
  va_list args;
342
  va_start (args, format);
343
  vfprintf_filtered (stream, format, args);
344
  va_end (args);
345
  /* Something non -ve.  */
346
  return 0;
347
}
348
 
349
static struct disassemble_info
350
gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
351
{
352
  struct disassemble_info di;
353
  init_disassemble_info (&di, file, fprintf_disasm);
354
  di.flavour = bfd_target_unknown_flavour;
355
  di.memory_error_func = dis_asm_memory_error;
356
  di.print_address_func = dis_asm_print_address;
357
  /* NOTE: cagney/2003-04-28: The original code, from the old Insight
358
     disassembler had a local optomization here.  By default it would
359
     access the executable file, instead of the target memory (there
360
     was a growing list of exceptions though).  Unfortunately, the
361
     heuristic was flawed.  Commands like "disassemble &variable"
362
     didn't work as they relied on the access going to the target.
363
     Further, it has been supperseeded by trust-read-only-sections
364
     (although that should be superseeded by target_trust..._p()).  */
365
  di.read_memory_func = dis_asm_read_memory;
366
  di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
367
  di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
368
  di.endian = gdbarch_byte_order (gdbarch);
369
  di.endian_code = gdbarch_byte_order_for_code (gdbarch);
370
  di.application_data = gdbarch;
371
  disassemble_init_for_target (&di);
372
  return di;
373
}
374
 
375
void
376
gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
377
                 char *file_string, int flags, int how_many,
378
                 CORE_ADDR low, CORE_ADDR high)
379
{
380
  struct ui_stream *stb = ui_out_stream_new (uiout);
381
  struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
382
  struct disassemble_info di = gdb_disassemble_info (gdbarch, stb->stream);
383
  /* To collect the instruction outputted from opcodes. */
384
  struct symtab *symtab = NULL;
385
  struct linetable_entry *le = NULL;
386
  int nlines = -1;
387
 
388
  /* Assume symtab is valid for whole PC range */
389
  symtab = find_pc_symtab (low);
390
 
391
  if (symtab != NULL && symtab->linetable != NULL)
392
    {
393
      /* Convert the linetable to a bunch of my_line_entry's.  */
394
      le = symtab->linetable->item;
395
      nlines = symtab->linetable->nitems;
396
    }
397
 
398
  if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
399
      || symtab == NULL || symtab->linetable == NULL)
400
    do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
401
 
402
  else if (flags & DISASSEMBLY_SOURCE)
403
    do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
404
                                  high, symtab, how_many, flags, stb);
405
 
406
  do_cleanups (cleanups);
407
  gdb_flush (gdb_stdout);
408
}
409
 
410
/* Print the instruction at address MEMADDR in debugged memory,
411
   on STREAM.  Returns the length of the instruction, in bytes,
412
   and, if requested, the number of branch delay slot instructions.  */
413
 
414
int
415
gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
416
                struct ui_file *stream, int *branch_delay_insns)
417
{
418
  struct disassemble_info di;
419
  int length;
420
 
421
  di = gdb_disassemble_info (gdbarch, stream);
422
  length = gdbarch_print_insn (gdbarch, memaddr, &di);
423
  if (branch_delay_insns)
424
    {
425
      if (di.insn_info_valid)
426
        *branch_delay_insns = di.branch_delay_insns;
427
      else
428
        *branch_delay_insns = 0;
429
    }
430
  return length;
431
}

powered by: WebSVN 2.1.0

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