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