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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [stabs.c] - Blame information for rev 1771

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

Line No. Rev Author Line
1 578 markom
/* Stabs in sections linking support.
2
   Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
3
   Written by Ian Lance Taylor, Cygnus Support.
4
 
5
This file is part of BFD, the Binary File Descriptor library.
6
 
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
/* This file contains support for linking stabs in sections, as used
22
   on COFF and ELF.  */
23
 
24
#include "bfd.h"
25
#include "sysdep.h"
26
#include "libbfd.h"
27
#include "aout/stab_gnu.h"
28
 
29
#include <ctype.h>
30
 
31
/* Stabs entries use a 12 byte format:
32
     4 byte string table index
33
     1 byte stab type
34
     1 byte stab other field
35
     2 byte stab desc field
36
     4 byte stab value
37
   FIXME: This will have to change for a 64 bit object format.
38
 
39
   The stabs symbols are divided into compilation units.  For the
40
   first entry in each unit, the type of 0, the value is the length of
41
   the string table for this unit, and the desc field is the number of
42
   stabs symbols for this unit.  */
43
 
44
#define STRDXOFF (0)
45
#define TYPEOFF (4)
46
#define OTHEROFF (5)
47
#define DESCOFF (6)
48
#define VALOFF (8)
49
#define STABSIZE (12)
50
 
51
/* A hash table used for header files with N_BINCL entries.  */
52
 
53
struct stab_link_includes_table
54
{
55
  struct bfd_hash_table root;
56
};
57
 
58
/* A linked list of totals that we have found for a particular header
59
   file.  */
60
 
61
struct stab_link_includes_totals
62
{
63
  struct stab_link_includes_totals *next;
64
  bfd_vma total;
65
};
66
 
67
/* An entry in the header file hash table.  */
68
 
69
struct stab_link_includes_entry
70
{
71
  struct bfd_hash_entry root;
72
  /* List of totals we have found for this file.  */
73
  struct stab_link_includes_totals *totals;
74
};
75
 
76
/* Look up an entry in an the header file hash table.  */
77
 
