xref: /openbsd-src/gnu/usr.bin/binutils/gas/config/obj-elf.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* ELF object file format
2c074d1c9Sdrahn    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3c074d1c9Sdrahn    2001, 2002, 2003 Free Software Foundation, Inc.
42159047fSniklas 
52159047fSniklas    This file is part of GAS, the GNU Assembler.
62159047fSniklas 
72159047fSniklas    GAS is free software; you can redistribute it and/or modify
82159047fSniklas    it under the terms of the GNU General Public License as
92159047fSniklas    published by the Free Software Foundation; either version 2,
102159047fSniklas    or (at your option) any later version.
112159047fSniklas 
122159047fSniklas    GAS is distributed in the hope that it will be useful, but
132159047fSniklas    WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
152159047fSniklas    the GNU General Public License for more details.
162159047fSniklas 
17191aa565Sniklas    You should have received a copy of the GNU General Public License
18191aa565Sniklas    along with GAS; see the file COPYING.  If not, write to the Free
19191aa565Sniklas    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20191aa565Sniklas    02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas #define OBJ_HEADER "obj-elf.h"
232159047fSniklas #include "as.h"
24c074d1c9Sdrahn #include "safe-ctype.h"
252159047fSniklas #include "subsegs.h"
262159047fSniklas #include "obstack.h"
27c074d1c9Sdrahn #include "struc-symbol.h"
28*007c2a45Smiod #include "dwarf2dbg.h"
292159047fSniklas 
302159047fSniklas #ifndef ECOFF_DEBUGGING
312159047fSniklas #define ECOFF_DEBUGGING 0
322159047fSniklas #else
332159047fSniklas #define NEED_ECOFF_DEBUG
342159047fSniklas #endif
352159047fSniklas 
362159047fSniklas #ifdef NEED_ECOFF_DEBUG
372159047fSniklas #include "ecoff.h"
382159047fSniklas #endif
392159047fSniklas 
40b305b0f1Sespie #ifdef TC_ALPHA
41b305b0f1Sespie #include "elf/alpha.h"
42b305b0f1Sespie #endif
43b305b0f1Sespie 
442159047fSniklas #ifdef TC_MIPS
452159047fSniklas #include "elf/mips.h"
462159047fSniklas #endif
472159047fSniklas 
48191aa565Sniklas #ifdef TC_PPC
49191aa565Sniklas #include "elf/ppc.h"
50191aa565Sniklas #endif
51191aa565Sniklas 
52b305b0f1Sespie #ifdef TC_I370
53b305b0f1Sespie #include "elf/i370.h"
54b305b0f1Sespie #endif
55b305b0f1Sespie 
56*007c2a45Smiod static void obj_elf_line (int);
57*007c2a45Smiod static void obj_elf_size (int);
58*007c2a45Smiod static void obj_elf_type (int);
59*007c2a45Smiod static void obj_elf_ident (int);
60*007c2a45Smiod static void obj_elf_weak (int);
61*007c2a45Smiod static void obj_elf_local (int);
62*007c2a45Smiod static void obj_elf_visibility (int);
63*007c2a45Smiod static void obj_elf_symver (int);
64*007c2a45Smiod static void obj_elf_subsection (int);
65*007c2a45Smiod static void obj_elf_popsection (int);
66*007c2a45Smiod static void obj_elf_tls_common (int);
67*007c2a45Smiod static void obj_elf_lcomm (int);
682159047fSniklas 
692159047fSniklas static const pseudo_typeS elf_pseudo_table[] =
702159047fSniklas {
712159047fSniklas   {"comm", obj_elf_common, 0},
72b305b0f1Sespie   {"common", obj_elf_common, 1},
732159047fSniklas   {"ident", obj_elf_ident, 0},
74*007c2a45Smiod   {"lcomm", obj_elf_lcomm, 0},
752159047fSniklas   {"local", obj_elf_local, 0},
762159047fSniklas   {"previous", obj_elf_previous, 0},
772159047fSniklas   {"section", obj_elf_section, 0},
782159047fSniklas   {"section.s", obj_elf_section, 0},
792159047fSniklas   {"sect", obj_elf_section, 0},
802159047fSniklas   {"sect.s", obj_elf_section, 0},
81b305b0f1Sespie   {"pushsection", obj_elf_section, 1},
82b305b0f1Sespie   {"popsection", obj_elf_popsection, 0},
832159047fSniklas   {"size", obj_elf_size, 0},
842159047fSniklas   {"type", obj_elf_type, 0},
852159047fSniklas   {"version", obj_elf_version, 0},
862159047fSniklas   {"weak", obj_elf_weak, 0},
872159047fSniklas 
88b305b0f1Sespie   /* These define symbol visibility.  */
89b305b0f1Sespie   {"internal", obj_elf_visibility, STV_INTERNAL},
90b305b0f1Sespie   {"hidden", obj_elf_visibility, STV_HIDDEN},
91b305b0f1Sespie   {"protected", obj_elf_visibility, STV_PROTECTED},
92b305b0f1Sespie 
932159047fSniklas   /* These are used for stabs-in-elf configurations.  */
942159047fSniklas   {"line", obj_elf_line, 0},
952159047fSniklas 
96b305b0f1Sespie   /* This is a GNU extension to handle symbol versions.  */
97b305b0f1Sespie   {"symver", obj_elf_symver, 0},
98b305b0f1Sespie 
99b305b0f1Sespie   /* A GNU extension to change subsection only.  */
100b305b0f1Sespie   {"subsection", obj_elf_subsection, 0},
101b305b0f1Sespie 
102b305b0f1Sespie   /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
103*007c2a45Smiod   {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0},
104*007c2a45Smiod   {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0},
105b305b0f1Sespie 
1062159047fSniklas   /* These are used for dwarf.  */
1072159047fSniklas   {"2byte", cons, 2},
1082159047fSniklas   {"4byte", cons, 4},
1092159047fSniklas   {"8byte", cons, 8},
110*007c2a45Smiod   /* These are used for dwarf2.  */
111*007c2a45Smiod   { "file", (void (*) (int)) dwarf2_directive_file, 0 },
112*007c2a45Smiod   { "loc",  dwarf2_directive_loc,  0 },
1132159047fSniklas 
1142159047fSniklas   /* We need to trap the section changing calls to handle .previous.  */
1152159047fSniklas   {"data", obj_elf_data, 0},
1162159047fSniklas   {"text", obj_elf_text, 0},
1172159047fSniklas 
118c074d1c9Sdrahn   {"tls_common", obj_elf_tls_common, 0},
119c074d1c9Sdrahn 
1202159047fSniklas   /* End sentinel.  */
121b305b0f1Sespie   {NULL, NULL, 0},
1222159047fSniklas };
1232159047fSniklas 
1242159047fSniklas static const pseudo_typeS ecoff_debug_pseudo_table[] =
1252159047fSniklas {
1262159047fSniklas #ifdef NEED_ECOFF_DEBUG
1272159047fSniklas   /* COFF style debugging information for ECOFF. .ln is not used; .loc
1282159047fSniklas      is used instead.  */
1292159047fSniklas   { "def",	ecoff_directive_def,	0 },
1302159047fSniklas   { "dim",	ecoff_directive_dim,	0 },
1312159047fSniklas   { "endef",	ecoff_directive_endef,	0 },
1322159047fSniklas   { "file",	ecoff_directive_file,	0 },
1332159047fSniklas   { "scl",	ecoff_directive_scl,	0 },
1342159047fSniklas   { "tag",	ecoff_directive_tag,	0 },
1352159047fSniklas   { "val",	ecoff_directive_val,	0 },
1362159047fSniklas 
1372159047fSniklas   /* COFF debugging requires pseudo-ops .size and .type, but ELF
1382159047fSniklas      already has meanings for those.  We use .esize and .etype
1392159047fSniklas      instead.  These are only generated by gcc anyhow.  */
1402159047fSniklas   { "esize",	ecoff_directive_size,	0 },
1412159047fSniklas   { "etype",	ecoff_directive_type,	0 },
1422159047fSniklas 
1432159047fSniklas   /* ECOFF specific debugging information.  */
1442159047fSniklas   { "begin",	ecoff_directive_begin,	0 },
1452159047fSniklas   { "bend",	ecoff_directive_bend,	0 },
1462159047fSniklas   { "end",	ecoff_directive_end,	0 },
1472159047fSniklas   { "ent",	ecoff_directive_ent,	0 },
1482159047fSniklas   { "fmask",	ecoff_directive_fmask,	0 },
1492159047fSniklas   { "frame",	ecoff_directive_frame,	0 },
1502159047fSniklas   { "loc",	ecoff_directive_loc,	0 },
1512159047fSniklas   { "mask",	ecoff_directive_mask,	0 },
1522159047fSniklas 
1532159047fSniklas   /* Other ECOFF directives.  */
1542159047fSniklas   { "extern",	ecoff_directive_extern,	0 },
1552159047fSniklas 
1562159047fSniklas   /* These are used on Irix.  I don't know how to implement them.  */
1572159047fSniklas   { "alias",	s_ignore,		0 },
1582159047fSniklas   { "bgnb",	s_ignore,		0 },
1592159047fSniklas   { "endb",	s_ignore,		0 },
1602159047fSniklas   { "lab",	s_ignore,		0 },
1612159047fSniklas   { "noalias",	s_ignore,		0 },
1622159047fSniklas   { "verstamp",	s_ignore,		0 },
1632159047fSniklas   { "vreg",	s_ignore,		0 },
1642159047fSniklas #endif
1652159047fSniklas 
166b305b0f1Sespie   {NULL, NULL, 0}			/* end sentinel */
1672159047fSniklas };
1682159047fSniklas 
1692159047fSniklas #undef NO_RELOC
1702159047fSniklas #include "aout/aout64.h"
1712159047fSniklas 
172e93f7393Sniklas /* This is called when the assembler starts.  */
173e93f7393Sniklas 
174e93f7393Sniklas void
elf_begin(void)175*007c2a45Smiod elf_begin (void)
176e93f7393Sniklas {
177*007c2a45Smiod   asection *s;
178*007c2a45Smiod 
179e93f7393Sniklas   /* Add symbols for the known sections to the symbol table.  */
180*007c2a45Smiod   s = bfd_get_section_by_name (stdoutput, TEXT_SECTION_NAME);
181*007c2a45Smiod   symbol_table_insert (section_symbol (s));
182*007c2a45Smiod   s = bfd_get_section_by_name (stdoutput, DATA_SECTION_NAME);
183*007c2a45Smiod   symbol_table_insert (section_symbol (s));
184*007c2a45Smiod   s = bfd_get_section_by_name (stdoutput, BSS_SECTION_NAME);
185*007c2a45Smiod   symbol_table_insert (section_symbol (s));
186e93f7393Sniklas }
187e93f7393Sniklas 
1882159047fSniklas void
elf_pop_insert(void)189*007c2a45Smiod elf_pop_insert (void)
1902159047fSniklas {
1912159047fSniklas   pop_insert (elf_pseudo_table);
1922159047fSniklas   if (ECOFF_DEBUGGING)
1932159047fSniklas     pop_insert (ecoff_debug_pseudo_table);
1942159047fSniklas }
1952159047fSniklas 
1962159047fSniklas static bfd_vma
elf_s_get_size(symbolS * sym)197*007c2a45Smiod elf_s_get_size (symbolS *sym)
1982159047fSniklas {
1992159047fSniklas   return S_GET_SIZE (sym);
2002159047fSniklas }
2012159047fSniklas 
2022159047fSniklas static void
elf_s_set_size(symbolS * sym,bfd_vma sz)203*007c2a45Smiod elf_s_set_size (symbolS *sym, bfd_vma sz)
2042159047fSniklas {
2052159047fSniklas   S_SET_SIZE (sym, sz);
2062159047fSniklas }
2072159047fSniklas 
2082159047fSniklas static bfd_vma
elf_s_get_align(symbolS * sym)209*007c2a45Smiod elf_s_get_align (symbolS *sym)
2102159047fSniklas {
2112159047fSniklas   return S_GET_ALIGN (sym);
2122159047fSniklas }
2132159047fSniklas 
2142159047fSniklas static void
elf_s_set_align(symbolS * sym,bfd_vma align)215*007c2a45Smiod elf_s_set_align (symbolS *sym, bfd_vma align)
2162159047fSniklas {
2172159047fSniklas   S_SET_ALIGN (sym, align);
2182159047fSniklas }
2192159047fSniklas 
220b305b0f1Sespie int
elf_s_get_other(symbolS * sym)221*007c2a45Smiod elf_s_get_other (symbolS *sym)
222b305b0f1Sespie {
223b305b0f1Sespie   return elf_symbol (symbol_get_bfdsym (sym))->internal_elf_sym.st_other;
224b305b0f1Sespie }
225b305b0f1Sespie 
2262159047fSniklas static void
elf_s_set_other(symbolS * sym,int other)227*007c2a45Smiod elf_s_set_other (symbolS *sym, int other)
228b55d4692Sfgsch {
229b55d4692Sfgsch   S_SET_OTHER (sym, other);
230b55d4692Sfgsch }
231b55d4692Sfgsch 
2322159047fSniklas static int
elf_sec_sym_ok_for_reloc(asection * sec)233*007c2a45Smiod elf_sec_sym_ok_for_reloc (asection *sec)
2342159047fSniklas {
2352159047fSniklas   return obj_sec_sym_ok_for_reloc (sec);
2362159047fSniklas }
2372159047fSniklas 
2382159047fSniklas void
elf_file_symbol(const char * s)239*007c2a45Smiod elf_file_symbol (const char *s)
2402159047fSniklas {
2412159047fSniklas   symbolS *sym;
2422159047fSniklas 
243*007c2a45Smiod   sym = symbol_new (s, absolute_section, 0, NULL);
244b305b0f1Sespie   symbol_set_frag (sym, &zero_address_frag);
245b305b0f1Sespie   symbol_get_bfdsym (sym)->flags |= BSF_FILE;
2462159047fSniklas 
2472159047fSniklas   if (symbol_rootP != sym)
2482159047fSniklas     {
2492159047fSniklas       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
2502159047fSniklas       symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
2512159047fSniklas #ifdef DEBUG
2522159047fSniklas       verify_symbol_chain (symbol_rootP, symbol_lastP);
2532159047fSniklas #endif
2542159047fSniklas     }
255b305b0f1Sespie 
256b305b0f1Sespie #ifdef NEED_ECOFF_DEBUG
257b305b0f1Sespie   ecoff_new_file (s);
258b305b0f1Sespie #endif
2592159047fSniklas }
2602159047fSniklas 
261*007c2a45Smiod /* Called from read.c:s_comm after we've parsed .comm symbol, size.
262*007c2a45Smiod    Parse a possible alignment value.  */
263*007c2a45Smiod 
264c074d1c9Sdrahn static symbolS *
elf_common_parse(int ignore ATTRIBUTE_UNUSED,symbolS * symbolP,addressT size)265*007c2a45Smiod elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
2662159047fSniklas {
267*007c2a45Smiod   addressT align = 0;
268*007c2a45Smiod   int is_local = symbol_get_obj (symbolP)->local;
2692159047fSniklas 
270*007c2a45Smiod   if (*input_line_pointer == ',')
271b305b0f1Sespie     {
272*007c2a45Smiod       char *save = input_line_pointer;
273b305b0f1Sespie 
2742159047fSniklas       input_line_pointer++;
2752159047fSniklas       SKIP_WHITESPACE ();
2762159047fSniklas 
277*007c2a45Smiod       if (*input_line_pointer == '"')
2782159047fSniklas 	{
279*007c2a45Smiod 	  /* For sparc.  Accept .common symbol, length, "bss"  */
2802159047fSniklas 	  input_line_pointer++;
281*007c2a45Smiod 	  /* Some use the dot, some don't.  */
2822159047fSniklas 	  if (*input_line_pointer == '.')
2832159047fSniklas 	    input_line_pointer++;
284*007c2a45Smiod 	  /* Some say data, some say bss.  */
285*007c2a45Smiod 	  if (strncmp (input_line_pointer, "bss\"", 4) == 0)
286*007c2a45Smiod 	    input_line_pointer += 4;
287*007c2a45Smiod 	  else if (strncmp (input_line_pointer, "data\"", 5) == 0)
288*007c2a45Smiod 	    input_line_pointer += 5;
289*007c2a45Smiod 	  else
2902159047fSniklas 	    {
291*007c2a45Smiod 	      char *p = input_line_pointer;
292*007c2a45Smiod 	      char c;
293*007c2a45Smiod 
294*007c2a45Smiod 	      while (*--p != '"')
2952159047fSniklas 		;
296*007c2a45Smiod 	      while (!is_end_of_line[(unsigned char) *input_line_pointer])
297*007c2a45Smiod 		if (*input_line_pointer++ == '"')
298*007c2a45Smiod 		  break;
299*007c2a45Smiod 	      c = *input_line_pointer;
300*007c2a45Smiod 	      *input_line_pointer = '\0';
301*007c2a45Smiod 	      as_bad (_("bad .common segment %s"), p);
302*007c2a45Smiod 	      *input_line_pointer = c;
303*007c2a45Smiod 	      ignore_rest_of_line ();
304*007c2a45Smiod 	      return NULL;
3052159047fSniklas 	    }
306*007c2a45Smiod 	  /* ??? Don't ask me why these are always global.  */
307*007c2a45Smiod 	  is_local = 0;
308*007c2a45Smiod 	}
309*007c2a45Smiod       else
310*007c2a45Smiod 	{
311*007c2a45Smiod 	  input_line_pointer = save;
312*007c2a45Smiod 	  align = parse_align (is_local);
313*007c2a45Smiod 	  if (align == (addressT) -1)
314*007c2a45Smiod 	    return NULL;
315*007c2a45Smiod 	}
316*007c2a45Smiod     }
317*007c2a45Smiod 
318*007c2a45Smiod   if (is_local)
319*007c2a45Smiod     {
320*007c2a45Smiod       bss_alloc (symbolP, size, align);
321*007c2a45Smiod       S_CLEAR_EXTERNAL (symbolP);
322*007c2a45Smiod     }
323*007c2a45Smiod   else
324*007c2a45Smiod     {
325*007c2a45Smiod       S_SET_VALUE (symbolP, size);
326*007c2a45Smiod       S_SET_ALIGN (symbolP, align);
327*007c2a45Smiod       S_SET_EXTERNAL (symbolP);
328*007c2a45Smiod       S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
3292159047fSniklas     }
330b305b0f1Sespie 
331b305b0f1Sespie   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
332b305b0f1Sespie 
333c074d1c9Sdrahn   return symbolP;
3342159047fSniklas }
3352159047fSniklas 
336c074d1c9Sdrahn void
obj_elf_common(int is_common)337*007c2a45Smiod obj_elf_common (int is_common)
338c074d1c9Sdrahn {
339*007c2a45Smiod   if (flag_mri && is_common)
340*007c2a45Smiod     s_mri_common (0);
341*007c2a45Smiod   else
342*007c2a45Smiod     s_comm_internal (0, elf_common_parse);
343c074d1c9Sdrahn }
344c074d1c9Sdrahn 
345c074d1c9Sdrahn static void
obj_elf_tls_common(int ignore ATTRIBUTE_UNUSED)346*007c2a45Smiod obj_elf_tls_common (int ignore ATTRIBUTE_UNUSED)
347c074d1c9Sdrahn {
348*007c2a45Smiod   symbolS *symbolP = s_comm_internal (0, elf_common_parse);
349c074d1c9Sdrahn 
350c074d1c9Sdrahn   if (symbolP)
351c074d1c9Sdrahn     symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
352c074d1c9Sdrahn }
353c074d1c9Sdrahn 
3542159047fSniklas static void
obj_elf_lcomm(int ignore ATTRIBUTE_UNUSED)355*007c2a45Smiod obj_elf_lcomm (int ignore ATTRIBUTE_UNUSED)
356*007c2a45Smiod {
357*007c2a45Smiod   symbolS *symbolP = s_comm_internal (0, s_lcomm_internal);
358*007c2a45Smiod 
359*007c2a45Smiod   if (symbolP)
360*007c2a45Smiod     symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
361*007c2a45Smiod }
362*007c2a45Smiod 
363*007c2a45Smiod static void
obj_elf_local(int ignore ATTRIBUTE_UNUSED)364*007c2a45Smiod obj_elf_local (int ignore ATTRIBUTE_UNUSED)
3652159047fSniklas {
3662159047fSniklas   char *name;
3672159047fSniklas   int c;
3682159047fSniklas   symbolS *symbolP;
3692159047fSniklas 
3702159047fSniklas   do
3712159047fSniklas     {
3722159047fSniklas       name = input_line_pointer;
3732159047fSniklas       c = get_symbol_end ();
3742159047fSniklas       symbolP = symbol_find_or_make (name);
3752159047fSniklas       *input_line_pointer = c;
3762159047fSniklas       SKIP_WHITESPACE ();
3772159047fSniklas       S_CLEAR_EXTERNAL (symbolP);
378b305b0f1Sespie       symbol_get_obj (symbolP)->local = 1;
3792159047fSniklas       if (c == ',')
3802159047fSniklas 	{
3812159047fSniklas 	  input_line_pointer++;
3822159047fSniklas 	  SKIP_WHITESPACE ();
3832159047fSniklas 	  if (*input_line_pointer == '\n')
3842159047fSniklas 	    c = '\n';
3852159047fSniklas 	}
3862159047fSniklas     }
3872159047fSniklas   while (c == ',');
3882159047fSniklas   demand_empty_rest_of_line ();
3892159047fSniklas }
3902159047fSniklas 
3912159047fSniklas static void
obj_elf_weak(int ignore ATTRIBUTE_UNUSED)392*007c2a45Smiod obj_elf_weak (int ignore ATTRIBUTE_UNUSED)
3932159047fSniklas {
3942159047fSniklas   char *name;
3952159047fSniklas   int c;
3962159047fSniklas   symbolS *symbolP;
3972159047fSniklas 
3982159047fSniklas   do
3992159047fSniklas     {
4002159047fSniklas       name = input_line_pointer;
4012159047fSniklas       c = get_symbol_end ();
4022159047fSniklas       symbolP = symbol_find_or_make (name);
4032159047fSniklas       *input_line_pointer = c;
4042159047fSniklas       SKIP_WHITESPACE ();
4052159047fSniklas       S_SET_WEAK (symbolP);
406b305b0f1Sespie       symbol_get_obj (symbolP)->local = 1;
4072159047fSniklas       if (c == ',')
4082159047fSniklas 	{
4092159047fSniklas 	  input_line_pointer++;
4102159047fSniklas 	  SKIP_WHITESPACE ();
4112159047fSniklas 	  if (*input_line_pointer == '\n')
4122159047fSniklas 	    c = '\n';
4132159047fSniklas 	}
4142159047fSniklas     }
4152159047fSniklas   while (c == ',');
4162159047fSniklas   demand_empty_rest_of_line ();
4172159047fSniklas }
4182159047fSniklas 
419b305b0f1Sespie static void
obj_elf_visibility(int visibility)420*007c2a45Smiod obj_elf_visibility (int visibility)
421b305b0f1Sespie {
422b305b0f1Sespie   char *name;
423b305b0f1Sespie   int c;
424b305b0f1Sespie   symbolS *symbolP;
425b305b0f1Sespie   asymbol *bfdsym;
426b305b0f1Sespie   elf_symbol_type *elfsym;
427b305b0f1Sespie 
428b305b0f1Sespie   do
429b305b0f1Sespie     {
430b305b0f1Sespie       name = input_line_pointer;
431b305b0f1Sespie       c = get_symbol_end ();
432b305b0f1Sespie       symbolP = symbol_find_or_make (name);
433b305b0f1Sespie       *input_line_pointer = c;
434b305b0f1Sespie 
435b305b0f1Sespie       SKIP_WHITESPACE ();
436b305b0f1Sespie 
437b305b0f1Sespie       bfdsym = symbol_get_bfdsym (symbolP);
438b305b0f1Sespie       elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
439b305b0f1Sespie 
440b305b0f1Sespie       assert (elfsym);
441b305b0f1Sespie 
442c074d1c9Sdrahn       elfsym->internal_elf_sym.st_other &= ~3;
443c074d1c9Sdrahn       elfsym->internal_elf_sym.st_other |= visibility;
444b305b0f1Sespie 
445b305b0f1Sespie       if (c == ',')
446b305b0f1Sespie 	{
447b305b0f1Sespie 	  input_line_pointer ++;
448b305b0f1Sespie 
449b305b0f1Sespie 	  SKIP_WHITESPACE ();
450b305b0f1Sespie 
451b305b0f1Sespie 	  if (*input_line_pointer == '\n')
452b305b0f1Sespie 	    c = '\n';
453b305b0f1Sespie 	}
454b305b0f1Sespie     }
455b305b0f1Sespie   while (c == ',');
456b305b0f1Sespie 
457b305b0f1Sespie   demand_empty_rest_of_line ();
458b305b0f1Sespie }
459b305b0f1Sespie 
4602159047fSniklas static segT previous_section;
4612159047fSniklas static int previous_subsection;
4622159047fSniklas 
463b305b0f1Sespie struct section_stack
464b305b0f1Sespie {
465b305b0f1Sespie   struct section_stack *next;
466b305b0f1Sespie   segT seg, prev_seg;
467b305b0f1Sespie   int subseg, prev_subseg;
468b305b0f1Sespie };
469b305b0f1Sespie 
470b305b0f1Sespie static struct section_stack *section_stack;
471b305b0f1Sespie 
4722159047fSniklas /* Handle the .section pseudo-op.  This code supports two different
4732159047fSniklas    syntaxes.
4742159047fSniklas 
4752159047fSniklas    The first is found on Solaris, and looks like
4762159047fSniklas        .section ".sec1",#alloc,#execinstr,#write
4772159047fSniklas    Here the names after '#' are the SHF_* flags to turn on for the
4782159047fSniklas    section.  I'm not sure how it determines the SHT_* type (BFD
4792159047fSniklas    doesn't really give us control over the type, anyhow).
4802159047fSniklas 
4812159047fSniklas    The second format is found on UnixWare, and probably most SVR4
4822159047fSniklas    machines, and looks like
4832159047fSniklas        .section .sec1,"a",@progbits
4842159047fSniklas    The quoted string may contain any combination of a, w, x, and
4852159047fSniklas    represents the SHF_* flags to turn on for the section.  The string
4862159047fSniklas    beginning with '@' can be progbits or nobits.  There should be
4872159047fSniklas    other possibilities, but I don't know what they are.  In any case,
4882159047fSniklas    BFD doesn't really let us set the section type.  */
4892159047fSniklas 
4902159047fSniklas void
obj_elf_change_section(const char * name,int type,int attr,int entsize,const char * group_name,int linkonce,int push)491*007c2a45Smiod obj_elf_change_section (const char *name,
492*007c2a45Smiod 			int type,
493*007c2a45Smiod 			int attr,
494*007c2a45Smiod 			int entsize,
495*007c2a45Smiod 			const char *group_name,
496*007c2a45Smiod 			int linkonce,
497*007c2a45Smiod 			int push)
4982159047fSniklas {
499b55d4692Sfgsch   asection *old_sec;
5002159047fSniklas   segT sec;
501b55d4692Sfgsch   flagword flags;
502*007c2a45Smiod   const struct bfd_elf_special_section *ssect;
5032159047fSniklas 
5042159047fSniklas #ifdef md_flush_pending_output
5052159047fSniklas   md_flush_pending_output ();
5062159047fSniklas #endif
5072159047fSniklas 
5082159047fSniklas   /* Switch to the section, creating it if necessary.  */
509b305b0f1Sespie   if (push)
510b305b0f1Sespie     {
511b305b0f1Sespie       struct section_stack *elt;
512b305b0f1Sespie       elt = xmalloc (sizeof (struct section_stack));
513b305b0f1Sespie       elt->next = section_stack;
514b305b0f1Sespie       elt->seg = now_seg;
515b305b0f1Sespie       elt->prev_seg = previous_section;
516b305b0f1Sespie       elt->subseg = now_subseg;
517b305b0f1Sespie       elt->prev_subseg = previous_subsection;
518b305b0f1Sespie       section_stack = elt;
519b305b0f1Sespie     }
5202159047fSniklas   previous_section = now_seg;
5212159047fSniklas   previous_subsection = now_subseg;
5222159047fSniklas 
523b55d4692Sfgsch   old_sec = bfd_get_section_by_name (stdoutput, name);
524b305b0f1Sespie   sec = subseg_new (name, 0);
525*007c2a45Smiod   ssect = _bfd_elf_get_sec_type_attr (stdoutput, name);
5262159047fSniklas 
527*007c2a45Smiod   if (ssect != NULL)
528b305b0f1Sespie     {
529*007c2a45Smiod       bfd_boolean override = FALSE;
530*007c2a45Smiod 
531b305b0f1Sespie       if (type == SHT_NULL)
532*007c2a45Smiod 	type = ssect->type;
533*007c2a45Smiod       else if (type != ssect->type)
534b55d4692Sfgsch 	{
535c074d1c9Sdrahn 	  if (old_sec == NULL
536c074d1c9Sdrahn 	      /* FIXME: gcc, as of 2002-10-22, will emit
537c074d1c9Sdrahn 
538c074d1c9Sdrahn 		 .section .init_array,"aw",@progbits
539c074d1c9Sdrahn 
540c074d1c9Sdrahn 		 for __attribute__ ((section (".init_array"))).
541c074d1c9Sdrahn 		 "@progbits" is incorrect.  */
542*007c2a45Smiod 	      && ssect->type != SHT_INIT_ARRAY
543*007c2a45Smiod 	      && ssect->type != SHT_FINI_ARRAY
544*007c2a45Smiod 	      && ssect->type != SHT_PREINIT_ARRAY)
545b55d4692Sfgsch 	    {
546*007c2a45Smiod 	      /* We allow to specify any type for a .note section.  */
547*007c2a45Smiod 	      if (ssect->type != SHT_NOTE)
548*007c2a45Smiod 		as_warn (_("setting incorrect section type for %s"),
549*007c2a45Smiod 			 name);
550b55d4692Sfgsch 	    }
551b55d4692Sfgsch 	  else
552b55d4692Sfgsch 	    {
553*007c2a45Smiod 	      as_warn (_("ignoring incorrect section type for %s"),
554*007c2a45Smiod 		       name);
555*007c2a45Smiod 	      type = ssect->type;
556b55d4692Sfgsch 	    }
557b55d4692Sfgsch 	}
558*007c2a45Smiod 
559*007c2a45Smiod       if (old_sec == NULL && (attr & ~ssect->attr) != 0)
560b305b0f1Sespie 	{
561b305b0f1Sespie 	  /* As a GNU extension, we permit a .note section to be
562*007c2a45Smiod 	     allocatable.  If the linker sees an allocatable .note
563b305b0f1Sespie 	     section, it will create a PT_NOTE segment in the output
564*007c2a45Smiod 	     file.  We also allow "x" for .note.GNU-stack.  */
565*007c2a45Smiod 	  if (ssect->type == SHT_NOTE
566*007c2a45Smiod 	      && (attr == SHF_ALLOC || attr == SHF_EXECINSTR))
567*007c2a45Smiod 	    ;
568*007c2a45Smiod 	  /* Allow different SHF_MERGE and SHF_STRINGS if we have
569*007c2a45Smiod 	     something like .rodata.str.  */
570*007c2a45Smiod 	  else if (ssect->suffix_length == -2
571*007c2a45Smiod 		   && name[ssect->prefix_length] == '.'
572*007c2a45Smiod 		   && (attr
573*007c2a45Smiod 		       & ~ssect->attr
574*007c2a45Smiod 		       & ~SHF_MERGE
575*007c2a45Smiod 		       & ~SHF_STRINGS) == 0)
576*007c2a45Smiod 	    ;
577*007c2a45Smiod 	  /* .interp, .strtab and .symtab can have SHF_ALLOC.  */
578*007c2a45Smiod 	  else if (attr == SHF_ALLOC
579*007c2a45Smiod 		   && (strcmp (name, ".interp") == 0
580*007c2a45Smiod 		       || strcmp (name, ".strtab") == 0
581*007c2a45Smiod 		       || strcmp (name, ".symtab") == 0))
582*007c2a45Smiod 	    override = TRUE;
583*007c2a45Smiod 	  else
584*007c2a45Smiod 	    {
585c074d1c9Sdrahn 	      as_warn (_("setting incorrect section attributes for %s"),
586b305b0f1Sespie 		       name);
587*007c2a45Smiod 	      override = TRUE;
588b305b0f1Sespie 	    }
589b305b0f1Sespie 	}
590*007c2a45Smiod       if (!override && old_sec == NULL)
591*007c2a45Smiod 	attr |= ssect->attr;
592*007c2a45Smiod     }
593*007c2a45Smiod 
594*007c2a45Smiod   if (type != SHT_NULL)
595*007c2a45Smiod     elf_section_type (sec) = type;
596*007c2a45Smiod   if (attr != 0)
597*007c2a45Smiod     elf_section_flags (sec) = attr;
598b305b0f1Sespie 
599b305b0f1Sespie   /* Convert ELF type and flags to BFD flags.  */
600b305b0f1Sespie   flags = (SEC_RELOC
601b305b0f1Sespie 	   | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
602b305b0f1Sespie 	   | ((attr & SHF_ALLOC) ? SEC_ALLOC : 0)
603b305b0f1Sespie 	   | (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
604c074d1c9Sdrahn 	   | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)
605c074d1c9Sdrahn 	   | ((attr & SHF_MERGE) ? SEC_MERGE : 0)
606c074d1c9Sdrahn 	   | ((attr & SHF_STRINGS) ? SEC_STRINGS : 0)
607c074d1c9Sdrahn 	   | ((attr & SHF_TLS) ? SEC_THREAD_LOCAL : 0));
608b305b0f1Sespie #ifdef md_elf_section_flags
609b305b0f1Sespie   flags = md_elf_section_flags (flags, attr, type);
610b305b0f1Sespie #endif
611b305b0f1Sespie 
612b55d4692Sfgsch   if (old_sec == NULL)
613b55d4692Sfgsch     {
614b55d4692Sfgsch       symbolS *secsym;
615b55d4692Sfgsch 
616b305b0f1Sespie       /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
617b305b0f1Sespie       if (type == SHT_NOBITS)
618b305b0f1Sespie 	seg_info (sec)->bss = 1;
619b305b0f1Sespie 
620c074d1c9Sdrahn       if (linkonce)
621c074d1c9Sdrahn 	flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
622b305b0f1Sespie       bfd_set_section_flags (stdoutput, sec, flags);
623c074d1c9Sdrahn       if (flags & SEC_MERGE)
624c074d1c9Sdrahn 	sec->entsize = entsize;
625c074d1c9Sdrahn       elf_group_name (sec) = group_name;
626b305b0f1Sespie 
627b305b0f1Sespie       /* Add a symbol for this section to the symbol table.  */
628b305b0f1Sespie       secsym = symbol_find (name);
629b305b0f1Sespie       if (secsym != NULL)
630b305b0f1Sespie 	symbol_set_bfdsym (secsym, sec->symbol);
631b305b0f1Sespie       else
632b305b0f1Sespie 	symbol_table_insert (section_symbol (sec));
633b305b0f1Sespie     }
634b55d4692Sfgsch   else if (attr != 0)
635b55d4692Sfgsch     {
636b55d4692Sfgsch       /* If section attributes are specified the second time we see a
637b55d4692Sfgsch 	 particular section, then check that they are the same as we
638b55d4692Sfgsch 	 saw the first time.  */
639c074d1c9Sdrahn       if (((old_sec->flags ^ flags)
640b55d4692Sfgsch 	   & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
641c074d1c9Sdrahn 	      | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS
642c074d1c9Sdrahn 	      | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
643c074d1c9Sdrahn 	      | SEC_THREAD_LOCAL)))
644c074d1c9Sdrahn 	as_warn (_("ignoring changed section attributes for %s"), name);
645c074d1c9Sdrahn       if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
646c074d1c9Sdrahn 	as_warn (_("ignoring changed section entity size for %s"), name);
647c074d1c9Sdrahn       if ((attr & SHF_GROUP) != 0
648c074d1c9Sdrahn 	  && strcmp (elf_group_name (old_sec), group_name) != 0)
649c074d1c9Sdrahn 	as_warn (_("ignoring new section group for %s"), name);
650b55d4692Sfgsch     }
6512159047fSniklas 
6522159047fSniklas #ifdef md_elf_section_change_hook
6532159047fSniklas   md_elf_section_change_hook ();
6542159047fSniklas #endif
6552159047fSniklas }
6562159047fSniklas 
657c074d1c9Sdrahn static int
obj_elf_parse_section_letters(char * str,size_t len)658*007c2a45Smiod obj_elf_parse_section_letters (char *str, size_t len)
6592159047fSniklas {
660b305b0f1Sespie   int attr = 0;
6612159047fSniklas 
662b305b0f1Sespie   while (len > 0)
6632159047fSniklas     {
664b305b0f1Sespie       switch (*str)
6652159047fSniklas 	{
6662159047fSniklas 	case 'a':
6672159047fSniklas 	  attr |= SHF_ALLOC;
6682159047fSniklas 	  break;
6692159047fSniklas 	case 'w':
6702159047fSniklas 	  attr |= SHF_WRITE;
6712159047fSniklas 	  break;
6722159047fSniklas 	case 'x':
6732159047fSniklas 	  attr |= SHF_EXECINSTR;
6742159047fSniklas 	  break;
675c074d1c9Sdrahn 	case 'M':
676c074d1c9Sdrahn 	  attr |= SHF_MERGE;
677c074d1c9Sdrahn 	  break;
678c074d1c9Sdrahn 	case 'S':
679c074d1c9Sdrahn 	  attr |= SHF_STRINGS;
680c074d1c9Sdrahn 	  break;
681c074d1c9Sdrahn 	case 'G':
682c074d1c9Sdrahn 	  attr |= SHF_GROUP;
683c074d1c9Sdrahn 	  break;
684c074d1c9Sdrahn 	case 'T':
685c074d1c9Sdrahn 	  attr |= SHF_TLS;
686c074d1c9Sdrahn 	  break;
687c074d1c9Sdrahn 	/* Compatibility.  */
688c074d1c9Sdrahn 	case 'm':
689c074d1c9Sdrahn 	  if (*(str - 1) == 'a')
690c074d1c9Sdrahn 	    {
691c074d1c9Sdrahn 	      attr |= SHF_MERGE;
692c074d1c9Sdrahn 	      if (len > 1 && str[1] == 's')
693c074d1c9Sdrahn 		{
694c074d1c9Sdrahn 		  attr |= SHF_STRINGS;
695c074d1c9Sdrahn 		  str++, len--;
696c074d1c9Sdrahn 		}
697c074d1c9Sdrahn 	      break;
698c074d1c9Sdrahn 	    }
6992159047fSniklas 	default:
700191aa565Sniklas 	  {
701c074d1c9Sdrahn 	    char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G,T");
702191aa565Sniklas #ifdef md_elf_section_letter
703b305b0f1Sespie 	    int md_attr = md_elf_section_letter (*str, &bad_msg);
704b305b0f1Sespie 	    if (md_attr >= 0)
705191aa565Sniklas 	      attr |= md_attr;
706191aa565Sniklas 	    else
707191aa565Sniklas #endif
708*007c2a45Smiod 	      as_fatal ("%s", bad_msg);
709b305b0f1Sespie 	  }
710b305b0f1Sespie 	  break;
711b305b0f1Sespie 	}
712b305b0f1Sespie       str++, len--;
713b305b0f1Sespie     }
714b305b0f1Sespie 
715b305b0f1Sespie   return attr;
716b305b0f1Sespie }
717b305b0f1Sespie 
718c074d1c9Sdrahn static int
obj_elf_section_word(char * str,size_t len)719*007c2a45Smiod obj_elf_section_word (char *str, size_t len)
720b305b0f1Sespie {
721b305b0f1Sespie   if (len == 5 && strncmp (str, "write", 5) == 0)
722b305b0f1Sespie     return SHF_WRITE;
723b305b0f1Sespie   if (len == 5 && strncmp (str, "alloc", 5) == 0)
724b305b0f1Sespie     return SHF_ALLOC;
725b305b0f1Sespie   if (len == 9 && strncmp (str, "execinstr", 9) == 0)
726b305b0f1Sespie     return SHF_EXECINSTR;
727c074d1c9Sdrahn   if (len == 3 && strncmp (str, "tls", 3) == 0)
728c074d1c9Sdrahn     return SHF_TLS;
729b305b0f1Sespie 
730b305b0f1Sespie #ifdef md_elf_section_word
731b305b0f1Sespie   {
732b305b0f1Sespie     int md_attr = md_elf_section_word (str, len);
733b305b0f1Sespie     if (md_attr >= 0)
734b305b0f1Sespie       return md_attr;
735b305b0f1Sespie   }
736b305b0f1Sespie #endif
737b305b0f1Sespie 
738c074d1c9Sdrahn   as_warn (_("unrecognized section attribute"));
739b305b0f1Sespie   return 0;
740b305b0f1Sespie }
741b305b0f1Sespie 
742c074d1c9Sdrahn static int
obj_elf_section_type(char * str,size_t len)743*007c2a45Smiod obj_elf_section_type (char *str, size_t len)
744b305b0f1Sespie {
745b305b0f1Sespie   if (len == 8 && strncmp (str, "progbits", 8) == 0)
746b305b0f1Sespie     return SHT_PROGBITS;
747b305b0f1Sespie   if (len == 6 && strncmp (str, "nobits", 6) == 0)
748b305b0f1Sespie     return SHT_NOBITS;
749*007c2a45Smiod   if (len == 4 && strncmp (str, "note", 4) == 0)
750*007c2a45Smiod     return SHT_NOTE;
751b305b0f1Sespie 
752b305b0f1Sespie #ifdef md_elf_section_type
753b305b0f1Sespie   {
754b305b0f1Sespie     int md_type = md_elf_section_type (str, len);
755b305b0f1Sespie     if (md_type >= 0)
756b305b0f1Sespie       return md_type;
757b305b0f1Sespie   }
758b305b0f1Sespie #endif
759b305b0f1Sespie 
760c074d1c9Sdrahn   as_warn (_("unrecognized section type"));
761b305b0f1Sespie   return 0;
762b305b0f1Sespie }
763b305b0f1Sespie 
764c074d1c9Sdrahn /* Get name of section.  */
765c074d1c9Sdrahn static char *
obj_elf_section_name(void)766*007c2a45Smiod obj_elf_section_name (void)
767c074d1c9Sdrahn {
768c074d1c9Sdrahn   char *name;
769c074d1c9Sdrahn 
770c074d1c9Sdrahn   SKIP_WHITESPACE ();
771c074d1c9Sdrahn   if (*input_line_pointer == '"')
772c074d1c9Sdrahn     {
773c074d1c9Sdrahn       int dummy;
774c074d1c9Sdrahn 
775c074d1c9Sdrahn       name = demand_copy_C_string (&dummy);
776c074d1c9Sdrahn       if (name == NULL)
777c074d1c9Sdrahn 	{
778c074d1c9Sdrahn 	  ignore_rest_of_line ();
779c074d1c9Sdrahn 	  return NULL;
780c074d1c9Sdrahn 	}
781c074d1c9Sdrahn     }
782c074d1c9Sdrahn   else
783c074d1c9Sdrahn     {
784c074d1c9Sdrahn       char *end = input_line_pointer;
785c074d1c9Sdrahn 
786c074d1c9Sdrahn       while (0 == strchr ("\n\t,; ", *end))
787c074d1c9Sdrahn 	end++;
788c074d1c9Sdrahn       if (end == input_line_pointer)
789c074d1c9Sdrahn 	{
790*007c2a45Smiod 	  as_bad (_("missing name"));
791c074d1c9Sdrahn 	  ignore_rest_of_line ();
792c074d1c9Sdrahn 	  return NULL;
793c074d1c9Sdrahn 	}
794c074d1c9Sdrahn 
795c074d1c9Sdrahn       name = xmalloc (end - input_line_pointer + 1);
796c074d1c9Sdrahn       memcpy (name, input_line_pointer, end - input_line_pointer);
797c074d1c9Sdrahn       name[end - input_line_pointer] = '\0';
798*007c2a45Smiod #ifdef tc_canonicalize_section_name
799*007c2a45Smiod       name = tc_canonicalize_section_name (name);
800*007c2a45Smiod #endif
801c074d1c9Sdrahn       input_line_pointer = end;
802c074d1c9Sdrahn     }
803c074d1c9Sdrahn   SKIP_WHITESPACE ();
804c074d1c9Sdrahn   return name;
805c074d1c9Sdrahn }
806c074d1c9Sdrahn 
807b305b0f1Sespie void
obj_elf_section(int push)808*007c2a45Smiod obj_elf_section (int push)
809b305b0f1Sespie {
810c074d1c9Sdrahn   char *name, *group_name, *beg;
811b305b0f1Sespie   int type, attr, dummy;
812c074d1c9Sdrahn   int entsize;
813c074d1c9Sdrahn   int linkonce;
814b305b0f1Sespie 
815b305b0f1Sespie #ifndef TC_I370
816b305b0f1Sespie   if (flag_mri)
817b305b0f1Sespie     {
818b305b0f1Sespie       char mri_type;
819b305b0f1Sespie 
820b305b0f1Sespie #ifdef md_flush_pending_output
821b305b0f1Sespie       md_flush_pending_output ();
822b305b0f1Sespie #endif
823b305b0f1Sespie 
824b305b0f1Sespie       previous_section = now_seg;
825b305b0f1Sespie       previous_subsection = now_subseg;
826b305b0f1Sespie 
827b305b0f1Sespie       s_mri_sect (&mri_type);
828b305b0f1Sespie 
829b305b0f1Sespie #ifdef md_elf_section_change_hook
830b305b0f1Sespie       md_elf_section_change_hook ();
831b305b0f1Sespie #endif
832b305b0f1Sespie 
833b305b0f1Sespie       return;
834b305b0f1Sespie     }
835b305b0f1Sespie #endif /* ! defined (TC_I370) */
836b305b0f1Sespie 
837c074d1c9Sdrahn   name = obj_elf_section_name ();
838b305b0f1Sespie   if (name == NULL)
8392159047fSniklas     return;
840b305b0f1Sespie   type = SHT_NULL;
841b305b0f1Sespie   attr = 0;
842c074d1c9Sdrahn   group_name = NULL;
843c074d1c9Sdrahn   entsize = 0;
844c074d1c9Sdrahn   linkonce = 0;
845b305b0f1Sespie 
846b305b0f1Sespie   if (*input_line_pointer == ',')
847b305b0f1Sespie     {
848b305b0f1Sespie       /* Skip the comma.  */
8492159047fSniklas       ++input_line_pointer;
850b305b0f1Sespie       SKIP_WHITESPACE ();
851b305b0f1Sespie 
852b305b0f1Sespie       if (*input_line_pointer == '"')
853b305b0f1Sespie 	{
854b305b0f1Sespie 	  beg = demand_copy_C_string (&dummy);
855b305b0f1Sespie 	  if (beg == NULL)
856b305b0f1Sespie 	    {
857b305b0f1Sespie 	      ignore_rest_of_line ();
858b305b0f1Sespie 	      return;
859b305b0f1Sespie 	    }
860b305b0f1Sespie 	  attr |= obj_elf_parse_section_letters (beg, strlen (beg));
8612159047fSniklas 
8622159047fSniklas 	  SKIP_WHITESPACE ();
8632159047fSniklas 	  if (*input_line_pointer == ',')
8642159047fSniklas 	    {
865b305b0f1Sespie 	      char c;
866c074d1c9Sdrahn 	      char *save = input_line_pointer;
867c074d1c9Sdrahn 
8682159047fSniklas 	      ++input_line_pointer;
8692159047fSniklas 	      SKIP_WHITESPACE ();
870b305b0f1Sespie 	      c = *input_line_pointer;
871b305b0f1Sespie 	      if (c == '"')
8722159047fSniklas 		{
873b305b0f1Sespie 		  beg = demand_copy_C_string (&dummy);
874b305b0f1Sespie 		  if (beg == NULL)
8752159047fSniklas 		    {
8762159047fSniklas 		      ignore_rest_of_line ();
877b305b0f1Sespie 		      return;
8782159047fSniklas 		    }
879b305b0f1Sespie 		  type = obj_elf_section_type (beg, strlen (beg));
8802159047fSniklas 		}
881b305b0f1Sespie 	      else if (c == '@' || c == '%')
882b305b0f1Sespie 		{
883b305b0f1Sespie 		  beg = ++input_line_pointer;
884b305b0f1Sespie 		  c = get_symbol_end ();
885b305b0f1Sespie 		  *input_line_pointer = c;
886b305b0f1Sespie 		  type = obj_elf_section_type (beg, input_line_pointer - beg);
8872159047fSniklas 		}
888c074d1c9Sdrahn 	      else
889c074d1c9Sdrahn 		input_line_pointer = save;
890c074d1c9Sdrahn 	    }
891c074d1c9Sdrahn 
892c074d1c9Sdrahn 	  SKIP_WHITESPACE ();
893c074d1c9Sdrahn 	  if ((attr & SHF_MERGE) != 0 && *input_line_pointer == ',')
894c074d1c9Sdrahn 	    {
895c074d1c9Sdrahn 	      ++input_line_pointer;
896c074d1c9Sdrahn 	      SKIP_WHITESPACE ();
897c074d1c9Sdrahn 	      entsize = get_absolute_expression ();
898c074d1c9Sdrahn 	      SKIP_WHITESPACE ();
899c074d1c9Sdrahn 	      if (entsize < 0)
900c074d1c9Sdrahn 		{
901c074d1c9Sdrahn 		  as_warn (_("invalid merge entity size"));
902c074d1c9Sdrahn 		  attr &= ~SHF_MERGE;
903c074d1c9Sdrahn 		  entsize = 0;
904c074d1c9Sdrahn 		}
905c074d1c9Sdrahn 	    }
906c074d1c9Sdrahn 	  else if ((attr & SHF_MERGE) != 0)
907c074d1c9Sdrahn 	    {
908c074d1c9Sdrahn 	      as_warn (_("entity size for SHF_MERGE not specified"));
909c074d1c9Sdrahn 	      attr &= ~SHF_MERGE;
910c074d1c9Sdrahn 	    }
911c074d1c9Sdrahn 
912c074d1c9Sdrahn 	  if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
913c074d1c9Sdrahn 	    {
914c074d1c9Sdrahn 	      ++input_line_pointer;
915c074d1c9Sdrahn 	      group_name = obj_elf_section_name ();
916c074d1c9Sdrahn 	      if (group_name == NULL)
917c074d1c9Sdrahn 		attr &= ~SHF_GROUP;
918c074d1c9Sdrahn 	      else if (strncmp (input_line_pointer, ",comdat", 7) == 0)
919c074d1c9Sdrahn 		{
920c074d1c9Sdrahn 		  input_line_pointer += 7;
921c074d1c9Sdrahn 		  linkonce = 1;
922c074d1c9Sdrahn 		}
923c074d1c9Sdrahn 	      else if (strncmp (name, ".gnu.linkonce", 13) == 0)
924c074d1c9Sdrahn 		linkonce = 1;
925c074d1c9Sdrahn 	    }
926c074d1c9Sdrahn 	  else if ((attr & SHF_GROUP) != 0)
927c074d1c9Sdrahn 	    {
928c074d1c9Sdrahn 	      as_warn (_("group name for SHF_GROUP not specified"));
929c074d1c9Sdrahn 	      attr &= ~SHF_GROUP;
9302159047fSniklas 	    }
931191aa565Sniklas 	}
9322159047fSniklas       else
9332159047fSniklas 	{
9342159047fSniklas 	  do
9352159047fSniklas 	    {
936b305b0f1Sespie 	      char c;
937b305b0f1Sespie 
9382159047fSniklas 	      SKIP_WHITESPACE ();
9392159047fSniklas 	      if (*input_line_pointer != '#')
9402159047fSniklas 		{
941*007c2a45Smiod 		  as_bad (_("character following name is not '#'"));
9422159047fSniklas 		  ignore_rest_of_line ();
9432159047fSniklas 		  return;
9442159047fSniklas 		}
945b305b0f1Sespie 	      beg = ++input_line_pointer;
946b305b0f1Sespie 	      c = get_symbol_end ();
947b305b0f1Sespie 	      *input_line_pointer = c;
948b305b0f1Sespie 
949b305b0f1Sespie 	      attr |= obj_elf_section_word (beg, input_line_pointer - beg);
950b305b0f1Sespie 
9512159047fSniklas 	      SKIP_WHITESPACE ();
9522159047fSniklas 	    }
9532159047fSniklas 	  while (*input_line_pointer++ == ',');
9542159047fSniklas 	  --input_line_pointer;
9552159047fSniklas 	}
9562159047fSniklas     }
9572159047fSniklas 
9582159047fSniklas   demand_empty_rest_of_line ();
959b305b0f1Sespie 
960c074d1c9Sdrahn   obj_elf_change_section (name, type, attr, entsize, group_name, linkonce, push);
9612159047fSniklas }
9622159047fSniklas 
9632159047fSniklas /* Change to the .data section.  */
9642159047fSniklas 
965b305b0f1Sespie void
obj_elf_data(int i)966*007c2a45Smiod obj_elf_data (int i)
9672159047fSniklas {
968b305b0f1Sespie #ifdef md_flush_pending_output
969b305b0f1Sespie   md_flush_pending_output ();
970b305b0f1Sespie #endif
971b305b0f1Sespie 
9722159047fSniklas   previous_section = now_seg;
9732159047fSniklas   previous_subsection = now_subseg;
9742159047fSniklas   s_data (i);
975b305b0f1Sespie 
976b305b0f1Sespie #ifdef md_elf_section_change_hook
977b305b0f1Sespie   md_elf_section_change_hook ();
978b305b0f1Sespie #endif
9792159047fSniklas }
9802159047fSniklas 
9812159047fSniklas /* Change to the .text section.  */
9822159047fSniklas 
983b305b0f1Sespie void
obj_elf_text(int i)984*007c2a45Smiod obj_elf_text (int i)
9852159047fSniklas {
986b305b0f1Sespie #ifdef md_flush_pending_output
987b305b0f1Sespie   md_flush_pending_output ();
988b305b0f1Sespie #endif
989b305b0f1Sespie 
9902159047fSniklas   previous_section = now_seg;
9912159047fSniklas   previous_subsection = now_subseg;
9922159047fSniklas   s_text (i);
993b305b0f1Sespie 
994b305b0f1Sespie #ifdef md_elf_section_change_hook
995b305b0f1Sespie   md_elf_section_change_hook ();
996b305b0f1Sespie #endif
997b305b0f1Sespie }
998b305b0f1Sespie 
999b305b0f1Sespie static void
obj_elf_subsection(int ignore ATTRIBUTE_UNUSED)1000*007c2a45Smiod obj_elf_subsection (int ignore ATTRIBUTE_UNUSED)
1001b305b0f1Sespie {
1002b305b0f1Sespie   register int temp;
1003b305b0f1Sespie 
1004b305b0f1Sespie #ifdef md_flush_pending_output
1005b305b0f1Sespie   md_flush_pending_output ();
1006b305b0f1Sespie #endif
1007b305b0f1Sespie 
1008b305b0f1Sespie   previous_section = now_seg;
1009b305b0f1Sespie   previous_subsection = now_subseg;
1010b305b0f1Sespie 
1011b305b0f1Sespie   temp = get_absolute_expression ();
1012b305b0f1Sespie   subseg_set (now_seg, (subsegT) temp);
1013b305b0f1Sespie   demand_empty_rest_of_line ();
1014b305b0f1Sespie 
1015b305b0f1Sespie #ifdef md_elf_section_change_hook
1016b305b0f1Sespie   md_elf_section_change_hook ();
1017b305b0f1Sespie #endif
1018b305b0f1Sespie }
1019b305b0f1Sespie 
1020b305b0f1Sespie /* This can be called from the processor backends if they change
1021b305b0f1Sespie    sections.  */
1022b305b0f1Sespie 
1023b305b0f1Sespie void
obj_elf_section_change_hook(void)1024*007c2a45Smiod obj_elf_section_change_hook (void)
1025b305b0f1Sespie {
1026b305b0f1Sespie   previous_section = now_seg;
1027b305b0f1Sespie   previous_subsection = now_subseg;
10282159047fSniklas }
10292159047fSniklas 
10302159047fSniklas void
obj_elf_previous(int ignore ATTRIBUTE_UNUSED)1031*007c2a45Smiod obj_elf_previous (int ignore ATTRIBUTE_UNUSED)
10322159047fSniklas {
1033b305b0f1Sespie   segT new_section;
1034b305b0f1Sespie   int new_subsection;
1035b305b0f1Sespie 
10362159047fSniklas   if (previous_section == 0)
10372159047fSniklas     {
1038c074d1c9Sdrahn       as_warn (_(".previous without corresponding .section; ignored"));
10392159047fSniklas       return;
10402159047fSniklas     }
1041b305b0f1Sespie 
1042b305b0f1Sespie #ifdef md_flush_pending_output
1043b305b0f1Sespie   md_flush_pending_output ();
1044b305b0f1Sespie #endif
1045b305b0f1Sespie 
1046b305b0f1Sespie   new_section = previous_section;
1047b305b0f1Sespie   new_subsection = previous_subsection;
1048b305b0f1Sespie   previous_section = now_seg;
1049b305b0f1Sespie   previous_subsection = now_subseg;
1050b305b0f1Sespie   subseg_set (new_section, new_subsection);
1051b305b0f1Sespie 
1052b305b0f1Sespie #ifdef md_elf_section_change_hook
1053b305b0f1Sespie   md_elf_section_change_hook ();
1054b305b0f1Sespie #endif
1055b305b0f1Sespie }
1056b305b0f1Sespie 
1057b305b0f1Sespie static void
obj_elf_popsection(int xxx ATTRIBUTE_UNUSED)1058*007c2a45Smiod obj_elf_popsection (int xxx ATTRIBUTE_UNUSED)
1059b305b0f1Sespie {
1060b305b0f1Sespie   struct section_stack *top = section_stack;
1061b305b0f1Sespie 
1062b305b0f1Sespie   if (top == NULL)
1063b305b0f1Sespie     {
1064c074d1c9Sdrahn       as_warn (_(".popsection without corresponding .pushsection; ignored"));
1065b305b0f1Sespie       return;
1066b305b0f1Sespie     }
1067b305b0f1Sespie 
1068b305b0f1Sespie #ifdef md_flush_pending_output
1069b305b0f1Sespie   md_flush_pending_output ();
1070b305b0f1Sespie #endif
1071b305b0f1Sespie 
1072b305b0f1Sespie   section_stack = top->next;
1073b305b0f1Sespie   previous_section = top->prev_seg;
1074b305b0f1Sespie   previous_subsection = top->prev_subseg;
1075b305b0f1Sespie   subseg_set (top->seg, top->subseg);
1076b305b0f1Sespie   free (top);
1077b305b0f1Sespie 
1078b305b0f1Sespie #ifdef md_elf_section_change_hook
1079b305b0f1Sespie   md_elf_section_change_hook ();
1080b305b0f1Sespie #endif
10812159047fSniklas }
10822159047fSniklas 
10832159047fSniklas static void
obj_elf_line(int ignore ATTRIBUTE_UNUSED)1084*007c2a45Smiod obj_elf_line (int ignore ATTRIBUTE_UNUSED)
10852159047fSniklas {
10862159047fSniklas   /* Assume delimiter is part of expression.  BSD4.2 as fails with
10872159047fSniklas      delightful bug, so we are not being incompatible here.  */
1088*007c2a45Smiod   new_logical_line (NULL, get_absolute_expression ());
10892159047fSniklas   demand_empty_rest_of_line ();
10902159047fSniklas }
10912159047fSniklas 
1092b305b0f1Sespie /* This handles the .symver pseudo-op, which is used to specify a
1093b305b0f1Sespie    symbol version.  The syntax is ``.symver NAME,SYMVERNAME''.
1094b305b0f1Sespie    SYMVERNAME may contain ELF_VER_CHR ('@') characters.  This
1095b305b0f1Sespie    pseudo-op causes the assembler to emit a symbol named SYMVERNAME
1096b305b0f1Sespie    with the same value as the symbol NAME.  */
1097b305b0f1Sespie 
1098b305b0f1Sespie static void
obj_elf_symver(int ignore ATTRIBUTE_UNUSED)1099*007c2a45Smiod obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
1100b305b0f1Sespie {
1101b305b0f1Sespie   char *name;
1102b305b0f1Sespie   char c;
1103c074d1c9Sdrahn   char old_lexat;
1104b305b0f1Sespie   symbolS *sym;
1105b305b0f1Sespie 
1106b305b0f1Sespie   name = input_line_pointer;
1107b305b0f1Sespie   c = get_symbol_end ();
1108b305b0f1Sespie 
1109b305b0f1Sespie   sym = symbol_find_or_make (name);
1110b305b0f1Sespie 
1111b305b0f1Sespie   *input_line_pointer = c;
1112b305b0f1Sespie 
1113b305b0f1Sespie   SKIP_WHITESPACE ();
1114b305b0f1Sespie   if (*input_line_pointer != ',')
1115b305b0f1Sespie     {
1116b305b0f1Sespie       as_bad (_("expected comma after name in .symver"));
1117b305b0f1Sespie       ignore_rest_of_line ();
1118b305b0f1Sespie       return;
1119b305b0f1Sespie     }
1120b305b0f1Sespie 
1121b305b0f1Sespie   ++input_line_pointer;
1122c074d1c9Sdrahn   SKIP_WHITESPACE ();
1123b305b0f1Sespie   name = input_line_pointer;
1124c074d1c9Sdrahn 
1125c074d1c9Sdrahn   /* Temporarily include '@' in symbol names.  */
1126c074d1c9Sdrahn   old_lexat = lex_type[(unsigned char) '@'];
1127c074d1c9Sdrahn   lex_type[(unsigned char) '@'] |= LEX_NAME;
1128b305b0f1Sespie   c = get_symbol_end ();
1129c074d1c9Sdrahn   lex_type[(unsigned char) '@'] = old_lexat;
1130b305b0f1Sespie 
1131b55d4692Sfgsch   if (symbol_get_obj (sym)->versioned_name == NULL)
1132b55d4692Sfgsch     {
1133b305b0f1Sespie       symbol_get_obj (sym)->versioned_name = xstrdup (name);
1134b305b0f1Sespie 
1135b305b0f1Sespie       *input_line_pointer = c;
1136b305b0f1Sespie 
1137b55d4692Sfgsch       if (strchr (symbol_get_obj (sym)->versioned_name,
1138b55d4692Sfgsch 		  ELF_VER_CHR) == NULL)
1139b305b0f1Sespie 	{
1140b305b0f1Sespie 	  as_bad (_("missing version name in `%s' for symbol `%s'"),
1141b55d4692Sfgsch 		  symbol_get_obj (sym)->versioned_name,
1142b55d4692Sfgsch 		  S_GET_NAME (sym));
1143b305b0f1Sespie 	  ignore_rest_of_line ();
1144b305b0f1Sespie 	  return;
1145b305b0f1Sespie 	}
1146b55d4692Sfgsch     }
1147b55d4692Sfgsch   else
1148b55d4692Sfgsch     {
1149b55d4692Sfgsch       if (strcmp (symbol_get_obj (sym)->versioned_name, name))
1150b55d4692Sfgsch 	{
1151b55d4692Sfgsch 	  as_bad (_("multiple versions [`%s'|`%s'] for symbol `%s'"),
1152b55d4692Sfgsch 		  name, symbol_get_obj (sym)->versioned_name,
1153b55d4692Sfgsch 		  S_GET_NAME (sym));
1154b55d4692Sfgsch 	  ignore_rest_of_line ();
1155b55d4692Sfgsch 	  return;
1156b55d4692Sfgsch 	}
1157b55d4692Sfgsch 
1158b55d4692Sfgsch       *input_line_pointer = c;
1159b55d4692Sfgsch     }
1160b305b0f1Sespie 
1161b305b0f1Sespie   demand_empty_rest_of_line ();
1162b305b0f1Sespie }
1163b305b0f1Sespie 
1164b305b0f1Sespie /* This handles the .vtable_inherit pseudo-op, which is used to indicate
1165b305b0f1Sespie    to the linker the hierarchy in which a particular table resides.  The
1166b305b0f1Sespie    syntax is ".vtable_inherit CHILDNAME, PARENTNAME".  */
1167b305b0f1Sespie 
1168b55d4692Sfgsch struct fix *
obj_elf_vtable_inherit(int ignore ATTRIBUTE_UNUSED)1169*007c2a45Smiod obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
1170b305b0f1Sespie {
1171b305b0f1Sespie   char *cname, *pname;
1172b305b0f1Sespie   symbolS *csym, *psym;
1173b305b0f1Sespie   char c, bad = 0;
1174b305b0f1Sespie 
1175b305b0f1Sespie   if (*input_line_pointer == '#')
1176b305b0f1Sespie     ++input_line_pointer;
1177b305b0f1Sespie 
1178b305b0f1Sespie   cname = input_line_pointer;
1179b305b0f1Sespie   c = get_symbol_end ();
1180b305b0f1Sespie   csym = symbol_find (cname);
1181b305b0f1Sespie 
1182b305b0f1Sespie   /* GCFIXME: should check that we don't have two .vtable_inherits for
1183b305b0f1Sespie      the same child symbol.  Also, we can currently only do this if the
1184b305b0f1Sespie      child symbol is already exists and is placed in a fragment.  */
1185b305b0f1Sespie 
1186b305b0f1Sespie   if (csym == NULL || symbol_get_frag (csym) == NULL)
1187b305b0f1Sespie     {
1188b305b0f1Sespie       as_bad ("expected `%s' to have already been set for .vtable_inherit",
1189b305b0f1Sespie 	      cname);
1190b305b0f1Sespie       bad = 1;
1191b305b0f1Sespie     }
1192b305b0f1Sespie 
1193b305b0f1Sespie   *input_line_pointer = c;
1194b305b0f1Sespie 
1195b305b0f1Sespie   SKIP_WHITESPACE ();
1196b305b0f1Sespie   if (*input_line_pointer != ',')
1197b305b0f1Sespie     {
1198b305b0f1Sespie       as_bad ("expected comma after name in .vtable_inherit");
1199b305b0f1Sespie       ignore_rest_of_line ();
1200b55d4692Sfgsch       return NULL;
1201b305b0f1Sespie     }
1202b305b0f1Sespie 
1203b305b0f1Sespie   ++input_line_pointer;
1204b305b0f1Sespie   SKIP_WHITESPACE ();
1205b305b0f1Sespie 
1206b305b0f1Sespie   if (*input_line_pointer == '#')
1207b305b0f1Sespie     ++input_line_pointer;
1208b305b0f1Sespie 
1209b305b0f1Sespie   if (input_line_pointer[0] == '0'
1210b305b0f1Sespie       && (input_line_pointer[1] == '\0'
1211c074d1c9Sdrahn 	  || ISSPACE (input_line_pointer[1])))
1212b305b0f1Sespie     {
1213b305b0f1Sespie       psym = section_symbol (absolute_section);
1214b305b0f1Sespie       ++input_line_pointer;
1215b305b0f1Sespie     }
1216b305b0f1Sespie   else
1217b305b0f1Sespie     {
1218b305b0f1Sespie       pname = input_line_pointer;
1219b305b0f1Sespie       c = get_symbol_end ();
1220b305b0f1Sespie       psym = symbol_find_or_make (pname);
1221b305b0f1Sespie       *input_line_pointer = c;
1222b305b0f1Sespie     }
1223b305b0f1Sespie 
1224b305b0f1Sespie   demand_empty_rest_of_line ();
1225b305b0f1Sespie 
1226b305b0f1Sespie   if (bad)
1227b55d4692Sfgsch     return NULL;
1228b305b0f1Sespie 
1229b305b0f1Sespie   assert (symbol_get_value_expression (csym)->X_op == O_constant);
1230b55d4692Sfgsch   return fix_new (symbol_get_frag (csym),
1231b55d4692Sfgsch 		  symbol_get_value_expression (csym)->X_add_number,
1232b55d4692Sfgsch 		  0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
1233b305b0f1Sespie }
1234b305b0f1Sespie 
1235b305b0f1Sespie /* This handles the .vtable_entry pseudo-op, which is used to indicate
1236b305b0f1Sespie    to the linker that a vtable slot was used.  The syntax is
1237b305b0f1Sespie    ".vtable_entry tablename, offset".  */
1238b305b0f1Sespie 
1239b55d4692Sfgsch struct fix *
obj_elf_vtable_entry(int ignore ATTRIBUTE_UNUSED)1240*007c2a45Smiod obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
1241b305b0f1Sespie {
1242b305b0f1Sespie   char *name;
1243b305b0f1Sespie   symbolS *sym;
1244b305b0f1Sespie   offsetT offset;
1245b305b0f1Sespie   char c;
1246b305b0f1Sespie 
1247b305b0f1Sespie   if (*input_line_pointer == '#')
1248b305b0f1Sespie     ++input_line_pointer;
1249b305b0f1Sespie 
1250b305b0f1Sespie   name = input_line_pointer;
1251b305b0f1Sespie   c = get_symbol_end ();
1252b305b0f1Sespie   sym = symbol_find_or_make (name);
1253b305b0f1Sespie   *input_line_pointer = c;
1254b305b0f1Sespie 
1255b305b0f1Sespie   SKIP_WHITESPACE ();
1256b305b0f1Sespie   if (*input_line_pointer != ',')
1257b305b0f1Sespie     {
1258b305b0f1Sespie       as_bad ("expected comma after name in .vtable_entry");
1259b305b0f1Sespie       ignore_rest_of_line ();
1260b55d4692Sfgsch       return NULL;
1261b305b0f1Sespie     }
1262b305b0f1Sespie 
1263b305b0f1Sespie   ++input_line_pointer;
1264b305b0f1Sespie   if (*input_line_pointer == '#')
1265b305b0f1Sespie     ++input_line_pointer;
1266b305b0f1Sespie 
1267b305b0f1Sespie   offset = get_absolute_expression ();
1268b305b0f1Sespie 
1269b305b0f1Sespie   demand_empty_rest_of_line ();
1270b55d4692Sfgsch 
1271b55d4692Sfgsch   return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
1272b55d4692Sfgsch 		  BFD_RELOC_VTABLE_ENTRY);
1273b305b0f1Sespie }
1274b305b0f1Sespie 
12752159047fSniklas void
elf_obj_read_begin_hook(void)1276*007c2a45Smiod elf_obj_read_begin_hook (void)
12772159047fSniklas {
12782159047fSniklas #ifdef NEED_ECOFF_DEBUG
12792159047fSniklas   if (ECOFF_DEBUGGING)
12802159047fSniklas     ecoff_read_begin_hook ();
12812159047fSniklas #endif
12822159047fSniklas }
12832159047fSniklas 
12842159047fSniklas void
elf_obj_symbol_new_hook(symbolS * symbolP)1285*007c2a45Smiod elf_obj_symbol_new_hook (symbolS *symbolP)
12862159047fSniklas {
1287b305b0f1Sespie   struct elf_obj_sy *sy_obj;
1288b305b0f1Sespie 
1289b305b0f1Sespie   sy_obj = symbol_get_obj (symbolP);
1290b305b0f1Sespie   sy_obj->size = NULL;
1291b305b0f1Sespie   sy_obj->versioned_name = NULL;
12922159047fSniklas 
12932159047fSniklas #ifdef NEED_ECOFF_DEBUG
12942159047fSniklas   if (ECOFF_DEBUGGING)
12952159047fSniklas     ecoff_symbol_new_hook (symbolP);
12962159047fSniklas #endif
12972159047fSniklas }
12982159047fSniklas 
1299c074d1c9Sdrahn /* When setting one symbol equal to another, by default we probably
1300c074d1c9Sdrahn    want them to have the same "size", whatever it means in the current
1301c074d1c9Sdrahn    context.  */
1302c074d1c9Sdrahn 
1303c074d1c9Sdrahn void
elf_copy_symbol_attributes(symbolS * dest,symbolS * src)1304*007c2a45Smiod elf_copy_symbol_attributes (symbolS *dest, symbolS *src)
1305c074d1c9Sdrahn {
1306c074d1c9Sdrahn   struct elf_obj_sy *srcelf = symbol_get_obj (src);
1307c074d1c9Sdrahn   struct elf_obj_sy *destelf = symbol_get_obj (dest);
1308c074d1c9Sdrahn   if (srcelf->size)
1309c074d1c9Sdrahn     {
1310c074d1c9Sdrahn       if (destelf->size == NULL)
1311*007c2a45Smiod 	destelf->size = xmalloc (sizeof (expressionS));
1312c074d1c9Sdrahn       *destelf->size = *srcelf->size;
1313c074d1c9Sdrahn     }
1314c074d1c9Sdrahn   else
1315c074d1c9Sdrahn     {
1316c074d1c9Sdrahn       if (destelf->size != NULL)
1317c074d1c9Sdrahn 	free (destelf->size);
1318c074d1c9Sdrahn       destelf->size = NULL;
1319c074d1c9Sdrahn     }
1320c074d1c9Sdrahn   S_SET_SIZE (dest, S_GET_SIZE (src));
1321c074d1c9Sdrahn   /* Don't copy visibility.  */
1322c074d1c9Sdrahn   S_SET_OTHER (dest, (ELF_ST_VISIBILITY (S_GET_OTHER (dest))
1323c074d1c9Sdrahn 		      | (S_GET_OTHER (src) & ~ELF_ST_VISIBILITY (-1))));
1324c074d1c9Sdrahn }
1325c074d1c9Sdrahn 
13262159047fSniklas void
obj_elf_version(int ignore ATTRIBUTE_UNUSED)1327*007c2a45Smiod obj_elf_version (int ignore ATTRIBUTE_UNUSED)
13282159047fSniklas {
13292159047fSniklas   char *name;
13302159047fSniklas   unsigned int c;
13312159047fSniklas   char *p;
13322159047fSniklas   asection *seg = now_seg;
13332159047fSniklas   subsegT subseg = now_subseg;
13342159047fSniklas   Elf_Internal_Note i_note;
13352159047fSniklas   Elf_External_Note e_note;
1336*007c2a45Smiod   asection *note_secp = NULL;
1337c074d1c9Sdrahn   int len;
13382159047fSniklas 
13392159047fSniklas   SKIP_WHITESPACE ();
13402159047fSniklas   if (*input_line_pointer == '\"')
13412159047fSniklas     {
13422159047fSniklas       ++input_line_pointer;	/* -> 1st char of string.  */
13432159047fSniklas       name = input_line_pointer;
13442159047fSniklas 
13452159047fSniklas       while (is_a_char (c = next_char_of_string ()))
13462159047fSniklas 	;
13472159047fSniklas       c = *input_line_pointer;
13482159047fSniklas       *input_line_pointer = '\0';
13492159047fSniklas       *(input_line_pointer - 1) = '\0';
13502159047fSniklas       *input_line_pointer = c;
13512159047fSniklas 
13522159047fSniklas       /* create the .note section */
13532159047fSniklas 
13542159047fSniklas       note_secp = subseg_new (".note", 0);
13552159047fSniklas       bfd_set_section_flags (stdoutput,
13562159047fSniklas 			     note_secp,
13572159047fSniklas 			     SEC_HAS_CONTENTS | SEC_READONLY);
13582159047fSniklas 
13592159047fSniklas       /* process the version string */
13602159047fSniklas 
13612159047fSniklas       len = strlen (name);
13622159047fSniklas 
13632159047fSniklas       i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
13642159047fSniklas       i_note.descsz = 0;	/* no description */
13652159047fSniklas       i_note.type = NT_VERSION;
13662159047fSniklas       p = frag_more (sizeof (e_note.namesz));
1367*007c2a45Smiod       md_number_to_chars (p, i_note.namesz, sizeof (e_note.namesz));
13682159047fSniklas       p = frag_more (sizeof (e_note.descsz));
1369*007c2a45Smiod       md_number_to_chars (p, i_note.descsz, sizeof (e_note.descsz));
13702159047fSniklas       p = frag_more (sizeof (e_note.type));
1371*007c2a45Smiod       md_number_to_chars (p, i_note.type, sizeof (e_note.type));
1372c074d1c9Sdrahn       p = frag_more (len + 1);
1373c074d1c9Sdrahn       strcpy (p, name);
13742159047fSniklas 
1375b305b0f1Sespie       frag_align (2, 0, 0);
13762159047fSniklas 
13772159047fSniklas       subseg_set (seg, subseg);
13782159047fSniklas     }
13792159047fSniklas   else
13802159047fSniklas     {
1381c074d1c9Sdrahn       as_bad (_("expected quoted string"));
13822159047fSniklas     }
13832159047fSniklas   demand_empty_rest_of_line ();
13842159047fSniklas }
13852159047fSniklas 
13862159047fSniklas static void
obj_elf_size(int ignore ATTRIBUTE_UNUSED)1387*007c2a45Smiod obj_elf_size (int ignore ATTRIBUTE_UNUSED)
13882159047fSniklas {
13892159047fSniklas   char *name = input_line_pointer;
13902159047fSniklas   char c = get_symbol_end ();
13912159047fSniklas   char *p;
13922159047fSniklas   expressionS exp;
13932159047fSniklas   symbolS *sym;
13942159047fSniklas 
13952159047fSniklas   p = input_line_pointer;
13962159047fSniklas   *p = c;
13972159047fSniklas   SKIP_WHITESPACE ();
13982159047fSniklas   if (*input_line_pointer != ',')
13992159047fSniklas     {
14002159047fSniklas       *p = 0;
1401b305b0f1Sespie       as_bad (_("expected comma after name `%s' in .size directive"), name);
14022159047fSniklas       *p = c;
14032159047fSniklas       ignore_rest_of_line ();
14042159047fSniklas       return;
14052159047fSniklas     }
14062159047fSniklas   input_line_pointer++;
14072159047fSniklas   expression (&exp);
14082159047fSniklas   if (exp.X_op == O_absent)
14092159047fSniklas     {
1410b305b0f1Sespie       as_bad (_("missing expression in .size directive"));
14112159047fSniklas       exp.X_op = O_constant;
14122159047fSniklas       exp.X_add_number = 0;
14132159047fSniklas     }
14142159047fSniklas   *p = 0;
14152159047fSniklas   sym = symbol_find_or_make (name);
14162159047fSniklas   *p = c;
14172159047fSniklas   if (exp.X_op == O_constant)
1418c074d1c9Sdrahn     {
14192159047fSniklas       S_SET_SIZE (sym, exp.X_add_number);
1420c074d1c9Sdrahn       if (symbol_get_obj (sym)->size)
1421c074d1c9Sdrahn 	{
1422c074d1c9Sdrahn 	  xfree (symbol_get_obj (sym)->size);
1423c074d1c9Sdrahn 	  symbol_get_obj (sym)->size = NULL;
1424c074d1c9Sdrahn 	}
1425c074d1c9Sdrahn     }
14262159047fSniklas   else
14272159047fSniklas     {
1428*007c2a45Smiod       symbol_get_obj (sym)->size = xmalloc (sizeof (expressionS));
1429b305b0f1Sespie       *symbol_get_obj (sym)->size = exp;
14302159047fSniklas     }
14312159047fSniklas   demand_empty_rest_of_line ();
14322159047fSniklas }
14332159047fSniklas 
14342159047fSniklas /* Handle the ELF .type pseudo-op.  This sets the type of a symbol.
1435b55d4692Sfgsch    There are five syntaxes:
1436b305b0f1Sespie 
1437b305b0f1Sespie    The first (used on Solaris) is
14382159047fSniklas        .type SYM,#function
14392159047fSniklas    The second (used on UnixWare) is
14402159047fSniklas        .type SYM,@function
14412159047fSniklas    The third (reportedly to be used on Irix 6.0) is
14422159047fSniklas        .type SYM STT_FUNC
1443b305b0f1Sespie    The fourth (used on NetBSD/Arm and Linux/ARM) is
1444b305b0f1Sespie        .type SYM,%function
1445b55d4692Sfgsch    The fifth (used on SVR4/860) is
1446b55d4692Sfgsch        .type SYM,"function"
1447191aa565Sniklas    */
14482159047fSniklas 
14492159047fSniklas static void
obj_elf_type(int ignore ATTRIBUTE_UNUSED)1450*007c2a45Smiod obj_elf_type (int ignore ATTRIBUTE_UNUSED)
14512159047fSniklas {
14522159047fSniklas   char *name;
14532159047fSniklas   char c;
14542159047fSniklas   int type;
14552159047fSniklas   const char *typename;
14562159047fSniklas   symbolS *sym;
1457b55d4692Sfgsch   elf_symbol_type *elfsym;
14582159047fSniklas 
14592159047fSniklas   name = input_line_pointer;
14602159047fSniklas   c = get_symbol_end ();
14612159047fSniklas   sym = symbol_find_or_make (name);
1462b55d4692Sfgsch   elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
14632159047fSniklas   *input_line_pointer = c;
14642159047fSniklas 
14652159047fSniklas   SKIP_WHITESPACE ();
14662159047fSniklas   if (*input_line_pointer == ',')
14672159047fSniklas     ++input_line_pointer;
14682159047fSniklas 
14692159047fSniklas   SKIP_WHITESPACE ();
1470b305b0f1Sespie   if (   *input_line_pointer == '#'
1471b305b0f1Sespie       || *input_line_pointer == '@'
1472b55d4692Sfgsch       || *input_line_pointer == '"'
1473b305b0f1Sespie       || *input_line_pointer == '%')
14742159047fSniklas     ++input_line_pointer;
14752159047fSniklas 
14762159047fSniklas   typename = input_line_pointer;
14772159047fSniklas   c = get_symbol_end ();
14782159047fSniklas 
14792159047fSniklas   type = 0;
14802159047fSniklas   if (strcmp (typename, "function") == 0
14812159047fSniklas       || strcmp (typename, "STT_FUNC") == 0)
14822159047fSniklas     type = BSF_FUNCTION;
14832159047fSniklas   else if (strcmp (typename, "object") == 0
14842159047fSniklas 	   || strcmp (typename, "STT_OBJECT") == 0)
1485191aa565Sniklas     type = BSF_OBJECT;
1486c074d1c9Sdrahn   else if (strcmp (typename, "tls_object") == 0
1487c074d1c9Sdrahn 	   || strcmp (typename, "STT_TLS") == 0)
1488c074d1c9Sdrahn     type = BSF_OBJECT | BSF_THREAD_LOCAL;
1489*007c2a45Smiod   else if (strcmp (typename, "notype") == 0
1490*007c2a45Smiod 	   || strcmp (typename, "STT_NOTYPE") == 0)
1491*007c2a45Smiod     ;
1492b55d4692Sfgsch #ifdef md_elf_symbol_type
1493b55d4692Sfgsch   else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
1494b55d4692Sfgsch     ;
1495b55d4692Sfgsch #endif
14962159047fSniklas   else
1497c074d1c9Sdrahn     as_bad (_("unrecognized symbol type \"%s\""), typename);
14982159047fSniklas 
14992159047fSniklas   *input_line_pointer = c;
15002159047fSniklas 
1501b55d4692Sfgsch   if (*input_line_pointer == '"')
1502b55d4692Sfgsch     ++input_line_pointer;
1503b55d4692Sfgsch 
1504b55d4692Sfgsch   elfsym->symbol.flags |= type;
15052159047fSniklas 
15062159047fSniklas   demand_empty_rest_of_line ();
15072159047fSniklas }
15082159047fSniklas 
15092159047fSniklas static void
obj_elf_ident(int ignore ATTRIBUTE_UNUSED)1510*007c2a45Smiod obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
15112159047fSniklas {
15122159047fSniklas   static segT comment_section;
15132159047fSniklas   segT old_section = now_seg;
15142159047fSniklas   int old_subsection = now_subseg;
15152159047fSniklas 
1516b305b0f1Sespie #ifdef md_flush_pending_output
1517b305b0f1Sespie   md_flush_pending_output ();
1518b305b0f1Sespie #endif
1519b305b0f1Sespie 
15202159047fSniklas   if (!comment_section)
15212159047fSniklas     {
15222159047fSniklas       char *p;
15232159047fSniklas       comment_section = subseg_new (".comment", 0);
15242159047fSniklas       bfd_set_section_flags (stdoutput, comment_section,
15252159047fSniklas 			     SEC_READONLY | SEC_HAS_CONTENTS);
15262159047fSniklas       p = frag_more (1);
15272159047fSniklas       *p = 0;
15282159047fSniklas     }
15292159047fSniklas   else
15302159047fSniklas     subseg_set (comment_section, 0);
15312159047fSniklas   stringer (1);
15322159047fSniklas   subseg_set (old_section, old_subsection);
15332159047fSniklas }
15342159047fSniklas 
15352159047fSniklas #ifdef INIT_STAB_SECTION
15362159047fSniklas 
15372159047fSniklas /* The first entry in a .stabs section is special.  */
15382159047fSniklas 
15392159047fSniklas void
obj_elf_init_stab_section(segT seg)1540*007c2a45Smiod obj_elf_init_stab_section (segT seg)
15412159047fSniklas {
15422159047fSniklas   char *file;
15432159047fSniklas   char *p;
15442159047fSniklas   char *stabstr_name;
15452159047fSniklas   unsigned int stroff;
15462159047fSniklas 
15472159047fSniklas   /* Force the section to align to a longword boundary.  Without this,
15482159047fSniklas      UnixWare ar crashes.  */
15492159047fSniklas   bfd_set_section_alignment (stdoutput, seg, 2);
15502159047fSniklas 
15512159047fSniklas   /* Make space for this first symbol.  */
15522159047fSniklas   p = frag_more (12);
15532159047fSniklas   /* Zero it out.  */
15542159047fSniklas   memset (p, 0, 12);
1555*007c2a45Smiod   as_where (&file, NULL);
1556*007c2a45Smiod   stabstr_name = xmalloc (strlen (segment_name (seg)) + 4);
15572159047fSniklas   strcpy (stabstr_name, segment_name (seg));
15582159047fSniklas   strcat (stabstr_name, "str");
15592159047fSniklas   stroff = get_stab_string_offset (file, stabstr_name);
15602159047fSniklas   know (stroff == 1);
15612159047fSniklas   md_number_to_chars (p, stroff, 4);
15622159047fSniklas   seg_info (seg)->stabu.p = p;
15632159047fSniklas }
15642159047fSniklas 
15652159047fSniklas #endif
15662159047fSniklas 
15672159047fSniklas /* Fill in the counts in the first entry in a .stabs section.  */
15682159047fSniklas 
15692159047fSniklas static void
adjust_stab_sections(bfd * abfd,asection * sec,void * xxx ATTRIBUTE_UNUSED)1570*007c2a45Smiod adjust_stab_sections (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
15712159047fSniklas {
15722159047fSniklas   char *name;
15732159047fSniklas   asection *strsec;
15742159047fSniklas   char *p;
15752159047fSniklas   int strsz, nsyms;
15762159047fSniklas 
15772159047fSniklas   if (strncmp (".stab", sec->name, 5))
15782159047fSniklas     return;
15792159047fSniklas   if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
15802159047fSniklas     return;
15812159047fSniklas 
1582*007c2a45Smiod   name = alloca (strlen (sec->name) + 4);
15832159047fSniklas   strcpy (name, sec->name);
15842159047fSniklas   strcat (name, "str");
15852159047fSniklas   strsec = bfd_get_section_by_name (abfd, name);
15862159047fSniklas   if (strsec)
15872159047fSniklas     strsz = bfd_section_size (abfd, strsec);
15882159047fSniklas   else
15892159047fSniklas     strsz = 0;
15902159047fSniklas   nsyms = bfd_section_size (abfd, sec) / 12 - 1;
15912159047fSniklas 
15922159047fSniklas   p = seg_info (sec)->stabu.p;
15932159047fSniklas   assert (p != 0);
15942159047fSniklas 
1595*007c2a45Smiod   bfd_h_put_16 (abfd, nsyms, p + 6);
1596*007c2a45Smiod   bfd_h_put_32 (abfd, strsz, p + 8);
15972159047fSniklas }
15982159047fSniklas 
15992159047fSniklas #ifdef NEED_ECOFF_DEBUG
16002159047fSniklas 
16012159047fSniklas /* This function is called by the ECOFF code.  It is supposed to
16022159047fSniklas    record the external symbol information so that the backend can
16032159047fSniklas    write it out correctly.  The ELF backend doesn't actually handle
16042159047fSniklas    this at the moment, so we do it ourselves.  We save the information
16052159047fSniklas    in the symbol.  */
16062159047fSniklas 
16072159047fSniklas void
elf_ecoff_set_ext(symbolS * sym,struct ecoff_extr * ext)1608*007c2a45Smiod elf_ecoff_set_ext (symbolS *sym, struct ecoff_extr *ext)
16092159047fSniklas {
1610*007c2a45Smiod   symbol_get_bfdsym (sym)->udata.p = ext;
16112159047fSniklas }
16122159047fSniklas 
16132159047fSniklas /* This function is called by bfd_ecoff_debug_externals.  It is
16142159047fSniklas    supposed to *EXT to the external symbol information, and return
16152159047fSniklas    whether the symbol should be used at all.  */
16162159047fSniklas 
1617c074d1c9Sdrahn static bfd_boolean
elf_get_extr(asymbol * sym,EXTR * ext)1618*007c2a45Smiod elf_get_extr (asymbol *sym, EXTR *ext)
16192159047fSniklas {
16202159047fSniklas   if (sym->udata.p == NULL)
1621c074d1c9Sdrahn     return FALSE;
16222159047fSniklas   *ext = *(EXTR *) sym->udata.p;
1623c074d1c9Sdrahn   return TRUE;
16242159047fSniklas }
16252159047fSniklas 
16262159047fSniklas /* This function is called by bfd_ecoff_debug_externals.  It has
16272159047fSniklas    nothing to do for ELF.  */
16282159047fSniklas 
16292159047fSniklas static void
elf_set_index(asymbol * sym ATTRIBUTE_UNUSED,bfd_size_type indx ATTRIBUTE_UNUSED)1630*007c2a45Smiod elf_set_index (asymbol *sym ATTRIBUTE_UNUSED,
1631*007c2a45Smiod 	       bfd_size_type indx ATTRIBUTE_UNUSED)
16322159047fSniklas {
16332159047fSniklas }
16342159047fSniklas 
16352159047fSniklas #endif /* NEED_ECOFF_DEBUG */
16362159047fSniklas 
16372159047fSniklas void
elf_frob_symbol(symbolS * symp,int * puntp)1638*007c2a45Smiod elf_frob_symbol (symbolS *symp, int *puntp)
16392159047fSniklas {
1640b305b0f1Sespie   struct elf_obj_sy *sy_obj;
1641b305b0f1Sespie 
16422159047fSniklas #ifdef NEED_ECOFF_DEBUG
16432159047fSniklas   if (ECOFF_DEBUGGING)
16442159047fSniklas     ecoff_frob_symbol (symp);
16452159047fSniklas #endif
16462159047fSniklas 
1647b305b0f1Sespie   sy_obj = symbol_get_obj (symp);
1648b305b0f1Sespie 
1649b305b0f1Sespie   if (sy_obj->size != NULL)
16502159047fSniklas     {
1651b305b0f1Sespie       switch (sy_obj->size->X_op)
16522159047fSniklas 	{
16532159047fSniklas 	case O_subtract:
16542159047fSniklas 	  S_SET_SIZE (symp,
1655b305b0f1Sespie 		      (S_GET_VALUE (sy_obj->size->X_add_symbol)
1656b305b0f1Sespie 		       + sy_obj->size->X_add_number
1657b305b0f1Sespie 		       - S_GET_VALUE (sy_obj->size->X_op_symbol)));
16582159047fSniklas 	  break;
16592159047fSniklas 	case O_constant:
16602159047fSniklas 	  S_SET_SIZE (symp,
1661b305b0f1Sespie 		      (S_GET_VALUE (sy_obj->size->X_add_symbol)
1662b305b0f1Sespie 		       + sy_obj->size->X_add_number));
16632159047fSniklas 	  break;
16642159047fSniklas 	default:
1665b305b0f1Sespie 	  as_bad (_(".size expression too complicated to fix up"));
16662159047fSniklas 	  break;
16672159047fSniklas 	}
1668b305b0f1Sespie       free (sy_obj->size);
1669b305b0f1Sespie       sy_obj->size = NULL;
1670b305b0f1Sespie     }
1671b305b0f1Sespie 
1672b305b0f1Sespie   if (sy_obj->versioned_name != NULL)
1673b305b0f1Sespie     {
1674b55d4692Sfgsch       char *p;
1675b55d4692Sfgsch 
1676b55d4692Sfgsch       p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
1677b55d4692Sfgsch       know (p != NULL);
1678b55d4692Sfgsch 
1679b305b0f1Sespie       /* This symbol was given a new name with the .symver directive.
1680b305b0f1Sespie 
1681b305b0f1Sespie 	 If this is an external reference, just rename the symbol to
1682b305b0f1Sespie 	 include the version string.  This will make the relocs be
1683b305b0f1Sespie 	 against the correct versioned symbol.
1684b305b0f1Sespie 
1685b305b0f1Sespie 	 If this is a definition, add an alias.  FIXME: Using an alias
1686b305b0f1Sespie 	 will permit the debugging information to refer to the right
1687b305b0f1Sespie 	 symbol.  However, it's not clear whether it is the best
1688b305b0f1Sespie 	 approach.  */
1689b305b0f1Sespie 
1690b305b0f1Sespie       if (! S_IS_DEFINED (symp))
1691b305b0f1Sespie 	{
1692b305b0f1Sespie 	  /* Verify that the name isn't using the @@ syntax--this is
1693b305b0f1Sespie 	     reserved for definitions of the default version to link
1694b305b0f1Sespie 	     against.  */
1695b305b0f1Sespie 	  if (p[1] == ELF_VER_CHR)
1696b305b0f1Sespie 	    {
1697b305b0f1Sespie 	      as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"),
1698b305b0f1Sespie 		      sy_obj->versioned_name);
1699c074d1c9Sdrahn 	      *puntp = TRUE;
1700b305b0f1Sespie 	    }
1701b305b0f1Sespie 	  S_SET_NAME (symp, sy_obj->versioned_name);
1702b305b0f1Sespie 	}
1703b305b0f1Sespie       else
1704b305b0f1Sespie 	{
1705b55d4692Sfgsch 	  if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
1706b55d4692Sfgsch 	    {
1707b55d4692Sfgsch 	      size_t l;
1708b55d4692Sfgsch 
1709b55d4692Sfgsch 	      /* The @@@ syntax is a special case. It renames the
1710b55d4692Sfgsch 		 symbol name to versioned_name with one `@' removed.  */
1711b55d4692Sfgsch 	      l = strlen (&p[3]) + 1;
1712b55d4692Sfgsch 	      memmove (&p[2], &p[3], l);
1713b55d4692Sfgsch 	      S_SET_NAME (symp, sy_obj->versioned_name);
1714b55d4692Sfgsch 	    }
1715b55d4692Sfgsch 	  else
1716b55d4692Sfgsch 	    {
1717b305b0f1Sespie 	      symbolS *symp2;
1718b305b0f1Sespie 
1719b55d4692Sfgsch 	      /* FIXME: Creating a new symbol here is risky.  We're
1720b55d4692Sfgsch 		 in the final loop over the symbol table.  We can
1721b55d4692Sfgsch 		 get away with it only because the symbol goes to
1722b55d4692Sfgsch 		 the end of the list, where the loop will still see
1723b55d4692Sfgsch 		 it.  It would probably be better to do this in
1724b55d4692Sfgsch 		 obj_frob_file_before_adjust.  */
1725b305b0f1Sespie 
1726b305b0f1Sespie 	      symp2 = symbol_find_or_make (sy_obj->versioned_name);
1727b305b0f1Sespie 
1728b305b0f1Sespie 	      /* Now we act as though we saw symp2 = sym.  */
1729b305b0f1Sespie 
1730b305b0f1Sespie 	      S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
1731b305b0f1Sespie 
1732b55d4692Sfgsch 	      /* Subtracting out the frag address here is a hack
1733b55d4692Sfgsch 		 because we are in the middle of the final loop.  */
1734b305b0f1Sespie 	      S_SET_VALUE (symp2,
1735b305b0f1Sespie 			   (S_GET_VALUE (symp)
1736b305b0f1Sespie 			    - symbol_get_frag (symp)->fr_address));
1737b305b0f1Sespie 
1738b305b0f1Sespie 	      symbol_set_frag (symp2, symbol_get_frag (symp));
1739b305b0f1Sespie 
1740b305b0f1Sespie 	      /* This will copy over the size information.  */
1741b305b0f1Sespie 	      copy_symbol_attributes (symp2, symp);
1742b305b0f1Sespie 
1743c074d1c9Sdrahn 	      S_SET_OTHER (symp2, S_GET_OTHER (symp));
1744c074d1c9Sdrahn 
1745b305b0f1Sespie 	      if (S_IS_WEAK (symp))
1746b305b0f1Sespie 		S_SET_WEAK (symp2);
1747b305b0f1Sespie 
1748b305b0f1Sespie 	      if (S_IS_EXTERNAL (symp))
1749b305b0f1Sespie 		S_SET_EXTERNAL (symp2);
1750b305b0f1Sespie 	    }
1751191aa565Sniklas 	}
1752b55d4692Sfgsch     }
17532159047fSniklas 
17542159047fSniklas   /* Double check weak symbols.  */
1755b305b0f1Sespie   if (S_IS_WEAK (symp))
17562159047fSniklas     {
17572159047fSniklas       if (S_IS_COMMON (symp))
1758c074d1c9Sdrahn 	as_bad (_("symbol `%s' can not be both weak and common"),
17592159047fSniklas 		S_GET_NAME (symp));
17602159047fSniklas     }
1761191aa565Sniklas 
1762191aa565Sniklas #ifdef TC_MIPS
1763b305b0f1Sespie   /* The Irix 5 and 6 assemblers set the type of any common symbol and
1764b305b0f1Sespie      any undefined non-function symbol to STT_OBJECT.  We try to be
1765b305b0f1Sespie      compatible, since newer Irix 5 and 6 linkers care.  However, we
1766b305b0f1Sespie      only set undefined symbols to be STT_OBJECT if we are on Irix,
1767b305b0f1Sespie      because that is the only time gcc will generate the necessary
1768b305b0f1Sespie      .global directives to mark functions.  */
1769b305b0f1Sespie 
1770191aa565Sniklas   if (S_IS_COMMON (symp))
1771b305b0f1Sespie     symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
1772b305b0f1Sespie 
1773b305b0f1Sespie   if (strstr (TARGET_OS, "irix") != NULL
1774b305b0f1Sespie       && ! S_IS_DEFINED (symp)
1775b305b0f1Sespie       && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0)
1776b305b0f1Sespie     symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
1777191aa565Sniklas #endif
1778191aa565Sniklas 
1779b305b0f1Sespie #if 0 /* TC_PPC */
1780b305b0f1Sespie   /* If TC_PPC is defined, we used to force the type of a symbol to be
1781b305b0f1Sespie      BSF_OBJECT if it was otherwise unset.  This was required by some
1782b305b0f1Sespie      version of VxWorks.  Thomas de Lellis <tdel@windriver.com> says
1783b305b0f1Sespie      that this is no longer needed, so it is now commented out.  */
1784b305b0f1Sespie   if ((symbol_get_bfdsym (symp)->flags
1785b305b0f1Sespie        & (BSF_FUNCTION | BSF_FILE | BSF_SECTION_SYM)) == 0
1786191aa565Sniklas       && S_IS_DEFINED (symp))
1787b305b0f1Sespie     symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
1788191aa565Sniklas #endif
17892159047fSniklas }
17902159047fSniklas 
1791c074d1c9Sdrahn struct group_list
1792c074d1c9Sdrahn {
1793c074d1c9Sdrahn   asection **head;		/* Section lists.  */
1794c074d1c9Sdrahn   unsigned int *elt_count;	/* Number of sections in each list.  */
1795c074d1c9Sdrahn   unsigned int num_group;	/* Number of lists.  */
1796c074d1c9Sdrahn };
1797c074d1c9Sdrahn 
1798c074d1c9Sdrahn /* Called via bfd_map_over_sections.  If SEC is a member of a group,
1799c074d1c9Sdrahn    add it to a list of sections belonging to the group.  INF is a
1800c074d1c9Sdrahn    pointer to a struct group_list, which is where we store the head of
1801c074d1c9Sdrahn    each list.  */
1802c074d1c9Sdrahn 
1803c074d1c9Sdrahn static void
build_group_lists(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * inf)1804*007c2a45Smiod build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
1805c074d1c9Sdrahn {
1806*007c2a45Smiod   struct group_list *list = inf;
1807c074d1c9Sdrahn   const char *group_name = elf_group_name (sec);
1808c074d1c9Sdrahn   unsigned int i;
1809c074d1c9Sdrahn 
1810c074d1c9Sdrahn   if (group_name == NULL)
1811c074d1c9Sdrahn     return;
1812c074d1c9Sdrahn 
1813c074d1c9Sdrahn   /* If this group already has a list, add the section to the head of
1814c074d1c9Sdrahn      the list.  */
1815c074d1c9Sdrahn   for (i = 0; i < list->num_group; i++)
1816c074d1c9Sdrahn     {
1817c074d1c9Sdrahn       if (strcmp (group_name, elf_group_name (list->head[i])) == 0)
1818c074d1c9Sdrahn 	{
1819c074d1c9Sdrahn 	  elf_next_in_group (sec) = list->head[i];
1820c074d1c9Sdrahn 	  list->head[i] = sec;
1821c074d1c9Sdrahn 	  list->elt_count[i] += 1;
1822c074d1c9Sdrahn 	  return;
1823c074d1c9Sdrahn 	}
1824c074d1c9Sdrahn     }
1825c074d1c9Sdrahn 
1826c074d1c9Sdrahn   /* New group.  Make the arrays bigger in chunks to minimize calls to
1827c074d1c9Sdrahn      realloc.  */
1828c074d1c9Sdrahn   i = list->num_group;
1829c074d1c9Sdrahn   if ((i & 127) == 0)
1830c074d1c9Sdrahn     {
1831c074d1c9Sdrahn       unsigned int newsize = i + 128;
1832c074d1c9Sdrahn       list->head = xrealloc (list->head, newsize * sizeof (*list->head));
1833c074d1c9Sdrahn       list->elt_count = xrealloc (list->elt_count,
1834c074d1c9Sdrahn 				  newsize * sizeof (*list->elt_count));
1835c074d1c9Sdrahn     }
1836c074d1c9Sdrahn   list->head[i] = sec;
1837c074d1c9Sdrahn   list->elt_count[i] = 1;
1838c074d1c9Sdrahn   list->num_group += 1;
1839c074d1c9Sdrahn }
1840c074d1c9Sdrahn 
18412159047fSniklas void
elf_frob_file(void)1842*007c2a45Smiod elf_frob_file (void)
18432159047fSniklas {
1844c074d1c9Sdrahn   struct group_list list;
1845c074d1c9Sdrahn   unsigned int i;
1846c074d1c9Sdrahn 
1847*007c2a45Smiod   bfd_map_over_sections (stdoutput, adjust_stab_sections, NULL);
18482159047fSniklas 
1849c074d1c9Sdrahn   /* Go find section groups.  */
1850c074d1c9Sdrahn   list.num_group = 0;
1851c074d1c9Sdrahn   list.head = NULL;
1852c074d1c9Sdrahn   list.elt_count = NULL;
1853*007c2a45Smiod   bfd_map_over_sections (stdoutput, build_group_lists, &list);
1854c074d1c9Sdrahn 
1855c074d1c9Sdrahn   /* Make the SHT_GROUP sections that describe each section group.  We
1856c074d1c9Sdrahn      can't set up the section contents here yet, because elf section
1857c074d1c9Sdrahn      indices have yet to be calculated.  elf.c:set_group_contents does
1858c074d1c9Sdrahn      the rest of the work.  */
1859c074d1c9Sdrahn   for (i = 0; i < list.num_group; i++)
1860c074d1c9Sdrahn     {
1861c074d1c9Sdrahn       const char *group_name = elf_group_name (list.head[i]);
1862c074d1c9Sdrahn       const char *sec_name;
1863c074d1c9Sdrahn       asection *s;
1864c074d1c9Sdrahn       flagword flags;
1865c074d1c9Sdrahn       struct symbol *sy;
1866c074d1c9Sdrahn       int has_sym;
1867c074d1c9Sdrahn 
1868c074d1c9Sdrahn       flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
1869c074d1c9Sdrahn       for (s = list.head[i]; s != NULL; s = elf_next_in_group (s))
1870c074d1c9Sdrahn 	if ((s->flags ^ flags) & SEC_LINK_ONCE)
1871c074d1c9Sdrahn 	  {
1872c074d1c9Sdrahn 	    flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
1873c074d1c9Sdrahn 	    if (s != list.head[i])
1874c074d1c9Sdrahn 	      {
1875c074d1c9Sdrahn 		as_warn (_("assuming all members of group `%s' are COMDAT"),
1876c074d1c9Sdrahn 			 group_name);
1877c074d1c9Sdrahn 		break;
1878c074d1c9Sdrahn 	      }
1879c074d1c9Sdrahn 	  }
1880c074d1c9Sdrahn 
1881c074d1c9Sdrahn       sec_name = group_name;
1882c074d1c9Sdrahn       sy = symbol_find_exact (group_name);
1883c074d1c9Sdrahn       has_sym = 0;
1884c074d1c9Sdrahn       if (sy != NULL
1885c074d1c9Sdrahn 	  && (sy == symbol_lastP
1886c074d1c9Sdrahn 	      || (sy->sy_next != NULL
1887c074d1c9Sdrahn 		  && sy->sy_next->sy_previous == sy)))
1888c074d1c9Sdrahn 	{
1889c074d1c9Sdrahn 	  has_sym = 1;
1890c074d1c9Sdrahn 	  sec_name = ".group";
1891c074d1c9Sdrahn 	}
1892c074d1c9Sdrahn       s = subseg_force_new (sec_name, 0);
1893c074d1c9Sdrahn       if (s == NULL
1894c074d1c9Sdrahn 	  || !bfd_set_section_flags (stdoutput, s, flags)
1895c074d1c9Sdrahn 	  || !bfd_set_section_alignment (stdoutput, s, 2))
1896c074d1c9Sdrahn 	{
1897c074d1c9Sdrahn 	  as_fatal (_("can't create group: %s"),
1898c074d1c9Sdrahn 		    bfd_errmsg (bfd_get_error ()));
1899c074d1c9Sdrahn 	}
1900*007c2a45Smiod       elf_section_type (s) = SHT_GROUP;
1901c074d1c9Sdrahn 
1902c074d1c9Sdrahn       /* Pass a pointer to the first section in this group.  */
1903c074d1c9Sdrahn       elf_next_in_group (s) = list.head[i];
1904c074d1c9Sdrahn       if (has_sym)
1905c074d1c9Sdrahn 	elf_group_id (s) = sy->bsym;
1906c074d1c9Sdrahn 
1907c074d1c9Sdrahn       s->_raw_size = 4 * (list.elt_count[i] + 1);
1908c074d1c9Sdrahn       s->contents = frag_more (s->_raw_size);
1909c074d1c9Sdrahn       frag_now->fr_fix = frag_now_fix_octets ();
1910c074d1c9Sdrahn     }
1911c074d1c9Sdrahn 
19122159047fSniklas #ifdef elf_tc_final_processing
19132159047fSniklas   elf_tc_final_processing ();
19142159047fSniklas #endif
1915e93f7393Sniklas }
19162159047fSniklas 
1917b55d4692Sfgsch /* It removes any unneeded versioned symbols from the symbol table.  */
1918b55d4692Sfgsch 
1919b55d4692Sfgsch void
elf_frob_file_before_adjust(void)1920*007c2a45Smiod elf_frob_file_before_adjust (void)
1921b55d4692Sfgsch {
1922b55d4692Sfgsch   if (symbol_rootP)
1923b55d4692Sfgsch     {
1924b55d4692Sfgsch       symbolS *symp;
1925b55d4692Sfgsch 
1926b55d4692Sfgsch       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
1927b55d4692Sfgsch 	if (!S_IS_DEFINED (symp))
1928b55d4692Sfgsch 	  {
1929c074d1c9Sdrahn 	    if (symbol_get_obj (symp)->versioned_name)
1930c074d1c9Sdrahn 	      {
1931b55d4692Sfgsch 		char *p;
1932b55d4692Sfgsch 
1933b55d4692Sfgsch 		/* The @@@ syntax is a special case. If the symbol is
1934b55d4692Sfgsch 		   not defined, 2 `@'s will be removed from the
1935b55d4692Sfgsch 		   versioned_name.  */
1936b55d4692Sfgsch 
1937b55d4692Sfgsch 		p = strchr (symbol_get_obj (symp)->versioned_name,
1938b55d4692Sfgsch 			    ELF_VER_CHR);
1939b55d4692Sfgsch 		know (p != NULL);
1940b55d4692Sfgsch 		if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
1941b55d4692Sfgsch 		  {
1942b55d4692Sfgsch 		    size_t l = strlen (&p[3]) + 1;
1943b55d4692Sfgsch 		    memmove (&p[1], &p[3], l);
1944b55d4692Sfgsch 		  }
1945b55d4692Sfgsch 		if (symbol_used_p (symp) == 0
1946b55d4692Sfgsch 		    && symbol_used_in_reloc_p (symp) == 0)
1947b55d4692Sfgsch 		  symbol_remove (symp, &symbol_rootP, &symbol_lastP);
1948b55d4692Sfgsch 	      }
1949c074d1c9Sdrahn 
1950c074d1c9Sdrahn 	    /* If there was .weak foo, but foo was neither defined nor
1951c074d1c9Sdrahn 	       used anywhere, remove it.  */
1952c074d1c9Sdrahn 
1953c074d1c9Sdrahn 	    else if (S_IS_WEAK (symp)
1954c074d1c9Sdrahn 		     && symbol_used_p (symp) == 0
1955c074d1c9Sdrahn 		     && symbol_used_in_reloc_p (symp) == 0)
1956c074d1c9Sdrahn 	      symbol_remove (symp, &symbol_rootP, &symbol_lastP);
1957b55d4692Sfgsch 	  }
1958b55d4692Sfgsch     }
1959b55d4692Sfgsch }
1960b55d4692Sfgsch 
1961e93f7393Sniklas /* It is required that we let write_relocs have the opportunity to
1962e93f7393Sniklas    optimize away fixups before output has begun, since it is possible
1963e93f7393Sniklas    to eliminate all fixups for a section and thus we never should
1964e93f7393Sniklas    have generated the relocation section.  */
1965e93f7393Sniklas 
1966e93f7393Sniklas void
elf_frob_file_after_relocs(void)1967*007c2a45Smiod elf_frob_file_after_relocs (void)
1968e93f7393Sniklas {
19692159047fSniklas #ifdef NEED_ECOFF_DEBUG
19702159047fSniklas   if (ECOFF_DEBUGGING)
19712159047fSniklas     /* Generate the ECOFF debugging information.  */
19722159047fSniklas     {
19732159047fSniklas       const struct ecoff_debug_swap *debug_swap;
19742159047fSniklas       struct ecoff_debug_info debug;
19752159047fSniklas       char *buf;
19762159047fSniklas       asection *sec;
19772159047fSniklas 
19782159047fSniklas       debug_swap
19792159047fSniklas 	= get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap;
1980*007c2a45Smiod       know (debug_swap != NULL);
19812159047fSniklas       ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
19822159047fSniklas 
19832159047fSniklas       /* Set up the pointers in debug.  */
19842159047fSniklas #define SET(ptr, offset, type) \
19852159047fSniklas     debug.ptr = (type) (buf + debug.symbolic_header.offset)
19862159047fSniklas 
19872159047fSniklas       SET (line, cbLineOffset, unsigned char *);
1988*007c2a45Smiod       SET (external_dnr, cbDnOffset, void *);
1989*007c2a45Smiod       SET (external_pdr, cbPdOffset, void *);
1990*007c2a45Smiod       SET (external_sym, cbSymOffset, void *);
1991*007c2a45Smiod       SET (external_opt, cbOptOffset, void *);
19922159047fSniklas       SET (external_aux, cbAuxOffset, union aux_ext *);
19932159047fSniklas       SET (ss, cbSsOffset, char *);
1994*007c2a45Smiod       SET (external_fdr, cbFdOffset, void *);
1995*007c2a45Smiod       SET (external_rfd, cbRfdOffset, void *);
19962159047fSniklas       /* ssext and external_ext are set up just below.  */
19972159047fSniklas 
19982159047fSniklas #undef SET
19992159047fSniklas 
20002159047fSniklas       /* Set up the external symbols.  */
20012159047fSniklas       debug.ssext = debug.ssext_end = NULL;
20022159047fSniklas       debug.external_ext = debug.external_ext_end = NULL;
2003c074d1c9Sdrahn       if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, TRUE,
20042159047fSniklas 				       elf_get_extr, elf_set_index))
2005c074d1c9Sdrahn 	as_fatal (_("failed to set up debugging information: %s"),
20062159047fSniklas 		  bfd_errmsg (bfd_get_error ()));
20072159047fSniklas 
20082159047fSniklas       sec = bfd_get_section_by_name (stdoutput, ".mdebug");
20092159047fSniklas       assert (sec != NULL);
20102159047fSniklas 
2011c074d1c9Sdrahn       know (!stdoutput->output_has_begun);
20122159047fSniklas 
20132159047fSniklas       /* We set the size of the section, call bfd_set_section_contents
20142159047fSniklas 	 to force the ELF backend to allocate a file position, and then
20152159047fSniklas 	 write out the data.  FIXME: Is this really the best way to do
20162159047fSniklas 	 this?  */
20172159047fSniklas       sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap);
20182159047fSniklas 
2019b305b0f1Sespie       /* Pass BUF to bfd_set_section_contents because this will
2020b305b0f1Sespie 	 eventually become a call to fwrite, and ISO C prohibits
2021b305b0f1Sespie 	 passing a NULL pointer to a stdio function even if the
2022b305b0f1Sespie 	 pointer will not be used.  */
2023*007c2a45Smiod       if (! bfd_set_section_contents (stdoutput, sec, buf, 0, 0))
2024c074d1c9Sdrahn 	as_fatal (_("can't start writing .mdebug section: %s"),
20252159047fSniklas 		  bfd_errmsg (bfd_get_error ()));
20262159047fSniklas 
2027c074d1c9Sdrahn       know (stdoutput->output_has_begun);
20282159047fSniklas       know (sec->filepos != 0);
20292159047fSniklas 
20302159047fSniklas       if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
20312159047fSniklas 				   sec->filepos))
2032c074d1c9Sdrahn 	as_fatal (_("could not write .mdebug section: %s"),
20332159047fSniklas 		  bfd_errmsg (bfd_get_error ()));
20342159047fSniklas     }
20352159047fSniklas #endif /* NEED_ECOFF_DEBUG */
20362159047fSniklas }
20372159047fSniklas 
2038b305b0f1Sespie #ifdef SCO_ELF
2039b305b0f1Sespie 
2040*007c2a45Smiod /* Heavily plagiarized from obj_elf_version.  The idea is to emit the
2041b305b0f1Sespie    SCO specific identifier in the .notes section to satisfy the SCO
2042b305b0f1Sespie    linker.
2043b305b0f1Sespie 
2044b305b0f1Sespie    This looks more complicated than it really is.  As opposed to the
2045b305b0f1Sespie    "obvious" solution, this should handle the cross dev cases
2046b305b0f1Sespie    correctly.  (i.e, hosting on a 64 bit big endian processor, but
2047b305b0f1Sespie    generating SCO Elf code) Efficiency isn't a concern, as there
2048b305b0f1Sespie    should be exactly one of these sections per object module.
2049b305b0f1Sespie 
2050b305b0f1Sespie    SCO OpenServer 5 identifies it's ELF modules with a standard ELF
2051b305b0f1Sespie    .note section.
2052b305b0f1Sespie 
2053b305b0f1Sespie    int_32 namesz  = 4 ;  Name size
2054b305b0f1Sespie    int_32 descsz  = 12 ; Descriptive information
2055b305b0f1Sespie    int_32 type    = 1 ;
2056b305b0f1Sespie    char   name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
2057b305b0f1Sespie    int_32 version = (major ver # << 16)  | version of tools ;
2058b305b0f1Sespie    int_32 source  = (tool_id << 16 ) | 1 ;
2059b305b0f1Sespie    int_32 info    = 0 ;    These are set by the SCO tools, but we
2060b305b0f1Sespie 			   don't know enough about the source
2061b305b0f1Sespie 			   environment to set them.  SCO ld currently
2062b305b0f1Sespie 			   ignores them, and recommends we set them
2063b305b0f1Sespie 			   to zero.  */
2064b305b0f1Sespie 
2065b305b0f1Sespie #define SCO_MAJOR_VERSION 0x1
2066b305b0f1Sespie #define SCO_MINOR_VERSION 0x1
2067b305b0f1Sespie 
2068b305b0f1Sespie void
sco_id(void)2069*007c2a45Smiod sco_id (void)
2070b305b0f1Sespie {
2071b305b0f1Sespie 
2072b305b0f1Sespie   char *name;
2073b305b0f1Sespie   unsigned int c;
2074b305b0f1Sespie   char ch;
2075b305b0f1Sespie   char *p;
2076b305b0f1Sespie   asection *seg = now_seg;
2077b305b0f1Sespie   subsegT subseg = now_subseg;
2078b305b0f1Sespie   Elf_Internal_Note i_note;
2079b305b0f1Sespie   Elf_External_Note e_note;
2080*007c2a45Smiod   asection *note_secp = NULL;
2081b305b0f1Sespie   int i, len;
2082b305b0f1Sespie 
2083b305b0f1Sespie   /* create the .note section */
2084b305b0f1Sespie 
2085b305b0f1Sespie   note_secp = subseg_new (".note", 0);
2086b305b0f1Sespie   bfd_set_section_flags (stdoutput,
2087b305b0f1Sespie 			 note_secp,
2088b305b0f1Sespie 			 SEC_HAS_CONTENTS | SEC_READONLY);
2089b305b0f1Sespie 
2090b305b0f1Sespie   /* process the version string */
2091b305b0f1Sespie 
2092b305b0f1Sespie   i_note.namesz = 4;
2093b305b0f1Sespie   i_note.descsz = 12;		/* 12 descriptive bytes */
2094b305b0f1Sespie   i_note.type = NT_VERSION;	/* Contains a version string */
2095b305b0f1Sespie 
2096b305b0f1Sespie   p = frag_more (sizeof (i_note.namesz));
2097*007c2a45Smiod   md_number_to_chars (p, i_note.namesz, 4);
2098b305b0f1Sespie 
2099b305b0f1Sespie   p = frag_more (sizeof (i_note.descsz));
2100*007c2a45Smiod   md_number_to_chars (p, i_note.descsz, 4);
2101b305b0f1Sespie 
2102b305b0f1Sespie   p = frag_more (sizeof (i_note.type));
2103*007c2a45Smiod   md_number_to_chars (p, i_note.type, 4);
2104b305b0f1Sespie 
2105b305b0f1Sespie   p = frag_more (4);
2106b305b0f1Sespie   strcpy (p, "SCO");
2107b305b0f1Sespie 
2108b305b0f1Sespie   /* Note: this is the version number of the ELF we're representing */
2109b305b0f1Sespie   p = frag_more (4);
2110b305b0f1Sespie   md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
2111b305b0f1Sespie 
2112b305b0f1Sespie   /* Here, we pick a magic number for ourselves (yes, I "registered"
2113b305b0f1Sespie      it with SCO.  The bottom bit shows that we are compat with the
2114b305b0f1Sespie      SCO ABI.  */
2115b305b0f1Sespie   p = frag_more (4);
2116b305b0f1Sespie   md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
2117b305b0f1Sespie 
2118b305b0f1Sespie   /* If we knew (or cared) what the source language options were, we'd
2119b305b0f1Sespie      fill them in here.  SCO has given us permission to ignore these
2120b305b0f1Sespie      and just set them to zero.  */
2121b305b0f1Sespie   p = frag_more (4);
2122b305b0f1Sespie   md_number_to_chars (p, 0x0000, 4);
2123b305b0f1Sespie 
2124b305b0f1Sespie   frag_align (2, 0, 0);
2125b305b0f1Sespie 
2126b305b0f1Sespie   /* We probably can't restore the current segment, for there likely
2127b305b0f1Sespie      isn't one yet...  */
2128b305b0f1Sespie   if (seg && subseg)
2129b305b0f1Sespie     subseg_set (seg, subseg);
2130b305b0f1Sespie 
2131b305b0f1Sespie }
2132b305b0f1Sespie 
2133b305b0f1Sespie #endif /* SCO_ELF */
2134b305b0f1Sespie 
2135b55d4692Sfgsch static int
elf_separate_stab_sections(void)2136*007c2a45Smiod elf_separate_stab_sections (void)
2137b55d4692Sfgsch {
2138b55d4692Sfgsch #ifdef NEED_ECOFF_DEBUG
2139b55d4692Sfgsch   return (!ECOFF_DEBUGGING);
2140b55d4692Sfgsch #else
2141b55d4692Sfgsch   return 1;
2142b55d4692Sfgsch #endif
2143b55d4692Sfgsch }
2144b55d4692Sfgsch 
2145b55d4692Sfgsch static void
elf_init_stab_section(segT seg)2146*007c2a45Smiod elf_init_stab_section (segT seg)
2147b55d4692Sfgsch {
2148b55d4692Sfgsch #ifdef NEED_ECOFF_DEBUG
2149b55d4692Sfgsch   if (!ECOFF_DEBUGGING)
2150b55d4692Sfgsch #endif
2151b55d4692Sfgsch     obj_elf_init_stab_section (seg);
2152b55d4692Sfgsch }
2153b55d4692Sfgsch 
21542159047fSniklas const struct format_ops elf_format_ops =
21552159047fSniklas {
21562159047fSniklas   bfd_target_elf_flavour,
2157b305b0f1Sespie   0,	/* dfl_leading_underscore */
2158b305b0f1Sespie   1,	/* emit_section_symbols */
2159b55d4692Sfgsch   elf_begin,
2160b55d4692Sfgsch   elf_file_symbol,
21612159047fSniklas   elf_frob_symbol,
21622159047fSniklas   elf_frob_file,
2163b55d4692Sfgsch   elf_frob_file_before_adjust,
2164c074d1c9Sdrahn   0,	/* obj_frob_file_before_fix */
2165e93f7393Sniklas   elf_frob_file_after_relocs,
21662159047fSniklas   elf_s_get_size, elf_s_set_size,
21672159047fSniklas   elf_s_get_align, elf_s_set_align,
2168b305b0f1Sespie   elf_s_get_other,
2169b55d4692Sfgsch   elf_s_set_other,
2170b305b0f1Sespie   0,	/* s_get_desc */
2171b55d4692Sfgsch   0,	/* s_set_desc */
2172b55d4692Sfgsch   0,	/* s_get_type */
2173b55d4692Sfgsch   0,	/* s_set_type */
21742159047fSniklas   elf_copy_symbol_attributes,
21752159047fSniklas #ifdef NEED_ECOFF_DEBUG
21762159047fSniklas   ecoff_generate_asm_lineno,
21772159047fSniklas   ecoff_stab,
21782159047fSniklas #else
2179b305b0f1Sespie   0,	/* generate_asm_lineno */
21802159047fSniklas   0,	/* process_stab */
21812159047fSniklas #endif
2182b55d4692Sfgsch   elf_separate_stab_sections,
2183b55d4692Sfgsch   elf_init_stab_section,
21842159047fSniklas   elf_sec_sym_ok_for_reloc,
21852159047fSniklas   elf_pop_insert,
21862159047fSniklas #ifdef NEED_ECOFF_DEBUG
21872159047fSniklas   elf_ecoff_set_ext,
21882159047fSniklas #else
2189b305b0f1Sespie   0,	/* ecoff_set_ext */
21902159047fSniklas #endif
2191b305b0f1Sespie   elf_obj_read_begin_hook,
2192b55d4692Sfgsch   elf_obj_symbol_new_hook
21932159047fSniklas };
2194