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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [dwarf1.c] - Blame information for rev 146

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

Line No. Rev Author Line
1 14 khays
/* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
2
   Copyright 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
 
5
   Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com).
6
 
7
   This file is part of BFD.
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 (at
12
   your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful, but
15
   WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
   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, write to the Free Software
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
 
24
#include "sysdep.h"
25
#include "bfd.h"
26
#include "libiberty.h"
27
#include "libbfd.h"
28
#include "elf-bfd.h"
29
#include "elf/dwarf.h"
30
 
31
/* dwarf1_debug is the starting point for all dwarf1 info.  */
32
 
33
struct dwarf1_debug
34
{
35
  /* The bfd we are working with.  */
36
  bfd* abfd;
37
 
38
  /* Pointer to the symbol table.  */
39
  asymbol** syms;
40
 
41
  /* List of already parsed compilation units.  */
42
  struct dwarf1_unit* lastUnit;
43
 
44
  /* The buffer for the .debug section.
45
     Zero indicates that the .debug section failed to load.  */
46
  bfd_byte *debug_section;
47
 
48
  /* Pointer to the end of the .debug_info section memory buffer.  */
49
  bfd_byte *debug_section_end;
50
 
51
  /* The buffer for the .line section.  */
52
  bfd_byte *line_section;
53
 
54
  /* End of that buffer.  */
55
  bfd_byte *line_section_end;
56
 
57
  /* The current or next unread die within the .debug section.  */
58
  bfd_byte *currentDie;
59
};
60
 
61
/* One dwarf1_unit for each parsed compilation unit die.  */
62
 
63
struct dwarf1_unit
64
{
65
  /* Linked starting from stash->lastUnit.  */
66
  struct dwarf1_unit* prev;
67
 
68
  /* Name of the compilation unit.  */
69
  char *name;
70
 
71
  /* The highest and lowest address used in the compilation unit.  */
72
  unsigned long low_pc;
73
  unsigned long high_pc;
74
 
75
  /* Does this unit have a statement list?  */
76
  int has_stmt_list;
77
 
78
  /* If any, the offset of the line number table in the .line section.  */
79
  unsigned long stmt_list_offset;
80
 
81
  /* If non-zero, a pointer to the first child of this unit.  */
82
  bfd_byte *first_child;
83
 
84
  /* How many line entries?  */
85
  unsigned long line_count;
86
 
87
  /* The decoded line number table (line_count entries).  */
88
  struct linenumber* linenumber_table;
89
 
90
  /* The list of functions in this unit.  */
91
  struct dwarf1_func* func_list;
92
};
93
 
94
/* One dwarf1_func for each parsed function die.  */
95
 
96
struct dwarf1_func
97
{
98
  /* Linked starting from aUnit->func_list.  */
99
  struct dwarf1_func* prev;
100
 
101
  /* Name of function.  */
102
  char* name;
103
 
104
  /* The highest and lowest address used in the compilation unit.  */
105
  unsigned long low_pc;
106
  unsigned long high_pc;
107
};
108
 
109
/* Used to return info about a parsed die.  */
110
struct die_info
111
{
112
  unsigned long length;
113
  unsigned long sibling;
114
  unsigned long low_pc;
115
  unsigned long high_pc;
116
  unsigned long stmt_list_offset;
117
 
118
  char* name;
119
 
120
  int has_stmt_list;
121
 
122
  unsigned short tag;
123
};
124
 
125
/* Parsed line number information.  */
126
struct linenumber
127
{
128
  /* First address in the line.  */
129
  unsigned long addr;
130
 
131
  /* The line number.  */
132
  unsigned long linenumber;
133
};
134
 
135
/* Find the form of an attr, from the attr field.  */
136
#define FORM_FROM_ATTR(attr)    ((attr) & 0xF)  /* Implicitly specified.  */
137
 
138
/* Return a newly allocated dwarf1_unit.  It should be cleared and
139
   then attached into the 'stash' at 'stash->lastUnit'.  */
140
 
141
static struct dwarf1_unit*
142
alloc_dwarf1_unit (struct dwarf1_debug* stash)
143
{
144
  bfd_size_type amt = sizeof (struct dwarf1_unit);
145
 
146
  struct dwarf1_unit* x = (struct dwarf1_unit *) bfd_zalloc (stash->abfd, amt);
147
  if (x)
148
    {
149
      x->prev = stash->lastUnit;
150
      stash->lastUnit = x;
151
    }
152
 
153
  return x;
154
}
155
 
