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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [dwarf2loc.c] - Blame information for rev 826

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

Line No. Rev Author Line
1 24 jeremybenn
/* DWARF 2 location expression support for GDB.
2
 
3
   Copyright (C) 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
4
 
5
   Contributed by Daniel Jacobowitz, MontaVista Software, Inc.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
#include "defs.h"
23
#include "ui-out.h"
24
#include "value.h"
25
#include "frame.h"
26
#include "gdbcore.h"
27
#include "target.h"
28
#include "inferior.h"
29
#include "ax.h"
30
#include "ax-gdb.h"
31
#include "regcache.h"
32
#include "objfiles.h"
33
#include "exceptions.h"
34
 
35
#include "elf/dwarf2.h"
36
#include "dwarf2expr.h"
37
#include "dwarf2loc.h"
38
 
39
#include "gdb_string.h"
40
#include "gdb_assert.h"
41
 
42
/* A helper function for dealing with location lists.  Given a
43
   symbol baton (BATON) and a pc value (PC), find the appropriate
44
   location expression, set *LOCEXPR_LENGTH, and return a pointer
45
   to the beginning of the expression.  Returns NULL on failure.
46
 
47
   For now, only return the first matching location expression; there
48
   can be more than one in the list.  */
49
 
50
static gdb_byte *
51
find_location_expression (struct dwarf2_loclist_baton *baton,
52
                          size_t *locexpr_length, CORE_ADDR pc)
53
{
54
  CORE_ADDR low, high;
55
  gdb_byte *loc_ptr, *buf_end;
56
  int length;
57
  unsigned int addr_size = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT;
58
  CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
59
  /* Adjust base_address for relocatable objects.  */
60
  CORE_ADDR base_offset = ANOFFSET (baton->objfile->section_offsets,
61
                                    SECT_OFF_TEXT (baton->objfile));
62
  CORE_ADDR base_address = baton->base_address + base_offset;
63
 
64
  loc_ptr = baton->data;
65
  buf_end = baton->data + baton->size;
66
 
67
  while (1)
68
    {
69
      low = dwarf2_read_address (loc_ptr, buf_end, &length);
70
      loc_ptr += length;
71
      high = dwarf2_read_address (loc_ptr, buf_end, &length);
72
      loc_ptr += length;
73
 
74
      /* An end-of-list entry.  */
75
      if (low == 0 && high == 0)
76
        return NULL;
77
 
78
      /* A base-address-selection entry.  */
79
      if ((low & base_mask) == base_mask)
80
        {
81
          base_address = high;
82
          continue;
83
        }
84
 
85
      /* Otherwise, a location expression entry.  */
86
      low += base_address;
87
      high += base_address;
88
 
89
      length = extract_unsigned_integer (loc_ptr, 2);
90
      loc_ptr += 2;
91
 
92
      if (pc >= low && pc < high)
93
        {
94
          *locexpr_length = length;
95
          return loc_ptr;
96
        }
97
 
98
      loc_ptr += length;
99
    }
100
}
101
 
102
/* This is the baton used when performing dwarf2 expression
103
   evaluation.  */
104
struct dwarf_expr_baton
105
{
106
  struct frame_info *frame;
107
  struct objfile *objfile;
108
};
109
 
110
/* Helper functions for dwarf2_evaluate_loc_desc.  */
111
 
112
/* Using the frame specified in BATON, return the value of register
113
   REGNUM, treated as a pointer.  */
114
static CORE_ADDR
115
dwarf_expr_read_reg (void *baton, int dwarf_regnum)
116
{
117
  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
118
  CORE_ADDR result;
119
  int regnum;
120
 
121
  regnum = gdbarch_dwarf2_reg_to_regnum (current_gdbarch, dwarf_regnum);
122
  result = address_from_register (builtin_type_void_data_ptr,
123
                                  regnum, debaton->frame);
124
  return result;
125
}
126
 
127
/* Read memory at ADDR (length LEN) into BUF.  */
128
 
129
static void
130
dwarf_expr_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
131
{
132
  read_memory (addr, buf, len);
133
}
134
 
