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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [bfd/] [dwarf1.c] - Blame information for rev 1771

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

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

powered by: WebSVN 2.1.0

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