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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [dwarf1.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
2
   Copyright 1998, 1999, 2000 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
/* One dwarf1_func for each parsed function die.  */
89
 
90
struct dwarf1_func {
91
  /* Linked starting from aUnit->func_list.  */
92
  struct dwarf1_func* prev;
93
 
94
  /* Name of function.  */
95
  char* name;
96
 
97
  /* The highest and lowest address used in the compilation unit.  */
98
  unsigned long low_pc;
99
  unsigned long high_pc;
100
};
101
 
102
/* Used to return info about a parsed die.  */
103
struct die_info {
104
  unsigned long length;
105
  unsigned long sibling;
106
  unsigned long low_pc;
107
  unsigned long high_pc;
108
  unsigned long stmt_list_offset;
109
 
110
  char* name;
111
 
112
  int has_stmt_list;
113
 
114
  unsigned short tag;
115
};
116
 
117
/* Parsed line number information.  */
118
struct linenumber {
119
  /* First address in the line.  */
120
  unsigned long addr;
121
 
122
  /* The line number.  */
123
  unsigned long linenumber;
124
};
125
 
126
/* Find the form of an attr, from the attr field.  */
127
#define FORM_FROM_ATTR(attr)    ((attr) & 0xF)  /* Implicitly specified */
128
 
129
/* Return a newly allocated dwarf1_unit.  It should be cleared and
130
   then attached into the 'stash' at 'stash->lastUnit'.  */
131
 
132
static struct dwarf1_unit*
133
alloc_dwarf1_unit (stash)
134
  struct dwarf1_debug* stash;
135
{
136
  struct dwarf1_unit* x =
137
    (struct dwarf1_unit*) bfd_zalloc (stash->abfd,
138
                                      sizeof (struct dwarf1_unit));
139
  x->prev = stash->lastUnit;
140
  stash->lastUnit = x;
141
 
142
  return x;
143
}
144
 
145
/* Return a newly allocated dwarf1_func.  It must be cleared and
146
   attached into 'aUnit' at 'aUnit->func_list'.  */
147
 
148
static struct dwarf1_func*
149
alloc_dwarf1_func (stash, aUnit)
150
     struct dwarf1_debug* stash;
151
     struct dwarf1_unit* aUnit;
152
{
153
  struct dwarf1_func* x =
154
    (struct dwarf1_func*) bfd_zalloc (stash->abfd,
155
                                      sizeof (struct dwarf1_func));
156
  x->prev = aUnit->func_list;
157
  aUnit->func_list = x;
158
 
159
  return x;
160
}
161
 
162
/* parse_die - parse a Dwarf1 die.
163
   Parse the die starting at 'aDiePtr' into 'aDieInfo'.
164
   'abfd' must be the bfd from which the section that 'aDiePtr'
165
   points to was pulled from.
166
 
167
   Return false if the die is invalidly formatted; true otherwise.  */
168
 
169
static boolean
170
parse_die (abfd, aDieInfo, aDiePtr)
171
     bfd* abfd;
172
     struct die_info* aDieInfo;
173
     char*            aDiePtr;
174
{
175
  char* this_die = aDiePtr;
176
  char* xptr = this_die;
177
 
178
  memset (aDieInfo,0,sizeof (*aDieInfo));
179
 
180
  /* First comes the length.  */
181
  aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr);
182
  xptr += 4;
183
  if (aDieInfo->length == 0)
184
    return false;
185
  if (aDieInfo->length < 6)
186
    {
187
      /* Just padding bytes.  */
188
      aDieInfo->tag = TAG_padding;
189
      return true;
190
    }
191
 
192
  /* Then the tag.  */
193
  aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr);
194
  xptr += 2;
195
 
196
  /* Then the attributes.  */
197
  while (xptr < (this_die + aDieInfo->length))
198
    {
199
      unsigned short attr;
200
 
201
      /* Parse the attribute based on its form.  This section
202
         must handle all dwarf1 forms, but need only handle the
203
         actual attributes that we care about.  */
204
 
205
      attr = bfd_get_16 (abfd, (bfd_byte *) xptr);
206
      xptr += 2;
207
 
208
      switch (FORM_FROM_ATTR (attr))
209
        {
210
        case FORM_DATA2:
211
          xptr += 2;
212
          break;
213
        case FORM_DATA4:
214
        case FORM_REF:
215
          if (attr == AT_sibling)
216
            aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr);
217
          else if (attr == AT_stmt_list)
218
            {
219
              aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr);
220
              aDieInfo->has_stmt_list = 1;
221
            }
222
          xptr += 4;
223
          break;
224
        case FORM_DATA8:
225
          xptr += 8;
226
          break;
227
        case FORM_ADDR:
228
          if (attr == AT_low_pc)
229
            aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
230
          else if (attr == AT_high_pc)
