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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* MI Command Set - disassemble commands.
2
   Copyright 2000, 2001 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, 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
 
116
  int mixed_source_and_assembly;
117
  int num_displayed;
118
  static disassemble_info di;
119
  static int di_initialized;
120
 
121
  struct symtab *s;
122
 
123
  /* To collect the instruction outputted from opcodes. */
124
  static struct ui_stream *stb = NULL;
125
 
126
  /* parts of the symbolic representation of the address */
127
  int line;
128
  int offset;
129
  int unmapped;
130
  char *filename = NULL;
131
  char *name = NULL;
132
 
133
  /* Which options have we processed ... */
134
  int file_seen = 0;
135
  int line_seen = 0;
136
  int num_seen = 0;
137
  int start_seen = 0;
138
  int end_seen = 0;
139
 
140
  /* ... and their corresponding value. */
141
  char *file_string = NULL;
142
  int line_num = -1;
143
  int how_many = -1;
144
  CORE_ADDR low = 0;
145
  CORE_ADDR high = 0;
146
 
147
  /* Options processing stuff. */
148
  int optind = 0;
149
  char *optarg;
150
  enum opt
151
    {
152
      FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT
153
    };
154
  static struct mi_opt opts[] =
155
  {
156
    {"f", FILE_OPT, 1},
157
    {"l", LINE_OPT, 1},
158
    {"n", NUM_OPT, 1},
159
    {"s", START_OPT, 1},
160
    {"e", END_OPT, 1},
161
 
162
  };
163
 
164
  /* Get the options with their arguments. Keep track of what we
165
     encountered. */
166
  while (1)
167
    {
168
      int opt = mi_getopt ("mi_cmd_disassemble", argc, argv, opts,
169
                           &optind, &optarg);
170
      if (opt < 0)
171
        break;
172
      switch ((enum opt) opt)
173
        {
174
        case FILE_OPT:
175
          file_string = xstrdup (optarg);
176
          file_seen = 1;
177
          break;
178
        case LINE_OPT:
179
          line_num = atoi (optarg);
180
          line_seen = 1;
181
          break;
182
        case NUM_OPT:
183
          how_many = atoi (optarg);
184
          num_seen = 1;
185
          break;
186
        case START_OPT:
187
          low = parse_and_eval_address (optarg);
188
          start_seen = 1;
189
          break;
190
        case END_OPT:
191
          high = parse_and_eval_address (optarg);
192
          end_seen = 1;
193
          break;
194
        }
195
    }
196
  argv += optind;
197
  argc -= optind;
198
 
199
  /* Allow only filename + linenum (with how_many which is not
200
     required) OR start_addr + and_addr */
201
 
202
  if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen)
203
        || (line_seen && file_seen && !num_seen && !start_seen && !end_seen)
204
      || (!line_seen && !file_seen && !num_seen && start_seen && end_seen)))
205
    error ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode.");
206
 
207
  if (argc != 1)
208
    error ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode.");
209
 
210
  mixed_source_and_assembly = atoi (argv[0]);
211
  if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1))
212
    error ("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.");
213
 
214
  /* We must get the function beginning and end where line_num is
215
     contained. */
216
 
217
  if (line_seen && file_seen)
218
    {
219
      s = lookup_symtab (file_string);
220
      if (s == NULL)
221
        error ("mi_cmd_disassemble: Invalid filename.");
222
      if (!find_line_pc (s, line_num, &start))
223
        error ("mi_cmd_disassemble: Invalid line number");
224
      if (find_pc_partial_function (start, NULL, &low, &high) == 0)
225
        error ("mi_cmd_disassemble: No function contains specified address");
226
    }
227
 
228
  if (!di_initialized)
229
    {
230
      /* We don't add a cleanup for this, because the allocation of
231
         the stream is done once only for each gdb run, and we need to
232
         keep it around until the end. Hopefully there won't be any
233
         errors in the init code below, that make this function bail
234
         out. */
235
      stb = ui_out_stream_new (uiout);
236
      INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream,
237
                                     (fprintf_ftype) fprintf_unfiltered);
238
      di.flavour = bfd_target_unknown_flavour;
239
      di.memory_error_func = dis_asm_memory_error;
240
      di.print_address_func = dis_asm_print_address;
241
      di_initialized = 1;
242
    }
243
 
244
  di.mach = TARGET_PRINT_INSN_INFO->mach;
245
  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
246
    di.endian = BFD_ENDIAN_BIG;
247
  else
