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