78
#define stab_link_includes_lookup(table, string, create, copy) \
79
  ((struct stab_link_includes_entry *) \
80
   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
81
 
82
/* This structure is used to hold a list of N_BINCL symbols, some of
83
   which might be converted into N_EXCL symbols.  */
84
 
85
struct stab_excl_list
86
{
87
  /* The next symbol to convert.  */
88
  struct stab_excl_list *next;
89
  /* The offset to this symbol in the section contents.  */
90
  bfd_size_type offset;
91
  /* The value to use for the symbol.  */
92
  bfd_vma val;
93
  /* The type of this symbol (N_BINCL or N_EXCL).  */
94
  int type;
95
};
96
 
97
/* This structure is stored with each .stab section.  */
98
 
99
struct stab_section_info
100
{
101
  /* This is a linked list of N_BINCL symbols which should be
102
     converted into N_EXCL symbols.  */
103
  struct stab_excl_list *excls;
104
 
105
  /* This is used to map input stab offsets within their sections
106
     to output stab offsets, to take into account stabs that have
107
     been deleted.  If it is NULL, the output offsets are the same
108
     as the input offsets, because no stabs have been deleted from
109
     this section.  Otherwise the i'th entry is the number of
110
     bytes of stabs that have been deleted prior to the i'th
111
     stab.  */
112
  bfd_size_type *cumulative_skips;
113
 
114
  /* This is an array of string indices.  For each stab symbol, we
115
     store the string index here.  If a stab symbol should not be
116
     included in the final output, the string index is -1.  */
117
  bfd_size_type stridxs[1];
118
};
119
 
120
/* This structure is used to keep track of stabs in sections
121
   information while linking.  */
122
 
123
struct stab_info
124
{
125
  /* A hash table used to hold stabs strings.  */
126
  struct bfd_strtab_hash *strings;
127
  /* The header file hash table.  */
128
  struct stab_link_includes_table includes;
129
  /* The first .stabstr section.  */
130
  asection *stabstr;
131
};
132
 
133
static struct bfd_hash_entry *stab_link_includes_newfunc
134
  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
135
 
136
/* The function to create a new entry in the header file hash table.  */
137
 
138
static struct bfd_hash_entry *
139
stab_link_includes_newfunc (entry, table, string)
140
     struct bfd_hash_entry *entry;
141
     struct bfd_hash_table *table;
142
     const char *string;
143
{
144
  struct stab_link_includes_entry *ret =
145
    (struct stab_link_includes_entry *) entry;
146
 
147
  /* Allocate the structure if it has not already been allocated by a
148
     subclass.  */
149
  if (ret == (struct stab_link_includes_entry *) NULL)
150
    ret = ((struct stab_link_includes_entry *)
151
           bfd_hash_allocate (table,
152
                              sizeof (struct stab_link_includes_entry)));
153
  if (ret == (struct stab_link_includes_entry *) NULL)
154
    return (struct bfd_hash_entry *) ret;
155
 
156
  /* Call the allocation method of the superclass.  */
157
  ret = ((struct stab_link_includes_entry *)
158
         bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
159
  if (ret)
160
    {
161
      /* Set local fields.  */
162
      ret->totals = NULL;
163
    }
164
 
165
  return (struct bfd_hash_entry *) ret;
166
}
167
 
168
/* This function is called for each input file from the add_symbols
169
   pass of the linker.  */
170
 
171
boolean
172
_bfd_link_section_stabs (abfd, psinfo, stabsec, stabstrsec, psecinfo)
173
     bfd *abfd;
174
     PTR *psinfo;
175
     asection *stabsec;
176
     asection *stabstrsec;
177
     PTR *psecinfo;
178
{
179
  boolean first;
180
  struct stab_info *sinfo;
181
  bfd_size_type count;
182
  struct stab_section_info *secinfo;
183
  bfd_byte *stabbuf = NULL;
184
  bfd_byte *stabstrbuf = NULL;
185
  bfd_byte *sym, *symend;
186
  bfd_size_type stroff, next_stroff, skip;
187
  bfd_size_type *pstridx;
188
 
189
  if (stabsec->_raw_size == 0
190
      || stabstrsec->_raw_size == 0)
191
    {
192
      /* This file does not contain stabs debugging information.  */
193
      return true;
194
    }
195
 
196
  if (stabsec->_raw_size % STABSIZE != 0)
197
    {
198
      /* Something is wrong with the format of these stab symbols.
199
         Don't try to optimize them.  */
200
      return true;
201
    }
202
 
203
  if ((stabstrsec->flags & SEC_RELOC) != 0)
204
    {
205
      /* We shouldn't see relocations in the strings, and we aren't
206
         prepared to handle them.  */
207
      return true;
208
    }
209
 
210
  if ((stabsec->output_section != NULL
211
       && bfd_is_abs_section (stabsec->output_section))
212
      || (stabstrsec->output_section != NULL
213
          && bfd_is_abs_section (stabstrsec->output_section)))
214
    {
215
      /* At least one of the sections is being discarded from the
216
         link, so we should just ignore them.  */
217
      return true;
218
    }
219
 
220
  first = false;
221
 
222
  if (*psinfo == NULL)
223
    {
224
      /* Initialize the stabs information we need to keep track of.  */
225
      first = true;
226
      *psinfo = (PTR) bfd_alloc (abfd, sizeof (struct stab_info));
227
      if (*psinfo == NULL)
228
        goto error_return;
229
      sinfo = (struct stab_info *) *psinfo;
230
      sinfo->strings = _bfd_stringtab_init ();
231
      if (sinfo->strings == NULL)
232
        goto error_return;
233
      /* Make sure the first byte is zero.  */
234
      (void) _bfd_stringtab_add (sinfo->strings, "", true, true);
235
      if (! bfd_hash_table_init_n (&sinfo->includes.root,
236
                                   stab_link_includes_newfunc,
237
                                   251))
238
        goto error_return;
239
      sinfo->stabstr = bfd_make_section_anyway (abfd, ".stabstr");
240
      sinfo->stabstr->flags |= SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
241
    }
242
 
243
  sinfo = (struct stab_info *) *psinfo;
244
 
245
  /* Initialize the information we are going to store for this .stab
246
     section.  */
247
 
248
  count = stabsec->_raw_size / STABSIZE;
249
 
250
  *psecinfo = bfd_alloc (abfd,
251
                         (sizeof (struct stab_section_info)
252
                          + (count - 1) * sizeof (bfd_size_type)));
253
  if (*psecinfo == NULL)
254
    goto error_return;
255
 
256
  secinfo = (struct stab_section_info *) *psecinfo;
257
  secinfo->excls = NULL;
258
  secinfo->cumulative_skips = NULL;
259
  memset (secinfo->stridxs, 0, count * sizeof (bfd_size_type));
260
 
261
  /* Read the stabs information from abfd.  */
262
 
263
  stabbuf = (bfd_byte *) bfd_malloc (stabsec->_raw_size);
264
  stabstrbuf = (bfd_byte *) bfd_malloc (stabstrsec->_raw_size);
265
  if (stabbuf == NULL || stabstrbuf == NULL)
266
    goto error_return;
267
 
268
  if (! bfd_get_section_contents (abfd, stabsec, stabbuf, 0,
269
                                  stabsec->_raw_size)
270
      || ! bfd_get_section_contents (abfd, stabstrsec, stabstrbuf, 0,
271
                                     stabstrsec->_raw_size))
272
    goto error_return;
273
 
274
  /* Look through the stabs symbols, work out the new string indices,
275
     and identify N_BINCL symbols which can be eliminated.  */
276
 
277
  stroff = 0;
278
  next_stroff = 0;
279
  skip = 0;
280
 
281
  symend = stabbuf + stabsec->_raw_size;
282
  for (sym = stabbuf, pstridx = secinfo->stridxs;
283
       sym < symend;
284
       sym += STABSIZE, ++pstridx)
285
    {
286
      int type;
287
      const char *string;
288
 
289
      if (*pstridx != 0)
290
        {
291
          /* This symbol has already been handled by an N_BINCL pass.  */
292
          continue;
293
        }
294
 
295
      type = sym[TYPEOFF];
296
 
297
      if (type == 0)
298
        {
299
          /* Special type 0 stabs indicate the offset to the next
300
             string table.  We only copy the very first one.  */
301
          stroff = next_stroff;
302
          next_stroff += bfd_get_32 (abfd, sym + 8);
303
          if (! first)
304
            {
305
              *pstridx = (bfd_size_type) -1;
306
              ++skip;
307
              continue;
308
            }
309
          first = false;
310
        }
311
 
312
      /* Store the string in the hash table, and record the index.  */
313
      string = ((char *) stabstrbuf
314
                + stroff
315
                + bfd_get_32 (abfd, sym + STRDXOFF));
316
      *pstridx = _bfd_stringtab_add (sinfo->strings, string, true, true);
317
 
318
      /* An N_BINCL symbol indicates the start of the stabs entries
319
         for a header file.  We need to scan ahead to the next N_EINCL
320
         symbol, ignoring nesting, adding up all the characters in the
321
         symbol names, not including the file numbers in types (the
322
         first number after an open parenthesis).  */
323
      if (type == N_BINCL)
324
        {
325
          bfd_vma val;
326
          int nest;
327
          bfd_byte *incl_sym;
328
          struct stab_link_includes_entry *incl_entry;
329
          struct stab_link_includes_totals *t;
330
          struct stab_excl_list *ne;
331
 
332
          val = 0;
333
          nest = 0;
334
          for (incl_sym = sym + STABSIZE;
335
               incl_sym < symend;
336
               incl_sym += STABSIZE)
337
            {
338
              int incl_type;
339
 
340
              incl_type = incl_sym[TYPEOFF];
341
              if (incl_type == 0)
342
                break;
343
              else if (incl_type == N_EINCL)
344
                {
345
                  if (nest == 0)
346
                    break;
347
                  --nest;
348
                }
349
              else if (incl_type == N_BINCL)
350
                ++nest;
351
              else if (nest == 0)
352
                {
353
                  const char *str;
354
 
355
                  str = ((char *) stabstrbuf
356
                         + stroff
357
                         + bfd_get_32 (abfd, incl_sym + STRDXOFF));
358
                  for (; *str != '\0'; str++)
359
                    {
360
                      val += *str;
361
                      if (*str == '(')
362
                        {
363
                          /* Skip the file number.  */
364
                          ++str;
365
                          while (isdigit ((unsigned char) *str))
366
                            ++str;
367
                          --str;
368
                        }
369
                    }
370
                }
371
            }
372
 
373
          /* If we have already included a header file with the same
374
             value, then replaced this one with an N_EXCL symbol.  */
375
          incl_entry = stab_link_includes_lookup (&sinfo->includes, string,
376
                                                  true, true);
377
          if (incl_entry == NULL)
378
            goto error_return;
379
 
380
          for (t = incl_entry->totals; t != NULL; t = t->next)
381
            if (t->total == val)
382
              break;
383
 
384
          /* Record this symbol, so that we can set the value
385
             correctly.  */
386
          ne = (struct stab_excl_list *) bfd_alloc (abfd, sizeof *ne);
387
          if (ne == NULL)
388
            goto error_return;
389
          ne->offset = sym - stabbuf;
390
          ne->val = val;
391
          ne->type = N_BINCL;
392
          ne->next = secinfo->excls;
393
          secinfo->excls = ne;
394
 
395
          if (t == NULL)
396
            {
397
              /* This is the first time we have seen this header file
398
                 with this set of stabs strings.  */
399
              t = ((struct stab_link_includes_totals *)
400
                   bfd_hash_allocate (&sinfo->includes.root, sizeof *t));
401
              if (t == NULL)
402
                goto error_return;
403
              t->total = val;
404
              t->next = incl_entry->totals;
405
              incl_entry->totals = t;
406
            }
407
          else
408
            {
409
              bfd_size_type *incl_pstridx;
410
 
411
              /* We have seen this header file before.  Tell the final
412
                 pass to change the type to N_EXCL.  */
413
              ne->type = N_EXCL;
414
 
415
              /* Mark the skipped symbols.  */
416
 
417
              nest = 0;
418
              for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
419
                   incl_sym < symend;
420
                   incl_sym += STABSIZE, ++incl_pstridx)
421
                {
422
                  int incl_type;
423
 
424
                  incl_type = incl_sym[TYPEOFF];
425
 
426
                  if (incl_type == N_EINCL)
427
                    {
428
                      if (nest == 0)
429
                        {
430
                          *incl_pstridx = (bfd_size_type) -1;
431
                          ++skip;
432
                          break;
433
                        }
434
                      --nest;
435
                    }
436
                  else if (incl_type == N_BINCL)
437
                    ++nest;
438
                  else if (nest == 0)
439
                    {
440
                      *incl_pstridx = (bfd_size_type) -1;
441
                      ++skip;
442
                    }
443
                }
444
            }
445
        }
446
    }
447
 
448
  free (stabbuf);
449
  stabbuf = NULL;
450
  free (stabstrbuf);
451
  stabstrbuf = NULL;
452
 
453
  /* We need to set the section sizes such that the linker will
454
     compute the output section sizes correctly.  We set the .stab
455
     size to not include the entries we don't want.  We set
456
     SEC_EXCLUDE for the .stabstr section, so that it will be dropped
457
     from the link.  We record the size of the strtab in the first
458
     .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
459
     for that section.  */
460
  stabsec->_cooked_size = (count - skip) * STABSIZE;
461
  if (stabsec->_cooked_size == 0)
462
    stabsec->flags |= SEC_EXCLUDE;
463
  stabstrsec->flags |= SEC_EXCLUDE;
464
  sinfo->stabstr->_cooked_size = _bfd_stringtab_size (sinfo->strings);
465
 
466
  /* Calculate the `cumulative_skips' array now that stabs have been
467
     deleted for this section.  */
468
 
469
  if (skip != 0)
470
    {
471
      bfd_size_type i, offset;
472
      bfd_size_type *pskips;
473
 
474
      secinfo->cumulative_skips =
475
        (bfd_size_type *) bfd_alloc (abfd, count * sizeof (bfd_size_type));
476
      if (secinfo->cumulative_skips == NULL)
477
        goto error_return;
478
 
479
      pskips = secinfo->cumulative_skips;
480
      pstridx = secinfo->stridxs;
481
      offset = 0;
482
 
483
      for (i = 0; i < count; i++, pskips++, pstridx++)
484
        {
485
          *pskips = offset;
486
          if (*pstridx == (bfd_size_type) -1)
487
            offset += STABSIZE;
488
        }
489
 
490
      BFD_ASSERT (offset != 0);
491
    }
492
 
493
  return true;
494
 
495
 error_return:
496
  if (stabbuf != NULL)
497
    free (stabbuf);
498
  if (stabstrbuf != NULL)
499
    free (stabstrbuf);
500
  return false;
501
}
502
 
503
/* Write out the stab section.  This is called with the relocated
504
   contents.  */
505
 
506
boolean
507
_bfd_write_section_stabs (output_bfd, psinfo, stabsec, psecinfo, contents)
508
     bfd *output_bfd;
509
     PTR *psinfo;
510
     asection *stabsec;
511
     PTR *psecinfo;
512
     bfd_byte *contents;
513
{
514
  struct stab_info *sinfo;
515
  struct stab_section_info *secinfo;
516
  struct stab_excl_list *e;
517
  bfd_byte *sym, *tosym, *symend;
518
  bfd_size_type *pstridx;
519
 
520
  sinfo = (struct stab_info *) *psinfo;
521
  secinfo = (struct stab_section_info *) *psecinfo;
522
 
523
  if (secinfo == NULL)
524
    return bfd_set_section_contents (output_bfd, stabsec->output_section,
525
                                     contents, stabsec->output_offset,
526
                                     stabsec->_raw_size);
527
 
528
  /* Handle each N_BINCL entry.  */
529
  for (e = secinfo->excls; e != NULL; e = e->next)
530
    {
531
      bfd_byte *excl_sym;
532
 
533
      BFD_ASSERT (e->offset < stabsec->_raw_size);
534
      excl_sym = contents + e->offset;
535
      bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
536
      excl_sym[TYPEOFF] = e->type;
537
    }
538
 
539
  /* Copy over all the stabs symbols, omitting the ones we don't want,
540
     and correcting the string indices for those we do want.  */
541
  tosym = contents;
542
  symend = contents + stabsec->_raw_size;
543
  for (sym = contents, pstridx = secinfo->stridxs;
544
       sym < symend;
545
       sym += STABSIZE, ++pstridx)
546
    {
547
      if (*pstridx != (bfd_size_type) -1)
548
        {
549
          if (tosym != sym)
550
            memcpy (tosym, sym, STABSIZE);
551
          bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
552
 
553
          if (sym[TYPEOFF] == 0)
554
            {
555
              /* This is the header symbol for the stabs section.  We
556
                 don't really need one, since we have merged all the
557
                 input stabs sections into one, but we generate one
558
                 for the benefit of readers which expect to see one.  */
559
              BFD_ASSERT (sym == contents);
560
              bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
561
                          tosym + VALOFF);
562
              bfd_put_16 (output_bfd,
563
                          stabsec->output_section->_raw_size / STABSIZE - 1,
564
                          tosym + DESCOFF);
565
            }
566
 
567
          tosym += STABSIZE;
568
        }
569
    }
570
 
571
  BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->_cooked_size);
