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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [mi/] [mi-cmd-disas.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 106 markom
/* MI Command Set - disassemble commands.
2
   Copyright (C) 2000, Free Software Foundation, Inc.
3
   Contributed by Cygnus Solutions (a Red Hat company).
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place - Suite 330,
20
   Boston, MA 02111-1307, USA.  */
21
 
22
#include "defs.h"
23
#include "target.h"
24
#include "value.h"
25
#include "mi-cmds.h"
26
#include "mi-getopt.h"
27
#include "ui-out.h"
28
 
29
static int gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr, unsigned int len,
30
                                    disassemble_info * info);
31
static int compare_lines (const PTR mle1p, const PTR mle2p);
32
 
33
/* Disassemble functions. FIXME: these do not really belong here. We
34
   should get rid of all the duplicate code in gdb that does the same
35
   thing: disassemble_command() and the gdbtk variation. */
36
 
37
/* This Structure is used in mi_cmd_disassemble.
38
   We need a different sort of line table from the normal one cuz we can't
39
   depend upon implicit line-end pc's for lines to do the
40
   reordering in this function.  */
41
 
42
struct dis_line_entry
43
  {
44
    int line;
45
    CORE_ADDR start_pc;
46
    CORE_ADDR end_pc;
47
  };
48
 
49
/* This variable determines where memory used for disassembly is read from. */
50
int gdb_disassemble_from_exec = -1;
51
 
52
/* This is the memory_read_func for gdb_disassemble when we are
53
   disassembling from the exec file. */
54
static int
55
gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr,
56
                         unsigned int len, disassemble_info * info)
57
{
58
  extern struct target_ops exec_ops;
59
  int res;
60
 
61
  errno = 0;
62
  res = xfer_memory (memaddr, myaddr, len, 0, &exec_ops);
63
 
64
  if (res == len)
65
    return 0;
66
  else if (errno == 0)
67
    return EIO;
68
  else
69
    return errno;
70
}
71
 
72
static int
73
compare_lines (const PTR mle1p, const PTR mle2p)
74
{
75
  struct dis_line_entry *mle1, *mle2;
76
  int val;
77
 
78
  mle1 = (struct dis_line_entry *) mle1p;
79
  mle2 = (struct dis_line_entry *) mle2p;
80
 
81
  val = mle1->line - mle2->line;
82
 
83
  if (val != 0)
84
    return val;
85
 
86
  return mle1->start_pc - mle2->start_pc;
87
}
88
 
89
/* The arguments to be passed on the command line and parsed here are:
90
 
91
   either:
92
 
93
   START-ADDRESS: address to start the disassembly at.
94
   END-ADDRESS: address to end the disassembly at.
95
 
96
   or:
97
 
98
   FILENAME: The name of the file where we want disassemble from.
99
   LINE: The line around which we want to disassemble. It will
100
   disassemble the function that contins that line.
101
   HOW_MANY: Number of disassembly lines to display. In mixed mode, it
102
   is the number of disassembly lines only, not counting the source
103
   lines.
104
 
105
   always required:
106
 
107
   MODE: 0 or 1 for disassembly only, or mixed source and disassembly,
108
   respectively. */
109
 