231
            aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
232
          xptr += 4;
233
          break;
234
        case FORM_BLOCK2:
235
          xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr);
236
          break;
237
        case FORM_BLOCK4:
238
          xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr);
239
          break;
240
        case FORM_STRING:
241
          if (attr == AT_name)
242
            aDieInfo->name = xptr;
243
          xptr += strlen (xptr) + 1;
244
          break;
245
        }
246
    }
247
 
248
  return true;
249
}
250
 
251
/* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset'
252
   into 'aUnit->linenumber_table'.  Return false if an error
253
   occurs; true otherwise.  */
254
 
255
static boolean
256
parse_line_table (stash, aUnit)
257
  struct dwarf1_debug* stash;
258
  struct dwarf1_unit* aUnit;
259
{
260
  char* xptr;
261
 
262
  /* Load the ".line" section from the bfd if we haven't already.  */
263
  if (stash->line_section == 0)
264
    {
265
      asection *msec;
266
      unsigned long size;
267
 
268
      msec = bfd_get_section_by_name (stash->abfd, ".line");
269
      if (! msec)
270
        return false;
271
 
272
      size = bfd_get_section_size_before_reloc (msec);
273
      stash->line_section = (char *) bfd_alloc (stash->abfd, size);
274
 
275
      if (! stash->line_section)
276
        return false;
277
 
278
      if (! bfd_get_section_contents (stash->abfd, msec, stash->line_section, 0, size))
279
        {
280
          stash->line_section = 0;
281
          return false;
282
        }
283
 
284
      stash->line_section_end = stash->line_section + size;
285
    }
286
 
287
  xptr = stash->line_section + aUnit->stmt_list_offset;
288
  if (xptr < stash->line_section_end)
289
    {
290
      unsigned long eachLine;
291
 
292
      char* tblend;
293
      unsigned long base;
294
 
295
      /* First comes the length.  */
296
      tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr;
297
      xptr += 4;
298
 
299
      /* Then the base address for each address in the table.  */
300
      base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
301
      xptr += 4;
302
 
303
      /* How many line entrys?
304
         10 = 4 (line number) + 2 (pos in line) + 4 (address in line) */
305
      aUnit->line_count = (tblend - xptr) / 10;
306
 
307
      /* Allocate an array for the entries.  */
308
      aUnit->linenumber_table = (struct linenumber *)
309
        bfd_alloc (stash->abfd,
310
                   sizeof (struct linenumber) * aUnit->line_count);
311
 
312
      for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
313
        {
314
          /* A line number.  */
315
          aUnit->linenumber_table[eachLine].linenumber
316
            = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
317
          xptr += 4;
318
 
319
          /* Skip the position within the line.  */
320
          xptr += 2;
321
 
322
          /* And finally the address.  */
323
          aUnit->linenumber_table[eachLine].addr
324
            = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
325
          xptr += 4;
326
        }
327
    }
328
 
329
  return true;
330
}
331
 
332
/* Parse each function die in a compilation unit 'aUnit'.
333
   The first child die of 'aUnit' should be in 'aUnit->first_child',
334
   the result is placed in 'aUnit->func_list'.
335
   Return false if error; true otherwise.  */
336
 
337
static boolean
338
parse_functions_in_unit (stash, aUnit)
339
     struct dwarf1_debug* stash;
340
     struct dwarf1_unit* aUnit;
341
{
342
  char* eachDie;
343
 
344
  if (aUnit->first_child)
345
    for (eachDie = aUnit->first_child;
346
         eachDie < stash->debug_section_end;
347
         )
348
      {
349
        struct die_info eachDieInfo;
350
 
351
        if (! parse_die (stash->abfd, &eachDieInfo, eachDie))
352
          return false;
353
 
354
        if (eachDieInfo.tag == TAG_global_subroutine
355
            || eachDieInfo.tag == TAG_subroutine
356
            || eachDieInfo.tag == TAG_inlined_subroutine
357
            || eachDieInfo.tag == TAG_entry_point)
358
          {
359
            struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
360
 
361
            aFunc->name = eachDieInfo.name;
362
            aFunc->low_pc = eachDieInfo.low_pc;
363
            aFunc->high_pc = eachDieInfo.high_pc;
364
          }
365
 
366
        /* Move to next sibling, if none, end loop */
367
        if (eachDieInfo.sibling)
368
          eachDie = stash->debug_section + eachDieInfo.sibling;
369
        else
370
          break;
371
      }
372
 
373
  return true;
374
}
375
 
376
/* Find the nearest line to 'addr' in 'aUnit'.
377
   Return whether we found the line (or a function) without error.  */
378
 
379
static boolean
380
dwarf1_unit_find_nearest_line (stash, aUnit, addr,
381
                       filename_ptr, functionname_ptr,
382
                       linenumber_ptr)