135
/* Using the frame specified in BATON, find the location expression
136
   describing the frame base.  Return a pointer to it in START and
137
   its length in LENGTH.  */
138
static void
139
dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length)
140
{
141
  /* FIXME: cagney/2003-03-26: This code should be using
142
     get_frame_base_address(), and then implement a dwarf2 specific
143
     this_base method.  */
144
  struct symbol *framefunc;
145
  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
146
 
147
  framefunc = get_frame_function (debaton->frame);
148
 
149
  /* If we found a frame-relative symbol then it was certainly within
150
     some function associated with a frame. If we can't find the frame,
151
     something has gone wrong.  */
152
  gdb_assert (framefunc != NULL);
153
 
154
  if (SYMBOL_OPS (framefunc) == &dwarf2_loclist_funcs)
155
    {
156
      struct dwarf2_loclist_baton *symbaton;
157
      struct frame_info *frame = debaton->frame;
158
 
159
      symbaton = SYMBOL_LOCATION_BATON (framefunc);
160
      *start = find_location_expression (symbaton, length,
161
                                         get_frame_address_in_block (frame));
162
    }
163
  else
164
    {
165
      struct dwarf2_locexpr_baton *symbaton;
166
      symbaton = SYMBOL_LOCATION_BATON (framefunc);
167
      *length = symbaton->size;
168
      *start = symbaton->data;
169
    }
170
 
171
  if (*start == NULL)
172
    error (_("Could not find the frame base for \"%s\"."),
173
           SYMBOL_NATURAL_NAME (framefunc));
174
}
175
 
176
/* Using the objfile specified in BATON, find the address for the
177
   current thread's thread-local storage with offset OFFSET.  */
178
static CORE_ADDR
179
dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
180
{
181
  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
182
 
183
  return target_translate_tls_address (debaton->objfile, offset);
184
}
185
 
186
/* Evaluate a location description, starting at DATA and with length
187
   SIZE, to find the current location of variable VAR in the context
188
   of FRAME.  */
189
static struct value *
190
dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
191
                          gdb_byte *data, unsigned short size,
192
                          struct objfile *objfile)
193
{
194
  struct gdbarch *arch = get_frame_arch (frame);
195
  struct value *retval;
196
  struct dwarf_expr_baton baton;
197
  struct dwarf_expr_context *ctx;
198
 
199
  if (size == 0)
200
    {
201
      retval = allocate_value (SYMBOL_TYPE (var));
202
      VALUE_LVAL (retval) = not_lval;
203
      set_value_optimized_out (retval, 1);
204
      return retval;
205
    }
206
 
207
  baton.frame = frame;
208
  baton.objfile = objfile;
209
 
210
  ctx = new_dwarf_expr_context ();
211
  ctx->baton = &baton;
212
  ctx->read_reg = dwarf_expr_read_reg;
213
  ctx->read_mem = dwarf_expr_read_mem;
214
  ctx->get_frame_base = dwarf_expr_frame_base;
215
  ctx->get_tls_address = dwarf_expr_tls_address;
216
 
217
  dwarf_expr_eval (ctx, data, size);
218
  if (ctx->num_pieces > 0)
219
    {
220
      int i;
221
      long offset = 0;
222
      bfd_byte *contents;
223
 
224
      retval = allocate_value (SYMBOL_TYPE (var));
225
      contents = value_contents_raw (retval);
226
      for (i = 0; i < ctx->num_pieces; i++)
227
        {
228
          struct dwarf_expr_piece *p = &ctx->pieces[i];
229
          if (p->in_reg)
230
            {
231
              bfd_byte regval[MAX_REGISTER_SIZE];
232
              int gdb_regnum = gdbarch_dwarf2_reg_to_regnum
233
                                 (arch, p->value);
234
              get_frame_register (frame, gdb_regnum, regval);
235
              memcpy (contents + offset, regval, p->size);
236
            }
237
          else /* In memory?  */
238
            {
239
              read_memory (p->value, contents + offset, p->size);
240
            }
241
          offset += p->size;
242
        }
243
    }
244
  else if (ctx->in_reg)
245
    {
246
      CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
247
      int gdb_regnum = gdbarch_dwarf2_reg_to_regnum
248
                         (arch, dwarf_regnum);
249
      retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
250
    }
251
  else
252
    {
253
      CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
254
 
255
      retval = allocate_value (SYMBOL_TYPE (var));
256
      VALUE_LVAL (retval) = lval_memory;
257
      set_value_lazy (retval, 1);
258
      VALUE_ADDRESS (retval) = address;
259
    }
260
 
261
  set_value_initialized (retval, ctx->initialized);
262
 
263
  free_dwarf_expr_context (ctx);
264
 
265
  return retval;
266
}
267
 