110
enum mi_cmd_result
111
mi_cmd_disassemble (char *command, char **argv, int argc)
112
{
113
  CORE_ADDR pc;
114
  CORE_ADDR start;
115
  CORE_ADDR low = 0;
116
  CORE_ADDR high = 0;
117
 
118
  int how_many = -1;
119
  int mixed_source_and_assembly;
120
  int num_displayed;
121
  int line_num;
122
 
123
  char *file_string;
124
  static disassemble_info di;
125
  static int di_initialized;
126
 
127
  struct symtab *s;
128
 
129
  /* To collect the instruction outputted from opcodes. */
130
  static struct ui_stream *stb = NULL;
131
 
132
  /* parts of the symbolic representation of the address */
133
  int line;
134
  int offset;
135
  int unmapped;
136
  char *filename = NULL;
137
  char *name = NULL;
138
 
139
  /* Which options have we processed? */
140
  int file_seen = 0;
141
  int line_seen = 0;
142
  int num_seen = 0;
143
  int start_seen = 0;
144
  int end_seen = 0;
145
 
146
  /* Options processing stuff. */
147
  int optind = 0;
148
  char *optarg;
149
  enum opt
150
    {
151
      FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT
152
    };
153
  static struct mi_opt opts[] =
154
  {
155
    {"f", FILE_OPT, 1},
156
    {"l", LINE_OPT, 1},
157
    {"n", NUM_OPT, 1},
158
    {"s", START_OPT, 1},
159
    {"e", END_OPT, 1},
160
 
161
  };
162
 
163
  /* Get the options with their arguments. Keep track of what we
164
     encountered. */
165
  while (1)
166
    {
167
      int opt = mi_getopt ("mi_cmd_disassemble", argc, argv, opts,
168
                           &optind, &optarg);
169
      if (opt < 0)
170
        break;
171
      switch ((enum opt) opt)
172
        {
173
        case FILE_OPT:
174
          file_string = xstrdup (optarg);
175
          file_seen = 1;
176
          break;
177
        case LINE_OPT:
178
          line_num = atoi (optarg);
179
          line_seen = 1;
180
          break;
181
        case NUM_OPT:
182
          how_many = atoi (optarg);
183
          num_seen = 1;
184
          break;
185
        case START_OPT:
186
          low = parse_and_eval_address (optarg);
187
          start_seen = 1;
188
          break;
189
        case END_OPT:
190
          high = parse_and_eval_address (optarg);
191
          end_seen = 1;
192
          break;
193
        }
194
    }
195
  argv += optind;
196
  argc -= optind;
197
 
198
  /* Allow only filename + linenum (with how_many which is not
199
     required) OR start_addr + and_addr */
200
 
201
  if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen)
202
        || (line_seen && file_seen && !num_seen && !start_seen && !end_seen)
203
      || (!line_seen && !file_seen && !num_seen && start_seen && end_seen)))
204
    error ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode.");
205
 
206
  if (argc != 1)
207
    error ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode.");
208
 
209
  mixed_source_and_assembly = atoi (argv[0]);
210
  if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1))
211
    error ("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.");
212
 
213
  /* We must get the function beginning and end where line_num is
214
     contained. */
215
 
216
  if (line_seen && file_seen)
217
    {
218
      s = lookup_symtab (file_string);
219
      if (s == NULL)
220
        error ("mi_cmd_disassemble: Invalid filename.");
221
      if (!find_line_pc (s, line_num, &start))
222
        error ("mi_cmd_disassemble: Invalid line number");
223
      if (find_pc_partial_function (start, NULL, &low, &high) == 0)
224
        error ("mi_cmd_disassemble: No function contains specified address");
225
    }
226
 
227
  if (!di_initialized)
228
    {
229
      /* We don't add a cleanup for this, because the allocation of
230
         the stream is done once only for each gdb run, and we need to
231
         keep it around until the end. Hopefully there won't be any
232
         errors in the init code below, that make this function bail
233
         out. */
234
      stb = ui_out_stream_new (uiout);
235
      INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream,
236
                                     (fprintf_ftype) fprintf_unfiltered);
237
      di.flavour = bfd_target_unknown_flavour;
238
      di.memory_error_func = dis_asm_memory_error;
239
      di.print_address_func = dis_asm_print_address;
240
      di_initialized = 1;
241
    }
242
 
243
  di.mach = TARGET_PRINT_INSN_INFO->mach;
244
  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
245
    di.endian = BFD_ENDIAN_BIG;
246
  else
247
    di.endian = BFD_ENDIAN_LITTLE;
248
 
249
  /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
250
     determine whether or not to do disassembly from target memory or from the
251
     exec file:
252
 
253
     If we're debugging a local process, read target memory, instead of the
254
     exec file.  This makes disassembly of functions in shared libs work
255
     correctly.  Also, read target memory if we are debugging native threads.
256
 
257
     Else, we're debugging a remote process, and should disassemble from the
258
     exec file for speed.  However, this is no good if the target modifies its
259
     code (for relocation, or whatever).
260
   */
261
 
262
  if (gdb_disassemble_from_exec == -1)
