xref: /dflybsd-src/contrib/binutils-2.34/gas/config/obj-elf.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
1*fae548d3Szrj /* ELF object file format
2*fae548d3Szrj    Copyright (C) 1992-2020 Free Software Foundation, Inc.
3*fae548d3Szrj 
4*fae548d3Szrj    This file is part of GAS, the GNU Assembler.
5*fae548d3Szrj 
6*fae548d3Szrj    GAS is free software; you can redistribute it and/or modify
7*fae548d3Szrj    it under the terms of the GNU General Public License as
8*fae548d3Szrj    published by the Free Software Foundation; either version 3,
9*fae548d3Szrj    or (at your option) any later version.
10*fae548d3Szrj 
11*fae548d3Szrj    GAS is distributed in the hope that it will be useful, but
12*fae548d3Szrj    WITHOUT ANY WARRANTY; without even the implied warranty of
13*fae548d3Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14*fae548d3Szrj    the GNU General Public License for more details.
15*fae548d3Szrj 
16*fae548d3Szrj    You should have received a copy of the GNU General Public License
17*fae548d3Szrj    along with GAS; see the file COPYING.  If not, write to the Free
18*fae548d3Szrj    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19*fae548d3Szrj    02110-1301, USA.  */
20*fae548d3Szrj 
21*fae548d3Szrj #define OBJ_HEADER "obj-elf.h"
22*fae548d3Szrj #include "as.h"
23*fae548d3Szrj #include "safe-ctype.h"
24*fae548d3Szrj #include "subsegs.h"
25*fae548d3Szrj #include "obstack.h"
26*fae548d3Szrj #include "dwarf2dbg.h"
27*fae548d3Szrj 
28*fae548d3Szrj #ifndef ECOFF_DEBUGGING
29*fae548d3Szrj #define ECOFF_DEBUGGING 0
30*fae548d3Szrj #else
31*fae548d3Szrj #define NEED_ECOFF_DEBUG
32*fae548d3Szrj #endif
33*fae548d3Szrj 
34*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
35*fae548d3Szrj #include "ecoff.h"
36*fae548d3Szrj #include "bfd/ecoff-bfd.h"
37*fae548d3Szrj #endif
38*fae548d3Szrj 
39*fae548d3Szrj #ifdef TC_ALPHA
40*fae548d3Szrj #include "elf/alpha.h"
41*fae548d3Szrj #endif
42*fae548d3Szrj 
43*fae548d3Szrj #ifdef TC_MIPS
44*fae548d3Szrj #include "elf/mips.h"
45*fae548d3Szrj #endif
46*fae548d3Szrj 
47*fae548d3Szrj #ifdef TC_PPC
48*fae548d3Szrj #include "elf/ppc.h"
49*fae548d3Szrj #endif
50*fae548d3Szrj 
51*fae548d3Szrj #ifdef TC_I386
52*fae548d3Szrj #include "elf/x86-64.h"
53*fae548d3Szrj #endif
54*fae548d3Szrj 
55*fae548d3Szrj #ifdef TC_MEP
56*fae548d3Szrj #include "elf/mep.h"
57*fae548d3Szrj #endif
58*fae548d3Szrj 
59*fae548d3Szrj #ifdef TC_NIOS2
60*fae548d3Szrj #include "elf/nios2.h"
61*fae548d3Szrj #endif
62*fae548d3Szrj 
63*fae548d3Szrj #ifdef TC_PRU
64*fae548d3Szrj #include "elf/pru.h"
65*fae548d3Szrj #endif
66*fae548d3Szrj 
67*fae548d3Szrj static void obj_elf_line (int);
68*fae548d3Szrj static void obj_elf_size (int);
69*fae548d3Szrj static void obj_elf_type (int);
70*fae548d3Szrj static void obj_elf_ident (int);
71*fae548d3Szrj static void obj_elf_weak (int);
72*fae548d3Szrj static void obj_elf_local (int);
73*fae548d3Szrj static void obj_elf_visibility (int);
74*fae548d3Szrj static void obj_elf_symver (int);
75*fae548d3Szrj static void obj_elf_subsection (int);
76*fae548d3Szrj static void obj_elf_popsection (int);
77*fae548d3Szrj static void obj_elf_gnu_attribute (int);
78*fae548d3Szrj static void obj_elf_tls_common (int);
79*fae548d3Szrj static void obj_elf_lcomm (int);
80*fae548d3Szrj static void obj_elf_struct (int);
81*fae548d3Szrj 
82*fae548d3Szrj static const pseudo_typeS elf_pseudo_table[] =
83*fae548d3Szrj {
84*fae548d3Szrj   {"comm", obj_elf_common, 0},
85*fae548d3Szrj   {"common", obj_elf_common, 1},
86*fae548d3Szrj   {"ident", obj_elf_ident, 0},
87*fae548d3Szrj   {"lcomm", obj_elf_lcomm, 0},
88*fae548d3Szrj   {"local", obj_elf_local, 0},
89*fae548d3Szrj   {"previous", obj_elf_previous, 0},
90*fae548d3Szrj   {"section", obj_elf_section, 0},
91*fae548d3Szrj   {"section.s", obj_elf_section, 0},
92*fae548d3Szrj   {"sect", obj_elf_section, 0},
93*fae548d3Szrj   {"sect.s", obj_elf_section, 0},
94*fae548d3Szrj   {"pushsection", obj_elf_section, 1},
95*fae548d3Szrj   {"popsection", obj_elf_popsection, 0},
96*fae548d3Szrj   {"size", obj_elf_size, 0},
97*fae548d3Szrj   {"type", obj_elf_type, 0},
98*fae548d3Szrj   {"version", obj_elf_version, 0},
99*fae548d3Szrj   {"weak", obj_elf_weak, 0},
100*fae548d3Szrj 
101*fae548d3Szrj   /* These define symbol visibility.  */
102*fae548d3Szrj   {"internal", obj_elf_visibility, STV_INTERNAL},
103*fae548d3Szrj   {"hidden", obj_elf_visibility, STV_HIDDEN},
104*fae548d3Szrj   {"protected", obj_elf_visibility, STV_PROTECTED},
105*fae548d3Szrj 
106*fae548d3Szrj   /* These are used for stabs-in-elf configurations.  */
107*fae548d3Szrj   {"line", obj_elf_line, 0},
108*fae548d3Szrj 
109*fae548d3Szrj   /* This is a GNU extension to handle symbol versions.  */
110*fae548d3Szrj   {"symver", obj_elf_symver, 0},
111*fae548d3Szrj 
112*fae548d3Szrj   /* A GNU extension to change subsection only.  */
113*fae548d3Szrj   {"subsection", obj_elf_subsection, 0},
114*fae548d3Szrj 
115*fae548d3Szrj   /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
116*fae548d3Szrj   {"vtable_inherit", obj_elf_vtable_inherit, 0},
117*fae548d3Szrj   {"vtable_entry", obj_elf_vtable_entry, 0},
118*fae548d3Szrj 
119*fae548d3Szrj   /* A GNU extension for object attributes.  */
120*fae548d3Szrj   {"gnu_attribute", obj_elf_gnu_attribute, 0},
121*fae548d3Szrj 
122*fae548d3Szrj   /* These are used for dwarf.  */
123*fae548d3Szrj   {"2byte", cons, 2},
124*fae548d3Szrj   {"4byte", cons, 4},
125*fae548d3Szrj   {"8byte", cons, 8},
126*fae548d3Szrj   /* These are used for dwarf2.  */
127*fae548d3Szrj   { "file", dwarf2_directive_file, 0 },
128*fae548d3Szrj   { "loc",  dwarf2_directive_loc,  0 },
129*fae548d3Szrj   { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
130*fae548d3Szrj 
131*fae548d3Szrj   /* We need to trap the section changing calls to handle .previous.  */
132*fae548d3Szrj   {"data", obj_elf_data, 0},
133*fae548d3Szrj   {"offset", obj_elf_struct, 0},
134*fae548d3Szrj   {"struct", obj_elf_struct, 0},
135*fae548d3Szrj   {"text", obj_elf_text, 0},
136*fae548d3Szrj 
137*fae548d3Szrj   {"tls_common", obj_elf_tls_common, 0},
138*fae548d3Szrj 
139*fae548d3Szrj   /* End sentinel.  */
140*fae548d3Szrj   {NULL, NULL, 0},
141*fae548d3Szrj };
142*fae548d3Szrj 
143*fae548d3Szrj static const pseudo_typeS ecoff_debug_pseudo_table[] =
144*fae548d3Szrj {
145*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
146*fae548d3Szrj   /* COFF style debugging information for ECOFF. .ln is not used; .loc
147*fae548d3Szrj      is used instead.  */
148*fae548d3Szrj   { "def",	ecoff_directive_def,	0 },
149*fae548d3Szrj   { "dim",	ecoff_directive_dim,	0 },
150*fae548d3Szrj   { "endef",	ecoff_directive_endef,	0 },
151*fae548d3Szrj   { "file",	ecoff_directive_file,	0 },
152*fae548d3Szrj   { "scl",	ecoff_directive_scl,	0 },
153*fae548d3Szrj   { "tag",	ecoff_directive_tag,	0 },
154*fae548d3Szrj   { "val",	ecoff_directive_val,	0 },
155*fae548d3Szrj 
156*fae548d3Szrj   /* COFF debugging requires pseudo-ops .size and .type, but ELF
157*fae548d3Szrj      already has meanings for those.  We use .esize and .etype
158*fae548d3Szrj      instead.  These are only generated by gcc anyhow.  */
159*fae548d3Szrj   { "esize",	ecoff_directive_size,	0 },
160*fae548d3Szrj   { "etype",	ecoff_directive_type,	0 },
161*fae548d3Szrj 
162*fae548d3Szrj   /* ECOFF specific debugging information.  */
163*fae548d3Szrj   { "aent",	ecoff_directive_ent,	1 },
164*fae548d3Szrj   { "begin",	ecoff_directive_begin,	0 },
165*fae548d3Szrj   { "bend",	ecoff_directive_bend,	0 },
166*fae548d3Szrj   { "end",	ecoff_directive_end,	0 },
167*fae548d3Szrj   { "ent",	ecoff_directive_ent,	0 },
168*fae548d3Szrj   { "fmask",	ecoff_directive_fmask,	0 },
169*fae548d3Szrj   { "frame",	ecoff_directive_frame,	0 },
170*fae548d3Szrj   { "loc",	ecoff_directive_loc,	0 },
171*fae548d3Szrj   { "mask",	ecoff_directive_mask,	0 },
172*fae548d3Szrj 
173*fae548d3Szrj   /* Other ECOFF directives.  */
174*fae548d3Szrj   { "extern",	ecoff_directive_extern,	0 },
175*fae548d3Szrj 
176*fae548d3Szrj   /* These are used on Irix.  I don't know how to implement them.  */
177*fae548d3Szrj   { "alias",	s_ignore,		0 },
178*fae548d3Szrj   { "bgnb",	s_ignore,		0 },
179*fae548d3Szrj   { "endb",	s_ignore,		0 },
180*fae548d3Szrj   { "lab",	s_ignore,		0 },
181*fae548d3Szrj   { "noalias",	s_ignore,		0 },
182*fae548d3Szrj   { "verstamp",	s_ignore,		0 },
183*fae548d3Szrj   { "vreg",	s_ignore,		0 },
184*fae548d3Szrj #endif
185*fae548d3Szrj 
186*fae548d3Szrj   {NULL, NULL, 0}			/* end sentinel */
187*fae548d3Szrj };
188*fae548d3Szrj 
189*fae548d3Szrj #undef NO_RELOC
190*fae548d3Szrj #include "aout/aout64.h"
191*fae548d3Szrj 
192*fae548d3Szrj /* This is called when the assembler starts.  */
193*fae548d3Szrj 
194*fae548d3Szrj asection *elf_com_section_ptr;
195*fae548d3Szrj 
196*fae548d3Szrj void
elf_begin(void)197*fae548d3Szrj elf_begin (void)
198*fae548d3Szrj {
199*fae548d3Szrj   asection *s;
200*fae548d3Szrj 
201*fae548d3Szrj   /* Add symbols for the known sections to the symbol table.  */
202*fae548d3Szrj   s = bfd_get_section_by_name (stdoutput, TEXT_SECTION_NAME);
203*fae548d3Szrj   symbol_table_insert (section_symbol (s));
204*fae548d3Szrj   s = bfd_get_section_by_name (stdoutput, DATA_SECTION_NAME);
205*fae548d3Szrj   symbol_table_insert (section_symbol (s));
206*fae548d3Szrj   s = bfd_get_section_by_name (stdoutput, BSS_SECTION_NAME);
207*fae548d3Szrj   symbol_table_insert (section_symbol (s));
208*fae548d3Szrj   elf_com_section_ptr = bfd_com_section_ptr;
209*fae548d3Szrj }
210*fae548d3Szrj 
211*fae548d3Szrj void
elf_pop_insert(void)212*fae548d3Szrj elf_pop_insert (void)
213*fae548d3Szrj {
214*fae548d3Szrj   pop_insert (elf_pseudo_table);
215*fae548d3Szrj   if (ECOFF_DEBUGGING)
216*fae548d3Szrj     pop_insert (ecoff_debug_pseudo_table);
217*fae548d3Szrj }
218*fae548d3Szrj 
219*fae548d3Szrj static bfd_vma
elf_s_get_size(symbolS * sym)220*fae548d3Szrj elf_s_get_size (symbolS *sym)
221*fae548d3Szrj {
222*fae548d3Szrj   return S_GET_SIZE (sym);
223*fae548d3Szrj }
224*fae548d3Szrj 
225*fae548d3Szrj static void
elf_s_set_size(symbolS * sym,bfd_vma sz)226*fae548d3Szrj elf_s_set_size (symbolS *sym, bfd_vma sz)
227*fae548d3Szrj {
228*fae548d3Szrj   S_SET_SIZE (sym, sz);
229*fae548d3Szrj }
230*fae548d3Szrj 
231*fae548d3Szrj static bfd_vma
elf_s_get_align(symbolS * sym)232*fae548d3Szrj elf_s_get_align (symbolS *sym)
233*fae548d3Szrj {
234*fae548d3Szrj   return S_GET_ALIGN (sym);
235*fae548d3Szrj }
236*fae548d3Szrj 
237*fae548d3Szrj static void
elf_s_set_align(symbolS * sym,bfd_vma align)238*fae548d3Szrj elf_s_set_align (symbolS *sym, bfd_vma align)
239*fae548d3Szrj {
240*fae548d3Szrj   S_SET_ALIGN (sym, align);
241*fae548d3Szrj }
242*fae548d3Szrj 
243*fae548d3Szrj int
elf_s_get_other(symbolS * sym)244*fae548d3Szrj elf_s_get_other (symbolS *sym)
245*fae548d3Szrj {
246*fae548d3Szrj   return elf_symbol (symbol_get_bfdsym (sym))->internal_elf_sym.st_other;
247*fae548d3Szrj }
248*fae548d3Szrj 
249*fae548d3Szrj static void
elf_s_set_other(symbolS * sym,int other)250*fae548d3Szrj elf_s_set_other (symbolS *sym, int other)
251*fae548d3Szrj {
252*fae548d3Szrj   S_SET_OTHER (sym, other);
253*fae548d3Szrj }
254*fae548d3Szrj 
255*fae548d3Szrj static int
elf_sec_sym_ok_for_reloc(asection * sec)256*fae548d3Szrj elf_sec_sym_ok_for_reloc (asection *sec)
257*fae548d3Szrj {
258*fae548d3Szrj   return obj_sec_sym_ok_for_reloc (sec);
259*fae548d3Szrj }
260*fae548d3Szrj 
261*fae548d3Szrj void
elf_file_symbol(const char * s,int appfile)262*fae548d3Szrj elf_file_symbol (const char *s, int appfile)
263*fae548d3Szrj {
264*fae548d3Szrj   asymbol *bsym;
265*fae548d3Szrj 
266*fae548d3Szrj   if (!appfile
267*fae548d3Szrj       || symbol_rootP == NULL
268*fae548d3Szrj       || (bsym = symbol_get_bfdsym (symbol_rootP)) == NULL
269*fae548d3Szrj       || (bsym->flags & BSF_FILE) == 0)
270*fae548d3Szrj     {
271*fae548d3Szrj       symbolS *sym;
272*fae548d3Szrj       size_t name_length;
273*fae548d3Szrj 
274*fae548d3Szrj       sym = symbol_new (s, absolute_section, 0, NULL);
275*fae548d3Szrj       symbol_set_frag (sym, &zero_address_frag);
276*fae548d3Szrj 
277*fae548d3Szrj       name_length = strlen (s);
278*fae548d3Szrj       if (name_length > strlen (S_GET_NAME (sym)))
279*fae548d3Szrj 	{
280*fae548d3Szrj 	  obstack_grow (&notes, s, name_length + 1);
281*fae548d3Szrj 	  S_SET_NAME (sym, (const char *) obstack_finish (&notes));
282*fae548d3Szrj 	}
283*fae548d3Szrj       else
284*fae548d3Szrj 	strcpy ((char *) S_GET_NAME (sym), s);
285*fae548d3Szrj 
286*fae548d3Szrj       symbol_get_bfdsym (sym)->flags |= BSF_FILE;
287*fae548d3Szrj 
288*fae548d3Szrj       if (symbol_rootP != sym
289*fae548d3Szrj 	  && ((bsym = symbol_get_bfdsym (symbol_rootP)) == NULL
290*fae548d3Szrj 	      || (bsym->flags & BSF_FILE) == 0))
291*fae548d3Szrj 	{
292*fae548d3Szrj 	  symbol_remove (sym, &symbol_rootP, &symbol_lastP);
293*fae548d3Szrj 	  symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
294*fae548d3Szrj 	}
295*fae548d3Szrj 
296*fae548d3Szrj #ifdef DEBUG
297*fae548d3Szrj       verify_symbol_chain (symbol_rootP, symbol_lastP);
298*fae548d3Szrj #endif
299*fae548d3Szrj     }
300*fae548d3Szrj 
301*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
302*fae548d3Szrj   ecoff_new_file (s, appfile);
303*fae548d3Szrj #endif
304*fae548d3Szrj }
305*fae548d3Szrj 
306*fae548d3Szrj /* Called from read.c:s_comm after we've parsed .comm symbol, size.
307*fae548d3Szrj    Parse a possible alignment value.  */
308*fae548d3Szrj 
309*fae548d3Szrj symbolS *
elf_common_parse(int ignore ATTRIBUTE_UNUSED,symbolS * symbolP,addressT size)310*fae548d3Szrj elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
311*fae548d3Szrj {
312*fae548d3Szrj   addressT align = 0;
313*fae548d3Szrj   int is_local = symbol_get_obj (symbolP)->local;
314*fae548d3Szrj 
315*fae548d3Szrj   if (*input_line_pointer == ',')
316*fae548d3Szrj     {
317*fae548d3Szrj       char *save = input_line_pointer;
318*fae548d3Szrj 
319*fae548d3Szrj       input_line_pointer++;
320*fae548d3Szrj       SKIP_WHITESPACE ();
321*fae548d3Szrj 
322*fae548d3Szrj       if (*input_line_pointer == '"')
323*fae548d3Szrj 	{
324*fae548d3Szrj 	  /* For sparc.  Accept .common symbol, length, "bss"  */
325*fae548d3Szrj 	  input_line_pointer++;
326*fae548d3Szrj 	  /* Some use the dot, some don't.  */
327*fae548d3Szrj 	  if (*input_line_pointer == '.')
328*fae548d3Szrj 	    input_line_pointer++;
329*fae548d3Szrj 	  /* Some say data, some say bss.  */
330*fae548d3Szrj 	  if (strncmp (input_line_pointer, "bss\"", 4) == 0)
331*fae548d3Szrj 	    input_line_pointer += 4;
332*fae548d3Szrj 	  else if (strncmp (input_line_pointer, "data\"", 5) == 0)
333*fae548d3Szrj 	    input_line_pointer += 5;
334*fae548d3Szrj 	  else
335*fae548d3Szrj 	    {
336*fae548d3Szrj 	      char *p = input_line_pointer;
337*fae548d3Szrj 	      char c;
338*fae548d3Szrj 
339*fae548d3Szrj 	      while (*--p != '"')
340*fae548d3Szrj 		;
341*fae548d3Szrj 	      while (!is_end_of_line[(unsigned char) *input_line_pointer])
342*fae548d3Szrj 		if (*input_line_pointer++ == '"')
343*fae548d3Szrj 		  break;
344*fae548d3Szrj 	      c = *input_line_pointer;
345*fae548d3Szrj 	      *input_line_pointer = '\0';
346*fae548d3Szrj 	      as_bad (_("bad .common segment %s"), p);
347*fae548d3Szrj 	      *input_line_pointer = c;
348*fae548d3Szrj 	      ignore_rest_of_line ();
349*fae548d3Szrj 	      return NULL;
350*fae548d3Szrj 	    }
351*fae548d3Szrj 	  /* ??? Don't ask me why these are always global.  */
352*fae548d3Szrj 	  is_local = 0;
353*fae548d3Szrj 	}
354*fae548d3Szrj       else
355*fae548d3Szrj 	{
356*fae548d3Szrj 	  input_line_pointer = save;
357*fae548d3Szrj 	  align = parse_align (is_local);
358*fae548d3Szrj 	  if (align == (addressT) -1)
359*fae548d3Szrj 	    return NULL;
360*fae548d3Szrj 	}
361*fae548d3Szrj     }
362*fae548d3Szrj 
363*fae548d3Szrj   if (is_local)
364*fae548d3Szrj     {
365*fae548d3Szrj       bss_alloc (symbolP, size, align);
366*fae548d3Szrj       S_CLEAR_EXTERNAL (symbolP);
367*fae548d3Szrj     }
368*fae548d3Szrj   else
369*fae548d3Szrj     {
370*fae548d3Szrj       S_SET_VALUE (symbolP, size);
371*fae548d3Szrj       S_SET_ALIGN (symbolP, align);
372*fae548d3Szrj       S_SET_EXTERNAL (symbolP);
373*fae548d3Szrj       S_SET_SEGMENT (symbolP, elf_com_section_ptr);
374*fae548d3Szrj     }
375*fae548d3Szrj 
376*fae548d3Szrj   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
377*fae548d3Szrj 
378*fae548d3Szrj   return symbolP;
379*fae548d3Szrj }
380*fae548d3Szrj 
381*fae548d3Szrj void
obj_elf_common(int is_common)382*fae548d3Szrj obj_elf_common (int is_common)
383*fae548d3Szrj {
384*fae548d3Szrj   if (flag_mri && is_common)
385*fae548d3Szrj     s_mri_common (0);
386*fae548d3Szrj   else
387*fae548d3Szrj     s_comm_internal (0, elf_common_parse);
388*fae548d3Szrj }
389*fae548d3Szrj 
390*fae548d3Szrj static void
obj_elf_tls_common(int ignore ATTRIBUTE_UNUSED)391*fae548d3Szrj obj_elf_tls_common (int ignore ATTRIBUTE_UNUSED)
392*fae548d3Szrj {
393*fae548d3Szrj   symbolS *symbolP = s_comm_internal (0, elf_common_parse);
394*fae548d3Szrj 
395*fae548d3Szrj   if (symbolP)
396*fae548d3Szrj     symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
397*fae548d3Szrj }
398*fae548d3Szrj 
399*fae548d3Szrj static void
obj_elf_lcomm(int ignore ATTRIBUTE_UNUSED)400*fae548d3Szrj obj_elf_lcomm (int ignore ATTRIBUTE_UNUSED)
401*fae548d3Szrj {
402*fae548d3Szrj   symbolS *symbolP = s_comm_internal (0, s_lcomm_internal);
403*fae548d3Szrj 
404*fae548d3Szrj   if (symbolP)
405*fae548d3Szrj     symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
406*fae548d3Szrj }
407*fae548d3Szrj 
408*fae548d3Szrj static symbolS *
get_sym_from_input_line_and_check(void)409*fae548d3Szrj get_sym_from_input_line_and_check (void)
410*fae548d3Szrj {
411*fae548d3Szrj   char *name;
412*fae548d3Szrj   char c;
413*fae548d3Szrj   symbolS *sym;
414*fae548d3Szrj 
415*fae548d3Szrj   c = get_symbol_name (& name);
416*fae548d3Szrj   sym = symbol_find_or_make (name);
417*fae548d3Szrj   *input_line_pointer = c;
418*fae548d3Szrj   SKIP_WHITESPACE_AFTER_NAME ();
419*fae548d3Szrj 
420*fae548d3Szrj   /* There is no symbol name if input_line_pointer has not moved.  */
421*fae548d3Szrj   if (name == input_line_pointer)
422*fae548d3Szrj     as_bad (_("Missing symbol name in directive"));
423*fae548d3Szrj   return sym;
424*fae548d3Szrj }
425*fae548d3Szrj 
426*fae548d3Szrj static void
obj_elf_local(int ignore ATTRIBUTE_UNUSED)427*fae548d3Szrj obj_elf_local (int ignore ATTRIBUTE_UNUSED)
428*fae548d3Szrj {
429*fae548d3Szrj   int c;
430*fae548d3Szrj   symbolS *symbolP;
431*fae548d3Szrj 
432*fae548d3Szrj   do
433*fae548d3Szrj     {
434*fae548d3Szrj       symbolP = get_sym_from_input_line_and_check ();
435*fae548d3Szrj       c = *input_line_pointer;
436*fae548d3Szrj       S_CLEAR_EXTERNAL (symbolP);
437*fae548d3Szrj       symbol_get_obj (symbolP)->local = 1;
438*fae548d3Szrj       if (c == ',')
439*fae548d3Szrj 	{
440*fae548d3Szrj 	  input_line_pointer++;
441*fae548d3Szrj 	  SKIP_WHITESPACE ();
442*fae548d3Szrj 	  if (*input_line_pointer == '\n')
443*fae548d3Szrj 	    c = '\n';
444*fae548d3Szrj 	}
445*fae548d3Szrj     }
446*fae548d3Szrj   while (c == ',');
447*fae548d3Szrj   demand_empty_rest_of_line ();
448*fae548d3Szrj }
449*fae548d3Szrj 
450*fae548d3Szrj static void
obj_elf_weak(int ignore ATTRIBUTE_UNUSED)451*fae548d3Szrj obj_elf_weak (int ignore ATTRIBUTE_UNUSED)
452*fae548d3Szrj {
453*fae548d3Szrj   int c;
454*fae548d3Szrj   symbolS *symbolP;
455*fae548d3Szrj 
456*fae548d3Szrj   do
457*fae548d3Szrj     {
458*fae548d3Szrj       symbolP = get_sym_from_input_line_and_check ();
459*fae548d3Szrj       c = *input_line_pointer;
460*fae548d3Szrj       S_SET_WEAK (symbolP);
461*fae548d3Szrj       if (c == ',')
462*fae548d3Szrj 	{
463*fae548d3Szrj 	  input_line_pointer++;
464*fae548d3Szrj 	  SKIP_WHITESPACE ();
465*fae548d3Szrj 	  if (*input_line_pointer == '\n')
466*fae548d3Szrj 	    c = '\n';
467*fae548d3Szrj 	}
468*fae548d3Szrj     }
469*fae548d3Szrj   while (c == ',');
470*fae548d3Szrj   demand_empty_rest_of_line ();
471*fae548d3Szrj }
472*fae548d3Szrj 
473*fae548d3Szrj static void
obj_elf_visibility(int visibility)474*fae548d3Szrj obj_elf_visibility (int visibility)
475*fae548d3Szrj {
476*fae548d3Szrj   int c;
477*fae548d3Szrj   symbolS *symbolP;
478*fae548d3Szrj   asymbol *bfdsym;
479*fae548d3Szrj   elf_symbol_type *elfsym;
480*fae548d3Szrj 
481*fae548d3Szrj   do
482*fae548d3Szrj     {
483*fae548d3Szrj       symbolP = get_sym_from_input_line_and_check ();
484*fae548d3Szrj 
485*fae548d3Szrj       bfdsym = symbol_get_bfdsym (symbolP);
486*fae548d3Szrj       elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
487*fae548d3Szrj 
488*fae548d3Szrj       gas_assert (elfsym);
489*fae548d3Szrj 
490*fae548d3Szrj       elfsym->internal_elf_sym.st_other &= ~3;
491*fae548d3Szrj       elfsym->internal_elf_sym.st_other |= visibility;
492*fae548d3Szrj 
493*fae548d3Szrj       c = *input_line_pointer;
494*fae548d3Szrj       if (c == ',')
495*fae548d3Szrj 	{
496*fae548d3Szrj 	  input_line_pointer ++;
497*fae548d3Szrj 
498*fae548d3Szrj 	  SKIP_WHITESPACE ();
499*fae548d3Szrj 
500*fae548d3Szrj 	  if (*input_line_pointer == '\n')
501*fae548d3Szrj 	    c = '\n';
502*fae548d3Szrj 	}
503*fae548d3Szrj     }
504*fae548d3Szrj   while (c == ',');
505*fae548d3Szrj 
506*fae548d3Szrj   demand_empty_rest_of_line ();
507*fae548d3Szrj }
508*fae548d3Szrj 
509*fae548d3Szrj static segT previous_section;
510*fae548d3Szrj static int previous_subsection;
511*fae548d3Szrj 
512*fae548d3Szrj struct section_stack
513*fae548d3Szrj {
514*fae548d3Szrj   struct section_stack *next;
515*fae548d3Szrj   segT seg, prev_seg;
516*fae548d3Szrj   int subseg, prev_subseg;
517*fae548d3Szrj };
518*fae548d3Szrj 
519*fae548d3Szrj static struct section_stack *section_stack;
520*fae548d3Szrj 
521*fae548d3Szrj /* Match both section group name and the sh_info field.  */
522*fae548d3Szrj struct section_match
523*fae548d3Szrj {
524*fae548d3Szrj   const char *group_name;
525*fae548d3Szrj   unsigned int info;
526*fae548d3Szrj };
527*fae548d3Szrj 
528*fae548d3Szrj static bfd_boolean
get_section(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * inf)529*fae548d3Szrj get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
530*fae548d3Szrj {
531*fae548d3Szrj   struct section_match *match = (struct section_match *) inf;
532*fae548d3Szrj   const char *gname = match->group_name;
533*fae548d3Szrj   const char *group_name = elf_group_name (sec);
534*fae548d3Szrj   unsigned int info = elf_section_data (sec)->this_hdr.sh_info;
535*fae548d3Szrj 
536*fae548d3Szrj   return (info == match->info
537*fae548d3Szrj 	  && (group_name == gname
538*fae548d3Szrj 	      || (group_name != NULL
539*fae548d3Szrj 		  && gname != NULL
540*fae548d3Szrj 		  && strcmp (group_name, gname) == 0)));
541*fae548d3Szrj }
542*fae548d3Szrj 
543*fae548d3Szrj /* Handle the .section pseudo-op.  This code supports two different
544*fae548d3Szrj    syntaxes.
545*fae548d3Szrj 
546*fae548d3Szrj    The first is found on Solaris, and looks like
547*fae548d3Szrj        .section ".sec1",#alloc,#execinstr,#write
548*fae548d3Szrj    Here the names after '#' are the SHF_* flags to turn on for the
549*fae548d3Szrj    section.  I'm not sure how it determines the SHT_* type (BFD
550*fae548d3Szrj    doesn't really give us control over the type, anyhow).
551*fae548d3Szrj 
552*fae548d3Szrj    The second format is found on UnixWare, and probably most SVR4
553*fae548d3Szrj    machines, and looks like
554*fae548d3Szrj        .section .sec1,"a",@progbits
555*fae548d3Szrj    The quoted string may contain any combination of a, w, x, and
556*fae548d3Szrj    represents the SHF_* flags to turn on for the section.  The string
557*fae548d3Szrj    beginning with '@' can be progbits or nobits.  There should be
558*fae548d3Szrj    other possibilities, but I don't know what they are.  In any case,
559*fae548d3Szrj    BFD doesn't really let us set the section type.  */
560*fae548d3Szrj 
561*fae548d3Szrj void
obj_elf_change_section(const char * name,unsigned int type,unsigned int info,bfd_vma attr,int entsize,const char * group_name,int linkonce,int push)562*fae548d3Szrj obj_elf_change_section (const char *name,
563*fae548d3Szrj 			unsigned int type,
564*fae548d3Szrj 			unsigned int info,
565*fae548d3Szrj 			bfd_vma attr,
566*fae548d3Szrj 			int entsize,
567*fae548d3Szrj 			const char *group_name,
568*fae548d3Szrj 			int linkonce,
569*fae548d3Szrj 			int push)
570*fae548d3Szrj {
571*fae548d3Szrj   asection *old_sec;
572*fae548d3Szrj   segT sec;
573*fae548d3Szrj   flagword flags;
574*fae548d3Szrj   const struct elf_backend_data *bed;
575*fae548d3Szrj   const struct bfd_elf_special_section *ssect;
576*fae548d3Szrj   struct section_match match;
577*fae548d3Szrj 
578*fae548d3Szrj #ifdef md_flush_pending_output
579*fae548d3Szrj   md_flush_pending_output ();
580*fae548d3Szrj #endif
581*fae548d3Szrj 
582*fae548d3Szrj   /* Switch to the section, creating it if necessary.  */
583*fae548d3Szrj   if (push)
584*fae548d3Szrj     {
585*fae548d3Szrj       struct section_stack *elt;
586*fae548d3Szrj       elt = XNEW (struct section_stack);
587*fae548d3Szrj       elt->next = section_stack;
588*fae548d3Szrj       elt->seg = now_seg;
589*fae548d3Szrj       elt->prev_seg = previous_section;
590*fae548d3Szrj       elt->subseg = now_subseg;
591*fae548d3Szrj       elt->prev_subseg = previous_subsection;
592*fae548d3Szrj       section_stack = elt;
593*fae548d3Szrj     }
594*fae548d3Szrj   previous_section = now_seg;
595*fae548d3Szrj   previous_subsection = now_subseg;
596*fae548d3Szrj 
597*fae548d3Szrj   match.group_name = group_name;
598*fae548d3Szrj   match.info = info;
599*fae548d3Szrj   old_sec = bfd_get_section_by_name_if (stdoutput, name, get_section,
600*fae548d3Szrj 					(void *) &match);
601*fae548d3Szrj   if (old_sec)
602*fae548d3Szrj     {
603*fae548d3Szrj       sec = old_sec;
604*fae548d3Szrj       subseg_set (sec, 0);
605*fae548d3Szrj     }
606*fae548d3Szrj   else
607*fae548d3Szrj     sec = subseg_force_new (name, 0);
608*fae548d3Szrj 
609*fae548d3Szrj   bed = get_elf_backend_data (stdoutput);
610*fae548d3Szrj   ssect = (*bed->get_sec_type_attr) (stdoutput, sec);
611*fae548d3Szrj 
612*fae548d3Szrj   if (ssect != NULL)
613*fae548d3Szrj     {
614*fae548d3Szrj       bfd_boolean override = FALSE;
615*fae548d3Szrj 
616*fae548d3Szrj       if (type == SHT_NULL)
617*fae548d3Szrj 	type = ssect->type;
618*fae548d3Szrj       else if (type != ssect->type)
619*fae548d3Szrj 	{
620*fae548d3Szrj 	  if (old_sec == NULL
621*fae548d3Szrj 	      /* Some older versions of gcc will emit
622*fae548d3Szrj 
623*fae548d3Szrj 		 .section .init_array,"aw",@progbits
624*fae548d3Szrj 
625*fae548d3Szrj 		 for __attribute__ ((section (".init_array"))).
626*fae548d3Szrj 		 "@progbits" is incorrect.  Also for x86-64 large bss
627*fae548d3Szrj 		 sections, some older versions of gcc will emit
628*fae548d3Szrj 
629*fae548d3Szrj 		 .section .lbss,"aw",@progbits
630*fae548d3Szrj 
631*fae548d3Szrj 		 "@progbits" is incorrect.  */
632*fae548d3Szrj #ifdef TC_I386
633*fae548d3Szrj 	      && (bed->s->arch_size != 64
634*fae548d3Szrj 		  || !(ssect->attr & SHF_X86_64_LARGE))
635*fae548d3Szrj #endif
636*fae548d3Szrj 	      && ssect->type != SHT_INIT_ARRAY
637*fae548d3Szrj 	      && ssect->type != SHT_FINI_ARRAY
638*fae548d3Szrj 	      && ssect->type != SHT_PREINIT_ARRAY)
639*fae548d3Szrj 	    {
640*fae548d3Szrj 	      /* We allow to specify any type for a .note section.  */
641*fae548d3Szrj 	      if (ssect->type != SHT_NOTE
642*fae548d3Szrj 		  /* Processor and application defined types are allowed too.  */
643*fae548d3Szrj 		  && type < SHT_LOPROC)
644*fae548d3Szrj 		as_warn (_("setting incorrect section type for %s"),
645*fae548d3Szrj 			 name);
646*fae548d3Szrj 	    }
647*fae548d3Szrj 	  else
648*fae548d3Szrj 	    {
649*fae548d3Szrj 	      as_warn (_("ignoring incorrect section type for %s"),
650*fae548d3Szrj 		       name);
651*fae548d3Szrj 	      type = ssect->type;
652*fae548d3Szrj 	    }
653*fae548d3Szrj 	}
654*fae548d3Szrj 
655*fae548d3Szrj       if (old_sec == NULL && ((attr & ~(SHF_MASKOS | SHF_MASKPROC))
656*fae548d3Szrj 			      & ~ssect->attr) != 0)
657*fae548d3Szrj 	{
658*fae548d3Szrj 	  /* As a GNU extension, we permit a .note section to be
659*fae548d3Szrj 	     allocatable.  If the linker sees an allocatable .note
660*fae548d3Szrj 	     section, it will create a PT_NOTE segment in the output
661*fae548d3Szrj 	     file.  We also allow "x" for .note.GNU-stack.  */
662*fae548d3Szrj 	  if (ssect->type == SHT_NOTE
663*fae548d3Szrj 	      && (attr == SHF_ALLOC || attr == SHF_EXECINSTR))
664*fae548d3Szrj 	    ;
665*fae548d3Szrj 	  /* Allow different SHF_MERGE and SHF_STRINGS if we have
666*fae548d3Szrj 	     something like .rodata.str.  */
667*fae548d3Szrj 	  else if (ssect->suffix_length == -2
668*fae548d3Szrj 		   && name[ssect->prefix_length] == '.'
669*fae548d3Szrj 		   && (attr
670*fae548d3Szrj 		       & ~ssect->attr
671*fae548d3Szrj 		       & ~SHF_MERGE
672*fae548d3Szrj 		       & ~SHF_STRINGS) == 0)
673*fae548d3Szrj 	    ;
674*fae548d3Szrj 	  /* .interp, .strtab and .symtab can have SHF_ALLOC.  */
675*fae548d3Szrj 	  else if (attr == SHF_ALLOC
676*fae548d3Szrj 		   && (strcmp (name, ".interp") == 0
677*fae548d3Szrj 		       || strcmp (name, ".strtab") == 0
678*fae548d3Szrj 		       || strcmp (name, ".symtab") == 0))
679*fae548d3Szrj 	    override = TRUE;
680*fae548d3Szrj 	  /* .note.GNU-stack can have SHF_EXECINSTR.  */
681*fae548d3Szrj 	  else if (attr == SHF_EXECINSTR
682*fae548d3Szrj 		   && strcmp (name, ".note.GNU-stack") == 0)
683*fae548d3Szrj 	    override = TRUE;
684*fae548d3Szrj #ifdef TC_ALPHA
685*fae548d3Szrj 	  /* A section on Alpha may have SHF_ALPHA_GPREL.  */
686*fae548d3Szrj 	  else if ((attr & ~ssect->attr) == SHF_ALPHA_GPREL)
687*fae548d3Szrj 	    override = TRUE;
688*fae548d3Szrj #endif
689*fae548d3Szrj #ifdef TC_RX
690*fae548d3Szrj 	  else if (attr == (SHF_EXECINSTR | SHF_WRITE | SHF_ALLOC)
691*fae548d3Szrj 		   && (ssect->type == SHT_INIT_ARRAY
692*fae548d3Szrj 		       || ssect->type == SHT_FINI_ARRAY
693*fae548d3Szrj 		       || ssect->type == SHT_PREINIT_ARRAY))
694*fae548d3Szrj 	    /* RX init/fini arrays can and should have the "awx" attributes set.  */
695*fae548d3Szrj 	    ;
696*fae548d3Szrj #endif
697*fae548d3Szrj 	  else
698*fae548d3Szrj 	    {
699*fae548d3Szrj 	      if (group_name == NULL)
700*fae548d3Szrj 		as_warn (_("setting incorrect section attributes for %s"),
701*fae548d3Szrj 			 name);
702*fae548d3Szrj 	      override = TRUE;
703*fae548d3Szrj 	    }
704*fae548d3Szrj 	}
705*fae548d3Szrj 
706*fae548d3Szrj       if (!override && old_sec == NULL)
707*fae548d3Szrj 	attr |= ssect->attr;
708*fae548d3Szrj     }
709*fae548d3Szrj 
710*fae548d3Szrj   /* Convert ELF type and flags to BFD flags.  */
711*fae548d3Szrj   flags = (SEC_RELOC
712*fae548d3Szrj 	   | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
713*fae548d3Szrj 	   | ((attr & SHF_ALLOC) ? SEC_ALLOC : 0)
714*fae548d3Szrj 	   | (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
715*fae548d3Szrj 	   | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)
716*fae548d3Szrj 	   | ((attr & SHF_MERGE) ? SEC_MERGE : 0)
717*fae548d3Szrj 	   | ((attr & SHF_STRINGS) ? SEC_STRINGS : 0)
718*fae548d3Szrj 	   | ((attr & SHF_EXCLUDE) ? SEC_EXCLUDE: 0)
719*fae548d3Szrj 	   | ((attr & SHF_TLS) ? SEC_THREAD_LOCAL : 0));
720*fae548d3Szrj #ifdef md_elf_section_flags
721*fae548d3Szrj   flags = md_elf_section_flags (flags, attr, type);
722*fae548d3Szrj #endif
723*fae548d3Szrj 
724*fae548d3Szrj   if (linkonce)
725*fae548d3Szrj     flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
726*fae548d3Szrj 
727*fae548d3Szrj   if (old_sec == NULL)
728*fae548d3Szrj     {
729*fae548d3Szrj       symbolS *secsym;
730*fae548d3Szrj 
731*fae548d3Szrj       if (type == SHT_NULL)
732*fae548d3Szrj 	type = bfd_elf_get_default_section_type (flags);
733*fae548d3Szrj       elf_section_type (sec) = type;
734*fae548d3Szrj       elf_section_flags (sec) = attr;
735*fae548d3Szrj       elf_section_data (sec)->this_hdr.sh_info = info;
736*fae548d3Szrj 
737*fae548d3Szrj       /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
738*fae548d3Szrj       if (type == SHT_NOBITS)
739*fae548d3Szrj 	seg_info (sec)->bss = 1;
740*fae548d3Szrj 
741*fae548d3Szrj       bfd_set_section_flags (sec, flags);
742*fae548d3Szrj       if (flags & SEC_MERGE)
743*fae548d3Szrj 	sec->entsize = entsize;
744*fae548d3Szrj       elf_group_name (sec) = group_name;
745*fae548d3Szrj 
746*fae548d3Szrj       /* Add a symbol for this section to the symbol table.  */
747*fae548d3Szrj       secsym = symbol_find (name);
748*fae548d3Szrj       if (secsym != NULL)
749*fae548d3Szrj 	symbol_set_bfdsym (secsym, sec->symbol);
750*fae548d3Szrj       else
751*fae548d3Szrj 	symbol_table_insert (section_symbol (sec));
752*fae548d3Szrj     }
753*fae548d3Szrj   else
754*fae548d3Szrj     {
755*fae548d3Szrj       if (type != SHT_NULL
756*fae548d3Szrj 	  && (unsigned) type != elf_section_type (old_sec))
757*fae548d3Szrj 	as_warn (_("ignoring changed section type for %s"), name);
758*fae548d3Szrj 
759*fae548d3Szrj       if (attr != 0)
760*fae548d3Szrj 	{
761*fae548d3Szrj 	  /* If section attributes are specified the second time we see a
762*fae548d3Szrj 	     particular section, then check that they are the same as we
763*fae548d3Szrj 	     saw the first time.  */
764*fae548d3Szrj 	  if (((old_sec->flags ^ flags)
765*fae548d3Szrj 	       & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
766*fae548d3Szrj 		  | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS
767*fae548d3Szrj 		  | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
768*fae548d3Szrj 		  | SEC_THREAD_LOCAL)))
769*fae548d3Szrj 	    as_warn (_("ignoring changed section attributes for %s"), name);
770*fae548d3Szrj 	  else
771*fae548d3Szrj 	    /* FIXME: Maybe we should consider removing a previously set
772*fae548d3Szrj 	       processor or application specific attribute as suspicious ?  */
773*fae548d3Szrj 	    elf_section_flags (sec) = attr;
774*fae548d3Szrj 
775*fae548d3Szrj 	  if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
776*fae548d3Szrj 	    as_warn (_("ignoring changed section entity size for %s"), name);
777*fae548d3Szrj 	}
778*fae548d3Szrj     }
779*fae548d3Szrj 
780*fae548d3Szrj #ifdef md_elf_section_change_hook
781*fae548d3Szrj   md_elf_section_change_hook ();
782*fae548d3Szrj #endif
783*fae548d3Szrj }
784*fae548d3Szrj 
785*fae548d3Szrj static bfd_vma
obj_elf_parse_section_letters(char * str,size_t len,bfd_boolean * is_clone,bfd_vma * gnu_attr)786*fae548d3Szrj obj_elf_parse_section_letters (char *str, size_t len,
787*fae548d3Szrj 			       bfd_boolean *is_clone, bfd_vma *gnu_attr)
788*fae548d3Szrj {
789*fae548d3Szrj   bfd_vma attr = 0;
790*fae548d3Szrj   *is_clone = FALSE;
791*fae548d3Szrj 
792*fae548d3Szrj   while (len > 0)
793*fae548d3Szrj     {
794*fae548d3Szrj       switch (*str)
795*fae548d3Szrj 	{
796*fae548d3Szrj 	case 'a':
797*fae548d3Szrj 	  attr |= SHF_ALLOC;
798*fae548d3Szrj 	  break;
799*fae548d3Szrj 	case 'e':
800*fae548d3Szrj 	  attr |= SHF_EXCLUDE;
801*fae548d3Szrj 	  break;
802*fae548d3Szrj 	case 'w':
803*fae548d3Szrj 	  attr |= SHF_WRITE;
804*fae548d3Szrj 	  break;
805*fae548d3Szrj 	case 'x':
806*fae548d3Szrj 	  attr |= SHF_EXECINSTR;
807*fae548d3Szrj 	  break;
808*fae548d3Szrj 	case 'M':
809*fae548d3Szrj 	  attr |= SHF_MERGE;
810*fae548d3Szrj 	  break;
811*fae548d3Szrj 	case 'S':
812*fae548d3Szrj 	  attr |= SHF_STRINGS;
813*fae548d3Szrj 	  break;
814*fae548d3Szrj 	case 'G':
815*fae548d3Szrj 	  attr |= SHF_GROUP;
816*fae548d3Szrj 	  break;
817*fae548d3Szrj 	case 'T':
818*fae548d3Szrj 	  attr |= SHF_TLS;
819*fae548d3Szrj 	  break;
820*fae548d3Szrj 	case 'd':
821*fae548d3Szrj 	  *gnu_attr |= SHF_GNU_MBIND;
822*fae548d3Szrj 	  break;
823*fae548d3Szrj 	case '?':
824*fae548d3Szrj 	  *is_clone = TRUE;
825*fae548d3Szrj 	  break;
826*fae548d3Szrj 	/* Compatibility.  */
827*fae548d3Szrj 	case 'm':
828*fae548d3Szrj 	  if (*(str - 1) == 'a')
829*fae548d3Szrj 	    {
830*fae548d3Szrj 	      attr |= SHF_MERGE;
831*fae548d3Szrj 	      if (len > 1 && str[1] == 's')
832*fae548d3Szrj 		{
833*fae548d3Szrj 		  attr |= SHF_STRINGS;
834*fae548d3Szrj 		  str++, len--;
835*fae548d3Szrj 		}
836*fae548d3Szrj 	      break;
837*fae548d3Szrj 	    }
838*fae548d3Szrj 	  /* Fall through.  */
839*fae548d3Szrj 	default:
840*fae548d3Szrj 	  {
841*fae548d3Szrj 	    const char *bad_msg = _("unrecognized .section attribute:"
842*fae548d3Szrj 				    " want a,e,w,x,M,S,G,T or number");
843*fae548d3Szrj #ifdef md_elf_section_letter
844*fae548d3Szrj 	    bfd_vma md_attr = md_elf_section_letter (*str, &bad_msg);
845*fae548d3Szrj 	    if (md_attr != (bfd_vma) -1)
846*fae548d3Szrj 	      attr |= md_attr;
847*fae548d3Szrj 	    else
848*fae548d3Szrj #endif
849*fae548d3Szrj 	      if (ISDIGIT (*str))
850*fae548d3Szrj 		{
851*fae548d3Szrj 		  char * end;
852*fae548d3Szrj 
853*fae548d3Szrj 		  attr |= strtoul (str, & end, 0);
854*fae548d3Szrj 		  /* Update str and len, allowing for the fact that
855*fae548d3Szrj 		     we will execute str++ and len-- below.  */
856*fae548d3Szrj 		  end --;
857*fae548d3Szrj 		  len -= (end - str);
858*fae548d3Szrj 		  str = end;
859*fae548d3Szrj 		}
860*fae548d3Szrj 	      else
861*fae548d3Szrj 		as_fatal ("%s", bad_msg);
862*fae548d3Szrj 	  }
863*fae548d3Szrj 	  break;
864*fae548d3Szrj 	}
865*fae548d3Szrj       str++, len--;
866*fae548d3Szrj     }
867*fae548d3Szrj 
868*fae548d3Szrj   return attr;
869*fae548d3Szrj }
870*fae548d3Szrj 
871*fae548d3Szrj static int
obj_elf_section_type(char * str,size_t len,bfd_boolean warn)872*fae548d3Szrj obj_elf_section_type (char *str, size_t len, bfd_boolean warn)
873*fae548d3Szrj {
874*fae548d3Szrj   if (len == 8 && strncmp (str, "progbits", 8) == 0)
875*fae548d3Szrj     return SHT_PROGBITS;
876*fae548d3Szrj   if (len == 6 && strncmp (str, "nobits", 6) == 0)
877*fae548d3Szrj     return SHT_NOBITS;
878*fae548d3Szrj   if (len == 4 && strncmp (str, "note", 4) == 0)
879*fae548d3Szrj     return SHT_NOTE;
880*fae548d3Szrj   if (len == 10 && strncmp (str, "init_array", 10) == 0)
881*fae548d3Szrj     return SHT_INIT_ARRAY;
882*fae548d3Szrj   if (len == 10 && strncmp (str, "fini_array", 10) == 0)
883*fae548d3Szrj     return SHT_FINI_ARRAY;
884*fae548d3Szrj   if (len == 13 && strncmp (str, "preinit_array", 13) == 0)
885*fae548d3Szrj     return SHT_PREINIT_ARRAY;
886*fae548d3Szrj 
887*fae548d3Szrj #ifdef md_elf_section_type
888*fae548d3Szrj   {
889*fae548d3Szrj     int md_type = md_elf_section_type (str, len);
890*fae548d3Szrj     if (md_type >= 0)
891*fae548d3Szrj       return md_type;
892*fae548d3Szrj   }
893*fae548d3Szrj #endif
894*fae548d3Szrj 
895*fae548d3Szrj   if (ISDIGIT (*str))
896*fae548d3Szrj     {
897*fae548d3Szrj       char * end;
898*fae548d3Szrj       int type = strtoul (str, & end, 0);
899*fae548d3Szrj 
900*fae548d3Szrj       if (warn && (size_t) (end - str) != len)
901*fae548d3Szrj 	as_warn (_("extraneous characters at end of numeric section type"));
902*fae548d3Szrj 
903*fae548d3Szrj       return type;
904*fae548d3Szrj     }
905*fae548d3Szrj 
906*fae548d3Szrj   if (warn)
907*fae548d3Szrj     as_warn (_("unrecognized section type"));
908*fae548d3Szrj   return 0;
909*fae548d3Szrj }
910*fae548d3Szrj 
911*fae548d3Szrj static bfd_vma
obj_elf_section_word(char * str,size_t len,int * type)912*fae548d3Szrj obj_elf_section_word (char *str, size_t len, int *type)
913*fae548d3Szrj {
914*fae548d3Szrj   int ret;
915*fae548d3Szrj 
916*fae548d3Szrj   if (len == 5 && strncmp (str, "write", 5) == 0)
917*fae548d3Szrj     return SHF_WRITE;
918*fae548d3Szrj   if (len == 5 && strncmp (str, "alloc", 5) == 0)
919*fae548d3Szrj     return SHF_ALLOC;
920*fae548d3Szrj   if (len == 9 && strncmp (str, "execinstr", 9) == 0)
921*fae548d3Szrj     return SHF_EXECINSTR;
922*fae548d3Szrj   if (len == 7 && strncmp (str, "exclude", 7) == 0)
923*fae548d3Szrj     return SHF_EXCLUDE;
924*fae548d3Szrj   if (len == 3 && strncmp (str, "tls", 3) == 0)
925*fae548d3Szrj     return SHF_TLS;
926*fae548d3Szrj 
927*fae548d3Szrj #ifdef md_elf_section_word
928*fae548d3Szrj   {
929*fae548d3Szrj     bfd_vma md_attr = md_elf_section_word (str, len);
930*fae548d3Szrj     if (md_attr > 0)
931*fae548d3Szrj       return md_attr;
932*fae548d3Szrj   }
933*fae548d3Szrj #endif
934*fae548d3Szrj 
935*fae548d3Szrj   ret = obj_elf_section_type (str, len, FALSE);
936*fae548d3Szrj   if (ret != 0)
937*fae548d3Szrj     *type = ret;
938*fae548d3Szrj   else
939*fae548d3Szrj     as_warn (_("unrecognized section attribute"));
940*fae548d3Szrj 
941*fae548d3Szrj   return 0;
942*fae548d3Szrj }
943*fae548d3Szrj 
944*fae548d3Szrj /* Get name of section.  */
945*fae548d3Szrj const char *
obj_elf_section_name(void)946*fae548d3Szrj obj_elf_section_name (void)
947*fae548d3Szrj {
948*fae548d3Szrj   char *name;
949*fae548d3Szrj 
950*fae548d3Szrj   SKIP_WHITESPACE ();
951*fae548d3Szrj   if (*input_line_pointer == '"')
952*fae548d3Szrj     {
953*fae548d3Szrj       int dummy;
954*fae548d3Szrj 
955*fae548d3Szrj       name = demand_copy_C_string (&dummy);
956*fae548d3Szrj       if (name == NULL)
957*fae548d3Szrj 	{
958*fae548d3Szrj 	  ignore_rest_of_line ();
959*fae548d3Szrj 	  return NULL;
960*fae548d3Szrj 	}
961*fae548d3Szrj     }
962*fae548d3Szrj   else
963*fae548d3Szrj     {
964*fae548d3Szrj       char *end = input_line_pointer;
965*fae548d3Szrj 
966*fae548d3Szrj       while (0 == strchr ("\n\t,; ", *end))
967*fae548d3Szrj 	end++;
968*fae548d3Szrj       if (end == input_line_pointer)
969*fae548d3Szrj 	{
970*fae548d3Szrj 	  as_bad (_("missing name"));
971*fae548d3Szrj 	  ignore_rest_of_line ();
972*fae548d3Szrj 	  return NULL;
973*fae548d3Szrj 	}
974*fae548d3Szrj 
975*fae548d3Szrj       name = xmemdup0 (input_line_pointer, end - input_line_pointer);
976*fae548d3Szrj 
977*fae548d3Szrj       while (flag_sectname_subst)
978*fae548d3Szrj         {
979*fae548d3Szrj 	  char *subst = strchr (name, '%');
980*fae548d3Szrj 	  if (subst && subst[1] == 'S')
981*fae548d3Szrj 	    {
982*fae548d3Szrj 	      int oldlen = strlen (name);
983*fae548d3Szrj 	      int substlen = strlen (now_seg->name);
984*fae548d3Szrj 	      int newlen = oldlen - 2 + substlen;
985*fae548d3Szrj 	      char *newname = XNEWVEC (char, newlen + 1);
986*fae548d3Szrj 	      int headlen = subst - name;
987*fae548d3Szrj 	      memcpy (newname, name, headlen);
988*fae548d3Szrj 	      strcpy (newname + headlen, now_seg->name);
989*fae548d3Szrj 	      strcat (newname + headlen, subst + 2);
990*fae548d3Szrj 	      xfree (name);
991*fae548d3Szrj 	      name = newname;
992*fae548d3Szrj 	    }
993*fae548d3Szrj 	  else
994*fae548d3Szrj 	    break;
995*fae548d3Szrj 	}
996*fae548d3Szrj 
997*fae548d3Szrj #ifdef tc_canonicalize_section_name
998*fae548d3Szrj       name = tc_canonicalize_section_name (name);
999*fae548d3Szrj #endif
1000*fae548d3Szrj       input_line_pointer = end;
1001*fae548d3Szrj     }
1002*fae548d3Szrj   SKIP_WHITESPACE ();
1003*fae548d3Szrj   return name;
1004*fae548d3Szrj }
1005*fae548d3Szrj 
1006*fae548d3Szrj void
obj_elf_section(int push)1007*fae548d3Szrj obj_elf_section (int push)
1008*fae548d3Szrj {
1009*fae548d3Szrj   const char *name, *group_name;
1010*fae548d3Szrj   char *beg;
1011*fae548d3Szrj   int type, dummy;
1012*fae548d3Szrj   bfd_vma attr;
1013*fae548d3Szrj   bfd_vma gnu_attr;
1014*fae548d3Szrj   int entsize;
1015*fae548d3Szrj   int linkonce;
1016*fae548d3Szrj   subsegT new_subsection = -1;
1017*fae548d3Szrj   unsigned int info = 0;
1018*fae548d3Szrj 
1019*fae548d3Szrj   if (flag_mri)
1020*fae548d3Szrj     {
1021*fae548d3Szrj       char mri_type;
1022*fae548d3Szrj 
1023*fae548d3Szrj #ifdef md_flush_pending_output
1024*fae548d3Szrj       md_flush_pending_output ();
1025*fae548d3Szrj #endif
1026*fae548d3Szrj 
1027*fae548d3Szrj       previous_section = now_seg;
1028*fae548d3Szrj       previous_subsection = now_subseg;
1029*fae548d3Szrj 
1030*fae548d3Szrj       s_mri_sect (&mri_type);
1031*fae548d3Szrj 
1032*fae548d3Szrj #ifdef md_elf_section_change_hook
1033*fae548d3Szrj       md_elf_section_change_hook ();
1034*fae548d3Szrj #endif
1035*fae548d3Szrj 
1036*fae548d3Szrj       return;
1037*fae548d3Szrj     }
1038*fae548d3Szrj 
1039*fae548d3Szrj   name = obj_elf_section_name ();
1040*fae548d3Szrj   if (name == NULL)
1041*fae548d3Szrj     return;
1042*fae548d3Szrj 
1043*fae548d3Szrj   symbolS * sym;
1044*fae548d3Szrj   if ((sym = symbol_find (name)) != NULL
1045*fae548d3Szrj       && ! symbol_section_p (sym)
1046*fae548d3Szrj       && S_IS_DEFINED (sym)
1047*fae548d3Szrj       && ! S_IS_VOLATILE (sym)
1048*fae548d3Szrj       && ! S_CAN_BE_REDEFINED (sym))
1049*fae548d3Szrj     {
1050*fae548d3Szrj       as_bad (_("section name '%s' already defined as another symbol"), name);
1051*fae548d3Szrj       ignore_rest_of_line ();
1052*fae548d3Szrj       return;
1053*fae548d3Szrj     }
1054*fae548d3Szrj   type = SHT_NULL;
1055*fae548d3Szrj   attr = 0;
1056*fae548d3Szrj   gnu_attr = 0;
1057*fae548d3Szrj   group_name = NULL;
1058*fae548d3Szrj   entsize = 0;
1059*fae548d3Szrj   linkonce = 0;
1060*fae548d3Szrj 
1061*fae548d3Szrj   if (*input_line_pointer == ',')
1062*fae548d3Szrj     {
1063*fae548d3Szrj       /* Skip the comma.  */
1064*fae548d3Szrj       ++input_line_pointer;
1065*fae548d3Szrj       SKIP_WHITESPACE ();
1066*fae548d3Szrj 
1067*fae548d3Szrj       if (push && ISDIGIT (*input_line_pointer))
1068*fae548d3Szrj 	{
1069*fae548d3Szrj 	  /* .pushsection has an optional subsection.  */
1070*fae548d3Szrj 	  new_subsection = (subsegT) get_absolute_expression ();
1071*fae548d3Szrj 
1072*fae548d3Szrj 	  SKIP_WHITESPACE ();
1073*fae548d3Szrj 
1074*fae548d3Szrj 	  /* Stop if we don't see a comma.  */
1075*fae548d3Szrj 	  if (*input_line_pointer != ',')
1076*fae548d3Szrj 	    goto done;
1077*fae548d3Szrj 
1078*fae548d3Szrj 	  /* Skip the comma.  */
1079*fae548d3Szrj 	  ++input_line_pointer;
1080*fae548d3Szrj 	  SKIP_WHITESPACE ();
1081*fae548d3Szrj 	}
1082*fae548d3Szrj 
1083*fae548d3Szrj       if (*input_line_pointer == '"')
1084*fae548d3Szrj 	{
1085*fae548d3Szrj 	  bfd_boolean is_clone;
1086*fae548d3Szrj 
1087*fae548d3Szrj 	  beg = demand_copy_C_string (&dummy);
1088*fae548d3Szrj 	  if (beg == NULL)
1089*fae548d3Szrj 	    {
1090*fae548d3Szrj 	      ignore_rest_of_line ();
1091*fae548d3Szrj 	      return;
1092*fae548d3Szrj 	    }
1093*fae548d3Szrj 	  attr |= obj_elf_parse_section_letters (beg, strlen (beg),
1094*fae548d3Szrj 						 &is_clone, &gnu_attr);
1095*fae548d3Szrj 
1096*fae548d3Szrj 	  SKIP_WHITESPACE ();
1097*fae548d3Szrj 	  if (*input_line_pointer == ',')
1098*fae548d3Szrj 	    {
1099*fae548d3Szrj 	      char c;
1100*fae548d3Szrj 	      char *save = input_line_pointer;
1101*fae548d3Szrj 
1102*fae548d3Szrj 	      ++input_line_pointer;
1103*fae548d3Szrj 	      SKIP_WHITESPACE ();
1104*fae548d3Szrj 	      c = *input_line_pointer;
1105*fae548d3Szrj 	      if (c == '"')
1106*fae548d3Szrj 		{
1107*fae548d3Szrj 		  beg = demand_copy_C_string (&dummy);
1108*fae548d3Szrj 		  if (beg == NULL)
1109*fae548d3Szrj 		    {
1110*fae548d3Szrj 		      ignore_rest_of_line ();
1111*fae548d3Szrj 		      return;
1112*fae548d3Szrj 		    }
1113*fae548d3Szrj 		  type = obj_elf_section_type (beg, strlen (beg), TRUE);
1114*fae548d3Szrj 		}
1115*fae548d3Szrj 	      else if (c == '@' || c == '%')
1116*fae548d3Szrj 		{
1117*fae548d3Szrj 		  ++input_line_pointer;
1118*fae548d3Szrj 
1119*fae548d3Szrj 		  if (ISDIGIT (* input_line_pointer))
1120*fae548d3Szrj 		    type = strtoul (input_line_pointer, &input_line_pointer, 0);
1121*fae548d3Szrj 		  else
1122*fae548d3Szrj 		    {
1123*fae548d3Szrj 		      c = get_symbol_name (& beg);
1124*fae548d3Szrj 		      (void) restore_line_pointer (c);
1125*fae548d3Szrj 		      type = obj_elf_section_type (beg,
1126*fae548d3Szrj 						   input_line_pointer - beg,
1127*fae548d3Szrj 						   TRUE);
1128*fae548d3Szrj 		    }
1129*fae548d3Szrj 		}
1130*fae548d3Szrj 	      else
1131*fae548d3Szrj 		input_line_pointer = save;
1132*fae548d3Szrj 	    }
1133*fae548d3Szrj 
1134*fae548d3Szrj 	  SKIP_WHITESPACE ();
1135*fae548d3Szrj 	  if ((attr & SHF_MERGE) != 0 && *input_line_pointer == ',')
1136*fae548d3Szrj 	    {
1137*fae548d3Szrj 	      ++input_line_pointer;
1138*fae548d3Szrj 	      SKIP_WHITESPACE ();
1139*fae548d3Szrj 	      entsize = get_absolute_expression ();
1140*fae548d3Szrj 	      SKIP_WHITESPACE ();
1141*fae548d3Szrj 	      if (entsize < 0)
1142*fae548d3Szrj 		{
1143*fae548d3Szrj 		  as_warn (_("invalid merge entity size"));
1144*fae548d3Szrj 		  attr &= ~SHF_MERGE;
1145*fae548d3Szrj 		  entsize = 0;
1146*fae548d3Szrj 		}
1147*fae548d3Szrj 	    }
1148*fae548d3Szrj 	  else if ((attr & SHF_MERGE) != 0)
1149*fae548d3Szrj 	    {
1150*fae548d3Szrj 	      as_warn (_("entity size for SHF_MERGE not specified"));
1151*fae548d3Szrj 	      attr &= ~SHF_MERGE;
1152*fae548d3Szrj 	    }
1153*fae548d3Szrj 
1154*fae548d3Szrj 	  if ((attr & SHF_GROUP) != 0 && is_clone)
1155*fae548d3Szrj 	    {
1156*fae548d3Szrj 	      as_warn (_("? section flag ignored with G present"));
1157*fae548d3Szrj 	      is_clone = FALSE;
1158*fae548d3Szrj 	    }
1159*fae548d3Szrj 	  if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
1160*fae548d3Szrj 	    {
1161*fae548d3Szrj 	      ++input_line_pointer;
1162*fae548d3Szrj 	      group_name = obj_elf_section_name ();
1163*fae548d3Szrj 	      if (group_name == NULL)
1164*fae548d3Szrj 		attr &= ~SHF_GROUP;
1165*fae548d3Szrj 	      else if (*input_line_pointer == ',')
1166*fae548d3Szrj 		{
1167*fae548d3Szrj 		  ++input_line_pointer;
1168*fae548d3Szrj 		  SKIP_WHITESPACE ();
1169*fae548d3Szrj 		  if (strncmp (input_line_pointer, "comdat", 6) == 0)
1170*fae548d3Szrj 		    {
1171*fae548d3Szrj 		      input_line_pointer += 6;
1172*fae548d3Szrj 		      linkonce = 1;
1173*fae548d3Szrj 		    }
1174*fae548d3Szrj 		}
1175*fae548d3Szrj 	      else if (strncmp (name, ".gnu.linkonce", 13) == 0)
1176*fae548d3Szrj 		linkonce = 1;
1177*fae548d3Szrj 	    }
1178*fae548d3Szrj 	  else if ((attr & SHF_GROUP) != 0)
1179*fae548d3Szrj 	    {
1180*fae548d3Szrj 	      as_warn (_("group name for SHF_GROUP not specified"));
1181*fae548d3Szrj 	      attr &= ~SHF_GROUP;
1182*fae548d3Szrj 	    }
1183*fae548d3Szrj 
1184*fae548d3Szrj 	  if (is_clone)
1185*fae548d3Szrj 	    {
1186*fae548d3Szrj 	      const char *now_group = elf_group_name (now_seg);
1187*fae548d3Szrj 	      if (now_group != NULL)
1188*fae548d3Szrj 		{
1189*fae548d3Szrj 		  group_name = xstrdup (now_group);
1190*fae548d3Szrj 		  linkonce = (now_seg->flags & SEC_LINK_ONCE) != 0;
1191*fae548d3Szrj 		}
1192*fae548d3Szrj 	    }
1193*fae548d3Szrj 
1194*fae548d3Szrj 	  if ((gnu_attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',')
1195*fae548d3Szrj 	    {
1196*fae548d3Szrj 	      ++input_line_pointer;
1197*fae548d3Szrj 	      SKIP_WHITESPACE ();
1198*fae548d3Szrj 	      if (ISDIGIT (* input_line_pointer))
1199*fae548d3Szrj 		{
1200*fae548d3Szrj 		  char *t = input_line_pointer;
1201*fae548d3Szrj 		  info = strtoul (input_line_pointer,
1202*fae548d3Szrj 				  &input_line_pointer, 0);
1203*fae548d3Szrj 		  if (info == (unsigned int) -1)
1204*fae548d3Szrj 		    {
1205*fae548d3Szrj 		      as_warn (_("unsupported mbind section info: %s"), t);
1206*fae548d3Szrj 		      info = 0;
1207*fae548d3Szrj 		    }
1208*fae548d3Szrj 		}
1209*fae548d3Szrj 	    }
1210*fae548d3Szrj 	}
1211*fae548d3Szrj       else
1212*fae548d3Szrj 	{
1213*fae548d3Szrj 	  do
1214*fae548d3Szrj 	    {
1215*fae548d3Szrj 	      char c;
1216*fae548d3Szrj 
1217*fae548d3Szrj 	      SKIP_WHITESPACE ();
1218*fae548d3Szrj 	      if (*input_line_pointer != '#')
1219*fae548d3Szrj 		{
1220*fae548d3Szrj 		  as_bad (_("character following name is not '#'"));
1221*fae548d3Szrj 		  ignore_rest_of_line ();
1222*fae548d3Szrj 		  return;
1223*fae548d3Szrj 		}
1224*fae548d3Szrj 	      ++input_line_pointer;
1225*fae548d3Szrj 	      c = get_symbol_name (& beg);
1226*fae548d3Szrj 	      (void) restore_line_pointer (c);
1227*fae548d3Szrj 
1228*fae548d3Szrj 	      attr |= obj_elf_section_word (beg, input_line_pointer - beg,
1229*fae548d3Szrj 					    &type);
1230*fae548d3Szrj 
1231*fae548d3Szrj 	      SKIP_WHITESPACE ();
1232*fae548d3Szrj 	    }
1233*fae548d3Szrj 	  while (*input_line_pointer++ == ',');
1234*fae548d3Szrj 	  --input_line_pointer;
1235*fae548d3Szrj 	}
1236*fae548d3Szrj     }
1237*fae548d3Szrj 
1238*fae548d3Szrj done:
1239*fae548d3Szrj   demand_empty_rest_of_line ();
1240*fae548d3Szrj 
1241*fae548d3Szrj   obj_elf_change_section (name, type, info, attr, entsize, group_name,
1242*fae548d3Szrj 			  linkonce, push);
1243*fae548d3Szrj 
1244*fae548d3Szrj   if ((gnu_attr & SHF_GNU_MBIND) != 0)
1245*fae548d3Szrj     {
1246*fae548d3Szrj       struct elf_backend_data *bed;
1247*fae548d3Szrj 
1248*fae548d3Szrj       if ((attr & SHF_ALLOC) == 0)
1249*fae548d3Szrj 	as_bad (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name);
1250*fae548d3Szrj 
1251*fae548d3Szrj       bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
1252*fae548d3Szrj       if (bed->elf_osabi == ELFOSABI_NONE)
1253*fae548d3Szrj 	bed->elf_osabi = ELFOSABI_GNU;
1254*fae548d3Szrj       else if (bed->elf_osabi != ELFOSABI_GNU
1255*fae548d3Szrj 	       && bed->elf_osabi != ELFOSABI_FREEBSD)
1256*fae548d3Szrj 	as_bad (_("GNU_MBIND section is supported only by GNU "
1257*fae548d3Szrj 		  "and FreeBSD targets"));
1258*fae548d3Szrj       elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind;
1259*fae548d3Szrj     }
1260*fae548d3Szrj   elf_section_flags (now_seg) |= gnu_attr;
1261*fae548d3Szrj 
1262*fae548d3Szrj   if (push && new_subsection != -1)
1263*fae548d3Szrj     subseg_set (now_seg, new_subsection);
1264*fae548d3Szrj }
1265*fae548d3Szrj 
1266*fae548d3Szrj /* Change to the .data section.  */
1267*fae548d3Szrj 
1268*fae548d3Szrj void
obj_elf_data(int i)1269*fae548d3Szrj obj_elf_data (int i)
1270*fae548d3Szrj {
1271*fae548d3Szrj #ifdef md_flush_pending_output
1272*fae548d3Szrj   md_flush_pending_output ();
1273*fae548d3Szrj #endif
1274*fae548d3Szrj 
1275*fae548d3Szrj   previous_section = now_seg;
1276*fae548d3Szrj   previous_subsection = now_subseg;
1277*fae548d3Szrj   s_data (i);
1278*fae548d3Szrj 
1279*fae548d3Szrj #ifdef md_elf_section_change_hook
1280*fae548d3Szrj   md_elf_section_change_hook ();
1281*fae548d3Szrj #endif
1282*fae548d3Szrj }
1283*fae548d3Szrj 
1284*fae548d3Szrj /* Change to the .text section.  */
1285*fae548d3Szrj 
1286*fae548d3Szrj void
obj_elf_text(int i)1287*fae548d3Szrj obj_elf_text (int i)
1288*fae548d3Szrj {
1289*fae548d3Szrj #ifdef md_flush_pending_output
1290*fae548d3Szrj   md_flush_pending_output ();
1291*fae548d3Szrj #endif
1292*fae548d3Szrj 
1293*fae548d3Szrj   previous_section = now_seg;
1294*fae548d3Szrj   previous_subsection = now_subseg;
1295*fae548d3Szrj   s_text (i);
1296*fae548d3Szrj 
1297*fae548d3Szrj #ifdef md_elf_section_change_hook
1298*fae548d3Szrj   md_elf_section_change_hook ();
1299*fae548d3Szrj #endif
1300*fae548d3Szrj }
1301*fae548d3Szrj 
1302*fae548d3Szrj /* Change to the *ABS* section.  */
1303*fae548d3Szrj 
1304*fae548d3Szrj void
obj_elf_struct(int i)1305*fae548d3Szrj obj_elf_struct (int i)
1306*fae548d3Szrj {
1307*fae548d3Szrj #ifdef md_flush_pending_output
1308*fae548d3Szrj   md_flush_pending_output ();
1309*fae548d3Szrj #endif
1310*fae548d3Szrj 
1311*fae548d3Szrj   previous_section = now_seg;
1312*fae548d3Szrj   previous_subsection = now_subseg;
1313*fae548d3Szrj   s_struct (i);
1314*fae548d3Szrj 
1315*fae548d3Szrj #ifdef md_elf_section_change_hook
1316*fae548d3Szrj   md_elf_section_change_hook ();
1317*fae548d3Szrj #endif
1318*fae548d3Szrj }
1319*fae548d3Szrj 
1320*fae548d3Szrj static void
obj_elf_subsection(int ignore ATTRIBUTE_UNUSED)1321*fae548d3Szrj obj_elf_subsection (int ignore ATTRIBUTE_UNUSED)
1322*fae548d3Szrj {
1323*fae548d3Szrj   int temp;
1324*fae548d3Szrj 
1325*fae548d3Szrj #ifdef md_flush_pending_output
1326*fae548d3Szrj   md_flush_pending_output ();
1327*fae548d3Szrj #endif
1328*fae548d3Szrj 
1329*fae548d3Szrj   previous_section = now_seg;
1330*fae548d3Szrj   previous_subsection = now_subseg;
1331*fae548d3Szrj 
1332*fae548d3Szrj   temp = get_absolute_expression ();
1333*fae548d3Szrj   subseg_set (now_seg, (subsegT) temp);
1334*fae548d3Szrj   demand_empty_rest_of_line ();
1335*fae548d3Szrj 
1336*fae548d3Szrj #ifdef md_elf_section_change_hook
1337*fae548d3Szrj   md_elf_section_change_hook ();
1338*fae548d3Szrj #endif
1339*fae548d3Szrj }
1340*fae548d3Szrj 
1341*fae548d3Szrj /* This can be called from the processor backends if they change
1342*fae548d3Szrj    sections.  */
1343*fae548d3Szrj 
1344*fae548d3Szrj void
obj_elf_section_change_hook(void)1345*fae548d3Szrj obj_elf_section_change_hook (void)
1346*fae548d3Szrj {
1347*fae548d3Szrj   previous_section = now_seg;
1348*fae548d3Szrj   previous_subsection = now_subseg;
1349*fae548d3Szrj }
1350*fae548d3Szrj 
1351*fae548d3Szrj void
obj_elf_previous(int ignore ATTRIBUTE_UNUSED)1352*fae548d3Szrj obj_elf_previous (int ignore ATTRIBUTE_UNUSED)
1353*fae548d3Szrj {
1354*fae548d3Szrj   segT new_section;
1355*fae548d3Szrj   int new_subsection;
1356*fae548d3Szrj 
1357*fae548d3Szrj   if (previous_section == 0)
1358*fae548d3Szrj     {
1359*fae548d3Szrj       as_warn (_(".previous without corresponding .section; ignored"));
1360*fae548d3Szrj       return;
1361*fae548d3Szrj     }
1362*fae548d3Szrj 
1363*fae548d3Szrj #ifdef md_flush_pending_output
1364*fae548d3Szrj   md_flush_pending_output ();
1365*fae548d3Szrj #endif
1366*fae548d3Szrj 
1367*fae548d3Szrj   new_section = previous_section;
1368*fae548d3Szrj   new_subsection = previous_subsection;
1369*fae548d3Szrj   previous_section = now_seg;
1370*fae548d3Szrj   previous_subsection = now_subseg;
1371*fae548d3Szrj   subseg_set (new_section, new_subsection);
1372*fae548d3Szrj 
1373*fae548d3Szrj #ifdef md_elf_section_change_hook
1374*fae548d3Szrj   md_elf_section_change_hook ();
1375*fae548d3Szrj #endif
1376*fae548d3Szrj }
1377*fae548d3Szrj 
1378*fae548d3Szrj static void
obj_elf_popsection(int xxx ATTRIBUTE_UNUSED)1379*fae548d3Szrj obj_elf_popsection (int xxx ATTRIBUTE_UNUSED)
1380*fae548d3Szrj {
1381*fae548d3Szrj   struct section_stack *top = section_stack;
1382*fae548d3Szrj 
1383*fae548d3Szrj   if (top == NULL)
1384*fae548d3Szrj     {
1385*fae548d3Szrj       as_warn (_(".popsection without corresponding .pushsection; ignored"));
1386*fae548d3Szrj       return;
1387*fae548d3Szrj     }
1388*fae548d3Szrj 
1389*fae548d3Szrj #ifdef md_flush_pending_output
1390*fae548d3Szrj   md_flush_pending_output ();
1391*fae548d3Szrj #endif
1392*fae548d3Szrj 
1393*fae548d3Szrj   section_stack = top->next;
1394*fae548d3Szrj   previous_section = top->prev_seg;
1395*fae548d3Szrj   previous_subsection = top->prev_subseg;
1396*fae548d3Szrj   subseg_set (top->seg, top->subseg);
1397*fae548d3Szrj   free (top);
1398*fae548d3Szrj 
1399*fae548d3Szrj #ifdef md_elf_section_change_hook
1400*fae548d3Szrj   md_elf_section_change_hook ();
1401*fae548d3Szrj #endif
1402*fae548d3Szrj }
1403*fae548d3Szrj 
1404*fae548d3Szrj static void
obj_elf_line(int ignore ATTRIBUTE_UNUSED)1405*fae548d3Szrj obj_elf_line (int ignore ATTRIBUTE_UNUSED)
1406*fae548d3Szrj {
1407*fae548d3Szrj   /* Assume delimiter is part of expression.  BSD4.2 as fails with
1408*fae548d3Szrj      delightful bug, so we are not being incompatible here.  */
1409*fae548d3Szrj   new_logical_line (NULL, get_absolute_expression ());
1410*fae548d3Szrj   demand_empty_rest_of_line ();
1411*fae548d3Szrj }
1412*fae548d3Szrj 
1413*fae548d3Szrj /* This handles the .symver pseudo-op, which is used to specify a
1414*fae548d3Szrj    symbol version.  The syntax is ``.symver NAME,SYMVERNAME''.
1415*fae548d3Szrj    SYMVERNAME may contain ELF_VER_CHR ('@') characters.  This
1416*fae548d3Szrj    pseudo-op causes the assembler to emit a symbol named SYMVERNAME
1417*fae548d3Szrj    with the same value as the symbol NAME.  */
1418*fae548d3Szrj 
1419*fae548d3Szrj static void
obj_elf_symver(int ignore ATTRIBUTE_UNUSED)1420*fae548d3Szrj obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
1421*fae548d3Szrj {
1422*fae548d3Szrj   char *name;
1423*fae548d3Szrj   char c;
1424*fae548d3Szrj   char old_lexat;
1425*fae548d3Szrj   symbolS *sym;
1426*fae548d3Szrj 
1427*fae548d3Szrj   sym = get_sym_from_input_line_and_check ();
1428*fae548d3Szrj 
1429*fae548d3Szrj   if (*input_line_pointer != ',')
1430*fae548d3Szrj     {
1431*fae548d3Szrj       as_bad (_("expected comma after name in .symver"));
1432*fae548d3Szrj       ignore_rest_of_line ();
1433*fae548d3Szrj       return;
1434*fae548d3Szrj     }
1435*fae548d3Szrj 
1436*fae548d3Szrj   ++input_line_pointer;
1437*fae548d3Szrj   SKIP_WHITESPACE ();
1438*fae548d3Szrj 
1439*fae548d3Szrj   /* Temporarily include '@' in symbol names.  */
1440*fae548d3Szrj   old_lexat = lex_type[(unsigned char) '@'];
1441*fae548d3Szrj   lex_type[(unsigned char) '@'] |= LEX_NAME;
1442*fae548d3Szrj   c = get_symbol_name (& name);
1443*fae548d3Szrj   lex_type[(unsigned char) '@'] = old_lexat;
1444*fae548d3Szrj 
1445*fae548d3Szrj   if (S_IS_COMMON (sym))
1446*fae548d3Szrj     {
1447*fae548d3Szrj       as_bad (_("`%s' can't be versioned to common symbol '%s'"),
1448*fae548d3Szrj 	      name, S_GET_NAME (sym));
1449*fae548d3Szrj       ignore_rest_of_line ();
1450*fae548d3Szrj       return;
1451*fae548d3Szrj     }
1452*fae548d3Szrj 
1453*fae548d3Szrj   if (symbol_get_obj (sym)->versioned_name == NULL)
1454*fae548d3Szrj     {
1455*fae548d3Szrj       symbol_get_obj (sym)->versioned_name = xstrdup (name);
1456*fae548d3Szrj 
1457*fae548d3Szrj       (void) restore_line_pointer (c);
1458*fae548d3Szrj 
1459*fae548d3Szrj       if (strchr (symbol_get_obj (sym)->versioned_name,
1460*fae548d3Szrj 		  ELF_VER_CHR) == NULL)
1461*fae548d3Szrj 	{
1462*fae548d3Szrj 	  as_bad (_("missing version name in `%s' for symbol `%s'"),
1463*fae548d3Szrj 		  symbol_get_obj (sym)->versioned_name,
1464*fae548d3Szrj 		  S_GET_NAME (sym));
1465*fae548d3Szrj 	  ignore_rest_of_line ();
1466*fae548d3Szrj 	  return;
1467*fae548d3Szrj 	}
1468*fae548d3Szrj     }
1469*fae548d3Szrj   else
1470*fae548d3Szrj     {
1471*fae548d3Szrj       if (strcmp (symbol_get_obj (sym)->versioned_name, name))
1472*fae548d3Szrj 	{
1473*fae548d3Szrj 	  as_bad (_("multiple versions [`%s'|`%s'] for symbol `%s'"),
1474*fae548d3Szrj 		  name, symbol_get_obj (sym)->versioned_name,
1475*fae548d3Szrj 		  S_GET_NAME (sym));
1476*fae548d3Szrj 	  ignore_rest_of_line ();
1477*fae548d3Szrj 	  return;
1478*fae548d3Szrj 	}
1479*fae548d3Szrj 
1480*fae548d3Szrj       (void) restore_line_pointer (c);
1481*fae548d3Szrj     }
1482*fae548d3Szrj 
1483*fae548d3Szrj   demand_empty_rest_of_line ();
1484*fae548d3Szrj }
1485*fae548d3Szrj 
1486*fae548d3Szrj /* This handles the .vtable_inherit pseudo-op, which is used to indicate
1487*fae548d3Szrj    to the linker the hierarchy in which a particular table resides.  The
1488*fae548d3Szrj    syntax is ".vtable_inherit CHILDNAME, PARENTNAME".  */
1489*fae548d3Szrj 
1490*fae548d3Szrj struct fix *
obj_elf_get_vtable_inherit(void)1491*fae548d3Szrj obj_elf_get_vtable_inherit (void)
1492*fae548d3Szrj {
1493*fae548d3Szrj   char *cname, *pname;
1494*fae548d3Szrj   symbolS *csym, *psym;
1495*fae548d3Szrj   char c, bad = 0;
1496*fae548d3Szrj 
1497*fae548d3Szrj   if (*input_line_pointer == '#')
1498*fae548d3Szrj     ++input_line_pointer;
1499*fae548d3Szrj 
1500*fae548d3Szrj   c = get_symbol_name (& cname);
1501*fae548d3Szrj   csym = symbol_find (cname);
1502*fae548d3Szrj 
1503*fae548d3Szrj   /* GCFIXME: should check that we don't have two .vtable_inherits for
1504*fae548d3Szrj      the same child symbol.  Also, we can currently only do this if the
1505*fae548d3Szrj      child symbol is already exists and is placed in a fragment.  */
1506*fae548d3Szrj 
1507*fae548d3Szrj   if (csym == NULL || symbol_get_frag (csym) == NULL)
1508*fae548d3Szrj     {
1509*fae548d3Szrj       as_bad (_("expected `%s' to have already been set for .vtable_inherit"),
1510*fae548d3Szrj 	      cname);
1511*fae548d3Szrj       bad = 1;
1512*fae548d3Szrj     }
1513*fae548d3Szrj 
1514*fae548d3Szrj   *input_line_pointer = c;
1515*fae548d3Szrj 
1516*fae548d3Szrj   SKIP_WHITESPACE_AFTER_NAME ();
1517*fae548d3Szrj   if (*input_line_pointer != ',')
1518*fae548d3Szrj     {
1519*fae548d3Szrj       as_bad (_("expected comma after name in .vtable_inherit"));
1520*fae548d3Szrj       ignore_rest_of_line ();
1521*fae548d3Szrj       return NULL;
1522*fae548d3Szrj     }
1523*fae548d3Szrj 
1524*fae548d3Szrj   ++input_line_pointer;
1525*fae548d3Szrj   SKIP_WHITESPACE ();
1526*fae548d3Szrj 
1527*fae548d3Szrj   if (*input_line_pointer == '#')
1528*fae548d3Szrj     ++input_line_pointer;
1529*fae548d3Szrj 
1530*fae548d3Szrj   if (input_line_pointer[0] == '0'
1531*fae548d3Szrj       && (input_line_pointer[1] == '\0'
1532*fae548d3Szrj 	  || ISSPACE (input_line_pointer[1])))
1533*fae548d3Szrj     {
1534*fae548d3Szrj       psym = section_symbol (absolute_section);
1535*fae548d3Szrj       ++input_line_pointer;
1536*fae548d3Szrj     }
1537*fae548d3Szrj   else
1538*fae548d3Szrj     {
1539*fae548d3Szrj       c = get_symbol_name (& pname);
1540*fae548d3Szrj       psym = symbol_find_or_make (pname);
1541*fae548d3Szrj       restore_line_pointer (c);
1542*fae548d3Szrj     }
1543*fae548d3Szrj 
1544*fae548d3Szrj   demand_empty_rest_of_line ();
1545*fae548d3Szrj 
1546*fae548d3Szrj   if (bad)
1547*fae548d3Szrj     return NULL;
1548*fae548d3Szrj 
1549*fae548d3Szrj   gas_assert (symbol_get_value_expression (csym)->X_op == O_constant);
1550*fae548d3Szrj   return fix_new (symbol_get_frag (csym),
1551*fae548d3Szrj 		  symbol_get_value_expression (csym)->X_add_number,
1552*fae548d3Szrj 		  0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
1553*fae548d3Szrj }
1554*fae548d3Szrj 
1555*fae548d3Szrj /* This is a version of obj_elf_get_vtable_inherit() that is
1556*fae548d3Szrj    suitable for use in struct _pseudo_type tables.  */
1557*fae548d3Szrj 
1558*fae548d3Szrj void
obj_elf_vtable_inherit(int ignore ATTRIBUTE_UNUSED)1559*fae548d3Szrj obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
1560*fae548d3Szrj {
1561*fae548d3Szrj   (void) obj_elf_get_vtable_inherit ();
1562*fae548d3Szrj }
1563*fae548d3Szrj 
1564*fae548d3Szrj /* This handles the .vtable_entry pseudo-op, which is used to indicate
1565*fae548d3Szrj    to the linker that a vtable slot was used.  The syntax is
1566*fae548d3Szrj    ".vtable_entry tablename, offset".  */
1567*fae548d3Szrj 
1568*fae548d3Szrj struct fix *
obj_elf_get_vtable_entry(void)1569*fae548d3Szrj obj_elf_get_vtable_entry (void)
1570*fae548d3Szrj {
1571*fae548d3Szrj   symbolS *sym;
1572*fae548d3Szrj   offsetT offset;
1573*fae548d3Szrj 
1574*fae548d3Szrj   if (*input_line_pointer == '#')
1575*fae548d3Szrj     ++input_line_pointer;
1576*fae548d3Szrj 
1577*fae548d3Szrj   sym = get_sym_from_input_line_and_check ();
1578*fae548d3Szrj   if (*input_line_pointer != ',')
1579*fae548d3Szrj     {
1580*fae548d3Szrj       as_bad (_("expected comma after name in .vtable_entry"));
1581*fae548d3Szrj       ignore_rest_of_line ();
1582*fae548d3Szrj       return NULL;
1583*fae548d3Szrj     }
1584*fae548d3Szrj 
1585*fae548d3Szrj   ++input_line_pointer;
1586*fae548d3Szrj   if (*input_line_pointer == '#')
1587*fae548d3Szrj     ++input_line_pointer;
1588*fae548d3Szrj 
1589*fae548d3Szrj   offset = get_absolute_expression ();
1590*fae548d3Szrj 
1591*fae548d3Szrj   demand_empty_rest_of_line ();
1592*fae548d3Szrj 
1593*fae548d3Szrj   return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
1594*fae548d3Szrj 		  BFD_RELOC_VTABLE_ENTRY);
1595*fae548d3Szrj }
1596*fae548d3Szrj 
1597*fae548d3Szrj /* This is a version of obj_elf_get_vtable_entry() that is
1598*fae548d3Szrj    suitable for use in struct _pseudo_type tables.  */
1599*fae548d3Szrj 
1600*fae548d3Szrj void
obj_elf_vtable_entry(int ignore ATTRIBUTE_UNUSED)1601*fae548d3Szrj obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
1602*fae548d3Szrj {
1603*fae548d3Szrj   (void) obj_elf_get_vtable_entry ();
1604*fae548d3Szrj }
1605*fae548d3Szrj 
1606*fae548d3Szrj #define skip_whitespace(str)  do { if (*(str) == ' ') ++(str); } while (0)
1607*fae548d3Szrj 
1608*fae548d3Szrj static inline int
skip_past_char(char ** str,char c)1609*fae548d3Szrj skip_past_char (char ** str, char c)
1610*fae548d3Szrj {
1611*fae548d3Szrj   if (**str == c)
1612*fae548d3Szrj     {
1613*fae548d3Szrj       (*str)++;
1614*fae548d3Szrj       return 0;
1615*fae548d3Szrj     }
1616*fae548d3Szrj   else
1617*fae548d3Szrj     return -1;
1618*fae548d3Szrj }
1619*fae548d3Szrj #define skip_past_comma(str) skip_past_char (str, ',')
1620*fae548d3Szrj 
1621*fae548d3Szrj /* A list of attributes that have been explicitly set by the assembly code.
1622*fae548d3Szrj    VENDOR is the vendor id, BASE is the tag shifted right by the number
1623*fae548d3Szrj    of bits in MASK, and bit N of MASK is set if tag BASE+N has been set.  */
1624*fae548d3Szrj struct recorded_attribute_info {
1625*fae548d3Szrj   struct recorded_attribute_info *next;
1626*fae548d3Szrj   int vendor;
1627*fae548d3Szrj   unsigned int base;
1628*fae548d3Szrj   unsigned long mask;
1629*fae548d3Szrj };
1630*fae548d3Szrj static struct recorded_attribute_info *recorded_attributes;
1631*fae548d3Szrj 
1632*fae548d3Szrj /* Record that we have seen an explicit specification of attribute TAG
1633*fae548d3Szrj    for vendor VENDOR.  */
1634*fae548d3Szrj 
1635*fae548d3Szrj static void
record_attribute(int vendor,unsigned int tag)1636*fae548d3Szrj record_attribute (int vendor, unsigned int tag)
1637*fae548d3Szrj {
1638*fae548d3Szrj   unsigned int base;
1639*fae548d3Szrj   unsigned long mask;
1640*fae548d3Szrj   struct recorded_attribute_info *rai;
1641*fae548d3Szrj 
1642*fae548d3Szrj   base = tag / (8 * sizeof (rai->mask));
1643*fae548d3Szrj   mask = 1UL << (tag % (8 * sizeof (rai->mask)));
1644*fae548d3Szrj   for (rai = recorded_attributes; rai; rai = rai->next)
1645*fae548d3Szrj     if (rai->vendor == vendor && rai->base == base)
1646*fae548d3Szrj       {
1647*fae548d3Szrj 	rai->mask |= mask;
1648*fae548d3Szrj 	return;
1649*fae548d3Szrj       }
1650*fae548d3Szrj 
1651*fae548d3Szrj   rai = XNEW (struct recorded_attribute_info);
1652*fae548d3Szrj   rai->next = recorded_attributes;
1653*fae548d3Szrj   rai->vendor = vendor;
1654*fae548d3Szrj   rai->base = base;
1655*fae548d3Szrj   rai->mask = mask;
1656*fae548d3Szrj   recorded_attributes = rai;
1657*fae548d3Szrj }
1658*fae548d3Szrj 
1659*fae548d3Szrj /* Return true if we have seen an explicit specification of attribute TAG
1660*fae548d3Szrj    for vendor VENDOR.  */
1661*fae548d3Szrj 
1662*fae548d3Szrj bfd_boolean
obj_elf_seen_attribute(int vendor,unsigned int tag)1663*fae548d3Szrj obj_elf_seen_attribute (int vendor, unsigned int tag)
1664*fae548d3Szrj {
1665*fae548d3Szrj   unsigned int base;
1666*fae548d3Szrj   unsigned long mask;
1667*fae548d3Szrj   struct recorded_attribute_info *rai;
1668*fae548d3Szrj 
1669*fae548d3Szrj   base = tag / (8 * sizeof (rai->mask));
1670*fae548d3Szrj   mask = 1UL << (tag % (8 * sizeof (rai->mask)));
1671*fae548d3Szrj   for (rai = recorded_attributes; rai; rai = rai->next)
1672*fae548d3Szrj     if (rai->vendor == vendor && rai->base == base)
1673*fae548d3Szrj       return (rai->mask & mask) != 0;
1674*fae548d3Szrj   return FALSE;
1675*fae548d3Szrj }
1676*fae548d3Szrj 
1677*fae548d3Szrj /* Parse an attribute directive for VENDOR.
1678*fae548d3Szrj    Returns the attribute number read, or zero on error.  */
1679*fae548d3Szrj 
1680*fae548d3Szrj int
obj_elf_vendor_attribute(int vendor)1681*fae548d3Szrj obj_elf_vendor_attribute (int vendor)
1682*fae548d3Szrj {
1683*fae548d3Szrj   expressionS exp;
1684*fae548d3Szrj   int type;
1685*fae548d3Szrj   int tag;
1686*fae548d3Szrj   unsigned int i = 0;
1687*fae548d3Szrj   char *s = NULL;
1688*fae548d3Szrj 
1689*fae548d3Szrj   /* Read the first number or name.  */
1690*fae548d3Szrj   skip_whitespace (input_line_pointer);
1691*fae548d3Szrj   s = input_line_pointer;
1692*fae548d3Szrj   if (ISDIGIT (*input_line_pointer))
1693*fae548d3Szrj     {
1694*fae548d3Szrj       expression (& exp);
1695*fae548d3Szrj       if (exp.X_op != O_constant)
1696*fae548d3Szrj 	goto bad;
1697*fae548d3Szrj       tag = exp.X_add_number;
1698*fae548d3Szrj     }
1699*fae548d3Szrj   else
1700*fae548d3Szrj     {
1701*fae548d3Szrj       char *name;
1702*fae548d3Szrj 
1703*fae548d3Szrj       /* A name may contain '_', but no other punctuation.  */
1704*fae548d3Szrj       for (; ISALNUM (*input_line_pointer) || *input_line_pointer == '_';
1705*fae548d3Szrj 	   ++input_line_pointer)
1706*fae548d3Szrj 	i++;
1707*fae548d3Szrj       if (i == 0)
1708*fae548d3Szrj 	goto bad;
1709*fae548d3Szrj 
1710*fae548d3Szrj       name = xstrndup (s, i);
1711*fae548d3Szrj 
1712*fae548d3Szrj #ifndef CONVERT_SYMBOLIC_ATTRIBUTE
1713*fae548d3Szrj #define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1
1714*fae548d3Szrj #endif
1715*fae548d3Szrj 
1716*fae548d3Szrj       tag = CONVERT_SYMBOLIC_ATTRIBUTE (name);
1717*fae548d3Szrj       if (tag == -1)
1718*fae548d3Szrj 	{
1719*fae548d3Szrj 	  as_bad (_("Attribute name not recognised: %s"), name);
1720*fae548d3Szrj 	  ignore_rest_of_line ();
1721*fae548d3Szrj 	  free (name);
1722*fae548d3Szrj 	  return 0;
1723*fae548d3Szrj 	}
1724*fae548d3Szrj       free (name);
1725*fae548d3Szrj     }
1726*fae548d3Szrj 
1727*fae548d3Szrj   type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag);
1728*fae548d3Szrj 
1729*fae548d3Szrj   if (skip_past_comma (&input_line_pointer) == -1)
1730*fae548d3Szrj     goto bad;
1731*fae548d3Szrj   if (type & 1)
1732*fae548d3Szrj     {
1733*fae548d3Szrj       expression (& exp);
1734*fae548d3Szrj       if (exp.X_op != O_constant)
1735*fae548d3Szrj 	{
1736*fae548d3Szrj 	  as_bad (_("expected numeric constant"));
1737*fae548d3Szrj 	  ignore_rest_of_line ();
1738*fae548d3Szrj 	  return 0;
1739*fae548d3Szrj 	}
1740*fae548d3Szrj       i = exp.X_add_number;
1741*fae548d3Szrj     }
1742*fae548d3Szrj   if ((type & 3) == 3
1743*fae548d3Szrj       && skip_past_comma (&input_line_pointer) == -1)
1744*fae548d3Szrj     {
1745*fae548d3Szrj       as_bad (_("expected comma"));
1746*fae548d3Szrj       ignore_rest_of_line ();
1747*fae548d3Szrj       return 0;
1748*fae548d3Szrj     }
1749*fae548d3Szrj   if (type & 2)
1750*fae548d3Szrj     {
1751*fae548d3Szrj       int len;
1752*fae548d3Szrj 
1753*fae548d3Szrj       skip_whitespace (input_line_pointer);
1754*fae548d3Szrj       if (*input_line_pointer != '"')
1755*fae548d3Szrj 	goto bad_string;
1756*fae548d3Szrj       s = demand_copy_C_string (&len);
1757*fae548d3Szrj     }
1758*fae548d3Szrj 
1759*fae548d3Szrj   record_attribute (vendor, tag);
1760*fae548d3Szrj   switch (type & 3)
1761*fae548d3Szrj     {
1762*fae548d3Szrj     case 3:
1763*fae548d3Szrj       bfd_elf_add_obj_attr_int_string (stdoutput, vendor, tag, i, s);
1764*fae548d3Szrj       break;
1765*fae548d3Szrj     case 2:
1766*fae548d3Szrj       bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s);
1767*fae548d3Szrj       break;
1768*fae548d3Szrj     case 1:
1769*fae548d3Szrj       bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i);
1770*fae548d3Szrj       break;
1771*fae548d3Szrj     default:
1772*fae548d3Szrj       abort ();
1773*fae548d3Szrj     }
1774*fae548d3Szrj 
1775*fae548d3Szrj   demand_empty_rest_of_line ();
1776*fae548d3Szrj   return tag;
1777*fae548d3Szrj bad_string:
1778*fae548d3Szrj   as_bad (_("bad string constant"));
1779*fae548d3Szrj   ignore_rest_of_line ();
1780*fae548d3Szrj   return 0;
1781*fae548d3Szrj bad:
1782*fae548d3Szrj   as_bad (_("expected <tag> , <value>"));
1783*fae548d3Szrj   ignore_rest_of_line ();
1784*fae548d3Szrj   return 0;
1785*fae548d3Szrj }
1786*fae548d3Szrj 
1787*fae548d3Szrj /* Parse a .gnu_attribute directive.  */
1788*fae548d3Szrj 
1789*fae548d3Szrj static void
obj_elf_gnu_attribute(int ignored ATTRIBUTE_UNUSED)1790*fae548d3Szrj obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
1791*fae548d3Szrj {
1792*fae548d3Szrj   obj_elf_vendor_attribute (OBJ_ATTR_GNU);
1793*fae548d3Szrj }
1794*fae548d3Szrj 
1795*fae548d3Szrj void
elf_obj_read_begin_hook(void)1796*fae548d3Szrj elf_obj_read_begin_hook (void)
1797*fae548d3Szrj {
1798*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
1799*fae548d3Szrj   if (ECOFF_DEBUGGING)
1800*fae548d3Szrj     ecoff_read_begin_hook ();
1801*fae548d3Szrj #endif
1802*fae548d3Szrj }
1803*fae548d3Szrj 
1804*fae548d3Szrj void
elf_obj_symbol_new_hook(symbolS * symbolP)1805*fae548d3Szrj elf_obj_symbol_new_hook (symbolS *symbolP)
1806*fae548d3Szrj {
1807*fae548d3Szrj   struct elf_obj_sy *sy_obj;
1808*fae548d3Szrj 
1809*fae548d3Szrj   sy_obj = symbol_get_obj (symbolP);
1810*fae548d3Szrj   sy_obj->size = NULL;
1811*fae548d3Szrj   sy_obj->versioned_name = NULL;
1812*fae548d3Szrj 
1813*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
1814*fae548d3Szrj   if (ECOFF_DEBUGGING)
1815*fae548d3Szrj     ecoff_symbol_new_hook (symbolP);
1816*fae548d3Szrj #endif
1817*fae548d3Szrj }
1818*fae548d3Szrj 
1819*fae548d3Szrj /* When setting one symbol equal to another, by default we probably
1820*fae548d3Szrj    want them to have the same "size", whatever it means in the current
1821*fae548d3Szrj    context.  */
1822*fae548d3Szrj 
1823*fae548d3Szrj void
elf_copy_symbol_attributes(symbolS * dest,symbolS * src)1824*fae548d3Szrj elf_copy_symbol_attributes (symbolS *dest, symbolS *src)
1825*fae548d3Szrj {
1826*fae548d3Szrj   struct elf_obj_sy *srcelf = symbol_get_obj (src);
1827*fae548d3Szrj   struct elf_obj_sy *destelf = symbol_get_obj (dest);
1828*fae548d3Szrj   if (srcelf->size)
1829*fae548d3Szrj     {
1830*fae548d3Szrj       if (destelf->size == NULL)
1831*fae548d3Szrj 	destelf->size = XNEW (expressionS);
1832*fae548d3Szrj       *destelf->size = *srcelf->size;
1833*fae548d3Szrj     }
1834*fae548d3Szrj   else
1835*fae548d3Szrj     {
1836*fae548d3Szrj       if (destelf->size != NULL)
1837*fae548d3Szrj 	free (destelf->size);
1838*fae548d3Szrj       destelf->size = NULL;
1839*fae548d3Szrj     }
1840*fae548d3Szrj   S_SET_SIZE (dest, S_GET_SIZE (src));
1841*fae548d3Szrj   /* Don't copy visibility.  */
1842*fae548d3Szrj   S_SET_OTHER (dest, (ELF_ST_VISIBILITY (S_GET_OTHER (dest))
1843*fae548d3Szrj 		      | (S_GET_OTHER (src) & ~ELF_ST_VISIBILITY (-1))));
1844*fae548d3Szrj }
1845*fae548d3Szrj 
1846*fae548d3Szrj void
obj_elf_version(int ignore ATTRIBUTE_UNUSED)1847*fae548d3Szrj obj_elf_version (int ignore ATTRIBUTE_UNUSED)
1848*fae548d3Szrj {
1849*fae548d3Szrj   char *name;
1850*fae548d3Szrj   unsigned int c;
1851*fae548d3Szrj   char *p;
1852*fae548d3Szrj   asection *seg = now_seg;
1853*fae548d3Szrj   subsegT subseg = now_subseg;
1854*fae548d3Szrj   Elf_Internal_Note i_note;
1855*fae548d3Szrj   Elf_External_Note e_note;
1856*fae548d3Szrj   asection *note_secp = NULL;
1857*fae548d3Szrj 
1858*fae548d3Szrj   SKIP_WHITESPACE ();
1859*fae548d3Szrj   if (*input_line_pointer == '\"')
1860*fae548d3Szrj     {
1861*fae548d3Szrj       unsigned int len;
1862*fae548d3Szrj 
1863*fae548d3Szrj       ++input_line_pointer;	/* -> 1st char of string.  */
1864*fae548d3Szrj       name = input_line_pointer;
1865*fae548d3Szrj 
1866*fae548d3Szrj       while (is_a_char (c = next_char_of_string ()))
1867*fae548d3Szrj 	;
1868*fae548d3Szrj       c = *input_line_pointer;
1869*fae548d3Szrj       *input_line_pointer = '\0';
1870*fae548d3Szrj       *(input_line_pointer - 1) = '\0';
1871*fae548d3Szrj       *input_line_pointer = c;
1872*fae548d3Szrj 
1873*fae548d3Szrj       /* Create the .note section.  */
1874*fae548d3Szrj       note_secp = subseg_new (".note", 0);
1875*fae548d3Szrj       bfd_set_section_flags (note_secp, SEC_HAS_CONTENTS | SEC_READONLY);
1876*fae548d3Szrj       record_alignment (note_secp, 2);
1877*fae548d3Szrj 
1878*fae548d3Szrj       /* Process the version string.  */
1879*fae548d3Szrj       len = strlen (name) + 1;
1880*fae548d3Szrj 
1881*fae548d3Szrj       /* PR 3456: Although the name field is padded out to an 4-byte
1882*fae548d3Szrj 	 boundary, the namesz field should not be adjusted.  */
1883*fae548d3Szrj       i_note.namesz = len;
1884*fae548d3Szrj       i_note.descsz = 0;	/* No description.  */
1885*fae548d3Szrj       i_note.type = NT_VERSION;
1886*fae548d3Szrj       p = frag_more (sizeof (e_note.namesz));
1887*fae548d3Szrj       md_number_to_chars (p, i_note.namesz, sizeof (e_note.namesz));
1888*fae548d3Szrj       p = frag_more (sizeof (e_note.descsz));
1889*fae548d3Szrj       md_number_to_chars (p, i_note.descsz, sizeof (e_note.descsz));
1890*fae548d3Szrj       p = frag_more (sizeof (e_note.type));
1891*fae548d3Szrj       md_number_to_chars (p, i_note.type, sizeof (e_note.type));
1892*fae548d3Szrj       p = frag_more (len);
1893*fae548d3Szrj       memcpy (p, name, len);
1894*fae548d3Szrj 
1895*fae548d3Szrj       frag_align (2, 0, 0);
1896*fae548d3Szrj 
1897*fae548d3Szrj       subseg_set (seg, subseg);
1898*fae548d3Szrj     }
1899*fae548d3Szrj   else
1900*fae548d3Szrj     as_bad (_("expected quoted string"));
1901*fae548d3Szrj 
1902*fae548d3Szrj   demand_empty_rest_of_line ();
1903*fae548d3Szrj }
1904*fae548d3Szrj 
1905*fae548d3Szrj static void
obj_elf_size(int ignore ATTRIBUTE_UNUSED)1906*fae548d3Szrj obj_elf_size (int ignore ATTRIBUTE_UNUSED)
1907*fae548d3Szrj {
1908*fae548d3Szrj   char *name;
1909*fae548d3Szrj   char c = get_symbol_name (&name);
1910*fae548d3Szrj   char *p;
1911*fae548d3Szrj   expressionS exp;
1912*fae548d3Szrj   symbolS *sym;
1913*fae548d3Szrj 
1914*fae548d3Szrj   p = input_line_pointer;
1915*fae548d3Szrj   *p = c;
1916*fae548d3Szrj   SKIP_WHITESPACE_AFTER_NAME ();
1917*fae548d3Szrj   if (*input_line_pointer != ',')
1918*fae548d3Szrj     {
1919*fae548d3Szrj       *p = 0;
1920*fae548d3Szrj       as_bad (_("expected comma after name `%s' in .size directive"), name);
1921*fae548d3Szrj       *p = c;
1922*fae548d3Szrj       ignore_rest_of_line ();
1923*fae548d3Szrj       return;
1924*fae548d3Szrj     }
1925*fae548d3Szrj   input_line_pointer++;
1926*fae548d3Szrj   expression (&exp);
1927*fae548d3Szrj   if (exp.X_op == O_absent)
1928*fae548d3Szrj     {
1929*fae548d3Szrj       as_bad (_("missing expression in .size directive"));
1930*fae548d3Szrj       exp.X_op = O_constant;
1931*fae548d3Szrj       exp.X_add_number = 0;
1932*fae548d3Szrj     }
1933*fae548d3Szrj   *p = 0;
1934*fae548d3Szrj   sym = symbol_find_or_make (name);
1935*fae548d3Szrj   *p = c;
1936*fae548d3Szrj   if (exp.X_op == O_constant)
1937*fae548d3Szrj     {
1938*fae548d3Szrj       S_SET_SIZE (sym, exp.X_add_number);
1939*fae548d3Szrj       if (symbol_get_obj (sym)->size)
1940*fae548d3Szrj 	{
1941*fae548d3Szrj 	  xfree (symbol_get_obj (sym)->size);
1942*fae548d3Szrj 	  symbol_get_obj (sym)->size = NULL;
1943*fae548d3Szrj 	}
1944*fae548d3Szrj     }
1945*fae548d3Szrj   else
1946*fae548d3Szrj     {
1947*fae548d3Szrj       symbol_get_obj (sym)->size = XNEW (expressionS);
1948*fae548d3Szrj       *symbol_get_obj (sym)->size = exp;
1949*fae548d3Szrj     }
1950*fae548d3Szrj   demand_empty_rest_of_line ();
1951*fae548d3Szrj }
1952*fae548d3Szrj 
1953*fae548d3Szrj /* Handle the ELF .type pseudo-op.  This sets the type of a symbol.
1954*fae548d3Szrj    There are six syntaxes:
1955*fae548d3Szrj 
1956*fae548d3Szrj    The first (used on Solaris) is
1957*fae548d3Szrj        .type SYM,#function
1958*fae548d3Szrj    The second (used on UnixWare) is
1959*fae548d3Szrj        .type SYM,@function
1960*fae548d3Szrj    The third (reportedly to be used on Irix 6.0) is
1961*fae548d3Szrj        .type SYM STT_FUNC
1962*fae548d3Szrj    The fourth (used on NetBSD/Arm and Linux/ARM) is
1963*fae548d3Szrj        .type SYM,%function
1964*fae548d3Szrj    The fifth (used on SVR4/860) is
1965*fae548d3Szrj        .type SYM,"function"
1966*fae548d3Szrj    The sixth (emitted by recent SunPRO under Solaris) is
1967*fae548d3Szrj        .type SYM,[0-9]
1968*fae548d3Szrj    where the integer is the STT_* value.
1969*fae548d3Szrj    */
1970*fae548d3Szrj 
1971*fae548d3Szrj static char *
obj_elf_type_name(char * cp)1972*fae548d3Szrj obj_elf_type_name (char *cp)
1973*fae548d3Szrj {
1974*fae548d3Szrj   char *p;
1975*fae548d3Szrj 
1976*fae548d3Szrj   p = input_line_pointer;
1977*fae548d3Szrj   if (*input_line_pointer >= '0'
1978*fae548d3Szrj       && *input_line_pointer <= '9')
1979*fae548d3Szrj     {
1980*fae548d3Szrj       while (*input_line_pointer >= '0'
1981*fae548d3Szrj 	     && *input_line_pointer <= '9')
1982*fae548d3Szrj 	++input_line_pointer;
1983*fae548d3Szrj       *cp = *input_line_pointer;
1984*fae548d3Szrj       *input_line_pointer = '\0';
1985*fae548d3Szrj     }
1986*fae548d3Szrj   else
1987*fae548d3Szrj     *cp = get_symbol_name (&p);
1988*fae548d3Szrj 
1989*fae548d3Szrj   return p;
1990*fae548d3Szrj }
1991*fae548d3Szrj 
1992*fae548d3Szrj static void
obj_elf_type(int ignore ATTRIBUTE_UNUSED)1993*fae548d3Szrj obj_elf_type (int ignore ATTRIBUTE_UNUSED)
1994*fae548d3Szrj {
1995*fae548d3Szrj   char c;
1996*fae548d3Szrj   int type;
1997*fae548d3Szrj   const char *type_name;
1998*fae548d3Szrj   symbolS *sym;
1999*fae548d3Szrj   elf_symbol_type *elfsym;
2000*fae548d3Szrj 
2001*fae548d3Szrj   sym = get_sym_from_input_line_and_check ();
2002*fae548d3Szrj   c = *input_line_pointer;
2003*fae548d3Szrj   elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
2004*fae548d3Szrj 
2005*fae548d3Szrj   if (*input_line_pointer == ',')
2006*fae548d3Szrj     ++input_line_pointer;
2007*fae548d3Szrj 
2008*fae548d3Szrj   SKIP_WHITESPACE ();
2009*fae548d3Szrj   if (   *input_line_pointer == '#'
2010*fae548d3Szrj       || *input_line_pointer == '@'
2011*fae548d3Szrj       || *input_line_pointer == '"'
2012*fae548d3Szrj       || *input_line_pointer == '%')
2013*fae548d3Szrj     ++input_line_pointer;
2014*fae548d3Szrj 
2015*fae548d3Szrj   type_name = obj_elf_type_name (& c);
2016*fae548d3Szrj 
2017*fae548d3Szrj   type = 0;
2018*fae548d3Szrj   if (strcmp (type_name, "function") == 0
2019*fae548d3Szrj       || strcmp (type_name, "2") == 0
2020*fae548d3Szrj       || strcmp (type_name, "STT_FUNC") == 0)
2021*fae548d3Szrj     type = BSF_FUNCTION;
2022*fae548d3Szrj   else if (strcmp (type_name, "object") == 0
2023*fae548d3Szrj 	   || strcmp (type_name, "1") == 0
2024*fae548d3Szrj 	   || strcmp (type_name, "STT_OBJECT") == 0)
2025*fae548d3Szrj     type = BSF_OBJECT;
2026*fae548d3Szrj   else if (strcmp (type_name, "tls_object") == 0
2027*fae548d3Szrj 	   || strcmp (type_name, "6") == 0
2028*fae548d3Szrj 	   || strcmp (type_name, "STT_TLS") == 0)
2029*fae548d3Szrj     type = BSF_OBJECT | BSF_THREAD_LOCAL;
2030*fae548d3Szrj   else if (strcmp (type_name, "notype") == 0
2031*fae548d3Szrj 	   || strcmp (type_name, "0") == 0
2032*fae548d3Szrj 	   || strcmp (type_name, "STT_NOTYPE") == 0)
2033*fae548d3Szrj     ;
2034*fae548d3Szrj   else if (strcmp (type_name, "common") == 0
2035*fae548d3Szrj 	   || strcmp (type_name, "5") == 0
2036*fae548d3Szrj 	   || strcmp (type_name, "STT_COMMON") == 0)
2037*fae548d3Szrj     {
2038*fae548d3Szrj       type = BSF_OBJECT;
2039*fae548d3Szrj 
2040*fae548d3Szrj       if (! S_IS_COMMON (sym))
2041*fae548d3Szrj 	{
2042*fae548d3Szrj 	  if (S_IS_VOLATILE (sym))
2043*fae548d3Szrj 	    {
2044*fae548d3Szrj 	      sym = symbol_clone (sym, 1);
2045*fae548d3Szrj 	      S_SET_SEGMENT (sym, bfd_com_section_ptr);
2046*fae548d3Szrj 	      S_SET_VALUE (sym, 0);
2047*fae548d3Szrj 	      S_SET_EXTERNAL (sym);
2048*fae548d3Szrj 	      symbol_set_frag (sym, &zero_address_frag);
2049*fae548d3Szrj 	      S_CLEAR_VOLATILE (sym);
2050*fae548d3Szrj 	    }
2051*fae548d3Szrj 	  else if (S_IS_DEFINED (sym) || symbol_equated_p (sym))
2052*fae548d3Szrj 	    as_bad (_("symbol '%s' is already defined"), S_GET_NAME (sym));
2053*fae548d3Szrj 	  else
2054*fae548d3Szrj 	    {
2055*fae548d3Szrj 	      /* FIXME: Is it safe to just change the section ?  */
2056*fae548d3Szrj 	      S_SET_SEGMENT (sym, bfd_com_section_ptr);
2057*fae548d3Szrj 	      S_SET_VALUE (sym, 0);
2058*fae548d3Szrj 	      S_SET_EXTERNAL (sym);
2059*fae548d3Szrj 	    }
2060*fae548d3Szrj 	}
2061*fae548d3Szrj     }
2062*fae548d3Szrj   else if (strcmp (type_name, "gnu_indirect_function") == 0
2063*fae548d3Szrj 	   || strcmp (type_name, "10") == 0
2064*fae548d3Szrj 	   || strcmp (type_name, "STT_GNU_IFUNC") == 0)
2065*fae548d3Szrj     {
2066*fae548d3Szrj       struct elf_backend_data *bed;
2067*fae548d3Szrj 
2068*fae548d3Szrj       bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
2069*fae548d3Szrj       if (bed->elf_osabi == ELFOSABI_NONE)
2070*fae548d3Szrj 	bed->elf_osabi = ELFOSABI_GNU;
2071*fae548d3Szrj       else if (bed->elf_osabi != ELFOSABI_GNU
2072*fae548d3Szrj 	       && bed->elf_osabi != ELFOSABI_FREEBSD)
2073*fae548d3Szrj 	as_bad (_("symbol type \"%s\" is supported only by GNU "
2074*fae548d3Szrj 		  "and FreeBSD targets"), type_name);
2075*fae548d3Szrj       elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
2076*fae548d3Szrj       type = BSF_FUNCTION | BSF_GNU_INDIRECT_FUNCTION;
2077*fae548d3Szrj     }
2078*fae548d3Szrj   else if (strcmp (type_name, "gnu_unique_object") == 0)
2079*fae548d3Szrj     {
2080*fae548d3Szrj       struct elf_backend_data *bed;
2081*fae548d3Szrj 
2082*fae548d3Szrj       bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
2083*fae548d3Szrj       if (bed->elf_osabi == ELFOSABI_NONE)
2084*fae548d3Szrj 	bed->elf_osabi = ELFOSABI_GNU;
2085*fae548d3Szrj       else if (bed->elf_osabi != ELFOSABI_GNU)
2086*fae548d3Szrj 	as_bad (_("symbol type \"%s\" is supported only by GNU targets"),
2087*fae548d3Szrj 		type_name);
2088*fae548d3Szrj       elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_unique;
2089*fae548d3Szrj       type = BSF_OBJECT | BSF_GNU_UNIQUE;
2090*fae548d3Szrj     }
2091*fae548d3Szrj #ifdef md_elf_symbol_type
2092*fae548d3Szrj   else if ((type = md_elf_symbol_type (type_name, sym, elfsym)) != -1)
2093*fae548d3Szrj     ;
2094*fae548d3Szrj #endif
2095*fae548d3Szrj   else
2096*fae548d3Szrj     as_bad (_("unrecognized symbol type \"%s\""), type_name);
2097*fae548d3Szrj 
2098*fae548d3Szrj   *input_line_pointer = c;
2099*fae548d3Szrj 
2100*fae548d3Szrj   if (*input_line_pointer == '"')
2101*fae548d3Szrj     ++input_line_pointer;
2102*fae548d3Szrj 
2103*fae548d3Szrj #ifdef md_elf_symbol_type_change
2104*fae548d3Szrj   if (!md_elf_symbol_type_change (sym, elfsym, type))
2105*fae548d3Szrj #endif
2106*fae548d3Szrj     {
2107*fae548d3Szrj       flagword mask = BSF_FUNCTION | BSF_OBJECT;
2108*fae548d3Szrj 
2109*fae548d3Szrj       if (type != BSF_FUNCTION)
2110*fae548d3Szrj 	mask |= BSF_GNU_INDIRECT_FUNCTION;
2111*fae548d3Szrj       if (type != BSF_OBJECT)
2112*fae548d3Szrj 	{
2113*fae548d3Szrj 	  mask |= BSF_GNU_UNIQUE | BSF_THREAD_LOCAL;
2114*fae548d3Szrj 
2115*fae548d3Szrj 	  if (S_IS_COMMON (sym))
2116*fae548d3Szrj 	    {
2117*fae548d3Szrj 	      as_bad (_("cannot change type of common symbol '%s'"),
2118*fae548d3Szrj 		      S_GET_NAME (sym));
2119*fae548d3Szrj 	      mask = type = 0;
2120*fae548d3Szrj 	    }
2121*fae548d3Szrj 	}
2122*fae548d3Szrj 
2123*fae548d3Szrj       /* Don't warn when changing to STT_NOTYPE.  */
2124*fae548d3Szrj       if (type)
2125*fae548d3Szrj 	{
2126*fae548d3Szrj 	  flagword new = (elfsym->symbol.flags & ~mask) | type;
2127*fae548d3Szrj 
2128*fae548d3Szrj 	  if (new != (elfsym->symbol.flags | type))
2129*fae548d3Szrj 	    as_warn (_("symbol '%s' already has its type set"), S_GET_NAME (sym));
2130*fae548d3Szrj 	  elfsym->symbol.flags = new;
2131*fae548d3Szrj 	}
2132*fae548d3Szrj       else
2133*fae548d3Szrj 	elfsym->symbol.flags &= ~mask;
2134*fae548d3Szrj     }
2135*fae548d3Szrj 
2136*fae548d3Szrj   demand_empty_rest_of_line ();
2137*fae548d3Szrj }
2138*fae548d3Szrj 
2139*fae548d3Szrj static void
obj_elf_ident(int ignore ATTRIBUTE_UNUSED)2140*fae548d3Szrj obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
2141*fae548d3Szrj {
2142*fae548d3Szrj   static segT comment_section;
2143*fae548d3Szrj   segT old_section = now_seg;
2144*fae548d3Szrj   int old_subsection = now_subseg;
2145*fae548d3Szrj 
2146*fae548d3Szrj #ifdef md_flush_pending_output
2147*fae548d3Szrj   md_flush_pending_output ();
2148*fae548d3Szrj #endif
2149*fae548d3Szrj 
2150*fae548d3Szrj   if (!comment_section)
2151*fae548d3Szrj     {
2152*fae548d3Szrj       char *p;
2153*fae548d3Szrj       comment_section = subseg_new (".comment", 0);
2154*fae548d3Szrj       bfd_set_section_flags (comment_section, (SEC_READONLY | SEC_HAS_CONTENTS
2155*fae548d3Szrj 					       | SEC_MERGE | SEC_STRINGS));
2156*fae548d3Szrj       comment_section->entsize = 1;
2157*fae548d3Szrj #ifdef md_elf_section_change_hook
2158*fae548d3Szrj       md_elf_section_change_hook ();
2159*fae548d3Szrj #endif
2160*fae548d3Szrj       p = frag_more (1);
2161*fae548d3Szrj       *p = 0;
2162*fae548d3Szrj     }
2163*fae548d3Szrj   else
2164*fae548d3Szrj     subseg_set (comment_section, 0);
2165*fae548d3Szrj   stringer (8 + 1);
2166*fae548d3Szrj   subseg_set (old_section, old_subsection);
2167*fae548d3Szrj }
2168*fae548d3Szrj 
2169*fae548d3Szrj #ifdef INIT_STAB_SECTION
2170*fae548d3Szrj 
2171*fae548d3Szrj /* The first entry in a .stabs section is special.  */
2172*fae548d3Szrj 
2173*fae548d3Szrj void
obj_elf_init_stab_section(segT seg)2174*fae548d3Szrj obj_elf_init_stab_section (segT seg)
2175*fae548d3Szrj {
2176*fae548d3Szrj   const char *file;
2177*fae548d3Szrj   char *p;
2178*fae548d3Szrj   char *stabstr_name;
2179*fae548d3Szrj   unsigned int stroff;
2180*fae548d3Szrj 
2181*fae548d3Szrj   /* Force the section to align to a longword boundary.  Without this,
2182*fae548d3Szrj      UnixWare ar crashes.  */
2183*fae548d3Szrj   bfd_set_section_alignment (seg, 2);
2184*fae548d3Szrj 
2185*fae548d3Szrj   /* Make space for this first symbol.  */
2186*fae548d3Szrj   p = frag_more (12);
2187*fae548d3Szrj   /* Zero it out.  */
2188*fae548d3Szrj   memset (p, 0, 12);
2189*fae548d3Szrj   file = as_where (NULL);
2190*fae548d3Szrj   stabstr_name = concat (segment_name (seg), "str", (char *) NULL);
2191*fae548d3Szrj   stroff = get_stab_string_offset (file, stabstr_name, TRUE);
2192*fae548d3Szrj   know (stroff == 1 || (stroff == 0 && file[0] == '\0'));
2193*fae548d3Szrj   md_number_to_chars (p, stroff, 4);
2194*fae548d3Szrj   seg_info (seg)->stabu.p = p;
2195*fae548d3Szrj }
2196*fae548d3Szrj 
2197*fae548d3Szrj #endif
2198*fae548d3Szrj 
2199*fae548d3Szrj /* Fill in the counts in the first entry in a .stabs section.  */
2200*fae548d3Szrj 
2201*fae548d3Szrj static void
adjust_stab_sections(bfd * abfd,asection * sec,void * xxx ATTRIBUTE_UNUSED)2202*fae548d3Szrj adjust_stab_sections (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
2203*fae548d3Szrj {
2204*fae548d3Szrj   char *name;
2205*fae548d3Szrj   asection *strsec;
2206*fae548d3Szrj   char *p;
2207*fae548d3Szrj   int strsz, nsyms;
2208*fae548d3Szrj 
2209*fae548d3Szrj   if (strncmp (".stab", sec->name, 5))
2210*fae548d3Szrj     return;
2211*fae548d3Szrj   if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
2212*fae548d3Szrj     return;
2213*fae548d3Szrj 
2214*fae548d3Szrj   name = concat (sec->name, "str", NULL);
2215*fae548d3Szrj   strsec = bfd_get_section_by_name (abfd, name);
2216*fae548d3Szrj   if (strsec)
2217*fae548d3Szrj     strsz = bfd_section_size (strsec);
2218*fae548d3Szrj   else
2219*fae548d3Szrj     strsz = 0;
2220*fae548d3Szrj   nsyms = bfd_section_size (sec) / 12 - 1;
2221*fae548d3Szrj 
2222*fae548d3Szrj   p = seg_info (sec)->stabu.p;
2223*fae548d3Szrj   gas_assert (p != 0);
2224*fae548d3Szrj 
2225*fae548d3Szrj   bfd_h_put_16 (abfd, nsyms, p + 6);
2226*fae548d3Szrj   bfd_h_put_32 (abfd, strsz, p + 8);
2227*fae548d3Szrj   free (name);
2228*fae548d3Szrj }
2229*fae548d3Szrj 
2230*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2231*fae548d3Szrj 
2232*fae548d3Szrj /* This function is called by the ECOFF code.  It is supposed to
2233*fae548d3Szrj    record the external symbol information so that the backend can
2234*fae548d3Szrj    write it out correctly.  The ELF backend doesn't actually handle
2235*fae548d3Szrj    this at the moment, so we do it ourselves.  We save the information
2236*fae548d3Szrj    in the symbol.  */
2237*fae548d3Szrj 
2238*fae548d3Szrj #ifdef OBJ_MAYBE_ELF
2239*fae548d3Szrj static
2240*fae548d3Szrj #endif
2241*fae548d3Szrj void
elf_ecoff_set_ext(symbolS * sym,struct ecoff_extr * ext)2242*fae548d3Szrj elf_ecoff_set_ext (symbolS *sym, struct ecoff_extr *ext)
2243*fae548d3Szrj {
2244*fae548d3Szrj   symbol_get_bfdsym (sym)->udata.p = ext;
2245*fae548d3Szrj }
2246*fae548d3Szrj 
2247*fae548d3Szrj /* This function is called by bfd_ecoff_debug_externals.  It is
2248*fae548d3Szrj    supposed to *EXT to the external symbol information, and return
2249*fae548d3Szrj    whether the symbol should be used at all.  */
2250*fae548d3Szrj 
2251*fae548d3Szrj static bfd_boolean
elf_get_extr(asymbol * sym,EXTR * ext)2252*fae548d3Szrj elf_get_extr (asymbol *sym, EXTR *ext)
2253*fae548d3Szrj {
2254*fae548d3Szrj   if (sym->udata.p == NULL)
2255*fae548d3Szrj     return FALSE;
2256*fae548d3Szrj   *ext = *(EXTR *) sym->udata.p;
2257*fae548d3Szrj   return TRUE;
2258*fae548d3Szrj }
2259*fae548d3Szrj 
2260*fae548d3Szrj /* This function is called by bfd_ecoff_debug_externals.  It has
2261*fae548d3Szrj    nothing to do for ELF.  */
2262*fae548d3Szrj 
2263*fae548d3Szrj static void
elf_set_index(asymbol * sym ATTRIBUTE_UNUSED,bfd_size_type indx ATTRIBUTE_UNUSED)2264*fae548d3Szrj elf_set_index (asymbol *sym ATTRIBUTE_UNUSED,
2265*fae548d3Szrj 	       bfd_size_type indx ATTRIBUTE_UNUSED)
2266*fae548d3Szrj {
2267*fae548d3Szrj }
2268*fae548d3Szrj 
2269*fae548d3Szrj #endif /* NEED_ECOFF_DEBUG */
2270*fae548d3Szrj 
2271*fae548d3Szrj void
elf_frob_symbol(symbolS * symp,int * puntp)2272*fae548d3Szrj elf_frob_symbol (symbolS *symp, int *puntp)
2273*fae548d3Szrj {
2274*fae548d3Szrj   struct elf_obj_sy *sy_obj;
2275*fae548d3Szrj   expressionS *size;
2276*fae548d3Szrj 
2277*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2278*fae548d3Szrj   if (ECOFF_DEBUGGING)
2279*fae548d3Szrj     ecoff_frob_symbol (symp);
2280*fae548d3Szrj #endif
2281*fae548d3Szrj 
2282*fae548d3Szrj   sy_obj = symbol_get_obj (symp);
2283*fae548d3Szrj 
2284*fae548d3Szrj   size = sy_obj->size;
2285*fae548d3Szrj   if (size != NULL)
2286*fae548d3Szrj     {
2287*fae548d3Szrj       if (resolve_expression (size)
2288*fae548d3Szrj 	  && size->X_op == O_constant)
2289*fae548d3Szrj 	S_SET_SIZE (symp, size->X_add_number);
2290*fae548d3Szrj       else
2291*fae548d3Szrj 	{
2292*fae548d3Szrj 	  if (!flag_allow_nonconst_size)
2293*fae548d3Szrj 	    as_bad (_(".size expression for %s "
2294*fae548d3Szrj 		      "does not evaluate to a constant"), S_GET_NAME (symp));
2295*fae548d3Szrj 	  else
2296*fae548d3Szrj 	    as_warn (_(".size expression for %s "
2297*fae548d3Szrj 		       "does not evaluate to a constant"), S_GET_NAME (symp));
2298*fae548d3Szrj 	}
2299*fae548d3Szrj       free (sy_obj->size);
2300*fae548d3Szrj       sy_obj->size = NULL;
2301*fae548d3Szrj     }
2302*fae548d3Szrj 
2303*fae548d3Szrj   if (sy_obj->versioned_name != NULL)
2304*fae548d3Szrj     {
2305*fae548d3Szrj       char *p;
2306*fae548d3Szrj 
2307*fae548d3Szrj       p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
2308*fae548d3Szrj       if (p == NULL)
2309*fae548d3Szrj 	/* We will have already reported an error about a missing version.  */
2310*fae548d3Szrj 	*puntp = TRUE;
2311*fae548d3Szrj 
2312*fae548d3Szrj       /* This symbol was given a new name with the .symver directive.
2313*fae548d3Szrj 
2314*fae548d3Szrj 	 If this is an external reference, just rename the symbol to
2315*fae548d3Szrj 	 include the version string.  This will make the relocs be
2316*fae548d3Szrj 	 against the correct versioned symbol.
2317*fae548d3Szrj 
2318*fae548d3Szrj 	 If this is a definition, add an alias.  FIXME: Using an alias
2319*fae548d3Szrj 	 will permit the debugging information to refer to the right
2320*fae548d3Szrj 	 symbol.  However, it's not clear whether it is the best
2321*fae548d3Szrj 	 approach.  */
2322*fae548d3Szrj 
2323*fae548d3Szrj       else if (! S_IS_DEFINED (symp))
2324*fae548d3Szrj 	{
2325*fae548d3Szrj 	  /* Verify that the name isn't using the @@ syntax--this is
2326*fae548d3Szrj 	     reserved for definitions of the default version to link
2327*fae548d3Szrj 	     against.  */
2328*fae548d3Szrj 	  if (p[1] == ELF_VER_CHR)
2329*fae548d3Szrj 	    {
2330*fae548d3Szrj 	      as_bad (_("invalid attempt to declare external version name"
2331*fae548d3Szrj 			" as default in symbol `%s'"),
2332*fae548d3Szrj 		      sy_obj->versioned_name);
2333*fae548d3Szrj 	      *puntp = TRUE;
2334*fae548d3Szrj 	    }
2335*fae548d3Szrj 	  S_SET_NAME (symp, sy_obj->versioned_name);
2336*fae548d3Szrj 	}
2337*fae548d3Szrj       else
2338*fae548d3Szrj 	{
2339*fae548d3Szrj 	  if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
2340*fae548d3Szrj 	    {
2341*fae548d3Szrj 	      size_t l;
2342*fae548d3Szrj 
2343*fae548d3Szrj 	      /* The @@@ syntax is a special case. It renames the
2344*fae548d3Szrj 		 symbol name to versioned_name with one `@' removed.  */
2345*fae548d3Szrj 	      l = strlen (&p[3]) + 1;
2346*fae548d3Szrj 	      memmove (&p[2], &p[3], l);
2347*fae548d3Szrj 	      S_SET_NAME (symp, sy_obj->versioned_name);
2348*fae548d3Szrj 	    }
2349*fae548d3Szrj 	  else
2350*fae548d3Szrj 	    {
2351*fae548d3Szrj 	      symbolS *symp2;
2352*fae548d3Szrj 
2353*fae548d3Szrj 	      /* FIXME: Creating a new symbol here is risky.  We're
2354*fae548d3Szrj 		 in the final loop over the symbol table.  We can
2355*fae548d3Szrj 		 get away with it only because the symbol goes to
2356*fae548d3Szrj 		 the end of the list, where the loop will still see
2357*fae548d3Szrj 		 it.  It would probably be better to do this in
2358*fae548d3Szrj 		 obj_frob_file_before_adjust.  */
2359*fae548d3Szrj 
2360*fae548d3Szrj 	      symp2 = symbol_find_or_make (sy_obj->versioned_name);
2361*fae548d3Szrj 
2362*fae548d3Szrj 	      /* Now we act as though we saw symp2 = sym.  */
2363*fae548d3Szrj 	      if (S_IS_COMMON (symp))
2364*fae548d3Szrj 		{
2365*fae548d3Szrj 		  as_bad (_("`%s' can't be versioned to common symbol '%s'"),
2366*fae548d3Szrj 			  sy_obj->versioned_name, S_GET_NAME (symp));
2367*fae548d3Szrj 		  *puntp = TRUE;
2368*fae548d3Szrj 		  return;
2369*fae548d3Szrj 		}
2370*fae548d3Szrj 
2371*fae548d3Szrj 	      S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
2372*fae548d3Szrj 
2373*fae548d3Szrj 	      /* Subtracting out the frag address here is a hack
2374*fae548d3Szrj 		 because we are in the middle of the final loop.  */
2375*fae548d3Szrj 	      S_SET_VALUE (symp2,
2376*fae548d3Szrj 			   (S_GET_VALUE (symp)
2377*fae548d3Szrj 			    - symbol_get_frag (symp)->fr_address));
2378*fae548d3Szrj 
2379*fae548d3Szrj 	      symbol_set_frag (symp2, symbol_get_frag (symp));
2380*fae548d3Szrj 
2381*fae548d3Szrj 	      /* This will copy over the size information.  */
2382*fae548d3Szrj 	      copy_symbol_attributes (symp2, symp);
2383*fae548d3Szrj 
2384*fae548d3Szrj 	      S_SET_OTHER (symp2, S_GET_OTHER (symp));
2385*fae548d3Szrj 
2386*fae548d3Szrj 	      if (S_IS_WEAK (symp))
2387*fae548d3Szrj 		S_SET_WEAK (symp2);
2388*fae548d3Szrj 
2389*fae548d3Szrj 	      if (S_IS_EXTERNAL (symp))
2390*fae548d3Szrj 		S_SET_EXTERNAL (symp2);
2391*fae548d3Szrj 	    }
2392*fae548d3Szrj 	}
2393*fae548d3Szrj     }
2394*fae548d3Szrj 
2395*fae548d3Szrj   /* Double check weak symbols.  */
2396*fae548d3Szrj   if (S_IS_WEAK (symp))
2397*fae548d3Szrj     {
2398*fae548d3Szrj       if (S_IS_COMMON (symp))
2399*fae548d3Szrj 	as_bad (_("symbol `%s' can not be both weak and common"),
2400*fae548d3Szrj 		S_GET_NAME (symp));
2401*fae548d3Szrj     }
2402*fae548d3Szrj }
2403*fae548d3Szrj 
2404*fae548d3Szrj struct group_list
2405*fae548d3Szrj {
2406*fae548d3Szrj   asection **head;		/* Section lists.  */
2407*fae548d3Szrj   unsigned int num_group;	/* Number of lists.  */
2408*fae548d3Szrj   struct hash_control *indexes; /* Maps group name to index in head array.  */
2409*fae548d3Szrj };
2410*fae548d3Szrj 
2411*fae548d3Szrj static struct group_list groups;
2412*fae548d3Szrj 
2413*fae548d3Szrj /* Called via bfd_map_over_sections.  If SEC is a member of a group,
2414*fae548d3Szrj    add it to a list of sections belonging to the group.  INF is a
2415*fae548d3Szrj    pointer to a struct group_list, which is where we store the head of
2416*fae548d3Szrj    each list.  */
2417*fae548d3Szrj 
2418*fae548d3Szrj static void
build_group_lists(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * inf)2419*fae548d3Szrj build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
2420*fae548d3Szrj {
2421*fae548d3Szrj   struct group_list *list = (struct group_list *) inf;
2422*fae548d3Szrj   const char *group_name = elf_group_name (sec);
2423*fae548d3Szrj   unsigned int i;
2424*fae548d3Szrj   unsigned int *elem_idx;
2425*fae548d3Szrj   unsigned int *idx_ptr;
2426*fae548d3Szrj 
2427*fae548d3Szrj   if (group_name == NULL)
2428*fae548d3Szrj     return;
2429*fae548d3Szrj 
2430*fae548d3Szrj   /* If this group already has a list, add the section to the head of
2431*fae548d3Szrj      the list.  */
2432*fae548d3Szrj   elem_idx = (unsigned int *) hash_find (list->indexes, group_name);
2433*fae548d3Szrj   if (elem_idx != NULL)
2434*fae548d3Szrj     {
2435*fae548d3Szrj       elf_next_in_group (sec) = list->head[*elem_idx];
2436*fae548d3Szrj       list->head[*elem_idx] = sec;
2437*fae548d3Szrj       return;
2438*fae548d3Szrj     }
2439*fae548d3Szrj 
2440*fae548d3Szrj   /* New group.  Make the arrays bigger in chunks to minimize calls to
2441*fae548d3Szrj      realloc.  */
2442*fae548d3Szrj   i = list->num_group;
2443*fae548d3Szrj   if ((i & 127) == 0)
2444*fae548d3Szrj     {
2445*fae548d3Szrj       unsigned int newsize = i + 128;
2446*fae548d3Szrj       list->head = XRESIZEVEC (asection *, list->head, newsize);
2447*fae548d3Szrj     }
2448*fae548d3Szrj   list->head[i] = sec;
2449*fae548d3Szrj   list->num_group += 1;
2450*fae548d3Szrj 
2451*fae548d3Szrj   /* Add index to hash.  */
2452*fae548d3Szrj   idx_ptr = XNEW (unsigned int);
2453*fae548d3Szrj   *idx_ptr = i;
2454*fae548d3Szrj   hash_insert (list->indexes, group_name, idx_ptr);
2455*fae548d3Szrj }
2456*fae548d3Szrj 
free_section_idx(const char * key ATTRIBUTE_UNUSED,void * val)2457*fae548d3Szrj static void free_section_idx (const char *key ATTRIBUTE_UNUSED, void *val)
2458*fae548d3Szrj {
2459*fae548d3Szrj   free ((unsigned int *) val);
2460*fae548d3Szrj }
2461*fae548d3Szrj 
2462*fae548d3Szrj /* Create symbols for group signature.  */
2463*fae548d3Szrj 
2464*fae548d3Szrj void
elf_adjust_symtab(void)2465*fae548d3Szrj elf_adjust_symtab (void)
2466*fae548d3Szrj {
2467*fae548d3Szrj   unsigned int i;
2468*fae548d3Szrj 
2469*fae548d3Szrj   /* Go find section groups.  */
2470*fae548d3Szrj   groups.num_group = 0;
2471*fae548d3Szrj   groups.head = NULL;
2472*fae548d3Szrj   groups.indexes = hash_new ();
2473*fae548d3Szrj   bfd_map_over_sections (stdoutput, build_group_lists, &groups);
2474*fae548d3Szrj 
2475*fae548d3Szrj   /* Make the SHT_GROUP sections that describe each section group.  We
2476*fae548d3Szrj      can't set up the section contents here yet, because elf section
2477*fae548d3Szrj      indices have yet to be calculated.  elf.c:set_group_contents does
2478*fae548d3Szrj      the rest of the work.  */
2479*fae548d3Szrj  for (i = 0; i < groups.num_group; i++)
2480*fae548d3Szrj     {
2481*fae548d3Szrj       const char *group_name = elf_group_name (groups.head[i]);
2482*fae548d3Szrj       const char *sec_name;
2483*fae548d3Szrj       asection *s;
2484*fae548d3Szrj       flagword flags;
2485*fae548d3Szrj       struct symbol *sy;
2486*fae548d3Szrj 
2487*fae548d3Szrj       flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
2488*fae548d3Szrj       for (s = groups.head[i]; s != NULL; s = elf_next_in_group (s))
2489*fae548d3Szrj 	if ((s->flags ^ flags) & SEC_LINK_ONCE)
2490*fae548d3Szrj 	  {
2491*fae548d3Szrj 	    flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
2492*fae548d3Szrj 	    if (s != groups.head[i])
2493*fae548d3Szrj 	      {
2494*fae548d3Szrj 		as_warn (_("assuming all members of group `%s' are COMDAT"),
2495*fae548d3Szrj 			 group_name);
2496*fae548d3Szrj 		break;
2497*fae548d3Szrj 	      }
2498*fae548d3Szrj 	  }
2499*fae548d3Szrj 
2500*fae548d3Szrj       sec_name = ".group";
2501*fae548d3Szrj       s = subseg_force_new (sec_name, 0);
2502*fae548d3Szrj       if (s == NULL
2503*fae548d3Szrj 	  || !bfd_set_section_flags (s, flags)
2504*fae548d3Szrj 	  || !bfd_set_section_alignment (s, 2))
2505*fae548d3Szrj 	{
2506*fae548d3Szrj 	  as_fatal (_("can't create group: %s"),
2507*fae548d3Szrj 		    bfd_errmsg (bfd_get_error ()));
2508*fae548d3Szrj 	}
2509*fae548d3Szrj       elf_section_type (s) = SHT_GROUP;
2510*fae548d3Szrj 
2511*fae548d3Szrj       /* Pass a pointer to the first section in this group.  */
2512*fae548d3Szrj       elf_next_in_group (s) = groups.head[i];
2513*fae548d3Szrj       elf_sec_group (groups.head[i]) = s;
2514*fae548d3Szrj       /* Make sure that the signature symbol for the group has the
2515*fae548d3Szrj 	 name of the group.  */
2516*fae548d3Szrj       sy = symbol_find_exact (group_name);
2517*fae548d3Szrj       if (!sy || !symbol_on_chain (sy, symbol_rootP, symbol_lastP))
2518*fae548d3Szrj 	{
2519*fae548d3Szrj 	  /* Create the symbol now.  */
2520*fae548d3Szrj 	  sy = symbol_new (group_name, now_seg, (valueT) 0, frag_now);
2521*fae548d3Szrj #ifdef TE_SOLARIS
2522*fae548d3Szrj 	  /* Before Solaris 11 build 154, Sun ld rejects local group
2523*fae548d3Szrj 	     signature symbols, so make them weak hidden instead.  */
2524*fae548d3Szrj 	  symbol_get_bfdsym (sy)->flags |= BSF_WEAK;
2525*fae548d3Szrj 	  S_SET_OTHER (sy, STV_HIDDEN);
2526*fae548d3Szrj #else
2527*fae548d3Szrj 	  symbol_get_obj (sy)->local = 1;
2528*fae548d3Szrj #endif
2529*fae548d3Szrj 	  symbol_table_insert (sy);
2530*fae548d3Szrj 	}
2531*fae548d3Szrj       elf_group_id (s) = symbol_get_bfdsym (sy);
2532*fae548d3Szrj     }
2533*fae548d3Szrj }
2534*fae548d3Szrj 
2535*fae548d3Szrj void
elf_frob_file(void)2536*fae548d3Szrj elf_frob_file (void)
2537*fae548d3Szrj {
2538*fae548d3Szrj   bfd_map_over_sections (stdoutput, adjust_stab_sections, NULL);
2539*fae548d3Szrj 
2540*fae548d3Szrj #ifdef elf_tc_final_processing
2541*fae548d3Szrj   elf_tc_final_processing ();
2542*fae548d3Szrj #endif
2543*fae548d3Szrj }
2544*fae548d3Szrj 
2545*fae548d3Szrj /* It removes any unneeded versioned symbols from the symbol table.  */
2546*fae548d3Szrj 
2547*fae548d3Szrj void
elf_frob_file_before_adjust(void)2548*fae548d3Szrj elf_frob_file_before_adjust (void)
2549*fae548d3Szrj {
2550*fae548d3Szrj   if (symbol_rootP)
2551*fae548d3Szrj     {
2552*fae548d3Szrj       symbolS *symp;
2553*fae548d3Szrj 
2554*fae548d3Szrj       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
2555*fae548d3Szrj 	if (!S_IS_DEFINED (symp))
2556*fae548d3Szrj 	  {
2557*fae548d3Szrj 	    if (symbol_get_obj (symp)->versioned_name)
2558*fae548d3Szrj 	      {
2559*fae548d3Szrj 		char *p;
2560*fae548d3Szrj 
2561*fae548d3Szrj 		/* The @@@ syntax is a special case. If the symbol is
2562*fae548d3Szrj 		   not defined, 2 `@'s will be removed from the
2563*fae548d3Szrj 		   versioned_name.  */
2564*fae548d3Szrj 
2565*fae548d3Szrj 		p = strchr (symbol_get_obj (symp)->versioned_name,
2566*fae548d3Szrj 			    ELF_VER_CHR);
2567*fae548d3Szrj 		if (p != NULL && p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
2568*fae548d3Szrj 		  {
2569*fae548d3Szrj 		    size_t l = strlen (&p[3]) + 1;
2570*fae548d3Szrj 		    memmove (&p[1], &p[3], l);
2571*fae548d3Szrj 		  }
2572*fae548d3Szrj 		if (symbol_used_p (symp) == 0
2573*fae548d3Szrj 		    && symbol_used_in_reloc_p (symp) == 0)
2574*fae548d3Szrj 		  symbol_remove (symp, &symbol_rootP, &symbol_lastP);
2575*fae548d3Szrj 	      }
2576*fae548d3Szrj 
2577*fae548d3Szrj 	    /* If there was .weak foo, but foo was neither defined nor
2578*fae548d3Szrj 	       used anywhere, remove it.  */
2579*fae548d3Szrj 
2580*fae548d3Szrj 	    else if (S_IS_WEAK (symp)
2581*fae548d3Szrj 		     && symbol_used_p (symp) == 0
2582*fae548d3Szrj 		     && symbol_used_in_reloc_p (symp) == 0)
2583*fae548d3Szrj 	      symbol_remove (symp, &symbol_rootP, &symbol_lastP);
2584*fae548d3Szrj 	  }
2585*fae548d3Szrj     }
2586*fae548d3Szrj }
2587*fae548d3Szrj 
2588*fae548d3Szrj /* It is required that we let write_relocs have the opportunity to
2589*fae548d3Szrj    optimize away fixups before output has begun, since it is possible
2590*fae548d3Szrj    to eliminate all fixups for a section and thus we never should
2591*fae548d3Szrj    have generated the relocation section.  */
2592*fae548d3Szrj 
2593*fae548d3Szrj void
elf_frob_file_after_relocs(void)2594*fae548d3Szrj elf_frob_file_after_relocs (void)
2595*fae548d3Szrj {
2596*fae548d3Szrj   unsigned int i;
2597*fae548d3Szrj 
2598*fae548d3Szrj   /* Set SHT_GROUP section size.  */
2599*fae548d3Szrj   for (i = 0; i < groups.num_group; i++)
2600*fae548d3Szrj     {
2601*fae548d3Szrj       asection *s, *head, *group;
2602*fae548d3Szrj       bfd_size_type size;
2603*fae548d3Szrj 
2604*fae548d3Szrj       head = groups.head[i];
2605*fae548d3Szrj       size = 4;
2606*fae548d3Szrj       for (s = head; s != NULL; s = elf_next_in_group (s))
2607*fae548d3Szrj 	size += (s->flags & SEC_RELOC) != 0 ? 8 : 4;
2608*fae548d3Szrj 
2609*fae548d3Szrj       group = elf_sec_group (head);
2610*fae548d3Szrj       subseg_set (group, 0);
2611*fae548d3Szrj       bfd_set_section_size (group, size);
2612*fae548d3Szrj       group->contents = (unsigned char *) frag_more (size);
2613*fae548d3Szrj       frag_now->fr_fix = frag_now_fix_octets ();
2614*fae548d3Szrj       frag_wane (frag_now);
2615*fae548d3Szrj     }
2616*fae548d3Szrj 
2617*fae548d3Szrj   /* Cleanup hash.  */
2618*fae548d3Szrj   hash_traverse (groups.indexes, free_section_idx);
2619*fae548d3Szrj   hash_die (groups.indexes);
2620*fae548d3Szrj 
2621*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2622*fae548d3Szrj   if (ECOFF_DEBUGGING)
2623*fae548d3Szrj     /* Generate the ECOFF debugging information.  */
2624*fae548d3Szrj     {
2625*fae548d3Szrj       const struct ecoff_debug_swap *debug_swap;
2626*fae548d3Szrj       struct ecoff_debug_info debug;
2627*fae548d3Szrj       char *buf;
2628*fae548d3Szrj       asection *sec;
2629*fae548d3Szrj 
2630*fae548d3Szrj       debug_swap
2631*fae548d3Szrj 	= get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap;
2632*fae548d3Szrj       know (debug_swap != NULL);
2633*fae548d3Szrj       ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
2634*fae548d3Szrj 
2635*fae548d3Szrj       /* Set up the pointers in debug.  */
2636*fae548d3Szrj #define SET(ptr, offset, type) \
2637*fae548d3Szrj     debug.ptr = (type) (buf + debug.symbolic_header.offset)
2638*fae548d3Szrj 
2639*fae548d3Szrj       SET (line, cbLineOffset, unsigned char *);
2640*fae548d3Szrj       SET (external_dnr, cbDnOffset, void *);
2641*fae548d3Szrj       SET (external_pdr, cbPdOffset, void *);
2642*fae548d3Szrj       SET (external_sym, cbSymOffset, void *);
2643*fae548d3Szrj       SET (external_opt, cbOptOffset, void *);
2644*fae548d3Szrj       SET (external_aux, cbAuxOffset, union aux_ext *);
2645*fae548d3Szrj       SET (ss, cbSsOffset, char *);
2646*fae548d3Szrj       SET (external_fdr, cbFdOffset, void *);
2647*fae548d3Szrj       SET (external_rfd, cbRfdOffset, void *);
2648*fae548d3Szrj       /* ssext and external_ext are set up just below.  */
2649*fae548d3Szrj 
2650*fae548d3Szrj #undef SET
2651*fae548d3Szrj 
2652*fae548d3Szrj       /* Set up the external symbols.  */
2653*fae548d3Szrj       debug.ssext = debug.ssext_end = NULL;
2654*fae548d3Szrj       debug.external_ext = debug.external_ext_end = NULL;
2655*fae548d3Szrj       if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, TRUE,
2656*fae548d3Szrj 				       elf_get_extr, elf_set_index))
2657*fae548d3Szrj 	as_fatal (_("failed to set up debugging information: %s"),
2658*fae548d3Szrj 		  bfd_errmsg (bfd_get_error ()));
2659*fae548d3Szrj 
2660*fae548d3Szrj       sec = bfd_get_section_by_name (stdoutput, ".mdebug");
2661*fae548d3Szrj       gas_assert (sec != NULL);
2662*fae548d3Szrj 
2663*fae548d3Szrj       know (!stdoutput->output_has_begun);
2664*fae548d3Szrj 
2665*fae548d3Szrj       /* We set the size of the section, call bfd_set_section_contents
2666*fae548d3Szrj 	 to force the ELF backend to allocate a file position, and then
2667*fae548d3Szrj 	 write out the data.  FIXME: Is this really the best way to do
2668*fae548d3Szrj 	 this?  */
2669*fae548d3Szrj       bfd_set_section_size (sec, bfd_ecoff_debug_size (stdoutput, &debug,
2670*fae548d3Szrj 						       debug_swap));
2671*fae548d3Szrj 
2672*fae548d3Szrj       /* Pass BUF to bfd_set_section_contents because this will
2673*fae548d3Szrj 	 eventually become a call to fwrite, and ISO C prohibits
2674*fae548d3Szrj 	 passing a NULL pointer to a stdio function even if the
2675*fae548d3Szrj 	 pointer will not be used.  */
2676*fae548d3Szrj       if (! bfd_set_section_contents (stdoutput, sec, buf, 0, 0))
2677*fae548d3Szrj 	as_fatal (_("can't start writing .mdebug section: %s"),
2678*fae548d3Szrj 		  bfd_errmsg (bfd_get_error ()));
2679*fae548d3Szrj 
2680*fae548d3Szrj       know (stdoutput->output_has_begun);
2681*fae548d3Szrj       know (sec->filepos != 0);
2682*fae548d3Szrj 
2683*fae548d3Szrj       if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
2684*fae548d3Szrj 				   sec->filepos))
2685*fae548d3Szrj 	as_fatal (_("could not write .mdebug section: %s"),
2686*fae548d3Szrj 		  bfd_errmsg (bfd_get_error ()));
2687*fae548d3Szrj     }
2688*fae548d3Szrj #endif /* NEED_ECOFF_DEBUG */
2689*fae548d3Szrj }
2690*fae548d3Szrj 
2691*fae548d3Szrj static void
elf_generate_asm_lineno(void)2692*fae548d3Szrj elf_generate_asm_lineno (void)
2693*fae548d3Szrj {
2694*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2695*fae548d3Szrj   if (ECOFF_DEBUGGING)
2696*fae548d3Szrj     ecoff_generate_asm_lineno ();
2697*fae548d3Szrj #endif
2698*fae548d3Szrj }
2699*fae548d3Szrj 
2700*fae548d3Szrj static void
elf_process_stab(segT sec ATTRIBUTE_UNUSED,int what ATTRIBUTE_UNUSED,const char * string ATTRIBUTE_UNUSED,int type ATTRIBUTE_UNUSED,int other ATTRIBUTE_UNUSED,int desc ATTRIBUTE_UNUSED)2701*fae548d3Szrj elf_process_stab (segT sec ATTRIBUTE_UNUSED,
2702*fae548d3Szrj 		  int what ATTRIBUTE_UNUSED,
2703*fae548d3Szrj 		  const char *string ATTRIBUTE_UNUSED,
2704*fae548d3Szrj 		  int type ATTRIBUTE_UNUSED,
2705*fae548d3Szrj 		  int other ATTRIBUTE_UNUSED,
2706*fae548d3Szrj 		  int desc ATTRIBUTE_UNUSED)
2707*fae548d3Szrj {
2708*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2709*fae548d3Szrj   if (ECOFF_DEBUGGING)
2710*fae548d3Szrj     ecoff_stab (sec, what, string, type, other, desc);
2711*fae548d3Szrj #endif
2712*fae548d3Szrj }
2713*fae548d3Szrj 
2714*fae548d3Szrj static int
elf_separate_stab_sections(void)2715*fae548d3Szrj elf_separate_stab_sections (void)
2716*fae548d3Szrj {
2717*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2718*fae548d3Szrj   return (!ECOFF_DEBUGGING);
2719*fae548d3Szrj #else
2720*fae548d3Szrj   return 1;
2721*fae548d3Szrj #endif
2722*fae548d3Szrj }
2723*fae548d3Szrj 
2724*fae548d3Szrj static void
elf_init_stab_section(segT seg)2725*fae548d3Szrj elf_init_stab_section (segT seg)
2726*fae548d3Szrj {
2727*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2728*fae548d3Szrj   if (!ECOFF_DEBUGGING)
2729*fae548d3Szrj #endif
2730*fae548d3Szrj     obj_elf_init_stab_section (seg);
2731*fae548d3Szrj }
2732*fae548d3Szrj 
2733*fae548d3Szrj const struct format_ops elf_format_ops =
2734*fae548d3Szrj {
2735*fae548d3Szrj   bfd_target_elf_flavour,
2736*fae548d3Szrj   0,	/* dfl_leading_underscore */
2737*fae548d3Szrj   1,	/* emit_section_symbols */
2738*fae548d3Szrj   elf_begin,
2739*fae548d3Szrj   elf_file_symbol,
2740*fae548d3Szrj   elf_frob_symbol,
2741*fae548d3Szrj   elf_frob_file,
2742*fae548d3Szrj   elf_frob_file_before_adjust,
2743*fae548d3Szrj   0,	/* obj_frob_file_before_fix */
2744*fae548d3Szrj   elf_frob_file_after_relocs,
2745*fae548d3Szrj   elf_s_get_size, elf_s_set_size,
2746*fae548d3Szrj   elf_s_get_align, elf_s_set_align,
2747*fae548d3Szrj   elf_s_get_other,
2748*fae548d3Szrj   elf_s_set_other,
2749*fae548d3Szrj   0,	/* s_get_desc */
2750*fae548d3Szrj   0,	/* s_set_desc */
2751*fae548d3Szrj   0,	/* s_get_type */
2752*fae548d3Szrj   0,	/* s_set_type */
2753*fae548d3Szrj   elf_copy_symbol_attributes,
2754*fae548d3Szrj   elf_generate_asm_lineno,
2755*fae548d3Szrj   elf_process_stab,
2756*fae548d3Szrj   elf_separate_stab_sections,
2757*fae548d3Szrj   elf_init_stab_section,
2758*fae548d3Szrj   elf_sec_sym_ok_for_reloc,
2759*fae548d3Szrj   elf_pop_insert,
2760*fae548d3Szrj #ifdef NEED_ECOFF_DEBUG
2761*fae548d3Szrj   elf_ecoff_set_ext,
2762*fae548d3Szrj #else
2763*fae548d3Szrj   0,	/* ecoff_set_ext */
2764*fae548d3Szrj #endif
2765*fae548d3Szrj   elf_obj_read_begin_hook,
2766*fae548d3Szrj   elf_obj_symbol_new_hook,
2767*fae548d3Szrj   0,
2768*fae548d3Szrj   elf_adjust_symtab
2769*fae548d3Szrj };
2770