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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [dwarf1.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 38 julius
/* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
2
   Copyright 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007
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 = 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 = 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 (aDieInfo->name) + 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 = bfd_alloc (stash->abfd, amt);
316
      if (!aUnit->linenumber_table)
317
        return FALSE;
318
 
319
      for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
320
        {
321
          /* A line number.  */
322
          aUnit->linenumber_table[eachLine].linenumber
323
            = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
324
          xptr += 4;
325
 
326
          /* Skip the position within the line.  */
327
          xptr += 2;
328
 
329
          /* And finally the address.  */
330
          aUnit->linenumber_table[eachLine].addr
331
            = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
332
          xptr += 4;
333
        }
334
    }
335
 
336
  return TRUE;
337
}
338
 
339
/* Parse each function die in a compilation unit 'aUnit'.
340
   The first child die of 'aUnit' should be in 'aUnit->first_child',
341
   the result is placed in 'aUnit->func_list'.
342
   Return FALSE if error; TRUE otherwise.  */
343
 
344
static bfd_boolean
345
parse_functions_in_unit (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
346
{
347
  bfd_byte *eachDie;
348
 
349
  if (aUnit->first_child)
350
    for (eachDie = aUnit->first_child;
351
         eachDie < stash->debug_section_end;
352
         )
353
      {
354
        struct die_info eachDieInfo;
355
 
356
        if (! parse_die (stash->abfd, &eachDieInfo, eachDie,
357
                         stash->debug_section_end))
358
          return FALSE;
359
 
360
        if (eachDieInfo.tag == TAG_global_subroutine
361
            || eachDieInfo.tag == TAG_subroutine
362
            || eachDieInfo.tag == TAG_inlined_subroutine
363
            || eachDieInfo.tag == TAG_entry_point)
364
          {
365
            struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
366
            if (!aFunc)
367
              return FALSE;
368
 
369
            aFunc->name = eachDieInfo.name;
370
            aFunc->low_pc = eachDieInfo.low_pc;
371
            aFunc->high_pc = eachDieInfo.high_pc;
372
          }
373
 
374
        /* Move to next sibling, if none, end loop */
375
        if (eachDieInfo.sibling)
376
          eachDie = stash->debug_section + eachDieInfo.sibling;
377
        else
378
          break;
379
      }
380
 
381
  return TRUE;
382
}
383
 
384
/* Find the nearest line to 'addr' in 'aUnit'.
385
   Return whether we found the line (or a function) without error.  */
386
 
387
static bfd_boolean
388
dwarf1_unit_find_nearest_line (struct dwarf1_debug* stash,
389
                               struct dwarf1_unit* aUnit,
390
                               unsigned long addr,
391
                               const char **filename_ptr,
392
                               const char **functionname_ptr,
393
                               unsigned int *linenumber_ptr)
394
{
395
  int line_p = FALSE;
396
  int func_p = FALSE;
397
 
398
  if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
399
    {
400
      if (aUnit->has_stmt_list)
401
        {
402
          unsigned long i;
403
          struct dwarf1_func* eachFunc;
404
 
405
          if (! aUnit->linenumber_table)
406
            {
407
              if (! parse_line_table (stash, aUnit))
408
                return FALSE;
409
            }
410
 
411
          if (! aUnit->func_list)
412
            {
413
              if (! parse_functions_in_unit (stash, aUnit))
414
                return FALSE;
415
            }
416
 
417
          for (i = 0; i < aUnit->line_count; i++)
418
            {
419
              if (aUnit->linenumber_table[i].addr <= addr
420
                  && addr < aUnit->linenumber_table[i+1].addr)
421
                {
422
                  *filename_ptr = aUnit->name;
423
                  *linenumber_ptr = aUnit->linenumber_table[i].linenumber;
424
                  line_p = TRUE;
425
                  break;
426
                }
427
            }
428
 
429
          for (eachFunc = aUnit->func_list;
430
               eachFunc;
431
               eachFunc = eachFunc->prev)
432
            {
433
              if (eachFunc->low_pc <= addr
434
                  && addr < eachFunc->high_pc)
435
                {
436
                  *functionname_ptr = eachFunc->name;
437
                  func_p = TRUE;
438
                  break;
439
                }
440
            }
441
        }
442
    }
443
 
444
  return line_p || func_p;
445
}
446
 
447
/* The DWARF 1 version of find_nearest line.
448
   Return TRUE if the line is found without error.  */
449
 
450
bfd_boolean
451
_bfd_dwarf1_find_nearest_line (bfd *abfd,
452
                               asection *section,
453
                               asymbol **symbols,
454
                               bfd_vma offset,
455
                               const char **filename_ptr,
456
                               const char **functionname_ptr,
457
                               unsigned int *linenumber_ptr)
458
{
459
  struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info;
460
 
461
  struct dwarf1_unit* eachUnit;
462
 
463
  /* What address are we looking for? */
464
  unsigned long addr = (unsigned long)(offset + section->vma);
465
 
466
  *filename_ptr = NULL;
467
  *functionname_ptr = NULL;
468
  *linenumber_ptr = 0;
469
 
470
  if (! stash)
471
    {
472
      asection *msec;
473
      bfd_size_type size = sizeof (struct dwarf1_debug);
474
 
475
      stash = elf_tdata (abfd)->dwarf1_find_line_info
476
        = bfd_zalloc (abfd, size);
477
 
478
      if (! stash)
479
        return FALSE;
480
 
481
      msec = bfd_get_section_by_name (abfd, ".debug");
482
      if (! msec)
483
        /* No dwarf1 info.  Note that at this point the stash
484
           has been allocated, but contains zeros, this lets
485
           future calls to this function fail quicker.  */
486
        return FALSE;
487
 
488
      size = msec->rawsize ? msec->rawsize : msec->size;
489
      stash->debug_section
490
        = bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
491
                                                     symbols);
492
 
493
      if (! stash->debug_section)
494
        return FALSE;
495
 
496
      stash->debug_section_end = stash->debug_section + size;
497
      stash->currentDie = stash->debug_section;
498
      stash->abfd = abfd;
499
      stash->syms = symbols;
500
    }
501
 
502
  /* A null debug_section indicates that there was no dwarf1 info
503
     or that an error occured while setting up the stash.  */
504
 
505
  if (! stash->debug_section)
506
    return FALSE;
507
 
508
  /* Look at the previously parsed units to see if any contain
509
     the addr.  */
510
  for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev)
