obj-elf.c revision 89857
1/* ELF object file format
2   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3   Free Software Foundation, Inc.
4
5   This file is part of GAS, the GNU Assembler.
6
7   GAS is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2,
10   or (at your option) any later version.
11
12   GAS is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15   the GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with GAS; see the file COPYING.  If not, write to the Free
19   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20   02111-1307, USA.  */
21
22#define OBJ_HEADER "obj-elf.h"
23#include "as.h"
24#include "safe-ctype.h"
25#include "subsegs.h"
26#include "obstack.h"
27
28#ifndef ECOFF_DEBUGGING
29#define ECOFF_DEBUGGING 0
30#else
31#define NEED_ECOFF_DEBUG
32#endif
33
34#ifdef NEED_ECOFF_DEBUG
35#include "ecoff.h"
36#endif
37
38#ifdef TC_ALPHA
39#include "elf/alpha.h"
40#endif
41
42#ifdef TC_MIPS
43#include "elf/mips.h"
44#endif
45
46#ifdef TC_PPC
47#include "elf/ppc.h"
48#endif
49
50#ifdef TC_I370
51#include "elf/i370.h"
52#endif
53
54static bfd_vma elf_s_get_size PARAMS ((symbolS *));
55static void elf_s_set_size PARAMS ((symbolS *, bfd_vma));
56static bfd_vma elf_s_get_align PARAMS ((symbolS *));
57static void elf_s_set_align PARAMS ((symbolS *, bfd_vma));
58static void elf_s_set_other PARAMS ((symbolS *, int));
59static int elf_sec_sym_ok_for_reloc PARAMS ((asection *));
60static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR));
61static void build_group_lists PARAMS ((bfd *, asection *, PTR));
62static int elf_separate_stab_sections PARAMS ((void));
63static void elf_init_stab_section PARAMS ((segT));
64
65#ifdef NEED_ECOFF_DEBUG
66static boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
67static void elf_set_index PARAMS ((asymbol *, bfd_size_type));
68#endif
69
70static void obj_elf_line PARAMS ((int));
71void obj_elf_version PARAMS ((int));
72static void obj_elf_size PARAMS ((int));
73static void obj_elf_type PARAMS ((int));
74static void obj_elf_ident PARAMS ((int));
75static void obj_elf_weak PARAMS ((int));
76static void obj_elf_local PARAMS ((int));
77static void obj_elf_visibility PARAMS ((int));
78static void obj_elf_change_section
79  PARAMS ((const char *, int, int, int, const char *, int));
80static int obj_elf_parse_section_letters PARAMS ((char *, size_t));
81static int obj_elf_section_word PARAMS ((char *, size_t));
82static char *obj_elf_section_name PARAMS ((void));
83static int obj_elf_section_type PARAMS ((char *, size_t));
84static void obj_elf_symver PARAMS ((int));
85static void obj_elf_subsection PARAMS ((int));
86static void obj_elf_popsection PARAMS ((int));
87
88static const pseudo_typeS elf_pseudo_table[] =
89{
90  {"comm", obj_elf_common, 0},
91  {"common", obj_elf_common, 1},
92  {"ident", obj_elf_ident, 0},
93  {"local", obj_elf_local, 0},
94  {"previous", obj_elf_previous, 0},
95  {"section", obj_elf_section, 0},
96  {"section.s", obj_elf_section, 0},
97  {"sect", obj_elf_section, 0},
98  {"sect.s", obj_elf_section, 0},
99  {"pushsection", obj_elf_section, 1},
100  {"popsection", obj_elf_popsection, 0},
101  {"size", obj_elf_size, 0},
102  {"type", obj_elf_type, 0},
103  {"version", obj_elf_version, 0},
104  {"weak", obj_elf_weak, 0},
105
106  /* These define symbol visibility.  */
107  {"internal", obj_elf_visibility, STV_INTERNAL},
108  {"hidden", obj_elf_visibility, STV_HIDDEN},
109  {"protected", obj_elf_visibility, STV_PROTECTED},
110
111  /* These are used for stabs-in-elf configurations.  */
112  {"line", obj_elf_line, 0},
113
114  /* This is a GNU extension to handle symbol versions.  */
115  {"symver", obj_elf_symver, 0},
116
117  /* A GNU extension to change subsection only.  */
118  {"subsection", obj_elf_subsection, 0},
119
120  /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
121  {"vtable_inherit", (void (*) PARAMS ((int))) &obj_elf_vtable_inherit, 0},
122  {"vtable_entry", (void (*) PARAMS ((int))) &obj_elf_vtable_entry, 0},
123
124  /* These are used for dwarf.  */
125  {"2byte", cons, 2},
126  {"4byte", cons, 4},
127  {"8byte", cons, 8},
128
129  /* We need to trap the section changing calls to handle .previous.  */
130  {"data", obj_elf_data, 0},
131  {"text", obj_elf_text, 0},
132
133  /* End sentinel.  */
134  {NULL, NULL, 0},
135};
136
137static const pseudo_typeS ecoff_debug_pseudo_table[] =
138{
139#ifdef NEED_ECOFF_DEBUG
140  /* COFF style debugging information for ECOFF. .ln is not used; .loc
141     is used instead.  */
142  { "def",	ecoff_directive_def,	0 },
143  { "dim",	ecoff_directive_dim,	0 },
144  { "endef",	ecoff_directive_endef,	0 },
145  { "file",	ecoff_directive_file,	0 },
146  { "scl",	ecoff_directive_scl,	0 },
147  { "tag",	ecoff_directive_tag,	0 },
148  { "val",	ecoff_directive_val,	0 },
149
150  /* COFF debugging requires pseudo-ops .size and .type, but ELF
151     already has meanings for those.  We use .esize and .etype
152     instead.  These are only generated by gcc anyhow.  */
153  { "esize",	ecoff_directive_size,	0 },
154  { "etype",	ecoff_directive_type,	0 },
155
156  /* ECOFF specific debugging information.  */
157  { "begin",	ecoff_directive_begin,	0 },
158  { "bend",	ecoff_directive_bend,	0 },
159  { "end",	ecoff_directive_end,	0 },
160  { "ent",	ecoff_directive_ent,	0 },
161  { "fmask",	ecoff_directive_fmask,	0 },
162  { "frame",	ecoff_directive_frame,	0 },
163  { "loc",	ecoff_directive_loc,	0 },
164  { "mask",	ecoff_directive_mask,	0 },
165
166  /* Other ECOFF directives.  */
167  { "extern",	ecoff_directive_extern,	0 },
168
169  /* These are used on Irix.  I don't know how to implement them.  */
170  { "alias",	s_ignore,		0 },
171  { "bgnb",	s_ignore,		0 },
172  { "endb",	s_ignore,		0 },
173  { "lab",	s_ignore,		0 },
174  { "noalias",	s_ignore,		0 },
175  { "verstamp",	s_ignore,		0 },
176  { "vreg",	s_ignore,		0 },
177#endif
178
179  {NULL, NULL, 0}			/* end sentinel */
180};
181
182#undef NO_RELOC
183#include "aout/aout64.h"
184
185/* This is called when the assembler starts.  */
186
187void
188elf_begin ()
189{
190  /* Add symbols for the known sections to the symbol table.  */
191  symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
192								TEXT_SECTION_NAME)));
193  symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
194								DATA_SECTION_NAME)));
195  symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
196								BSS_SECTION_NAME)));
197}
198
199void
200elf_pop_insert ()
201{
202  pop_insert (elf_pseudo_table);
203  if (ECOFF_DEBUGGING)
204    pop_insert (ecoff_debug_pseudo_table);
205}
206
207static bfd_vma
208elf_s_get_size (sym)
209     symbolS *sym;
210{
211  return S_GET_SIZE (sym);
212}
213
214static void
215elf_s_set_size (sym, sz)
216     symbolS *sym;
217     bfd_vma sz;
218{
219  S_SET_SIZE (sym, sz);
220}
221
222static bfd_vma
223elf_s_get_align (sym)
224     symbolS *sym;
225{
226  return S_GET_ALIGN (sym);
227}
228
229static void
230elf_s_set_align (sym, align)
231     symbolS *sym;
232     bfd_vma align;
233{
234  S_SET_ALIGN (sym, align);
235}
236
237int
238elf_s_get_other (sym)
239     symbolS *sym;
240{
241  return elf_symbol (symbol_get_bfdsym (sym))->internal_elf_sym.st_other;
242}
243
244static void
245elf_s_set_other (sym, other)
246     symbolS *sym;
247     int other;
248{
249  S_SET_OTHER (sym, other);
250}
251
252static int
253elf_sec_sym_ok_for_reloc (sec)
254     asection *sec;
255{
256  return obj_sec_sym_ok_for_reloc (sec);
257}
258
259void
260elf_file_symbol (s)
261     const char *s;
262{
263  symbolS *sym;
264
265  sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0);
266  symbol_set_frag (sym, &zero_address_frag);
267  symbol_get_bfdsym (sym)->flags |= BSF_FILE;
268
269  if (symbol_rootP != sym)
270    {
271      symbol_remove (sym, &symbol_rootP, &symbol_lastP);
272      symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
273#ifdef DEBUG
274      verify_symbol_chain (symbol_rootP, symbol_lastP);
275#endif
276    }
277
278#ifdef NEED_ECOFF_DEBUG
279  ecoff_new_file (s);
280#endif
281}
282
283void
284obj_elf_common (is_common)
285     int is_common;
286{
287  char *name;
288  char c;
289  char *p;
290  int temp, size;
291  symbolS *symbolP;
292  int have_align;
293
294  if (flag_mri && is_common)
295    {
296      s_mri_common (0);
297      return;
298    }
299
300  name = input_line_pointer;
301  c = get_symbol_end ();
302  /* just after name is now '\0' */
303  p = input_line_pointer;
304  *p = c;
305  SKIP_WHITESPACE ();
306  if (*input_line_pointer != ',')
307    {
308      as_bad (_("expected comma after symbol-name"));
309      ignore_rest_of_line ();
310      return;
311    }
312  input_line_pointer++;		/* skip ',' */
313  if ((temp = get_absolute_expression ()) < 0)
314    {
315      as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
316      ignore_rest_of_line ();
317      return;
318    }
319  size = temp;
320  *p = 0;
321  symbolP = symbol_find_or_make (name);
322  *p = c;
323  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
324    {
325      as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
326      ignore_rest_of_line ();
327      return;
328    }
329  if (S_GET_VALUE (symbolP) != 0)
330    {
331      if (S_GET_VALUE (symbolP) != (valueT) size)
332	{
333	  as_warn (_("length of .comm \"%s\" is already %ld; not changed to %d"),
334		   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
335	}
336    }
337  know (symbolP->sy_frag == &zero_address_frag);
338  if (*input_line_pointer != ',')
339    have_align = 0;
340  else
341    {
342      have_align = 1;
343      input_line_pointer++;
344      SKIP_WHITESPACE ();
345    }
346  if (! have_align || *input_line_pointer != '"')
347    {
348      if (! have_align)
349	temp = 0;
350      else
351	{
352	  temp = get_absolute_expression ();
353	  if (temp < 0)
354	    {
355	      temp = 0;
356	      as_warn (_("common alignment negative; 0 assumed"));
357	    }
358	}
359      if (symbol_get_obj (symbolP)->local)
360	{
361	  segT old_sec;
362	  int old_subsec;
363	  char *pfrag;
364	  int align;
365
366	/* allocate_bss: */
367	  old_sec = now_seg;
368	  old_subsec = now_subseg;
369	  if (temp)
370	    {
371	      /* convert to a power of 2 alignment */
372	      for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
373	      if (temp != 1)
374		{
375		  as_bad (_("common alignment not a power of 2"));
376		  ignore_rest_of_line ();
377		  return;
378		}
379	    }
380	  else
381	    align = 0;
382	  record_alignment (bss_section, align);
383	  subseg_set (bss_section, 0);
384	  if (align)
385	    frag_align (align, 0, 0);
386	  if (S_GET_SEGMENT (symbolP) == bss_section)
387	    symbol_get_frag (symbolP)->fr_symbol = 0;
388	  symbol_set_frag (symbolP, frag_now);
389	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
390			    (offsetT) size, (char *) 0);
391	  *pfrag = 0;
392	  S_SET_SIZE (symbolP, size);
393	  S_SET_SEGMENT (symbolP, bss_section);
394	  S_CLEAR_EXTERNAL (symbolP);
395	  subseg_set (old_sec, old_subsec);
396	}
397      else
398	{
399	allocate_common:
400	  S_SET_VALUE (symbolP, (valueT) size);
401	  S_SET_ALIGN (symbolP, temp);
402	  S_SET_EXTERNAL (symbolP);
403	  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
404	}
405    }
406  else
407    {
408      input_line_pointer++;
409      /* @@ Some use the dot, some don't.  Can we get some consistency??  */
410      if (*input_line_pointer == '.')
411	input_line_pointer++;
412      /* @@ Some say data, some say bss.  */
413      if (strncmp (input_line_pointer, "bss\"", 4)
414	  && strncmp (input_line_pointer, "data\"", 5))
415	{
416	  while (*--input_line_pointer != '"')
417	    ;
418	  input_line_pointer--;
419	  goto bad_common_segment;
420	}
421      while (*input_line_pointer++ != '"')
422	;
423      goto allocate_common;
424    }
425
426  symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
427
428  demand_empty_rest_of_line ();
429  return;
430
431  {
432  bad_common_segment:
433    p = input_line_pointer;
434    while (*p && *p != '\n')
435      p++;
436    c = *p;
437    *p = '\0';
438    as_bad (_("bad .common segment %s"), input_line_pointer + 1);
439    *p = c;
440    input_line_pointer = p;
441    ignore_rest_of_line ();
442    return;
443  }
444}
445
446static void
447obj_elf_local (ignore)
448     int ignore ATTRIBUTE_UNUSED;
449{
450  char *name;
451  int c;
452  symbolS *symbolP;
453
454  do
455    {
456      name = input_line_pointer;
457      c = get_symbol_end ();
458      symbolP = symbol_find_or_make (name);
459      *input_line_pointer = c;
460      SKIP_WHITESPACE ();
461      S_CLEAR_EXTERNAL (symbolP);
462      symbol_get_obj (symbolP)->local = 1;
463      if (c == ',')
464	{
465	  input_line_pointer++;
466	  SKIP_WHITESPACE ();
467	  if (*input_line_pointer == '\n')
468	    c = '\n';
469	}
470    }
471  while (c == ',');
472  demand_empty_rest_of_line ();
473}
474
475static void
476obj_elf_weak (ignore)
477     int ignore ATTRIBUTE_UNUSED;
478{
479  char *name;
480  int c;
481  symbolS *symbolP;
482
483  do
484    {
485      name = input_line_pointer;
486      c = get_symbol_end ();
487      symbolP = symbol_find_or_make (name);
488      *input_line_pointer = c;
489      SKIP_WHITESPACE ();
490      S_SET_WEAK (symbolP);
491      symbol_get_obj (symbolP)->local = 1;
492      if (c == ',')
493	{
494	  input_line_pointer++;
495	  SKIP_WHITESPACE ();
496	  if (*input_line_pointer == '\n')
497	    c = '\n';
498	}
499    }
500  while (c == ',');
501  demand_empty_rest_of_line ();
502}
503
504static void
505obj_elf_visibility (visibility)
506     int visibility;
507{
508  char *name;
509  int c;
510  symbolS *symbolP;
511  asymbol *bfdsym;
512  elf_symbol_type *elfsym;
513
514  do
515    {
516      name = input_line_pointer;
517      c = get_symbol_end ();
518      symbolP = symbol_find_or_make (name);
519      *input_line_pointer = c;
520
521      SKIP_WHITESPACE ();
522
523      bfdsym = symbol_get_bfdsym (symbolP);
524      elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
525
526      assert (elfsym);
527
528      elfsym->internal_elf_sym.st_other = visibility;
529
530      if (c == ',')
531	{
532	  input_line_pointer ++;
533
534	  SKIP_WHITESPACE ();
535
536	  if (*input_line_pointer == '\n')
537	    c = '\n';
538	}
539    }
540  while (c == ',');
541
542  demand_empty_rest_of_line ();
543}
544
545static segT previous_section;
546static int previous_subsection;
547
548struct section_stack
549{
550  struct section_stack *next;
551  segT seg, prev_seg;
552  int subseg, prev_subseg;
553};
554
555static struct section_stack *section_stack;
556
557/* Handle the .section pseudo-op.  This code supports two different
558   syntaxes.
559
560   The first is found on Solaris, and looks like
561       .section ".sec1",#alloc,#execinstr,#write
562   Here the names after '#' are the SHF_* flags to turn on for the
563   section.  I'm not sure how it determines the SHT_* type (BFD
564   doesn't really give us control over the type, anyhow).
565
566   The second format is found on UnixWare, and probably most SVR4
567   machines, and looks like
568       .section .sec1,"a",@progbits
569   The quoted string may contain any combination of a, w, x, and
570   represents the SHF_* flags to turn on for the section.  The string
571   beginning with '@' can be progbits or nobits.  There should be
572   other possibilities, but I don't know what they are.  In any case,
573   BFD doesn't really let us set the section type.  */
574
575/* Certain named sections have particular defined types, listed on p.
576   4-19 of the ABI.  */
577struct special_section
578{
579  const char *name;
580  int type;
581  int attributes;
582};
583
584static struct special_section const special_sections[] =
585{
586  { ".bss",	SHT_NOBITS,	SHF_ALLOC + SHF_WRITE		},
587  { ".comment",	SHT_PROGBITS,	0				},
588  { ".data",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE		},
589  { ".data1",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE		},
590  { ".debug",	SHT_PROGBITS,	0				},
591  { ".fini",	SHT_PROGBITS,	SHF_ALLOC + SHF_EXECINSTR	},
592  { ".init",	SHT_PROGBITS,	SHF_ALLOC + SHF_EXECINSTR	},
593  { ".line",	SHT_PROGBITS,	0				},
594  { ".note",	SHT_NOTE,	0				},
595  { ".rodata",	SHT_PROGBITS,	SHF_ALLOC			},
596  { ".rodata1",	SHT_PROGBITS,	SHF_ALLOC			},
597  { ".text",	SHT_PROGBITS,	SHF_ALLOC + SHF_EXECINSTR	},
598
599#ifdef ELF_TC_SPECIAL_SECTIONS
600  ELF_TC_SPECIAL_SECTIONS
601#endif
602
603#if 0
604  /* The following section names are special, but they can not
605     reasonably appear in assembler code.  Some of the attributes are
606     processor dependent.  */
607  { ".dynamic",	SHT_DYNAMIC,	SHF_ALLOC /* + SHF_WRITE */ 	},
608  { ".dynstr",	SHT_STRTAB,	SHF_ALLOC			},
609  { ".dynsym",	SHT_DYNSYM,	SHF_ALLOC			},
610  { ".got",	SHT_PROGBITS,	0				},
611  { ".hash",	SHT_HASH,	SHF_ALLOC			},
612  { ".interp",	SHT_PROGBITS,	/* SHF_ALLOC */			},
613  { ".plt",	SHT_PROGBITS,	0				},
614  { ".shstrtab",SHT_STRTAB,	0				},
615  { ".strtab",	SHT_STRTAB,	/* SHF_ALLOC */			},
616  { ".symtab",	SHT_SYMTAB,	/* SHF_ALLOC */			},
617#endif
618
619  { NULL,	0,		0				}
620};
621
622static void
623obj_elf_change_section (name, type, attr, entsize, group_name, push)
624     const char *name;
625     int type;
626     int attr;
627     int entsize;
628     const char *group_name;
629     int push;
630{
631  asection *old_sec;
632  segT sec;
633  flagword flags;
634  int i;
635
636#ifdef md_flush_pending_output
637  md_flush_pending_output ();
638#endif
639
640  /* Switch to the section, creating it if necessary.  */
641  if (push)
642    {
643      struct section_stack *elt;
644      elt = xmalloc (sizeof (struct section_stack));
645      elt->next = section_stack;
646      elt->seg = now_seg;
647      elt->prev_seg = previous_section;
648      elt->subseg = now_subseg;
649      elt->prev_subseg = previous_subsection;
650      section_stack = elt;
651    }
652  previous_section = now_seg;
653  previous_subsection = now_subseg;
654
655  old_sec = bfd_get_section_by_name (stdoutput, name);
656  sec = subseg_new (name, 0);
657
658  /* See if this is one of the special sections.  */
659  for (i = 0; special_sections[i].name != NULL; i++)
660    if (strcmp (name, special_sections[i].name) == 0)
661      {
662	if (type == SHT_NULL)
663	  type = special_sections[i].type;
664	else if (type != special_sections[i].type)
665	  {
666	    if (old_sec == NULL)
667	      {
668		as_warn (_("setting incorrect section type for %s"), name);
669	      }
670	    else
671	      {
672		as_warn (_("ignoring incorrect section type for %s"), name);
673		type = special_sections[i].type;
674	      }
675	  }
676	if ((attr &~ special_sections[i].attributes) != 0
677	    && old_sec == NULL)
678	  {
679	    /* As a GNU extension, we permit a .note section to be
680	       allocatable.  If the linker sees an allocateable .note
681	       section, it will create a PT_NOTE segment in the output
682	       file.  */
683	    if (strcmp (name, ".note") != 0
684		|| attr != SHF_ALLOC)
685	      as_warn (_("setting incorrect section attributes for %s"),
686		       name);
687	  }
688	attr |= special_sections[i].attributes;
689	break;
690      }
691
692  /* Convert ELF type and flags to BFD flags.  */
693  flags = (SEC_RELOC
694	   | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
695	   | ((attr & SHF_ALLOC) ? SEC_ALLOC : 0)
696	   | (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
697	   | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)
698	   | ((attr & SHF_MERGE) ? SEC_MERGE : 0)
699	   | ((attr & SHF_STRINGS) ? SEC_STRINGS : 0));
700#ifdef md_elf_section_flags
701  flags = md_elf_section_flags (flags, attr, type);
702#endif
703
704  if (old_sec == NULL)
705    {
706      symbolS *secsym;
707
708      /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
709      if (type == SHT_NOBITS)
710        seg_info (sec)->bss = 1;
711
712      bfd_set_section_flags (stdoutput, sec, flags);
713      if (flags & SEC_MERGE)
714	sec->entsize = entsize;
715      elf_group_name (sec) = group_name;
716
717      /* Add a symbol for this section to the symbol table.  */
718      secsym = symbol_find (name);
719      if (secsym != NULL)
720	symbol_set_bfdsym (secsym, sec->symbol);
721      else
722        symbol_table_insert (section_symbol (sec));
723    }
724  else if (attr != 0)
725    {
726      /* If section attributes are specified the second time we see a
727	 particular section, then check that they are the same as we
728	 saw the first time.  */
729      if ((old_sec->flags ^ flags)
730	  & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
731	     | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS))
732	as_warn (_("ignoring changed section attributes for %s"), name);
733      else if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
734	as_warn (_("ignoring changed section entity size for %s"), name);
735      else if ((attr & SHF_GROUP) != 0
736	       && strcmp (elf_group_name (old_sec), group_name) != 0)
737	as_warn (_("ignoring new section group for %s"), name);
738    }
739
740#ifdef md_elf_section_change_hook
741  md_elf_section_change_hook ();
742#endif
743}
744
745static int
746obj_elf_parse_section_letters (str, len)
747     char *str;
748     size_t len;
749{
750  int attr = 0;
751
752  while (len > 0)
753    {
754      switch (*str)
755	{
756	case 'a':
757	  attr |= SHF_ALLOC;
758	  break;
759	case 'w':
760	  attr |= SHF_WRITE;
761	  break;
762	case 'x':
763	  attr |= SHF_EXECINSTR;
764	  break;
765	case 'M':
766	  attr |= SHF_MERGE;
767	  break;
768	case 'S':
769	  attr |= SHF_STRINGS;
770	  break;
771	case 'G':
772	  attr |= SHF_GROUP;
773	  break;
774	/* Compatibility.  */
775	case 'm':
776	  if (*(str - 1) == 'a')
777	    {
778	      attr |= SHF_MERGE;
779	      if (len > 1 && str[1] == 's')
780		{
781		  attr |= SHF_STRINGS;
782		  str++, len--;
783		}
784	      break;
785	    }
786	default:
787	  {
788	    char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G");
789#ifdef md_elf_section_letter
790	    int md_attr = md_elf_section_letter (*str, &bad_msg);
791	    if (md_attr >= 0)
792	      attr |= md_attr;
793	    else
794#endif
795	      {
796		as_warn ("%s", bad_msg);
797		attr = -1;
798	      }
799	  }
800	  break;
801	}
802      str++, len--;
803    }
804
805  return attr;
806}
807
808static int
809obj_elf_section_word (str, len)
810     char *str;
811     size_t len;
812{
813  if (len == 5 && strncmp (str, "write", 5) == 0)
814    return SHF_WRITE;
815  if (len == 5 && strncmp (str, "alloc", 5) == 0)
816    return SHF_ALLOC;
817  if (len == 9 && strncmp (str, "execinstr", 9) == 0)
818    return SHF_EXECINSTR;
819
820#ifdef md_elf_section_word
821  {
822    int md_attr = md_elf_section_word (str, len);
823    if (md_attr >= 0)
824      return md_attr;
825  }
826#endif
827
828  as_warn (_("unrecognized section attribute"));
829  return 0;
830}
831
832static int
833obj_elf_section_type (str, len)
834     char *str;
835     size_t len;
836{
837  if (len == 8 && strncmp (str, "progbits", 8) == 0)
838    return SHT_PROGBITS;
839  if (len == 6 && strncmp (str, "nobits", 6) == 0)
840    return SHT_NOBITS;
841
842#ifdef md_elf_section_type
843  {
844    int md_type = md_elf_section_type (str, len);
845    if (md_type >= 0)
846      return md_type;
847  }
848#endif
849
850  as_warn (_("unrecognized section type"));
851  return 0;
852}
853
854/* Get name of section.  */
855static char *
856obj_elf_section_name ()
857{
858  char *name;
859
860  SKIP_WHITESPACE ();
861  if (*input_line_pointer == '"')
862    {
863      int dummy;
864
865      name = demand_copy_C_string (&dummy);
866      if (name == NULL)
867	{
868	  ignore_rest_of_line ();
869	  return NULL;
870	}
871    }
872  else
873    {
874      char *end = input_line_pointer;
875
876      while (0 == strchr ("\n\t,; ", *end))
877	end++;
878      if (end == input_line_pointer)
879	{
880	  as_warn (_("missing name"));
881	  ignore_rest_of_line ();
882	  return NULL;
883	}
884
885      name = xmalloc (end - input_line_pointer + 1);
886      memcpy (name, input_line_pointer, end - input_line_pointer);
887      name[end - input_line_pointer] = '\0';
888      input_line_pointer = end;
889    }
890  SKIP_WHITESPACE ();
891  return name;
892}
893
894void
895obj_elf_section (push)
896     int push;
897{
898  char *name, *group_name, *beg;
899  int type, attr, dummy;
900  int entsize;
901
902#ifndef TC_I370
903  if (flag_mri)
904    {
905      char mri_type;
906
907#ifdef md_flush_pending_output
908      md_flush_pending_output ();
909#endif
910
911      previous_section = now_seg;
912      previous_subsection = now_subseg;
913
914      s_mri_sect (&mri_type);
915
916#ifdef md_elf_section_change_hook
917      md_elf_section_change_hook ();
918#endif
919
920      return;
921    }
922#endif /* ! defined (TC_I370) */
923
924  name = obj_elf_section_name ();
925  if (name == NULL)
926    return;
927  type = SHT_NULL;
928  attr = 0;
929  group_name = NULL;
930  entsize = 0;
931
932  if (*input_line_pointer == ',')
933    {
934      /* Skip the comma.  */
935      ++input_line_pointer;
936      SKIP_WHITESPACE ();
937
938      if (*input_line_pointer == '"')
939	{
940	  beg = demand_copy_C_string (&dummy);
941	  if (beg == NULL)
942	    {
943	      ignore_rest_of_line ();
944	      return;
945	    }
946	  attr |= obj_elf_parse_section_letters (beg, strlen (beg));
947
948	  SKIP_WHITESPACE ();
949	  if (*input_line_pointer == ',')
950	    {
951	      char c;
952	      char *save = input_line_pointer;
953
954	      ++input_line_pointer;
955	      SKIP_WHITESPACE ();
956	      c = *input_line_pointer;
957	      if (c == '"')
958		{
959		  beg = demand_copy_C_string (&dummy);
960		  if (beg == NULL)
961		    {
962		      ignore_rest_of_line ();
963		      return;
964		    }
965		  type = obj_elf_section_type (beg, strlen (beg));
966		}
967	      else if (c == '@' || c == '%')
968		{
969		  beg = ++input_line_pointer;
970		  c = get_symbol_end ();
971		  *input_line_pointer = c;
972		  type = obj_elf_section_type (beg, input_line_pointer - beg);
973		}
974	      else
975		input_line_pointer = save;
976	    }
977
978	  SKIP_WHITESPACE ();
979	  if ((attr & SHF_MERGE) != 0 && *input_line_pointer == ',')
980	    {
981	      ++input_line_pointer;
982	      SKIP_WHITESPACE ();
983	      entsize = get_absolute_expression ();
984	      SKIP_WHITESPACE ();
985	      if (entsize < 0)
986		{
987		  as_warn (_("invalid merge entity size"));
988		  attr &= ~SHF_MERGE;
989		  entsize = 0;
990		}
991	    }
992	  else if ((attr & SHF_MERGE) != 0)
993	    {
994	      as_warn (_("entity size for SHF_MERGE not specified"));
995	      attr &= ~SHF_MERGE;
996	    }
997
998	  if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
999	    {
1000	      ++input_line_pointer;
1001	      group_name = obj_elf_section_name ();
1002	      if (group_name == NULL)
1003		attr &= ~SHF_GROUP;
1004	    }
1005	  else if ((attr & SHF_GROUP) != 0)
1006	    {
1007	      as_warn (_("group name for SHF_GROUP not specified"));
1008	      attr &= ~SHF_GROUP;
1009	    }
1010	}
1011      else
1012	{
1013	  do
1014	    {
1015	      char c;
1016
1017	      SKIP_WHITESPACE ();
1018	      if (*input_line_pointer != '#')
1019		{
1020		  as_warn (_("character following name is not '#'"));
1021		  ignore_rest_of_line ();
1022		  return;
1023		}
1024	      beg = ++input_line_pointer;
1025	      c = get_symbol_end ();
1026	      *input_line_pointer = c;
1027
1028	      attr |= obj_elf_section_word (beg, input_line_pointer - beg);
1029
1030	      SKIP_WHITESPACE ();
1031	    }
1032	  while (*input_line_pointer++ == ',');
1033	  --input_line_pointer;
1034	}
1035    }
1036
1037  demand_empty_rest_of_line ();
1038
1039  obj_elf_change_section (name, type, attr, entsize, group_name, push);
1040}
1041
1042/* Change to the .data section.  */
1043
1044void
1045obj_elf_data (i)
1046     int i;
1047{
1048#ifdef md_flush_pending_output
1049  md_flush_pending_output ();
1050#endif
1051
1052  previous_section = now_seg;
1053  previous_subsection = now_subseg;
1054  s_data (i);
1055
1056#ifdef md_elf_section_change_hook
1057  md_elf_section_change_hook ();
1058#endif
1059}
1060
1061/* Change to the .text section.  */
1062
1063void
1064obj_elf_text (i)
1065     int i;
1066{
1067#ifdef md_flush_pending_output
1068  md_flush_pending_output ();
1069#endif
1070
1071  previous_section = now_seg;
1072  previous_subsection = now_subseg;
1073  s_text (i);
1074
1075#ifdef md_elf_section_change_hook
1076  md_elf_section_change_hook ();
1077#endif
1078}
1079
1080static void
1081obj_elf_subsection (ignore)
1082     int ignore ATTRIBUTE_UNUSED;
1083{
1084  register int temp;
1085
1086#ifdef md_flush_pending_output
1087  md_flush_pending_output ();
1088#endif
1089
1090  previous_section = now_seg;
1091  previous_subsection = now_subseg;
1092
1093  temp = get_absolute_expression ();
1094  subseg_set (now_seg, (subsegT) temp);
1095  demand_empty_rest_of_line ();
1096
1097#ifdef md_elf_section_change_hook
1098  md_elf_section_change_hook ();
1099#endif
1100}
1101
1102/* This can be called from the processor backends if they change
1103   sections.  */
1104
1105void
1106obj_elf_section_change_hook ()
1107{
1108  previous_section = now_seg;
1109  previous_subsection = now_subseg;
1110}
1111
1112void
1113obj_elf_previous (ignore)
1114     int ignore ATTRIBUTE_UNUSED;
1115{
1116  segT new_section;
1117  int new_subsection;
1118
1119  if (previous_section == 0)
1120    {
1121      as_warn (_(".previous without corresponding .section; ignored"));
1122      return;
1123    }
1124
1125#ifdef md_flush_pending_output
1126  md_flush_pending_output ();
1127#endif
1128
1129  new_section = previous_section;
1130  new_subsection = previous_subsection;
1131  previous_section = now_seg;
1132  previous_subsection = now_subseg;
1133  subseg_set (new_section, new_subsection);
1134
1135#ifdef md_elf_section_change_hook
1136  md_elf_section_change_hook ();
1137#endif
1138}
1139
1140static void
1141obj_elf_popsection (xxx)
1142     int xxx ATTRIBUTE_UNUSED;
1143{
1144  struct section_stack *top = section_stack;
1145
1146  if (top == NULL)
1147    {
1148      as_warn (_(".popsection without corresponding .pushsection; ignored"));
1149      return;
1150    }
1151
1152#ifdef md_flush_pending_output
1153  md_flush_pending_output ();
1154#endif
1155
1156  section_stack = top->next;
1157  previous_section = top->prev_seg;
1158  previous_subsection = top->prev_subseg;
1159  subseg_set (top->seg, top->subseg);
1160  free (top);
1161
1162#ifdef md_elf_section_change_hook
1163  md_elf_section_change_hook ();
1164#endif
1165}
1166
1167static void
1168obj_elf_line (ignore)
1169     int ignore ATTRIBUTE_UNUSED;
1170{
1171  /* Assume delimiter is part of expression.  BSD4.2 as fails with
1172     delightful bug, so we are not being incompatible here.  */
1173  new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
1174  demand_empty_rest_of_line ();
1175}
1176
1177/* This handles the .symver pseudo-op, which is used to specify a
1178   symbol version.  The syntax is ``.symver NAME,SYMVERNAME''.
1179   SYMVERNAME may contain ELF_VER_CHR ('@') characters.  This
1180   pseudo-op causes the assembler to emit a symbol named SYMVERNAME
1181   with the same value as the symbol NAME.  */
1182
1183static void
1184obj_elf_symver (ignore)
1185     int ignore ATTRIBUTE_UNUSED;
1186{
1187  char *name;
1188  char c;
1189  char old_lexat;
1190  symbolS *sym;
1191
1192  name = input_line_pointer;
1193  c = get_symbol_end ();
1194
1195  sym = symbol_find_or_make (name);
1196
1197  *input_line_pointer = c;
1198
1199  SKIP_WHITESPACE ();
1200  if (*input_line_pointer != ',')
1201    {
1202      as_bad (_("expected comma after name in .symver"));
1203      ignore_rest_of_line ();
1204      return;
1205    }
1206
1207  ++input_line_pointer;
1208  name = input_line_pointer;
1209
1210  /* Temporarily include '@' in symbol names.  */
1211  old_lexat = lex_type[(unsigned char) '@'];
1212  lex_type[(unsigned char) '@'] |= LEX_NAME;
1213  c = get_symbol_end ();
1214  lex_type[(unsigned char) '@'] = old_lexat;
1215
1216  if (symbol_get_obj (sym)->versioned_name == NULL)
1217    {
1218      symbol_get_obj (sym)->versioned_name = xstrdup (name);
1219
1220      *input_line_pointer = c;
1221
1222      if (strchr (symbol_get_obj (sym)->versioned_name,
1223		  ELF_VER_CHR) == NULL)
1224	{
1225	  as_bad (_("missing version name in `%s' for symbol `%s'"),
1226		  symbol_get_obj (sym)->versioned_name,
1227		  S_GET_NAME (sym));
1228	  ignore_rest_of_line ();
1229	  return;
1230	}
1231    }
1232  else
1233    {
1234      if (strcmp (symbol_get_obj (sym)->versioned_name, name))
1235	{
1236	  as_bad (_("multiple versions [`%s'|`%s'] for symbol `%s'"),
1237		  name, symbol_get_obj (sym)->versioned_name,
1238		  S_GET_NAME (sym));
1239	  ignore_rest_of_line ();
1240	  return;
1241	}
1242
1243      *input_line_pointer = c;
1244    }
1245
1246  demand_empty_rest_of_line ();
1247}
1248
1249/* This handles the .vtable_inherit pseudo-op, which is used to indicate
1250   to the linker the hierarchy in which a particular table resides.  The
1251   syntax is ".vtable_inherit CHILDNAME, PARENTNAME".  */
1252
1253struct fix *
1254obj_elf_vtable_inherit (ignore)
1255     int ignore ATTRIBUTE_UNUSED;
1256{
1257  char *cname, *pname;
1258  symbolS *csym, *psym;
1259  char c, bad = 0;
1260
1261  if (*input_line_pointer == '#')
1262    ++input_line_pointer;
1263
1264  cname = input_line_pointer;
1265  c = get_symbol_end ();
1266  csym = symbol_find (cname);
1267
1268  /* GCFIXME: should check that we don't have two .vtable_inherits for
1269     the same child symbol.  Also, we can currently only do this if the
1270     child symbol is already exists and is placed in a fragment.  */
1271
1272  if (csym == NULL || symbol_get_frag (csym) == NULL)
1273    {
1274      as_bad ("expected `%s' to have already been set for .vtable_inherit",
1275	      cname);
1276      bad = 1;
1277    }
1278
1279  *input_line_pointer = c;
1280
1281  SKIP_WHITESPACE ();
1282  if (*input_line_pointer != ',')
1283    {
1284      as_bad ("expected comma after name in .vtable_inherit");
1285      ignore_rest_of_line ();
1286      return NULL;
1287    }
1288
1289  ++input_line_pointer;
1290  SKIP_WHITESPACE ();
1291
1292  if (*input_line_pointer == '#')
1293    ++input_line_pointer;
1294
1295  if (input_line_pointer[0] == '0'
1296      && (input_line_pointer[1] == '\0'
1297	  || ISSPACE (input_line_pointer[1])))
1298    {
1299      psym = section_symbol (absolute_section);
1300      ++input_line_pointer;
1301    }
1302  else
1303    {
1304      pname = input_line_pointer;
1305      c = get_symbol_end ();
1306      psym = symbol_find_or_make (pname);
1307      *input_line_pointer = c;
1308    }
1309
1310  demand_empty_rest_of_line ();
1311
1312  if (bad)
1313    return NULL;
1314
1315  assert (symbol_get_value_expression (csym)->X_op == O_constant);
1316  return fix_new (symbol_get_frag (csym),
1317		  symbol_get_value_expression (csym)->X_add_number,
1318		  0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
1319}
1320
1321/* This handles the .vtable_entry pseudo-op, which is used to indicate
1322   to the linker that a vtable slot was used.  The syntax is
1323   ".vtable_entry tablename, offset".  */
1324
1325struct fix *
1326obj_elf_vtable_entry (ignore)
1327     int ignore ATTRIBUTE_UNUSED;
1328{
1329  char *name;
1330  symbolS *sym;
1331  offsetT offset;
1332  char c;
1333
1334  if (*input_line_pointer == '#')
1335    ++input_line_pointer;
1336
1337  name = input_line_pointer;
1338  c = get_symbol_end ();
1339  sym = symbol_find_or_make (name);
1340  *input_line_pointer = c;
1341
1342  SKIP_WHITESPACE ();
1343  if (*input_line_pointer != ',')
1344    {
1345      as_bad ("expected comma after name in .vtable_entry");
1346      ignore_rest_of_line ();
1347      return NULL;
1348    }
1349
1350  ++input_line_pointer;
1351  if (*input_line_pointer == '#')
1352    ++input_line_pointer;
1353
1354  offset = get_absolute_expression ();
1355
1356  demand_empty_rest_of_line ();
1357
1358  return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
1359		  BFD_RELOC_VTABLE_ENTRY);
1360}
1361
1362void
1363elf_obj_read_begin_hook ()
1364{
1365#ifdef NEED_ECOFF_DEBUG
1366  if (ECOFF_DEBUGGING)
1367    ecoff_read_begin_hook ();
1368#endif
1369}
1370
1371void
1372elf_obj_symbol_new_hook (symbolP)
1373     symbolS *symbolP;
1374{
1375  struct elf_obj_sy *sy_obj;
1376
1377  sy_obj = symbol_get_obj (symbolP);
1378  sy_obj->size = NULL;
1379  sy_obj->versioned_name = NULL;
1380
1381#ifdef NEED_ECOFF_DEBUG
1382  if (ECOFF_DEBUGGING)
1383    ecoff_symbol_new_hook (symbolP);
1384#endif
1385}
1386
1387/* When setting one symbol equal to another, by default we probably
1388   want them to have the same "size", whatever it means in the current
1389   context.  */
1390
1391void
1392elf_copy_symbol_attributes (dest, src)
1393     symbolS *dest, *src;
1394{
1395  struct elf_obj_sy *srcelf = symbol_get_obj (src);
1396  struct elf_obj_sy *destelf = symbol_get_obj (dest);
1397  if (srcelf->size)
1398    {
1399      if (destelf->size == NULL)
1400	destelf->size =
1401	  (expressionS *) xmalloc (sizeof (expressionS));
1402      *destelf->size = *srcelf->size;
1403    }
1404  else
1405    {
1406      if (destelf->size != NULL)
1407	free (destelf->size);
1408      destelf->size = NULL;
1409    }
1410  S_SET_SIZE (dest, S_GET_SIZE (src));
1411  S_SET_OTHER (dest, S_GET_OTHER (src));
1412}
1413
1414void
1415obj_elf_version (ignore)
1416     int ignore ATTRIBUTE_UNUSED;
1417{
1418  char *name;
1419  unsigned int c;
1420  char *p;
1421  asection *seg = now_seg;
1422  subsegT subseg = now_subseg;
1423  Elf_Internal_Note i_note;
1424  Elf_External_Note e_note;
1425  asection *note_secp = (asection *) NULL;
1426  int len;
1427
1428  SKIP_WHITESPACE ();
1429  if (*input_line_pointer == '\"')
1430    {
1431      ++input_line_pointer;	/* -> 1st char of string.  */
1432      name = input_line_pointer;
1433
1434      while (is_a_char (c = next_char_of_string ()))
1435	;
1436      c = *input_line_pointer;
1437      *input_line_pointer = '\0';
1438      *(input_line_pointer - 1) = '\0';
1439      *input_line_pointer = c;
1440
1441      /* create the .note section */
1442
1443      note_secp = subseg_new (".note", 0);
1444      bfd_set_section_flags (stdoutput,
1445			     note_secp,
1446			     SEC_HAS_CONTENTS | SEC_READONLY);
1447
1448      /* process the version string */
1449
1450      len = strlen (name);
1451
1452      i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
1453      i_note.descsz = 0;	/* no description */
1454      i_note.type = NT_VERSION;
1455      p = frag_more (sizeof (e_note.namesz));
1456      md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz));
1457      p = frag_more (sizeof (e_note.descsz));
1458      md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz));
1459      p = frag_more (sizeof (e_note.type));
1460      md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type));
1461      p = frag_more (len + 1);
1462      strcpy (p, name);
1463
1464      frag_align (2, 0, 0);
1465
1466      subseg_set (seg, subseg);
1467    }
1468  else
1469    {
1470      as_bad (_("expected quoted string"));
1471    }
1472  demand_empty_rest_of_line ();
1473}
1474
1475static void
1476obj_elf_size (ignore)
1477     int ignore ATTRIBUTE_UNUSED;
1478{
1479  char *name = input_line_pointer;
1480  char c = get_symbol_end ();
1481  char *p;
1482  expressionS exp;
1483  symbolS *sym;
1484
1485  p = input_line_pointer;
1486  *p = c;
1487  SKIP_WHITESPACE ();
1488  if (*input_line_pointer != ',')
1489    {
1490      *p = 0;
1491      as_bad (_("expected comma after name `%s' in .size directive"), name);
1492      *p = c;
1493      ignore_rest_of_line ();
1494      return;
1495    }
1496  input_line_pointer++;
1497  expression (&exp);
1498  if (exp.X_op == O_absent)
1499    {
1500      as_bad (_("missing expression in .size directive"));
1501      exp.X_op = O_constant;
1502      exp.X_add_number = 0;
1503    }
1504  *p = 0;
1505  sym = symbol_find_or_make (name);
1506  *p = c;
1507  if (exp.X_op == O_constant)
1508    {
1509      S_SET_SIZE (sym, exp.X_add_number);
1510      if (symbol_get_obj (sym)->size)
1511	{
1512	  xfree (symbol_get_obj (sym)->size);
1513	  symbol_get_obj (sym)->size = NULL;
1514	}
1515    }
1516  else
1517    {
1518      symbol_get_obj (sym)->size =
1519	(expressionS *) xmalloc (sizeof (expressionS));
1520      *symbol_get_obj (sym)->size = exp;
1521    }
1522  demand_empty_rest_of_line ();
1523}
1524
1525/* Handle the ELF .type pseudo-op.  This sets the type of a symbol.
1526   There are five syntaxes:
1527
1528   The first (used on Solaris) is
1529       .type SYM,#function
1530   The second (used on UnixWare) is
1531       .type SYM,@function
1532   The third (reportedly to be used on Irix 6.0) is
1533       .type SYM STT_FUNC
1534   The fourth (used on NetBSD/Arm and Linux/ARM) is
1535       .type SYM,%function
1536   The fifth (used on SVR4/860) is
1537       .type SYM,"function"
1538   */
1539
1540static void
1541obj_elf_type (ignore)
1542     int ignore ATTRIBUTE_UNUSED;
1543{
1544  char *name;
1545  char c;
1546  int type;
1547  const char *typename;
1548  symbolS *sym;
1549  elf_symbol_type *elfsym;
1550
1551  name = input_line_pointer;
1552  c = get_symbol_end ();
1553  sym = symbol_find_or_make (name);
1554  elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
1555  *input_line_pointer = c;
1556
1557  SKIP_WHITESPACE ();
1558  if (*input_line_pointer == ',')
1559    ++input_line_pointer;
1560
1561  SKIP_WHITESPACE ();
1562  if (   *input_line_pointer == '#'
1563      || *input_line_pointer == '@'
1564      || *input_line_pointer == '"'
1565      || *input_line_pointer == '%')
1566    ++input_line_pointer;
1567
1568  typename = input_line_pointer;
1569  c = get_symbol_end ();
1570
1571  type = 0;
1572  if (strcmp (typename, "function") == 0
1573      || strcmp (typename, "STT_FUNC") == 0)
1574    type = BSF_FUNCTION;
1575  else if (strcmp (typename, "object") == 0
1576	   || strcmp (typename, "STT_OBJECT") == 0)
1577    type = BSF_OBJECT;
1578#ifdef md_elf_symbol_type
1579  else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
1580    ;
1581#endif
1582  else
1583    as_bad (_("unrecognized symbol type \"%s\""), typename);
1584
1585  *input_line_pointer = c;
1586
1587  if (*input_line_pointer == '"')
1588    ++input_line_pointer;
1589
1590  elfsym->symbol.flags |= type;
1591
1592  demand_empty_rest_of_line ();
1593}
1594
1595static void
1596obj_elf_ident (ignore)
1597     int ignore ATTRIBUTE_UNUSED;
1598{
1599  static segT comment_section;
1600  segT old_section = now_seg;
1601  int old_subsection = now_subseg;
1602
1603#ifdef md_flush_pending_output
1604  md_flush_pending_output ();
1605#endif
1606
1607  if (!comment_section)
1608    {
1609      char *p;
1610      comment_section = subseg_new (".comment", 0);
1611      bfd_set_section_flags (stdoutput, comment_section,
1612			     SEC_READONLY | SEC_HAS_CONTENTS);
1613      p = frag_more (1);
1614      *p = 0;
1615    }
1616  else
1617    subseg_set (comment_section, 0);
1618  stringer (1);
1619  subseg_set (old_section, old_subsection);
1620}
1621
1622#ifdef INIT_STAB_SECTION
1623
1624/* The first entry in a .stabs section is special.  */
1625
1626void
1627obj_elf_init_stab_section (seg)
1628     segT seg;
1629{
1630  char *file;
1631  char *p;
1632  char *stabstr_name;
1633  unsigned int stroff;
1634
1635  /* Force the section to align to a longword boundary.  Without this,
1636     UnixWare ar crashes.  */
1637  bfd_set_section_alignment (stdoutput, seg, 2);
1638
1639  /* Make space for this first symbol.  */
1640  p = frag_more (12);
1641  /* Zero it out.  */
1642  memset (p, 0, 12);
1643  as_where (&file, (unsigned int *) NULL);
1644  stabstr_name = (char *) xmalloc (strlen (segment_name (seg)) + 4);
1645  strcpy (stabstr_name, segment_name (seg));
1646  strcat (stabstr_name, "str");
1647  stroff = get_stab_string_offset (file, stabstr_name);
1648  know (stroff == 1);
1649  md_number_to_chars (p, stroff, 4);
1650  seg_info (seg)->stabu.p = p;
1651}
1652
1653#endif
1654
1655/* Fill in the counts in the first entry in a .stabs section.  */
1656
1657static void
1658adjust_stab_sections (abfd, sec, xxx)
1659     bfd *abfd;
1660     asection *sec;
1661     PTR xxx ATTRIBUTE_UNUSED;
1662{
1663  char *name;
1664  asection *strsec;
1665  char *p;
1666  int strsz, nsyms;
1667
1668  if (strncmp (".stab", sec->name, 5))
1669    return;
1670  if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
1671    return;
1672
1673  name = (char *) alloca (strlen (sec->name) + 4);
1674  strcpy (name, sec->name);
1675  strcat (name, "str");
1676  strsec = bfd_get_section_by_name (abfd, name);
1677  if (strsec)
1678    strsz = bfd_section_size (abfd, strsec);
1679  else
1680    strsz = 0;
1681  nsyms = bfd_section_size (abfd, sec) / 12 - 1;
1682
1683  p = seg_info (sec)->stabu.p;
1684  assert (p != 0);
1685
1686  bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
1687  bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
1688}
1689
1690#ifdef NEED_ECOFF_DEBUG
1691
1692/* This function is called by the ECOFF code.  It is supposed to
1693   record the external symbol information so that the backend can
1694   write it out correctly.  The ELF backend doesn't actually handle
1695   this at the moment, so we do it ourselves.  We save the information
1696   in the symbol.  */
1697
1698void
1699elf_ecoff_set_ext (sym, ext)
1700     symbolS *sym;
1701     struct ecoff_extr *ext;
1702{
1703  symbol_get_bfdsym (sym)->udata.p = (PTR) ext;
1704}
1705
1706/* This function is called by bfd_ecoff_debug_externals.  It is
1707   supposed to *EXT to the external symbol information, and return
1708   whether the symbol should be used at all.  */
1709
1710static boolean
1711elf_get_extr (sym, ext)
1712     asymbol *sym;
1713     EXTR *ext;
1714{
1715  if (sym->udata.p == NULL)
1716    return false;
1717  *ext = *(EXTR *) sym->udata.p;
1718  return true;
1719}
1720
1721/* This function is called by bfd_ecoff_debug_externals.  It has
1722   nothing to do for ELF.  */
1723
1724/*ARGSUSED*/
1725static void
1726elf_set_index (sym, indx)
1727     asymbol *sym ATTRIBUTE_UNUSED;
1728     bfd_size_type indx ATTRIBUTE_UNUSED;
1729{
1730}
1731
1732#endif /* NEED_ECOFF_DEBUG */
1733
1734void
1735elf_frob_symbol (symp, puntp)
1736     symbolS *symp;
1737     int *puntp;
1738{
1739  struct elf_obj_sy *sy_obj;
1740
1741#ifdef NEED_ECOFF_DEBUG
1742  if (ECOFF_DEBUGGING)
1743    ecoff_frob_symbol (symp);
1744#endif
1745
1746  sy_obj = symbol_get_obj (symp);
1747
1748  if (sy_obj->size != NULL)
1749    {
1750      switch (sy_obj->size->X_op)
1751	{
1752	case O_subtract:
1753	  S_SET_SIZE (symp,
1754		      (S_GET_VALUE (sy_obj->size->X_add_symbol)
1755		       + sy_obj->size->X_add_number
1756		       - S_GET_VALUE (sy_obj->size->X_op_symbol)));
1757	  break;
1758	case O_constant:
1759	  S_SET_SIZE (symp,
1760		      (S_GET_VALUE (sy_obj->size->X_add_symbol)
1761		       + sy_obj->size->X_add_number));
1762	  break;
1763	default:
1764	  as_bad (_(".size expression too complicated to fix up"));
1765	  break;
1766	}
1767      free (sy_obj->size);
1768      sy_obj->size = NULL;
1769    }
1770
1771  if (sy_obj->versioned_name != NULL)
1772    {
1773      char *p;
1774
1775      p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
1776      know (p != NULL);
1777
1778      /* This symbol was given a new name with the .symver directive.
1779
1780         If this is an external reference, just rename the symbol to
1781         include the version string.  This will make the relocs be
1782         against the correct versioned symbol.
1783
1784	 If this is a definition, add an alias.  FIXME: Using an alias
1785	 will permit the debugging information to refer to the right
1786	 symbol.  However, it's not clear whether it is the best
1787	 approach.  */
1788
1789      if (! S_IS_DEFINED (symp))
1790	{
1791	  /* Verify that the name isn't using the @@ syntax--this is
1792             reserved for definitions of the default version to link
1793             against.  */
1794	  if (p[1] == ELF_VER_CHR)
1795	    {
1796	      as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"),
1797		      sy_obj->versioned_name);
1798	      *puntp = true;
1799	    }
1800	  S_SET_NAME (symp, sy_obj->versioned_name);
1801	}
1802      else
1803	{
1804	  if (p [1] == ELF_VER_CHR && p [2] == ELF_VER_CHR)
1805	    {
1806	      size_t l;
1807
1808	      /* The @@@ syntax is a special case. It renames the
1809		 symbol name to versioned_name with one `@' removed.  */
1810	      l = strlen (&p[3]) + 1;
1811	      memmove (&p [2], &p[3], l);
1812	      S_SET_NAME (symp, sy_obj->versioned_name);
1813	    }
1814	  else
1815	    {
1816	      symbolS *symp2;
1817
1818	      /* FIXME: Creating a new symbol here is risky.  We're
1819		 in the final loop over the symbol table.  We can
1820		 get away with it only because the symbol goes to
1821		 the end of the list, where the loop will still see
1822		 it.  It would probably be better to do this in
1823		 obj_frob_file_before_adjust.  */
1824
1825	      symp2 = symbol_find_or_make (sy_obj->versioned_name);
1826
1827	      /* Now we act as though we saw symp2 = sym.  */
1828
1829	      S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
1830
1831	      /* Subtracting out the frag address here is a hack
1832		 because we are in the middle of the final loop.  */
1833	      S_SET_VALUE (symp2,
1834			   (S_GET_VALUE (symp)
1835			    - symbol_get_frag (symp)->fr_address));
1836
1837	      symbol_set_frag (symp2, symbol_get_frag (symp));
1838
1839	      /* This will copy over the size information.  */
1840	      copy_symbol_attributes (symp2, symp);
1841
1842	      if (S_IS_WEAK (symp))
1843		S_SET_WEAK (symp2);
1844
1845	      if (S_IS_EXTERNAL (symp))
1846		S_SET_EXTERNAL (symp2);
1847	    }
1848	}
1849    }
1850
1851  /* Double check weak symbols.  */
1852  if (S_IS_WEAK (symp))
1853    {
1854      if (S_IS_COMMON (symp))
1855	as_bad (_("symbol `%s' can not be both weak and common"),
1856		S_GET_NAME (symp));
1857    }
1858
1859#ifdef TC_MIPS
1860  /* The Irix 5 and 6 assemblers set the type of any common symbol and
1861     any undefined non-function symbol to STT_OBJECT.  We try to be
1862     compatible, since newer Irix 5 and 6 linkers care.  However, we
1863     only set undefined symbols to be STT_OBJECT if we are on Irix,
1864     because that is the only time gcc will generate the necessary
1865     .global directives to mark functions.  */
1866
1867  if (S_IS_COMMON (symp))
1868    symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
1869
1870  if (strstr (TARGET_OS, "irix") != NULL
1871      && ! S_IS_DEFINED (symp)
1872      && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0)
1873    symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
1874#endif
1875
1876#if 0 /* TC_PPC */
1877  /* If TC_PPC is defined, we used to force the type of a symbol to be
1878     BSF_OBJECT if it was otherwise unset.  This was required by some
1879     version of VxWorks.  Thomas de Lellis <tdel@windriver.com> says
1880     that this is no longer needed, so it is now commented out.  */
1881  if ((symbol_get_bfdsym (symp)->flags
1882       & (BSF_FUNCTION | BSF_FILE | BSF_SECTION_SYM)) == 0
1883      && S_IS_DEFINED (symp))
1884    symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
1885#endif
1886}
1887
1888struct group_list
1889{
1890  asection **head;		/* Section lists.  */
1891  unsigned int *elt_count;	/* Number of sections in each list.  */
1892  unsigned int num_group;	/* Number of lists.  */
1893};
1894
1895/* Called via bfd_map_over_sections.  If SEC is a member of a group,
1896   add it to a list of sections belonging to the group.  INF is a
1897   pointer to a struct group_list, which is where we store the head of
1898   each list.  */
1899
1900static void
1901build_group_lists (abfd, sec, inf)
1902     bfd *abfd ATTRIBUTE_UNUSED;
1903     asection *sec;
1904     PTR inf;
1905{
1906  struct group_list *list = (struct group_list *) inf;
1907  const char *group_name = elf_group_name (sec);
1908  unsigned int i;
1909
1910  if (group_name == NULL)
1911    return;
1912
1913  /* If this group already has a list, add the section to the head of
1914     the list.  */
1915  for (i = 0; i < list->num_group; i++)
1916    {
1917      if (strcmp (group_name, elf_group_name (list->head[i])) == 0)
1918	{
1919	  elf_next_in_group (sec) = list->head[i];
1920	  list->head[i] = sec;
1921	  list->elt_count[i] += 1;
1922	  return;
1923	}
1924    }
1925
1926  /* New group.  Make the arrays bigger in chunks to minimize calls to
1927     realloc.  */
1928  i = list->num_group;
1929  if ((i & 127) == 0)
1930    {
1931      unsigned int newsize = i + 128;
1932      list->head = xrealloc (list->head, newsize * sizeof (*list->head));
1933      list->elt_count = xrealloc (list->elt_count,
1934				  newsize * sizeof (*list->elt_count));
1935    }
1936  list->head[i] = sec;
1937  list->elt_count[i] = 1;
1938  list->num_group += 1;
1939}
1940
1941void
1942elf_frob_file ()
1943{
1944  struct group_list list;
1945  unsigned int i;
1946
1947  bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
1948
1949  /* Go find section groups.  */
1950  list.num_group = 0;
1951  list.head = NULL;
1952  list.elt_count = NULL;
1953  bfd_map_over_sections (stdoutput, build_group_lists, (PTR) &list);
1954
1955  /* Make the SHT_GROUP sections that describe each section group.  We
1956     can't set up the section contents here yet, because elf section
1957     indices have yet to be calculated.  elf.c:set_group_contents does
1958     the rest of the work.  */
1959  for (i = 0; i < list.num_group; i++)
1960    {
1961      const char *group_name = elf_group_name (list.head[i]);
1962      asection *s;
1963      flagword flags;
1964
1965      s = subseg_force_new (group_name, 0);
1966      flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
1967      if (s == NULL
1968	  || !bfd_set_section_flags (stdoutput, s, flags)
1969	  || !bfd_set_section_alignment (stdoutput, s, 2))
1970	{
1971	  as_fatal (_("can't create group: %s"),
1972		    bfd_errmsg (bfd_get_error ()));
1973	}
1974
1975      /* Pass a pointer to the first section in this group.  */
1976      elf_next_in_group (s) = list.head[i];
1977
1978      s->_raw_size = 4 * (list.elt_count[i] + 1);
1979      s->contents = frag_more (s->_raw_size);
1980      frag_now->fr_fix = frag_now_fix_octets ();
1981    }
1982
1983#ifdef elf_tc_final_processing
1984  elf_tc_final_processing ();
1985#endif
1986}
1987
1988/* It removes any unneeded versioned symbols from the symbol table.  */
1989
1990void
1991elf_frob_file_before_adjust ()
1992{
1993  if (symbol_rootP)
1994    {
1995      symbolS *symp;
1996
1997      for (symp = symbol_rootP; symp; symp = symbol_next (symp))
1998	if (symbol_get_obj (symp)->versioned_name)
1999	  {
2000	    if (!S_IS_DEFINED (symp))
2001	      {
2002		char *p;
2003
2004		/* The @@@ syntax is a special case. If the symbol is
2005		   not defined, 2 `@'s will be removed from the
2006		   versioned_name.  */
2007
2008		p = strchr (symbol_get_obj (symp)->versioned_name,
2009			    ELF_VER_CHR);
2010		know (p != NULL);
2011		if (p [1] == ELF_VER_CHR && p [2] == ELF_VER_CHR)
2012		  {
2013		    size_t l = strlen (&p[3]) + 1;
2014		    memmove (&p [1], &p[3], l);
2015		  }
2016		if (symbol_used_p (symp) == 0
2017		    && symbol_used_in_reloc_p (symp) == 0)
2018		  symbol_remove (symp, &symbol_rootP, &symbol_lastP);
2019	      }
2020	  }
2021    }
2022}
2023
2024/* It is required that we let write_relocs have the opportunity to
2025   optimize away fixups before output has begun, since it is possible
2026   to eliminate all fixups for a section and thus we never should
2027   have generated the relocation section.  */
2028
2029void
2030elf_frob_file_after_relocs ()
2031{
2032#ifdef NEED_ECOFF_DEBUG
2033  if (ECOFF_DEBUGGING)
2034    /* Generate the ECOFF debugging information.  */
2035    {
2036      const struct ecoff_debug_swap *debug_swap;
2037      struct ecoff_debug_info debug;
2038      char *buf;
2039      asection *sec;
2040
2041      debug_swap
2042	= get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap;
2043      know (debug_swap != (const struct ecoff_debug_swap *) NULL);
2044      ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
2045
2046      /* Set up the pointers in debug.  */
2047#define SET(ptr, offset, type) \
2048    debug.ptr = (type) (buf + debug.symbolic_header.offset)
2049
2050      SET (line, cbLineOffset, unsigned char *);
2051      SET (external_dnr, cbDnOffset, PTR);
2052      SET (external_pdr, cbPdOffset, PTR);
2053      SET (external_sym, cbSymOffset, PTR);
2054      SET (external_opt, cbOptOffset, PTR);
2055      SET (external_aux, cbAuxOffset, union aux_ext *);
2056      SET (ss, cbSsOffset, char *);
2057      SET (external_fdr, cbFdOffset, PTR);
2058      SET (external_rfd, cbRfdOffset, PTR);
2059      /* ssext and external_ext are set up just below.  */
2060
2061#undef SET
2062
2063      /* Set up the external symbols.  */
2064      debug.ssext = debug.ssext_end = NULL;
2065      debug.external_ext = debug.external_ext_end = NULL;
2066      if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true,
2067				       elf_get_extr, elf_set_index))
2068	as_fatal (_("failed to set up debugging information: %s"),
2069		  bfd_errmsg (bfd_get_error ()));
2070
2071      sec = bfd_get_section_by_name (stdoutput, ".mdebug");
2072      assert (sec != NULL);
2073
2074      know (stdoutput->output_has_begun == false);
2075
2076      /* We set the size of the section, call bfd_set_section_contents
2077	 to force the ELF backend to allocate a file position, and then
2078	 write out the data.  FIXME: Is this really the best way to do
2079	 this?  */
2080      sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap);
2081
2082      /* Pass BUF to bfd_set_section_contents because this will
2083         eventually become a call to fwrite, and ISO C prohibits
2084         passing a NULL pointer to a stdio function even if the
2085         pointer will not be used.  */
2086      if (! bfd_set_section_contents (stdoutput, sec, (PTR) buf,
2087				      (file_ptr) 0, (bfd_size_type) 0))
2088	as_fatal (_("can't start writing .mdebug section: %s"),
2089		  bfd_errmsg (bfd_get_error ()));
2090
2091      know (stdoutput->output_has_begun == true);
2092      know (sec->filepos != 0);
2093
2094      if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
2095				   sec->filepos))
2096	as_fatal (_("could not write .mdebug section: %s"),
2097		  bfd_errmsg (bfd_get_error ()));
2098    }
2099#endif /* NEED_ECOFF_DEBUG */
2100}
2101
2102#ifdef SCO_ELF
2103
2104/* Heavily plagarized from obj_elf_version.  The idea is to emit the
2105   SCO specific identifier in the .notes section to satisfy the SCO
2106   linker.
2107
2108   This looks more complicated than it really is.  As opposed to the
2109   "obvious" solution, this should handle the cross dev cases
2110   correctly.  (i.e, hosting on a 64 bit big endian processor, but
2111   generating SCO Elf code) Efficiency isn't a concern, as there
2112   should be exactly one of these sections per object module.
2113
2114   SCO OpenServer 5 identifies it's ELF modules with a standard ELF
2115   .note section.
2116
2117   int_32 namesz  = 4 ;  Name size
2118   int_32 descsz  = 12 ; Descriptive information
2119   int_32 type    = 1 ;
2120   char   name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
2121   int_32 version = (major ver # << 16)  | version of tools ;
2122   int_32 source  = (tool_id << 16 ) | 1 ;
2123   int_32 info    = 0 ;    These are set by the SCO tools, but we
2124                           don't know enough about the source
2125			   environment to set them.  SCO ld currently
2126			   ignores them, and recommends we set them
2127			   to zero.  */
2128
2129#define SCO_MAJOR_VERSION 0x1
2130#define SCO_MINOR_VERSION 0x1
2131
2132void
2133sco_id ()
2134{
2135
2136  char *name;
2137  unsigned int c;
2138  char ch;
2139  char *p;
2140  asection *seg = now_seg;
2141  subsegT subseg = now_subseg;
2142  Elf_Internal_Note i_note;
2143  Elf_External_Note e_note;
2144  asection *note_secp = (asection *) NULL;
2145  int i, len;
2146
2147  /* create the .note section */
2148
2149  note_secp = subseg_new (".note", 0);
2150  bfd_set_section_flags (stdoutput,
2151			 note_secp,
2152			 SEC_HAS_CONTENTS | SEC_READONLY);
2153
2154  /* process the version string */
2155
2156  i_note.namesz = 4;
2157  i_note.descsz = 12;		/* 12 descriptive bytes */
2158  i_note.type = NT_VERSION;	/* Contains a version string */
2159
2160  p = frag_more (sizeof (i_note.namesz));
2161  md_number_to_chars (p, (valueT) i_note.namesz, 4);
2162
2163  p = frag_more (sizeof (i_note.descsz));
2164  md_number_to_chars (p, (valueT) i_note.descsz, 4);
2165
2166  p = frag_more (sizeof (i_note.type));
2167  md_number_to_chars (p, (valueT) i_note.type, 4);
2168
2169  p = frag_more (4);
2170  strcpy (p, "SCO");
2171
2172  /* Note: this is the version number of the ELF we're representing */
2173  p = frag_more (4);
2174  md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
2175
2176  /* Here, we pick a magic number for ourselves (yes, I "registered"
2177     it with SCO.  The bottom bit shows that we are compat with the
2178     SCO ABI.  */
2179  p = frag_more (4);
2180  md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
2181
2182  /* If we knew (or cared) what the source language options were, we'd
2183     fill them in here.  SCO has given us permission to ignore these
2184     and just set them to zero.  */
2185  p = frag_more (4);
2186  md_number_to_chars (p, 0x0000, 4);
2187
2188  frag_align (2, 0, 0);
2189
2190  /* We probably can't restore the current segment, for there likely
2191     isn't one yet...  */
2192  if (seg && subseg)
2193    subseg_set (seg, subseg);
2194
2195}
2196
2197#endif /* SCO_ELF */
2198
2199static int
2200elf_separate_stab_sections ()
2201{
2202#ifdef NEED_ECOFF_DEBUG
2203  return (!ECOFF_DEBUGGING);
2204#else
2205  return 1;
2206#endif
2207}
2208
2209static void
2210elf_init_stab_section (seg)
2211     segT seg;
2212{
2213#ifdef NEED_ECOFF_DEBUG
2214  if (!ECOFF_DEBUGGING)
2215#endif
2216    obj_elf_init_stab_section (seg);
2217}
2218
2219const struct format_ops elf_format_ops =
2220{
2221  bfd_target_elf_flavour,
2222  0,	/* dfl_leading_underscore */
2223  1,	/* emit_section_symbols */
2224  elf_begin,
2225  elf_file_symbol,
2226  elf_frob_symbol,
2227  elf_frob_file,
2228  elf_frob_file_before_adjust,
2229  elf_frob_file_after_relocs,
2230  elf_s_get_size, elf_s_set_size,
2231  elf_s_get_align, elf_s_set_align,
2232  elf_s_get_other,
2233  elf_s_set_other,
2234  0,	/* s_get_desc */
2235  0,	/* s_set_desc */
2236  0,	/* s_get_type */
2237  0,	/* s_set_type */
2238  elf_copy_symbol_attributes,
2239#ifdef NEED_ECOFF_DEBUG
2240  ecoff_generate_asm_lineno,
2241  ecoff_stab,
2242#else
2243  0,	/* generate_asm_lineno */
2244  0,	/* process_stab */
2245#endif
2246  elf_separate_stab_sections,
2247  elf_init_stab_section,
2248  elf_sec_sym_ok_for_reloc,
2249  elf_pop_insert,
2250#ifdef NEED_ECOFF_DEBUG
2251  elf_ecoff_set_ext,
2252#else
2253  0,	/* ecoff_set_ext */
2254#endif
2255  elf_obj_read_begin_hook,
2256  elf_obj_symbol_new_hook
2257};
2258