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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 330 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
 
68
  print_address (gdbarch, addr, info->stream);
69
}
70
 
71
static int
72
compare_lines (const void *mle1p, const void *mle2p)
73
{
74
  struct dis_line_entry *mle1, *mle2;
75
  int val;
76
 
77
  mle1 = (struct dis_line_entry *) mle1p;
78
  mle2 = (struct dis_line_entry *) mle2p;
79
 
80
  val = mle1->line - mle2->line;
81
 
82
  if (val != 0)
83
    return val;
84
 
85
  return mle1->start_pc - mle2->start_pc;
86
}
87
 
88
static int
89
dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
90
            struct disassemble_info * di,
91
            CORE_ADDR low, CORE_ADDR high,
92
            int how_many, int flags, struct ui_stream *stb)
93
{
94
  int num_displayed = 0;
95
  CORE_ADDR pc;
96
 
97
  /* parts of the symbolic representation of the address */
98
  int unmapped;
99
  int offset;
100
  int line;
101
  struct cleanup *ui_out_chain;
102
 
103
  for (pc = low; pc < high;)
104
    {
105
      char *filename = NULL;
106
      char *name = NULL;
107
 
108
      QUIT;
109
      if (how_many >= 0)
110
        {
111
          if (num_displayed >= how_many)
112
            break;
113
          else
114
            num_displayed++;
115
        }
116
      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
117
      ui_out_text (uiout, pc_prefix (pc));
118
      ui_out_field_core_addr (uiout, "address", gdbarch, pc);
119
 
120
      if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
121
                                   &line, &unmapped))
122
        {
123
          /* We don't care now about line, filename and
124
             unmapped. But we might in the future. */
125
          ui_out_text (uiout, " <");
126
          if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
127
            ui_out_field_string (uiout, "func-name", name);
128
          ui_out_text (uiout, "+");
129
          ui_out_field_int (uiout, "offset", offset);
130
          ui_out_text (uiout, ">:\t");
131
        }
132
      else
133
        ui_out_text (uiout, ":\t");
134
 
135
      if (filename != NULL)
136
        xfree (filename);
137
      if (name != NULL)
138
        xfree (name);
139
 
140
      ui_file_rewind (stb->stream);
141
      if (flags & DISASSEMBLY_RAW_INSN)
142
        {
143
          CORE_ADDR old_pc = pc;
144
          bfd_byte data;
145
          int status;
146
 
147
          pc += gdbarch_print_insn (gdbarch, pc, di);
148
          for (;old_pc < pc; old_pc++)
149
            {
150
              status = (*di->read_memory_func) (old_pc, &data, 1, di);
151
              if (status != 0)
152
                (*di->memory_error_func) (status, old_pc, di);
153
              ui_out_message (uiout, 0, " %02x", (unsigned)data);
154
            }
155
          ui_out_text (uiout, "\t");
156
        }
157
      else
158
        pc += gdbarch_print_insn (gdbarch, pc, di);
159
      ui_out_field_stream (uiout, "inst", stb);
160
      ui_file_rewind (stb->stream);
161
      do_cleanups (ui_out_chain);
162
      ui_out_text (uiout, "\n");
163
    }
164
  return num_displayed;
165
}
166
 
167
/* The idea here is to present a source-O-centric view of a
168
   function to the user.  This means that things are presented
169
   in source order, with (possibly) out of order assembly
170
   immediately following.  */
171
static void
172
do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
173
                              struct disassemble_info *di, int nlines,
174
                              struct linetable_entry *le,
175
                              CORE_ADDR low, CORE_ADDR high,
176
                              struct symtab *symtab,
177
                              int how_many, int flags, struct ui_stream *stb)