156
/* Return a newly allocated dwarf1_func.  It must be cleared and
157
   attached into 'aUnit' at 'aUnit->func_list'.  */
158
 
159
static struct dwarf1_func *
160
alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
161
{
162
  bfd_size_type amt = sizeof (struct dwarf1_func);
163
 
164
  struct dwarf1_func* x = (struct dwarf1_func *) bfd_zalloc (stash->abfd, amt);
165
  if (x)
166
    {
167
      x->prev = aUnit->func_list;
168
      aUnit->func_list = x;
169
    }
170
 
171
  return x;
172
}
173
 
174
/* parse_die - parse a Dwarf1 die.
175
   Parse the die starting at 'aDiePtr' into 'aDieInfo'.
176
   'abfd' must be the bfd from which the section that 'aDiePtr'
177
   points to was pulled from.
178
 
179
   Return FALSE if the die is invalidly formatted; TRUE otherwise.  */
180
 
181
static bfd_boolean
182
parse_die (bfd *             abfd,
183
           struct die_info * aDieInfo,
184
           bfd_byte *        aDiePtr,
185
           bfd_byte *        aDiePtrEnd)
186
{
187
  bfd_byte *this_die = aDiePtr;
188
  bfd_byte *xptr = this_die;
189
 
190
  memset (aDieInfo, 0, sizeof (* aDieInfo));
191
 
192
  /* First comes the length.  */
193
  aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr);
194
  xptr += 4;
195
  if (aDieInfo->length == 0
196
      || (this_die + aDieInfo->length) >= aDiePtrEnd)
197
    return FALSE;
198
  if (aDieInfo->length < 6)
199
    {
200
      /* Just padding bytes.  */
201
      aDieInfo->tag = TAG_padding;
202
      return TRUE;
203
    }
204
 
205
  /* Then the tag.  */
206
  aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr);
207
  xptr += 2;
208
 
209
  /* Then the attributes.  */
210
  while (xptr < (this_die + aDieInfo->length))
211
    {
212
      unsigned short attr;
213
 
214
      /* Parse the attribute based on its form.  This section
215
         must handle all dwarf1 forms, but need only handle the
216
         actual attributes that we care about.  */
217
      attr = bfd_get_16 (abfd, (bfd_byte *) xptr);
218
      xptr += 2;
219
 
220
      switch (FORM_FROM_ATTR (attr))
221
        {
222
        case FORM_DATA2:
223
          xptr += 2;
224
          break;
225
        case FORM_DATA4:
226
        case FORM_REF:
227
          if (attr == AT_sibling)
228
            aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr);
229
          else if (attr == AT_stmt_list)
230
            {
231
              aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr);
232
              aDieInfo->has_stmt_list = 1;
233
            }
234
          xptr += 4;
235
          break;
236
        case FORM_DATA8:
237
          xptr += 8;
238
          break;
239
        case FORM_ADDR:
240
          if (attr == AT_low_pc)
241
            aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
242
          else if (attr == AT_high_pc)
243
            aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
244
          xptr += 4;
245
          break;
246
        case FORM_BLOCK2:
247
          xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr);
248
          break;
249
        case FORM_BLOCK4:
250
          xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr);
251
          break;
252
        case FORM_STRING:
253
          if (attr == AT_name)
254
            aDieInfo->name = (char *) xptr;
255
          xptr += strlen ((char *) xptr) + 1;
256
          break;
257
        }
258
    }
259
 
260
  return TRUE;
261
}
262
 
263
/* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset'
264
   into 'aUnit->linenumber_table'.  Return FALSE if an error
265
   occurs; TRUE otherwise.  */
266
 