572
 
573
  return bfd_set_section_contents (output_bfd, stabsec->output_section,
574
                                   contents, stabsec->output_offset,
575
                                   stabsec->_cooked_size);
576
}
577
 
578
/* Write out the .stabstr section.  */
579
 
580
boolean
581
_bfd_write_stab_strings (output_bfd, psinfo)
582
     bfd *output_bfd;
583
     PTR *psinfo;
584
{
585
  struct stab_info *sinfo;
586
 
587
  sinfo = (struct stab_info *) *psinfo;
588
 
589
  if (sinfo == NULL)
590
    return true;
591
 
592
  if (bfd_is_abs_section (sinfo->stabstr->output_section))
593
    {
594
      /* The section was discarded from the link.  */
595
      return true;
596
    }
597
 
598
  BFD_ASSERT ((sinfo->stabstr->output_offset
599
               + _bfd_stringtab_size (sinfo->strings))
600
              <= sinfo->stabstr->output_section->_raw_size);
601
 
602
  if (bfd_seek (output_bfd,
603
                (sinfo->stabstr->output_section->filepos
604
                 + sinfo->stabstr->output_offset),
605
                SEEK_SET) != 0)
606
    return false;
607
 
608
  if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
609
    return false;
610
 
611
  /* We no longer need the stabs information.  */
612
  _bfd_stringtab_free (sinfo->strings);
613
  bfd_hash_table_free (&sinfo->includes.root);
614
 
615
  return true;
616
}
617
 