178
{
179
  int newlines = 0;
180
  struct dis_line_entry *mle;
181
  struct symtab_and_line sal;
182
  int i;
183
  int out_of_order = 0;
184
  int next_line = 0;
185
  int num_displayed = 0;
186
  struct cleanup *ui_out_chain;
187
  struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
188
  struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
189
 
190
  mle = (struct dis_line_entry *) alloca (nlines
191
                                          * sizeof (struct dis_line_entry));
192
 
193
  /* Copy linetable entries for this function into our data
194
     structure, creating end_pc's and setting out_of_order as
195
     appropriate.  */
196
 
197
  /* First, skip all the preceding functions.  */
198
 
199
  for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
200
 
201
  /* Now, copy all entries before the end of this function.  */
202
 
203
  for (; i < nlines - 1 && le[i].pc < high; i++)
204
    {
205
      if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
206
        continue;               /* Ignore duplicates */
207
 
208
      /* Skip any end-of-function markers.  */
209
      if (le[i].line == 0)
210
        continue;
211
 
212
      mle[newlines].line = le[i].line;
213
      if (le[i].line > le[i + 1].line)
214
        out_of_order = 1;
215
      mle[newlines].start_pc = le[i].pc;
216
      mle[newlines].end_pc = le[i + 1].pc;
217
      newlines++;
218
    }
219
 
220
  /* If we're on the last line, and it's part of the function,
221
     then we need to get the end pc in a special way.  */
222
 
223
  if (i == nlines - 1 && le[i].pc < high)
224
    {
225
      mle[newlines].line = le[i].line;
226
      mle[newlines].start_pc = le[i].pc;
227
      sal = find_pc_line (le[i].pc, 0);
228
      mle[newlines].end_pc = sal.end;
229
      newlines++;
230
    }
231
 
232
  /* Now, sort mle by line #s (and, then by addresses within
233
     lines). */
234
 
235
  if (out_of_order)
236
    qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
237
 
238
  /* Now, for each line entry, emit the specified lines (unless
239
     they have been emitted before), followed by the assembly code
240
     for that line.  */
241
 
242
  ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
243
 
244
  for (i = 0; i < newlines; i++)
245
    {
246
      /* Print out everything from next_line to the current line.  */
247
      if (mle[i].line >= next_line)
248
        {
249
          if (next_line != 0)
250
            {
251
              /* Just one line to print. */
252
              if (next_line == mle[i].line)
253
                {
254
                  ui_out_tuple_chain
255
                    = make_cleanup_ui_out_tuple_begin_end (uiout,
256
                                                           "src_and_asm_line");
257
                  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
258
                }
259
              else
260
                {
261
                  /* Several source lines w/o asm instructions associated. */
262
                  for (; next_line < mle[i].line; next_line++)
263
                    {
264
                      struct cleanup *ui_out_list_chain_line;
265
                      struct cleanup *ui_out_tuple_chain_line;
266
 
267
                      ui_out_tuple_chain_line
268
                        = make_cleanup_ui_out_tuple_begin_end (uiout,
269
                                                               "src_and_asm_line");
270
                      print_source_lines (symtab, next_line, next_line + 1,
271
                                          0);
272
                      ui_out_list_chain_line
273
                        = make_cleanup_ui_out_list_begin_end (uiout,
274
                                                              "line_asm_insn");
275
                      do_cleanups (ui_out_list_chain_line);
276
                      do_cleanups (ui_out_tuple_chain_line);
277
                    }
278
                  /* Print the last line and leave list open for
279
                     asm instructions to be added. */
280
                  ui_out_tuple_chain
281
                    = make_cleanup_ui_out_tuple_begin_end (uiout,
282
                                                           "src_and_asm_line");
283
                  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
284
                }
285
            }
286
          else
287
            {
288
              ui_out_tuple_chain
289
                = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
290
              print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
291
            }
292
 
293
          next_line = mle[i].line + 1;
294
          ui_out_list_chain
295
            = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
296
        }
297
 
298
      num_displayed += dump_insns (gdbarch, uiout, di,
299
                                   mle[i].start_pc, mle[i].end_pc,
300
                                   how_many, flags, stb);
301
 
302
      /* When we've reached the end of the mle array, or we've seen the last
303
         assembly range for this source line, close out the list/tuple.  */
304
      if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
305
        {
306
          do_cleanups (ui_out_list_chain);
307
          do_cleanups (ui_out_tuple_chain);
308
          ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
309
          ui_out_list_chain = make_cleanup (null_cleanup, 0);
310
          ui_out_text (uiout, "\n");
311
        }
312
      if (how_many >= 0 && num_displayed >= how_many)
313
        break;
314
    }
315
  do_cleanups (ui_out_chain);
316
}
317
 
318
 
319
static void
320
do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
321
                  struct disassemble_info * di,
322
                  CORE_ADDR low, CORE_ADDR high,
323
                  int how_many, int flags, struct ui_stream *stb)
324
{
325
  int num_displayed = 0;
326
  struct cleanup *ui_out_chain;
327
 
328
  ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
329
 
330
  num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
331
                              flags, stb);
332
 
333
  do_cleanups (ui_out_chain);
334
}
335
 
336
/* Initialize the disassemble info struct ready for the specified
337
   stream.  */
338
 
339
static int ATTRIBUTE_PRINTF (2, 3)
340
fprintf_disasm (void *stream, const char *format, ...)
341
{
342
  va_list args;
343
 
344
  va_start (args, format);
345
  vfprintf_filtered (stream, format, args);
346
  va_end (args);
347
  /* Something non -ve.  */
348
  return 0;
349
}
350
 