263
    {
264
      if (strcmp (target_shortname, "child") == 0
265
          || strcmp (target_shortname, "procfs") == 0
266
          || strcmp (target_shortname, "vxprocess") == 0
267
          || strstr (target_shortname, "-threads") != NULL)
268
        gdb_disassemble_from_exec = 0;   /* It's a child process, read inferior mem */
269
      else
270
        gdb_disassemble_from_exec = 1;  /* It's remote, read the exec file */
271
    }
272
 
273
  if (gdb_disassemble_from_exec)
274
    di.read_memory_func = gdb_dis_asm_read_memory;
275
  else
276
    di.read_memory_func = dis_asm_read_memory;
277
 
278
  /* If just doing straight assembly, all we need to do is disassemble
279
     everything between low and high.  If doing mixed source/assembly,
280
     we've got a totally different path to follow.  */
281
 
282
  if (mixed_source_and_assembly)
283
    {
284
      /* Come here for mixed source/assembly */
285
      /* The idea here is to present a source-O-centric view of a
286
         function to the user.  This means that things are presented
287
         in source order, with (possibly) out of order assembly
288
         immediately following.  */
289
      struct symtab *symtab;
290
      struct linetable_entry *le;
291
      int nlines;
292
      int newlines;
293
      struct dis_line_entry *mle;
294
      struct symtab_and_line sal;
295
      int i;
296
      int out_of_order;
297
      int next_line;
298
 
299
      /* Assume symtab is valid for whole PC range */
300
      symtab = find_pc_symtab (low);
301
 
302
      if (!symtab || !symtab->linetable)
303
        goto assembly_only;
304
 
305
      /* First, convert the linetable to a bunch of my_line_entry's.  */
306
 
307
      le = symtab->linetable->item;
308
      nlines = symtab->linetable->nitems;
309
 
310
      if (nlines <= 0)
311
        goto assembly_only;
312
 
313
      mle = (struct dis_line_entry *) alloca (nlines * sizeof (struct dis_line_entry));
314
 
315
      out_of_order = 0;
316
 
317
      /* Copy linetable entries for this function into our data
318
         structure, creating end_pc's and setting out_of_order as
319
         appropriate.  */
320
 
321
      /* First, skip all the preceding functions.  */
322
 
323
      for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
324
 
325
      /* Now, copy all entries before the end of this function.  */
326
 
327
      newlines = 0;
328
      for (; i < nlines - 1 && le[i].pc < high; i++)
329
        {
330
          if (le[i].line == le[i + 1].line
331
              && le[i].pc == le[i + 1].pc)
332
            continue;           /* Ignore duplicates */
333
 
334
          mle[newlines].line = le[i].line;
335
          if (le[i].line > le[i + 1].line)
336
            out_of_order = 1;
337
          mle[newlines].start_pc = le[i].pc;
338
          mle[newlines].end_pc = le[i + 1].pc;
339
          newlines++;
340
        }
341
 
342
      /* If we're on the last line, and it's part of the function,
343
         then we need to get the end pc in a special way.  */
344
 
345
      if (i == nlines - 1
346
          && le[i].pc < high)
347
        {
348
          mle[newlines].line = le[i].line;
349
          mle[newlines].start_pc = le[i].pc;
350
          sal = find_pc_line (le[i].pc, 0);
351
          mle[newlines].end_pc = sal.end;
352
          newlines++;
353
        }
354
 
355
      /* Now, sort mle by line #s (and, then by addresses within
356
         lines). */
357
 
358
      if (out_of_order)
359
        qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
360
 
361
      /* Now, for each line entry, emit the specified lines (unless
362
         they have been emitted before), followed by the assembly code
363
         for that line.  */
364
 
365
      next_line = 0;             /* Force out first line */
366
      ui_out_list_begin (uiout, "asm_insns");
367
      num_displayed = 0;
368
      for (i = 0; i < newlines; i++)
369
        {
370
          int close_list = 1;
371
          /* Print out everything from next_line to the current line.  */
372
          if (mle[i].line >= next_line)
373
            {
374
              if (next_line != 0)
375
                {
376
                  /* Just one line to print. */
377
                  if (next_line == mle[i].line)
378
                    {
379
                      ui_out_list_begin (uiout, "src_and_asm_line");
380
                      print_source_lines (symtab, next_line, mle[i].line + 1, 0);
381
                    }
382
                  else
383
                    {
384
                      /* Several source lines w/o asm instructions associated. */
385
                      for (; next_line < mle[i].line; next_line++)
386
                        {
387
                          ui_out_list_begin (uiout, "src_and_asm_line");
388
                          print_source_lines (symtab, next_line, mle[i].line + 1, 0);
389
                          ui_out_list_begin (uiout, "line_asm_insn");
390
                          ui_out_list_end (uiout);
391
                          ui_out_list_end (uiout);
392
                        }
393
                      /* Print the last line and leave list open for
394
                         asm instructions to be added. */
395
                      ui_out_list_begin (uiout, "src_and_asm_line");
396
                      print_source_lines (symtab, next_line, mle[i].line + 1, 0);
397
                    }
398
                }
399
              else
400
                {
401
                  ui_out_list_begin (uiout, "src_and_asm_line");
402
                  print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
403
                }
404
 
405
              next_line = mle[i].line + 1;
406
              ui_out_list_begin (uiout, "line_asm_insn");
407
              if (i + 1 < newlines && mle[i + 1].line <= mle[i].line)
408
                close_list = 0;
409
            }
410
          for (pc = mle[i].start_pc; pc < mle[i].end_pc;)
411
            {
412
              QUIT;
413
              if (how_many >= 0)
414
                {
415
                  if (num_displayed >= how_many)
416
                    break;
417
                  else
418
                    num_displayed++;
419
                }
420
              ui_out_list_begin (uiout, NULL);
421
              ui_out_field_core_addr (uiout, "address", pc);
422
 
423
              if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped))
424
                {
425
                  /* We don't care now about line, filename and
426
                     unmapped, but we might in the future. */
427
                  ui_out_field_string (uiout, "func-name", name);
428
                  ui_out_field_int (uiout, "offset", offset);
429
                }
430
              if (filename != NULL)
431
                free (filename);
432
              if (name != NULL)
433
                free (name);
434
 
435
              ui_file_rewind (stb->stream);
436
              pc += (*tm_print_insn) (pc, &di);
437
              ui_out_field_stream (uiout, "inst", stb);
438
              ui_file_rewind (stb->stream);
439
              ui_out_list_end (uiout);
440
            }