268
 
269
 
270
 
271
 
272
/* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
273
 
274
struct needs_frame_baton
275
{
276
  int needs_frame;
277
};
278
 
279
/* Reads from registers do require a frame.  */
280
static CORE_ADDR
281
needs_frame_read_reg (void *baton, int regnum)
282
{
283
  struct needs_frame_baton *nf_baton = baton;
284
  nf_baton->needs_frame = 1;
285
  return 1;
286
}
287
 
288
/* Reads from memory do not require a frame.  */
289
static void
290
needs_frame_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
291
{
292
  memset (buf, 0, len);
293
}
294
 
295
/* Frame-relative accesses do require a frame.  */
296
static void
297
needs_frame_frame_base (void *baton, gdb_byte **start, size_t * length)
298
{
299
  static gdb_byte lit0 = DW_OP_lit0;
300
  struct needs_frame_baton *nf_baton = baton;
301
 
302
  *start = &lit0;
303
  *length = 1;
304
 
305
  nf_baton->needs_frame = 1;
306
}
307
 
308
/* Thread-local accesses do require a frame.  */
309
static CORE_ADDR
310
needs_frame_tls_address (void *baton, CORE_ADDR offset)
311
{
312
  struct needs_frame_baton *nf_baton = baton;
313
  nf_baton->needs_frame = 1;
314
  return 1;
315
}
316
 
317
/* Return non-zero iff the location expression at DATA (length SIZE)
318
   requires a frame to evaluate.  */
319
 
320
static int
321
dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size)
322
{
323
  struct needs_frame_baton baton;
324
  struct dwarf_expr_context *ctx;
325
  int in_reg;
326
 
327
  baton.needs_frame = 0;
328
 
329
  ctx = new_dwarf_expr_context ();
330
  ctx->baton = &baton;
331
  ctx->read_reg = needs_frame_read_reg;
332
  ctx->read_mem = needs_frame_read_mem;
333
  ctx->get_frame_base = needs_frame_frame_base;
334
  ctx->get_tls_address = needs_frame_tls_address;
335
 
336
  dwarf_expr_eval (ctx, data, size);
337
 
338
  in_reg = ctx->in_reg;
339
 
340
  if (ctx->num_pieces > 0)
341
    {
342
      int i;
343
 
344
      /* If the location has several pieces, and any of them are in
345
         registers, then we will need a frame to fetch them from.  */
346
      for (i = 0; i < ctx->num_pieces; i++)
347
        if (ctx->pieces[i].in_reg)
348
          in_reg = 1;
349
    }
350
 
351
  free_dwarf_expr_context (ctx);
352
 
353
  return baton.needs_frame || in_reg;
354
}
355
 
356
static void
357
dwarf2_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax,
358
                           struct axs_value *value, gdb_byte *data,
359
                           int size)