351
static struct disassemble_info
352
gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
353
{
354
  struct disassemble_info di;
355
 
356
  init_disassemble_info (&di, file, fprintf_disasm);
357
  di.flavour = bfd_target_unknown_flavour;
358
  di.memory_error_func = dis_asm_memory_error;
359
  di.print_address_func = dis_asm_print_address;
360
  /* NOTE: cagney/2003-04-28: The original code, from the old Insight
361
     disassembler had a local optomization here.  By default it would
362
     access the executable file, instead of the target memory (there
363
     was a growing list of exceptions though).  Unfortunately, the
364
     heuristic was flawed.  Commands like "disassemble &variable"
365
     didn't work as they relied on the access going to the target.
366
     Further, it has been supperseeded by trust-read-only-sections
367
     (although that should be superseeded by target_trust..._p()).  */
368
  di.read_memory_func = dis_asm_read_memory;
369
  di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
370
  di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
371
  di.endian = gdbarch_byte_order (gdbarch);
372
  di.endian_code = gdbarch_byte_order_for_code (gdbarch);
373
  di.application_data = gdbarch;
374
  disassemble_init_for_target (&di);
375
  return di;
376
}
377
 
378
void
379
gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
380
                 char *file_string, int flags, int how_many,
381
                 CORE_ADDR low, CORE_ADDR high)
382
{
383
  struct ui_stream *stb = ui_out_stream_new (uiout);
384
  struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
385
  struct disassemble_info di = gdb_disassemble_info (gdbarch, stb->stream);
386
  /* To collect the instruction outputted from opcodes. */
387
  struct symtab *symtab = NULL;
388
  struct linetable_entry *le = NULL;
389
  int nlines = -1;
390
 
391
  /* Assume symtab is valid for whole PC range */
392
  symtab = find_pc_symtab (low);
393
 
394
  if (symtab != NULL && symtab->linetable != NULL)
395
    {
396
      /* Convert the linetable to a bunch of my_line_entry's.  */
397
      le = symtab->linetable->item;
398
      nlines = symtab->linetable->nitems;
399
    }
400
 
401
  if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
402
      || symtab == NULL || symtab->linetable == NULL)
403
    do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
404
 
405
  else if (flags & DISASSEMBLY_SOURCE)
406
    do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
407
                                  high, symtab, how_many, flags, stb);
408
 
409
  do_cleanups (cleanups);
410
  gdb_flush (gdb_stdout);
411
}
412
 
413
/* Print the instruction at address MEMADDR in debugged memory,
414
   on STREAM.  Returns the length of the instruction, in bytes,
415
   and, if requested, the number of branch delay slot instructions.  */
416
 
417
int
418
gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
419
                struct ui_file *stream, int *branch_delay_insns)
420
{
421
  struct disassemble_info di;
422
  int length;
423
 
424
  di = gdb_disassemble_info (gdbarch, stream);
425
  length = gdbarch_print_insn (gdbarch, memaddr, &di);
426
  if (branch_delay_insns)
427
    {
428
      if (di.insn_info_valid)
429
        *branch_delay_insns = di.branch_delay_insns;
430
      else
431
        *branch_delay_insns = 0;
432
    }
433
  return length;
434
}
435
 
436
static void
437
do_ui_file_delete (void *arg)
438
{
439
  ui_file_delete (arg);
440
}
441
 
442
/* Return the length in bytes of the instruction at address MEMADDR in
443
   debugged memory.  */
444
 
445
int
446
gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
447
{
448
  static struct ui_file *null_stream = NULL;
449
 
450
  /* Dummy file descriptor for the disassembler.  */
451
  if (!null_stream)
452
    {
453
      null_stream = ui_file_new ();
454
      make_final_cleanup (do_ui_file_delete, null_stream);
455
    }
456
 
457
  return gdb_print_insn (gdbarch, addr, null_stream, NULL);
458
}
459
 
460
/* fprintf-function for gdb_buffered_insn_length.  This function is a
461
   nop, we don't want to print anything, we just want to compute the
462
   length of the insn.  */
463
 
464
static int ATTRIBUTE_PRINTF (2, 3)
465
gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
466
{
467
  return 0;
468
}
469
 
470
/* Initialize a struct disassemble_info for gdb_buffered_insn_length.  */
471
 
472
static void
473
gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
474
                                   struct disassemble_info *di,
475
                                   const gdb_byte *insn, int max_len,
476
                                   CORE_ADDR addr)
477
{
478
  init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
479
 
480
  /* init_disassemble_info installs buffer_read_memory, etc.
481
     so we don't need to do that here.
482
     The cast is necessary until disassemble_info is const-ified.  */
483
  di->buffer = (gdb_byte *) insn;
484
  di->buffer_length = max_len;
485
  di->buffer_vma = addr;
486
 
487
  di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
488
  di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
489
  di->endian = gdbarch_byte_order (gdbarch);
490
  di->endian_code = gdbarch_byte_order_for_code (gdbarch);
491
 
492
  disassemble_init_for_target (di);
493
}
494
 
495
/* Return the length in bytes of INSN.  MAX_LEN is the size of the
496
   buffer containing INSN.  */
497
 
498
int
499
gdb_buffered_insn_length (struct gdbarch *gdbarch,
500
                          const gdb_byte *insn, int max_len, CORE_ADDR addr)
501
{
502
  struct disassemble_info di;
503
 
504
  gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
505
 
506
  return gdbarch_print_insn (gdbarch, addr, &di);
507
}

powered by: WebSVN 2.1.0

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