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

Subversion Repositories or1k

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

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

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

powered by: WebSVN 2.1.0

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