248
    di.endian = BFD_ENDIAN_LITTLE;
249
 
250
  /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
251
     determine whether or not to do disassembly from target memory or from the
252
     exec file:
253
 
254
     If we're debugging a local process, read target memory, instead of the
255
     exec file.  This makes disassembly of functions in shared libs work
256
     correctly.  Also, read target memory if we are debugging native threads.
257
 
258
     Else, we're debugging a remote process, and should disassemble from the
259
     exec file for speed.  However, this is no good if the target modifies its
260
     code (for relocation, or whatever).
261
   */
262
 
263
  if (gdb_disassemble_from_exec == -1)
264
    {
265
      if (strcmp (target_shortname, "child") == 0
266
          || strcmp (target_shortname, "procfs") == 0
267
          || strcmp (target_shortname, "vxprocess") == 0
268
          || strstr (target_shortname, "-threads") != NULL)
269
        gdb_disassemble_from_exec = 0;   /* It's a child process, read inferior mem */
270
      else
271
        gdb_disassemble_from_exec = 1;  /* It's remote, read the exec file */
272
    }
273
 
274
  if (gdb_disassemble_from_exec)
275
    di.read_memory_func = gdb_dis_asm_read_memory;
276
  else
277
    di.read_memory_func = dis_asm_read_memory;
278
 
279
  /* If just doing straight assembly, all we need to do is disassemble
280
     everything between low and high.  If doing mixed source/assembly,
281
     we've got a totally different path to follow.  */
282
 
283
  if (mixed_source_and_assembly)
284
    {
285
      /* Come here for mixed source/assembly */
286
      /* The idea here is to present a source-O-centric view of a
287
         function to the user.  This means that things are presented
288
         in source order, with (possibly) out of order assembly
289
         immediately following.  */
290
      struct symtab *symtab;
291
      struct linetable_entry *le;
292
      int nlines;
293
      int newlines;
294
      struct dis_line_entry *mle;
295
      struct symtab_and_line sal;
296
      int i;
297
      int out_of_order;
298
      int next_line;
299
 
300
      /* Assume symtab is valid for whole PC range */
301
      symtab = find_pc_symtab (low);
302
 
303
      if (!symtab || !symtab->linetable)
304
        goto assembly_only;
305
 
306
      /* First, convert the linetable to a bunch of my_line_entry's.  */
307
 
308
      le = symtab->linetable->item;
309
      nlines = symtab->linetable->nitems;
310
 
311
      if (nlines <= 0)
312
        goto assembly_only;
313
 
314
      mle = (struct dis_line_entry *) alloca (nlines * sizeof (struct dis_line_entry));
315
 
316
      out_of_order = 0;
317
 
318
      /* Copy linetable entries for this function into our data
319
         structure, creating end_pc's and setting out_of_order as
320
         appropriate.  */
321
 
322
      /* First, skip all the preceding functions.  */
323
 
324
      for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
325
 
326
      /* Now, copy all entries before the end of this function.  */
327
 
328
      newlines = 0;
329
      for (; i < nlines - 1 && le[i].pc < high; i++)
330
        {
331
          if (le[i].line == le[i + 1].line
332
              && le[i].pc == le[i + 1].pc)
333
            continue;           /* Ignore duplicates */
334
 
335
          mle[newlines].line = le[i].line;
336
          if (le[i].line > le[i + 1].line)
337
            out_of_order = 1;
338
          mle[newlines].start_pc = le[i].pc;
339
          mle[newlines].end_pc = le[i + 1].pc;
340
          newlines++;
341
        }
342
 
343
      /* If we're on the last line, and it's part of the function,
344
         then we need to get the end pc in a special way.  */
345
 
346
      if (i == nlines - 1
347
          && le[i].pc < high)
348
        {
349
          mle[newlines].line = le[i].line;
350
          mle[newlines].start_pc = le[i].pc;
351
          sal = find_pc_line (le[i].pc, 0);
352
          mle[newlines].end_pc = sal.end;
353
          newlines++;
354
        }
355
 
356
      /* Now, sort mle by line #s (and, then by addresses within
357
         lines). */
358
 
359
      if (out_of_order)
360
        qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
361
 
362
      /* Now, for each line entry, emit the specified lines (unless
363
         they have been emitted before), followed by the assembly code
364
         for that line.  */
365
 
366
      next_line = 0;             /* Force out first line */
367
      ui_out_list_begin (uiout, "asm_insns");
368
      num_displayed = 0;
369
      for (i = 0; i < newlines; i++)
370
        {
371
          int close_list = 1;
372
          /* Print out everything from next_line to the current line.  */
373
          if (mle[i].line >= next_line)
374
            {
375
              if (next_line != 0)
376
                {
377
                  /* Just one line to print. */
378
                  if (next_line == mle[i].line)
379
                    {
380
                      ui_out_tuple_begin (uiout, "src_and_asm_line");
381
                      print_source_lines (symtab, next_line, mle[i].line + 1, 0);
382
                    }
383
                  else
384
                    {
385
                      /* Several source lines w/o asm instructions associated. */
386
                      for (; next_line < mle[i].line; next_line++)
387
                        {
388
                          ui_out_tuple_begin (uiout, "src_and_asm_line");
389
                          print_source_lines (symtab, next_line, mle[i].line + 1, 0);
390
                          ui_out_list_begin (uiout, "line_asm_insn");
391
                          ui_out_list_end (uiout);
392
                          ui_out_tuple_end (uiout);
393
                        }
394
                      /* Print the last line and leave list open for
395
                         asm instructions to be added. */
396
                      ui_out_tuple_begin (uiout, "src_and_asm_line");
397
                      print_source_lines (symtab, next_line, mle[i].line + 1, 0);
398
                    }
399
                }
400
              else
401
                {
402
                  ui_out_tuple_begin (uiout, "src_and_asm_line");
403
                  print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
404
                }
405
 
406
              next_line = mle[i].line + 1;
407
              ui_out_list_begin (uiout, "line_asm_insn");
408
              if (i + 1 < newlines && mle[i + 1].line <= mle[i].line)
409
                close_list = 0;
410
            }
411
          for (pc = mle[i].start_pc; pc < mle[i].end_pc;)
412
            {
413
              QUIT;
414
              if (how_many >= 0)
415
                {
416
                  if (num_displayed >= how_many)
417
                    break;
418
                  else
419
                    num_displayed++;
420
                }
421
              ui_out_tuple_begin (uiout, NULL);
422
              ui_out_field_core_addr (uiout, "address", pc);
423
 
424
              if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped))
425
                {
426
                  /* We don't care now about line, filename and
427
                     unmapped, but we might in the future. */
428
                  ui_out_field_string (uiout, "func-name", name);
429
                  ui_out_field_int (uiout, "offset", offset);
430
                }
431
              if (filename != NULL)
432
                xfree (filename);
433
              if (name != NULL)
434
                xfree (name);
435
 
436
              ui_file_rewind (stb->stream);
437
              pc += (*tm_print_insn) (pc, &di);
438
              ui_out_field_stream (uiout, "inst", stb);
439
              ui_file_rewind (stb->stream);
440
              ui_out_tuple_end (uiout);
441
            }