360
{
361
  if (size == 0)
362
    error (_("Symbol \"%s\" has been optimized out."),
363
           SYMBOL_PRINT_NAME (symbol));
364
 
365
  if (size == 1
366
      && data[0] >= DW_OP_reg0
367
      && data[0] <= DW_OP_reg31)
368
    {
369
      value->kind = axs_lvalue_register;
370
      value->u.reg = data[0] - DW_OP_reg0;
371
    }
372
  else if (data[0] == DW_OP_regx)
373
    {
374
      ULONGEST reg;
375
      read_uleb128 (data + 1, data + size, &reg);
376
      value->kind = axs_lvalue_register;
377
      value->u.reg = reg;
378
    }
379
  else if (data[0] == DW_OP_fbreg)
380
    {
381
      /* And this is worse than just minimal; we should honor the frame base
382
         as above.  */
383
      int frame_reg;
384
      LONGEST frame_offset;
385
      gdb_byte *buf_end;
386
 
387
      buf_end = read_sleb128 (data + 1, data + size, &frame_offset);
388
      if (buf_end != data + size)
389
        error (_("Unexpected opcode after DW_OP_fbreg for symbol \"%s\"."),
390
               SYMBOL_PRINT_NAME (symbol));
391
 
392
      gdbarch_virtual_frame_pointer (current_gdbarch,
393
                                     ax->scope, &frame_reg, &frame_offset);
394
      ax_reg (ax, frame_reg);
395
      ax_const_l (ax, frame_offset);
396
      ax_simple (ax, aop_add);
397
 
398
      value->kind = axs_lvalue_memory;
399
    }
400
  else if (data[0] >= DW_OP_breg0
401
           && data[0] <= DW_OP_breg31)
402
    {
403
      unsigned int reg;
404
      LONGEST offset;
405
      gdb_byte *buf_end;
406
 
407
      reg = data[0] - DW_OP_breg0;
408
      buf_end = read_sleb128 (data + 1, data + size, &offset);
409
      if (buf_end != data + size)
410
        error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."),
411
               reg, SYMBOL_PRINT_NAME (symbol));
412
 
413
      ax_reg (ax, reg);
414
      ax_const_l (ax, offset);
415
      ax_simple (ax, aop_add);
416
 
417
      value->kind = axs_lvalue_memory;
418
    }
419
  else
420
    error (_("Unsupported DWARF opcode 0x%x in the location of \"%s\"."),
421
           data[0], SYMBOL_PRINT_NAME (symbol));
422
}
423
 
424
/* Return the value of SYMBOL in FRAME using the DWARF-2 expression
425
   evaluator to calculate the location.  */
426
static struct value *
427
locexpr_read_variable (struct symbol *symbol, struct frame_info *frame)
428
{
429
  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
430
  struct value *val;
431
  val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size,
432
                                  dlbaton->objfile);
433
 
434
  return val;
435
}
436
 
437
/* Return non-zero iff we need a frame to evaluate SYMBOL.  */
438
static int
439
locexpr_read_needs_frame (struct symbol *symbol)
440
{
441
  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
442
  return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size);
443
}
444
 
445
/* Print a natural-language description of SYMBOL to STREAM.  */
446
static int
447
locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
448
{
449
  /* FIXME: be more extensive.  */
450
  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
451
 
452
  if (dlbaton->size == 1
453
      && dlbaton->data[0] >= DW_OP_reg0
454
      && dlbaton->data[0] <= DW_OP_reg31)
455
    {
456
      int regno = gdbarch_dwarf2_reg_to_regnum
457
                    (current_gdbarch, dlbaton->data[0] - DW_OP_reg0);
458
      fprintf_filtered (stream,
459
                        "a variable in register %s",
460
                        gdbarch_register_name (current_gdbarch, regno));
461
      return 1;
462
    }
463
 
464
  /* The location expression for a TLS variable looks like this (on a
465
     64-bit LE machine):
466
 
467
     DW_AT_location    : 10 byte block: 3 4 0 0 0 0 0 0 0 e0
468
                        (DW_OP_addr: 4; DW_OP_GNU_push_tls_address)
469
 
470
     0x3 is the encoding for DW_OP_addr, which has an operand as long
471
     as the size of an address on the target machine (here is 8
472
     bytes).  0xe0 is the encoding for DW_OP_GNU_push_tls_address.
473
     The operand represents the offset at which the variable is within
474
     the thread local storage.  */
475
 
476
  if (dlbaton->size > 1
477
      && dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address)
478
    if (dlbaton->data[0] == DW_OP_addr)
479
      {
480
        int bytes_read;
481
        CORE_ADDR offset = dwarf2_read_address (&dlbaton->data[1],
482
                                                &dlbaton->data[dlbaton->size - 1],
483
                                                &bytes_read);
484
        fprintf_filtered (stream,
485
                          "a thread-local variable at offset %s in the "
486
                          "thread-local storage for `%s'",
487
                          paddr_nz (offset), dlbaton->objfile->name);
488
        return 1;
489
      }
490
 
491
 
492
  fprintf_filtered (stream,
493
                    "a variable with complex or multiple locations (DWARF2)");
494
  return 1;
495
}
496
 