267
static bfd_boolean
268
parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
269
{
270
  bfd_byte *xptr;
271
 
272
  /* Load the ".line" section from the bfd if we haven't already.  */
273
  if (stash->line_section == 0)
274
    {
275
      asection *msec;
276
      bfd_size_type size;
277
 
278
      msec = bfd_get_section_by_name (stash->abfd, ".line");
279
      if (! msec)
280
        return FALSE;
281
 
282
      size = msec->rawsize ? msec->rawsize : msec->size;
283
      stash->line_section
284
        = bfd_simple_get_relocated_section_contents
285
        (stash->abfd, msec, NULL, stash->syms);
286
 
287
      if (! stash->line_section)
288
        return FALSE;
289
 
290
      stash->line_section_end = stash->line_section + size;
291
    }
292
 
293
  xptr = stash->line_section + aUnit->stmt_list_offset;
294
  if (xptr < stash->line_section_end)
295
    {
296
      unsigned long eachLine;
297
      bfd_byte *tblend;
298
      unsigned long base;
299
      bfd_size_type amt;
300
 
301
      /* First comes the length.  */
302
      tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr;
303
      xptr += 4;
304
 
305
      /* Then the base address for each address in the table.  */
306
      base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
307
      xptr += 4;
308
 
309
      /* How many line entrys?
310
         10 = 4 (line number) + 2 (pos in line) + 4 (address in line).  */
311
      aUnit->line_count = (tblend - xptr) / 10;
312
 
313
      /* Allocate an array for the entries.  */
314
      amt = sizeof (struct linenumber) * aUnit->line_count;
315
      aUnit->linenumber_table = (struct linenumber *) bfd_alloc (stash->abfd,
316
                                                                 amt);
317
      if (!aUnit->linenumber_table)
318
        return FALSE;
319
 
320
      for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
321
        {
322
          /* A line number.  */
323
          aUnit->linenumber_table[eachLine].linenumber
324
            = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
325
          xptr += 4;
326
 
327
          /* Skip the position within the line.  */
328
          xptr += 2;
329
 
330
          /* And finally the address.  */
331
          aUnit->linenumber_table[eachLine].addr
332
            = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
333
          xptr += 4;
334
        }
335
    }
336
 
337
  return TRUE;
338
}
339
 
340
/* Parse each function die in a compilation unit 'aUnit'.
341
   The first child die of 'aUnit' should be in 'aUnit->first_child',
342
   the result is placed in 'aUnit->func_list'.
343
   Return FALSE if error; TRUE otherwise.  */
344
 
345
static bfd_boolean
346
parse_functions_in_unit (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
347
{
348
  bfd_byte *eachDie;
349
 
350
  if (aUnit->first_child)
351
    for (eachDie = aUnit->first_child;
352
         eachDie < stash->debug_section_end;
353
         )
354
      {
355
        struct die_info eachDieInfo;
356
 
357
        if (! parse_die (stash->abfd, &eachDieInfo, eachDie,
358
                         stash->debug_section_end))
359
          return FALSE;
360
 
361
        if (eachDieInfo.tag == TAG_global_subroutine
362
            || eachDieInfo.tag == TAG_subroutine
363
            || eachDieInfo.tag == TAG_inlined_subroutine
364
            || eachDieInfo.tag == TAG_entry_point)
365
          {
366
            struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
367
            if (!aFunc)
368
              return FALSE;
369
 
370
            aFunc->name = eachDieInfo.name;
371
            aFunc->low_pc = eachDieInfo.low_pc;
372
            aFunc->high_pc = eachDieInfo.high_pc;
373
          }
374
 
375
        /* Move to next sibling, if none, end loop */
376
        if (eachDieInfo.sibling)
377
          eachDie = stash->debug_section + eachDieInfo.sibling;
378
        else
379
          break;
380
      }
381
 
382
  return TRUE;
383
}
384
 
385
/* Find the nearest line to 'addr' in 'aUnit'.
386
   Return whether we found the line (or a function) without error.  */
387
 
388
static bfd_boolean
389
dwarf1_unit_find_nearest_line (struct dwarf1_debug* stash,
390
                               struct dwarf1_unit* aUnit,
391
                               unsigned long addr,
392
                               const char **filename_ptr,
393
                               const char **functionname_ptr,
394
                               unsigned int *linenumber_ptr)
395
{
396
  int line_p = FALSE;
397
  int func_p = FALSE;
398
 
399
  if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
400
    {
401
      if (aUnit->has_stmt_list)
402
        {
403
          unsigned long i;
404
          struct dwarf1_func* eachFunc;
405
 
406
          if (! aUnit->linenumber_table)
407
            {
408
              if (! parse_line_table (stash, aUnit))
409
                return FALSE;
410
            }
411
 
412
          if (! aUnit->func_list)
413
            {
414
              if (! parse_functions_in_unit (stash, aUnit))
415
                return FALSE;
416
            }
417
 
418
          for (i = 0; i < aUnit->line_count; i++)
419
            {
420
              if (aUnit->linenumber_table[i].addr <= addr
421
                  && addr < aUnit->linenumber_table[i+1].addr)
422
                {
423
                  *filename_ptr = aUnit->name;
424
                  *linenumber_ptr = aUnit->linenumber_table[i].linenumber;
425
                  line_p = TRUE;
426
                  break;
427
                }
428
            }
429
 
430
          for (eachFunc = aUnit->func_list;
431
               eachFunc;
432
               eachFunc = eachFunc->prev)
433
            {
434
              if (eachFunc->low_pc <= addr
435
                  && addr < eachFunc->high_pc)
436
                {
437
                  *functionname_ptr = eachFunc->name;
438
                  func_p = TRUE;
439
                  break;
440
                }
441
            }
442
        }
443
    }
444
 
445
  return line_p || func_p;
446
}
447
 
448
/* The DWARF 1 version of find_nearest line.
449
   Return TRUE if the line is found without error.  */
450
 
451
bfd_boolean
452
_bfd_dwarf1_find_nearest_line (bfd *abfd,
453
                               asection *section,
454
                               asymbol **symbols,
455
                               bfd_vma offset,
456
                               const char **filename_ptr,
457
                               const char **functionname_ptr,
458
                               unsigned int *linenumber_ptr)
459
{
460
  struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info;
461
 
462
  struct dwarf1_unit* eachUnit;
463
 
464
  /* What address are we looking for? */
465
  unsigned long addr = (unsigned long)(offset + section->vma);
466
 
467
  *filename_ptr = NULL;
468
  *functionname_ptr = NULL;
469
  *linenumber_ptr = 0;
470
 
471
  if (! stash)
472
    {
473
      asection *msec;
474
      bfd_size_type size = sizeof (struct dwarf1_debug);
475
 
476
      stash = elf_tdata (abfd)->dwarf1_find_line_info
477
        = (struct dwarf1_debug *) bfd_zalloc (abfd, size);
478
 
479
      if (! stash)
480
        return FALSE;
481
 
482
      msec = bfd_get_section_by_name (abfd, ".debug");
483
      if (! msec)
484
        /* No dwarf1 info.  Note that at this point the stash
485
           has been allocated, but contains zeros, this lets
486
           future calls to this function fail quicker.  */
487
        return FALSE;
488
 
489
      size = msec->rawsize ? msec->rawsize : msec->size;
490
      stash->debug_section
491
        = bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
492
                                                     symbols);
493
 
494
      if (! stash->debug_section)
495
        return FALSE;
496
 
497
      stash->debug_section_end = stash->debug_section + size;
498
      stash->currentDie = stash->debug_section;
499
      stash->abfd = abfd;
500
      stash->syms = symbols;
501
    }
502
 
503
  /* A null debug_section indicates that there was no dwarf1 info
504
     or that an error occured while setting up the stash.  */
505
 
506
  if (! stash->debug_section)
507
    return FALSE;
508
 
509
  /* Look at the previously parsed units to see if any contain
510
     the addr.  */
511
  for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev)