383
  struct dwarf1_debug* stash;
384
  struct dwarf1_unit* aUnit;
385
  unsigned long addr;
386
  const char **filename_ptr;
387
  const char **functionname_ptr;
388
  unsigned int *linenumber_ptr;
389
{
390
  int line_p = false;
391
  int func_p = false;
392
 
393
  if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
394
    {
395
      if (aUnit->has_stmt_list)
396
        {
397
          unsigned long i;
398
          struct dwarf1_func* eachFunc;
399
 
400
          if (! aUnit->linenumber_table)
401
            {
402
              if (! parse_line_table (stash, aUnit))
403
                return false;
404
            }
405
 
406
          if (! aUnit->func_list)
407
            {
408
              if (! parse_functions_in_unit (stash, aUnit))
409
                return false;
410
            }
411
 
412
          for (i = 0; i < aUnit->line_count; i++)
413
            {
414
              if (aUnit->linenumber_table[i].addr <= addr
415
                  && addr < aUnit->linenumber_table[i+1].addr)
416
                {
417
                  *filename_ptr = aUnit->name;
418
                  *linenumber_ptr = aUnit->linenumber_table[i].linenumber;
419
                  line_p = true;
420
                  break;
421
                }
422
            }
423
 
424
          for (eachFunc = aUnit->func_list;
425
               eachFunc;
426
               eachFunc = eachFunc->prev)
427
            {
428
              if (eachFunc->low_pc <= addr
429
                  && addr < eachFunc->high_pc)
430
                {
431
                  *functionname_ptr = eachFunc->name;
432
                  func_p = true;
433
                  break;
434
                }
435
            }
436
        }
437
    }
438
 
439
  return line_p || func_p;
440
}
441
 
442
/* The DWARF 1 version of find_nearest line.
443
   Return true if the line is found without error.  */
444
 
445
boolean
446
_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
447
                              filename_ptr, functionname_ptr, linenumber_ptr)
448
     bfd *abfd;
449
     asection *section;
450
     asymbol **symbols ATTRIBUTE_UNUSED;
451
     bfd_vma offset;
452
     const char **filename_ptr;
453
     const char **functionname_ptr;
454
     unsigned int *linenumber_ptr;
455
{
456
  struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info;
457
 
458
  struct dwarf1_unit* eachUnit;
459
 
460
  /* What address are we looking for? */
461
  unsigned long addr = (unsigned long)(offset + section->vma);
462
 
463
  *filename_ptr = NULL;
464
  *functionname_ptr = NULL;
465
  *linenumber_ptr = 0;
466
 
467
  if (! stash)
468
    {
469
      asection *msec;
470
      unsigned long size;
471
 
472
      stash = elf_tdata (abfd)->dwarf1_find_line_info =
473
        (struct dwarf1_debug*) bfd_zalloc (abfd, sizeof (struct dwarf1_debug));
474
 
475
      if (! stash)
476
        return false;
477
 
478
      msec = bfd_get_section_by_name (abfd, ".debug");
479
      if (! msec)
480
        {
481
          /* No dwarf1 info.  Note that at this point the stash
482
             has been allocated, but contains zeros, this lets
483
             future calls to this function fail quicker.  */
484
          return false;
485
        }
486
 
487
      size = bfd_get_section_size_before_reloc (msec);
488
      stash->debug_section = (char *) bfd_alloc (abfd, size);
489
 
490
      if (! stash->debug_section)
491
        return false;
492
 
493
      if (! bfd_get_section_contents (abfd, msec, stash->debug_section, 0, size))
494
        {
495
          stash->debug_section = 0;
496
          return false;
497
        }
498
 
499
      stash->debug_section_end = stash->debug_section + size;
500
      stash->currentDie = stash->debug_section;
501
      stash->abfd = abfd;
502
    }
503
 
504
  /* A null debug_section indicates that there was no dwarf1 info
505
     or that an error occured while setting up the stash.  */
506
 
507
  if (! stash->debug_section)
508
    return false;
509
 
510
  /* Look at the previously parsed units to see if any contain
511
     the addr.  */
512
  for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev)
513
    {
514
      if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc)
515
        return dwarf1_unit_find_nearest_line (stash, eachUnit, addr,
516
                                              filename_ptr,
517
                                              functionname_ptr,
518
                                              linenumber_ptr);
519
    }
520
 
521
  while (stash->currentDie < stash->debug_section_end)
522
    {
523
      struct die_info aDieInfo;
524
 
525
      if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie))
526
        return false;
527
 
528
      if (aDieInfo.tag == TAG_compile_unit)
529
        {
530
          struct dwarf1_unit* aUnit
531
            = alloc_dwarf1_unit (stash);
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
}
565
 
566
/* EOF */

powered by: WebSVN 2.1.0

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