497
 
498
/* Describe the location of SYMBOL as an agent value in VALUE, generating
499
   any necessary bytecode in AX.
500
 
501
   NOTE drow/2003-02-26: This function is extremely minimal, because
502
   doing it correctly is extremely complicated and there is no
503
   publicly available stub with tracepoint support for me to test
504
   against.  When there is one this function should be revisited.  */
505
 
506
static void
507
locexpr_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
508
                            struct axs_value * value)
509
{
510
  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
511
 
512
  dwarf2_tracepoint_var_ref (symbol, ax, value, dlbaton->data, dlbaton->size);
513
}
514
 
515
/* The set of location functions used with the DWARF-2 expression
516
   evaluator.  */
517
const struct symbol_ops dwarf2_locexpr_funcs = {
518
  locexpr_read_variable,
519
  locexpr_read_needs_frame,
520
  locexpr_describe_location,
521
  locexpr_tracepoint_var_ref
522
};
523
 
524
 
525
/* Wrapper functions for location lists.  These generally find
526
   the appropriate location expression and call something above.  */
527
 
528
/* Return the value of SYMBOL in FRAME using the DWARF-2 expression
529
   evaluator to calculate the location.  */
530
static struct value *
531
loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
532
{
533
  struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
534
  struct value *val;
535
  gdb_byte *data;
536
  size_t size;
537
 
538
  data = find_location_expression (dlbaton, &size,
539
                                   frame ? get_frame_address_in_block (frame)
540
                                   : 0);
541
  if (data == NULL)
542
    {
543
      val = allocate_value (SYMBOL_TYPE (symbol));
544
      VALUE_LVAL (val) = not_lval;
545
      set_value_optimized_out (val, 1);
546
    }
547
  else
548
    val = dwarf2_evaluate_loc_desc (symbol, frame, data, size,
549
                                    dlbaton->objfile);
550
 
551
  return val;
552
}
553
 
554
/* Return non-zero iff we need a frame to evaluate SYMBOL.  */
555
static int
556
loclist_read_needs_frame (struct symbol *symbol)
557
{
558
  /* If there's a location list, then assume we need to have a frame
559
     to choose the appropriate location expression.  With tracking of
560
     global variables this is not necessarily true, but such tracking
561
     is disabled in GCC at the moment until we figure out how to
562
     represent it.  */
563
 
564
  return 1;
565
}
566
 
567
/* Print a natural-language description of SYMBOL to STREAM.  */
568
static int
569
loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
570
{
571
  /* FIXME: Could print the entire list of locations.  */
572
  fprintf_filtered (stream, "a variable with multiple locations");
573
  return 1;
574
}
575
 
576
/* Describe the location of SYMBOL as an agent value in VALUE, generating
577
   any necessary bytecode in AX.  */
578
static void
579
loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
580
                            struct axs_value * value)
581
{
582
  struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
583
  gdb_byte *data;
584
  size_t size;
585
 
586
  data = find_location_expression (dlbaton, &size, ax->scope);
587
  if (data == NULL)
588
    error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol));
589
 
590
  dwarf2_tracepoint_var_ref (symbol, ax, value, data, size);
591
}
592
 
593
/* The set of location functions used with the DWARF-2 expression
594
   evaluator and location lists.  */
595
const struct symbol_ops dwarf2_loclist_funcs = {
596
  loclist_read_variable,
597
  loclist_read_needs_frame,
598
  loclist_describe_location,
599
  loclist_tracepoint_var_ref
600
};

powered by: WebSVN 2.1.0

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