618
/* Adjust an address in the .stab section.  Given OFFSET within
619
   STABSEC, this returns the new offset in the adjusted stab section,
620
   or -1 if the address refers to a stab which has been removed.  */
621
 
622
bfd_vma
623
_bfd_stab_section_offset (output_bfd, psinfo, stabsec, psecinfo, offset)
624
     bfd *output_bfd ATTRIBUTE_UNUSED;
625
     PTR *psinfo ATTRIBUTE_UNUSED;
626
     asection *stabsec;
627
     PTR *psecinfo;
628
     bfd_vma offset;
629
{
630
  struct stab_section_info *secinfo;
631
 
632
  secinfo = (struct stab_section_info *) *psecinfo;
633
 
634
  if (secinfo == NULL)
635
    return offset;
636
 
637
  if (offset >= stabsec->_raw_size)
638
    return offset - (stabsec->_cooked_size - stabsec->_raw_size);
639
 
640
  if (secinfo->cumulative_skips)
641
    {
642
      bfd_vma i;
643
 
644
      i = offset / STABSIZE;
645
 
646
      if (secinfo->stridxs [i] == (bfd_size_type) -1)
647
        return (bfd_vma) -1;
648
 
649
      return offset - secinfo->cumulative_skips [i];
650
    }
651
 
652
  return offset;
653
}

powered by: WebSVN 2.1.0

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