511
    if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc)
512
      return dwarf1_unit_find_nearest_line (stash, eachUnit, addr,
513
                                            filename_ptr,
514
                                            functionname_ptr,
515
                                            linenumber_ptr);
516
 
517
  while (stash->currentDie < stash->debug_section_end)
518
    {
519
      struct die_info aDieInfo;
520
 
521
      if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie,
522
                       stash->debug_section_end))
523
        return FALSE;
524
 
525
      if (aDieInfo.tag == TAG_compile_unit)
526
        {
527
          struct dwarf1_unit* aUnit
528
            = alloc_dwarf1_unit (stash);
529
          if (!aUnit)
530
            return FALSE;
531
 
532
          aUnit->name = aDieInfo.name;
533
          aUnit->low_pc = aDieInfo.low_pc;
534
          aUnit->high_pc = aDieInfo.high_pc;
535
          aUnit->has_stmt_list = aDieInfo.has_stmt_list;
536
          aUnit->stmt_list_offset = aDieInfo.stmt_list_offset;
537
 
538
          /* A die has a child if it's followed by a die that is
539
             not it's sibling.  */
540
          if (aDieInfo.sibling
541
              && stash->currentDie + aDieInfo.length
542
                    < stash->debug_section_end
543
              && stash->currentDie + aDieInfo.length
544
                    != stash->debug_section + aDieInfo.sibling)
545
            aUnit->first_child = stash->currentDie + aDieInfo.length;
546
          else
547
            aUnit->first_child = 0;
548
 
549
          if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
550
            return dwarf1_unit_find_nearest_line (stash, aUnit, addr,
551
                                                  filename_ptr,
552
                                                  functionname_ptr,
553
                                                  linenumber_ptr);
554
        }
555
 
556
      if (aDieInfo.sibling != 0)
557
        stash->currentDie = stash->debug_section + aDieInfo.sibling;
558
      else
559
        stash->currentDie += aDieInfo.length;
560
    }
561
 
562
  return FALSE;
563
}

powered by: WebSVN 2.1.0

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