442
          if (close_list)
443
            {
444
              ui_out_list_end (uiout);
445
              ui_out_tuple_end (uiout);
446
              close_list = 0;
447
            }
448
          if (how_many >= 0)
449
            if (num_displayed >= how_many)
450
              break;
451
        }
452
      ui_out_list_end (uiout);
453
    }
454
  else
455
    {
456
    assembly_only:
457
      ui_out_list_begin (uiout, "asm_insns");
458
      num_displayed = 0;
459
      for (pc = low; pc < high;)
460
        {
461
          QUIT;
462
          if (how_many >= 0)
463
            {
464
              if (num_displayed >= how_many)
465
                break;
466
              else
467
                num_displayed++;
468
            }
469
          ui_out_tuple_begin (uiout, NULL);
470
          ui_out_field_core_addr (uiout, "address", pc);
471
 
472
          if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped))
473
            {
474
              /* We don't care now about line, filename and
475
                 unmapped. But we might in the future. */
476
              ui_out_field_string (uiout, "func-name", name);
477
              ui_out_field_int (uiout, "offset", offset);
478
            }
479
          if (filename != NULL)
480
            xfree (filename);
481
          if (name != NULL)
482
            xfree (name);
483
 
484
          ui_file_rewind (stb->stream);
485
          pc += (*tm_print_insn) (pc, &di);
486
          ui_out_field_stream (uiout, "inst", stb);
487
          ui_file_rewind (stb->stream);
488
          ui_out_tuple_end (uiout);
489
        }
490
      ui_out_list_end (uiout);
491
    }
492
  gdb_flush (gdb_stdout);
493
 
494
  return MI_CMD_DONE;
495
}

powered by: WebSVN 2.1.0

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