512
    if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc)
513
      return dwarf1_unit_find_nearest_line (stash, eachUnit, addr,
514
                                            filename_ptr,
515
                                            functionname_ptr,
516
                                            linenumber_ptr);
517
 
518
  while (stash->currentDie < stash->debug_section_end)
519
    {
520
      struct die_info aDieInfo;
521
 
522
      if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie,
523
                       stash->debug_section_end))
524
        return FALSE;
525
 
526
      if (aDieInfo.tag == TAG_compile_unit)
527
        {
528
          struct dwarf1_unit* aUnit
529
            = alloc_dwarf1_unit (stash);
530
          if (!aUnit)
531
            return FALSE;
532
 
533
          aUnit->name = aDieInfo.name;
534
          aUnit->low_pc = aDieInfo.low_pc;
535
          aUnit->high_pc = aDieInfo.high_pc;
536
          aUnit->has_stmt_list = aDieInfo.has_stmt_list;
537
          aUnit->stmt_list_offset = aDieInfo.stmt_list_offset;
538
 
539
          /* A die has a child if it's followed by a die that is
540
             not it's sibling.  */
541
          if (aDieInfo.sibling
542
              && stash->currentDie + aDieInfo.length
543
                    < stash->debug_section_end
544
              && stash->currentDie + aDieInfo.length
545
                    != stash->debug_section + aDieInfo.sibling)
546
            aUnit->first_child = stash->currentDie + aDieInfo.length;
547
          else
548
            aUnit->first_child = 0;
549
 
550
          if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
551
            return dwarf1_unit_find_nearest_line (stash, aUnit, addr,
552
                                                  filename_ptr,
553
                                                  functionname_ptr,
554
                                                  linenumber_ptr);
555
        }
556
 
557
      if (aDieInfo.sibling != 0)
558
        stash->currentDie = stash->debug_section + aDieInfo.sibling;
559
      else
560
        stash->currentDie += aDieInfo.length;
561
    }
562
 
563
  return FALSE;
564
}

powered by: WebSVN 2.1.0

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