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