441
          if (close_list)
442
            {
443
              ui_out_list_end (uiout);
444
              ui_out_list_end (uiout);
445
              close_list = 0;
446
            }
447
          if (how_many >= 0)
448
            if (num_displayed >= how_many)
449
              break;
450
        }
451
      ui_out_list_end (uiout);
452
    }
453
  else
454
    {
455
    assembly_only:
456
      ui_out_list_begin (uiout, "asm_insns");
457
      num_displayed = 0;
458
      for (pc = low; pc < high;)
459
        {
460
          QUIT;
461
          if (how_many >= 0)
462
            {
463
              if (num_displayed >= how_many)
464
                break;
465
              else
466
                num_displayed++;
467
            }
468
          ui_out_list_begin (uiout, NULL);
469
          ui_out_field_core_addr (uiout, "address", pc);
470
 
471
          if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped))
472
            {
473
              /* We don't care now about line, filename and
474
                 unmapped. But we might in the future. */
475
              ui_out_field_string (uiout, "func-name", name);
476
              ui_out_field_int (uiout, "offset", offset);
477
            }
478
          if (filename != NULL)
479
            free (filename);
480
          if (name != NULL)
481
            free (name);
482
 
483
          ui_file_rewind (stb->stream);
484
          pc += (*tm_print_insn) (pc, &di);
485
          ui_out_field_stream (uiout, "inst", stb);
486
          ui_file_rewind (stb->stream);
487
          ui_out_list_end (uiout);
488
        }
489
      ui_out_list_end (uiout);
490
    }
491
  gdb_flush (gdb_stdout);
492
 
493
  return MI_CMD_DONE;
494
}
495
 
496
/* Local variables: */
497
/* change-log-default-name: "ChangeLog-mi" */
498
/* End: */

powered by: WebSVN 2.1.0

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