Back to index

cell-binutils  2.17cvs20070401
obj-elf.c
Go to the documentation of this file.
00001 /* ELF object file format
00002    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
00003    2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
00004 
00005    This file is part of GAS, the GNU Assembler.
00006 
00007    GAS is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as
00009    published by the Free Software Foundation; either version 2,
00010    or (at your option) any later version.
00011 
00012    GAS is distributed in the hope that it will be useful, but
00013    WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
00015    the GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with GAS; see the file COPYING.  If not, write to the Free
00019    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 #define OBJ_HEADER "obj-elf.h"
00023 #include "as.h"
00024 #include "safe-ctype.h"
00025 #include "subsegs.h"
00026 #include "obstack.h"
00027 #include "struc-symbol.h"
00028 #include "dwarf2dbg.h"
00029 
00030 #ifndef ECOFF_DEBUGGING
00031 #define ECOFF_DEBUGGING 0
00032 #else
00033 #define NEED_ECOFF_DEBUG
00034 #endif
00035 
00036 #ifdef NEED_ECOFF_DEBUG
00037 #include "ecoff.h"
00038 #endif
00039 
00040 #ifdef TC_ALPHA
00041 #include "elf/alpha.h"
00042 #endif
00043 
00044 #ifdef TC_MIPS
00045 #include "elf/mips.h"
00046 #endif
00047 
00048 #ifdef TC_PPC
00049 #include "elf/ppc.h"
00050 #endif
00051 
00052 #ifdef TC_I370
00053 #include "elf/i370.h"
00054 #endif
00055 
00056 #ifdef TC_I386
00057 #include "elf/x86-64.h"
00058 #endif
00059 
00060 #ifdef TC_MEP
00061 #include "elf/mep.h"
00062 #endif
00063 
00064 static void obj_elf_line (int);
00065 static void obj_elf_size (int);
00066 static void obj_elf_type (int);
00067 static void obj_elf_ident (int);
00068 static void obj_elf_weak (int);
00069 static void obj_elf_local (int);
00070 static void obj_elf_visibility (int);
00071 static void obj_elf_symver (int);
00072 static void obj_elf_subsection (int);
00073 static void obj_elf_popsection (int);
00074 static void obj_elf_tls_common (int);
00075 static void obj_elf_lcomm (int);
00076 static void obj_elf_struct (int);
00077 
00078 static const pseudo_typeS elf_pseudo_table[] =
00079 {
00080   {"comm", obj_elf_common, 0},
00081   {"common", obj_elf_common, 1},
00082   {"ident", obj_elf_ident, 0},
00083   {"lcomm", obj_elf_lcomm, 0},
00084   {"local", obj_elf_local, 0},
00085   {"previous", obj_elf_previous, 0},
00086   {"section", obj_elf_section, 0},
00087   {"section.s", obj_elf_section, 0},
00088   {"sect", obj_elf_section, 0},
00089   {"sect.s", obj_elf_section, 0},
00090   {"pushsection", obj_elf_section, 1},
00091   {"popsection", obj_elf_popsection, 0},
00092   {"size", obj_elf_size, 0},
00093   {"type", obj_elf_type, 0},
00094   {"version", obj_elf_version, 0},
00095   {"weak", obj_elf_weak, 0},
00096 
00097   /* These define symbol visibility.  */
00098   {"internal", obj_elf_visibility, STV_INTERNAL},
00099   {"hidden", obj_elf_visibility, STV_HIDDEN},
00100   {"protected", obj_elf_visibility, STV_PROTECTED},
00101 
00102   /* These are used for stabs-in-elf configurations.  */
00103   {"line", obj_elf_line, 0},
00104 
00105   /* This is a GNU extension to handle symbol versions.  */
00106   {"symver", obj_elf_symver, 0},
00107 
00108   /* A GNU extension to change subsection only.  */
00109   {"subsection", obj_elf_subsection, 0},
00110 
00111   /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
00112   {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0},
00113   {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0},
00114 
00115   /* These are used for dwarf.  */
00116   {"2byte", cons, 2},
00117   {"4byte", cons, 4},
00118   {"8byte", cons, 8},
00119   /* These are used for dwarf2.  */
00120   { "file", (void (*) (int)) dwarf2_directive_file, 0 },
00121   { "loc",  dwarf2_directive_loc,  0 },
00122   { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
00123 
00124   /* We need to trap the section changing calls to handle .previous.  */
00125   {"data", obj_elf_data, 0},
00126   {"offset", obj_elf_struct, 0},
00127   {"struct", obj_elf_struct, 0},
00128   {"text", obj_elf_text, 0},
00129 
00130   {"tls_common", obj_elf_tls_common, 0},
00131 
00132   /* End sentinel.  */
00133   {NULL, NULL, 0},
00134 };
00135 
00136 static const pseudo_typeS ecoff_debug_pseudo_table[] =
00137 {
00138 #ifdef NEED_ECOFF_DEBUG
00139   /* COFF style debugging information for ECOFF. .ln is not used; .loc
00140      is used instead.  */
00141   { "def",    ecoff_directive_def, 0 },
00142   { "dim",    ecoff_directive_dim, 0 },
00143   { "endef",  ecoff_directive_endef,      0 },
00144   { "file",   ecoff_directive_file,       0 },
00145   { "scl",    ecoff_directive_scl, 0 },
00146   { "tag",    ecoff_directive_tag, 0 },
00147   { "val",    ecoff_directive_val, 0 },
00148 
00149   /* COFF debugging requires pseudo-ops .size and .type, but ELF
00150      already has meanings for those.  We use .esize and .etype
00151      instead.  These are only generated by gcc anyhow.  */
00152   { "esize",  ecoff_directive_size,       0 },
00153   { "etype",  ecoff_directive_type,       0 },
00154 
00155   /* ECOFF specific debugging information.  */
00156   { "begin",  ecoff_directive_begin,      0 },
00157   { "bend",   ecoff_directive_bend,       0 },
00158   { "end",    ecoff_directive_end, 0 },
00159   { "ent",    ecoff_directive_ent, 0 },
00160   { "fmask",  ecoff_directive_fmask,      0 },
00161   { "frame",  ecoff_directive_frame,      0 },
00162   { "loc",    ecoff_directive_loc, 0 },
00163   { "mask",   ecoff_directive_mask,       0 },
00164 
00165   /* Other ECOFF directives.  */
00166   { "extern", ecoff_directive_extern,     0 },
00167 
00168   /* These are used on Irix.  I don't know how to implement them.  */
00169   { "alias",  s_ignore,            0 },
00170   { "bgnb",   s_ignore,            0 },
00171   { "endb",   s_ignore,            0 },
00172   { "lab",    s_ignore,            0 },
00173   { "noalias",       s_ignore,            0 },
00174   { "verstamp",      s_ignore,            0 },
00175   { "vreg",   s_ignore,            0 },
00176 #endif
00177 
00178   {NULL, NULL, 0}                  /* end sentinel */
00179 };
00180 
00181 #undef NO_RELOC
00182 #include "aout/aout64.h"
00183 
00184 /* This is called when the assembler starts.  */
00185 
00186 asection *elf_com_section_ptr;
00187 
00188 void
00189 elf_begin (void)
00190 {
00191   asection *s;
00192 
00193   /* Add symbols for the known sections to the symbol table.  */
00194   s = bfd_get_section_by_name (stdoutput, TEXT_SECTION_NAME);
00195   symbol_table_insert (section_symbol (s));
00196   s = bfd_get_section_by_name (stdoutput, DATA_SECTION_NAME);
00197   symbol_table_insert (section_symbol (s));
00198   s = bfd_get_section_by_name (stdoutput, BSS_SECTION_NAME);
00199   symbol_table_insert (section_symbol (s));
00200   elf_com_section_ptr = bfd_com_section_ptr;
00201 }
00202 
00203 void
00204 elf_pop_insert (void)
00205 {
00206   pop_insert (elf_pseudo_table);
00207   if (ECOFF_DEBUGGING)
00208     pop_insert (ecoff_debug_pseudo_table);
00209 }
00210 
00211 static bfd_vma
00212 elf_s_get_size (symbolS *sym)
00213 {
00214   return S_GET_SIZE (sym);
00215 }
00216 
00217 static void
00218 elf_s_set_size (symbolS *sym, bfd_vma sz)
00219 {
00220   S_SET_SIZE (sym, sz);
00221 }
00222 
00223 static bfd_vma
00224 elf_s_get_align (symbolS *sym)
00225 {
00226   return S_GET_ALIGN (sym);
00227 }
00228 
00229 static void
00230 elf_s_set_align (symbolS *sym, bfd_vma align)
00231 {
00232   S_SET_ALIGN (sym, align);
00233 }
00234 
00235 int
00236 elf_s_get_other (symbolS *sym)
00237 {
00238   return elf_symbol (symbol_get_bfdsym (sym))->internal_elf_sym.st_other;
00239 }
00240 
00241 static void
00242 elf_s_set_other (symbolS *sym, int other)
00243 {
00244   S_SET_OTHER (sym, other);
00245 }
00246 
00247 static int
00248 elf_sec_sym_ok_for_reloc (asection *sec)
00249 {
00250   return obj_sec_sym_ok_for_reloc (sec);
00251 }
00252 
00253 void
00254 elf_file_symbol (const char *s, int appfile)
00255 {
00256   if (!appfile
00257       || symbol_rootP == NULL
00258       || symbol_rootP->bsym == NULL
00259       || (symbol_rootP->bsym->flags & BSF_FILE) == 0)
00260     {
00261       symbolS *sym;
00262 
00263       sym = symbol_new (s, absolute_section, 0, NULL);
00264       symbol_set_frag (sym, &zero_address_frag);
00265       symbol_get_bfdsym (sym)->flags |= BSF_FILE;
00266 
00267       if (symbol_rootP != sym)
00268        {
00269          symbol_remove (sym, &symbol_rootP, &symbol_lastP);
00270          symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
00271 #ifdef DEBUG
00272          verify_symbol_chain (symbol_rootP, symbol_lastP);
00273 #endif
00274        }
00275     }
00276 
00277 #ifdef NEED_ECOFF_DEBUG
00278   ecoff_new_file (s, appfile);
00279 #endif
00280 }
00281 
00282 /* Called from read.c:s_comm after we've parsed .comm symbol, size.
00283    Parse a possible alignment value.  */
00284 
00285 symbolS *
00286 elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
00287 {
00288   addressT align = 0;
00289   int is_local = symbol_get_obj (symbolP)->local;
00290 
00291   if (*input_line_pointer == ',')
00292     {
00293       char *save = input_line_pointer;
00294 
00295       input_line_pointer++;
00296       SKIP_WHITESPACE ();
00297 
00298       if (*input_line_pointer == '"')
00299        {
00300          /* For sparc.  Accept .common symbol, length, "bss"  */
00301          input_line_pointer++;
00302          /* Some use the dot, some don't.  */
00303          if (*input_line_pointer == '.')
00304            input_line_pointer++;
00305          /* Some say data, some say bss.  */
00306          if (strncmp (input_line_pointer, "bss\"", 4) == 0)
00307            input_line_pointer += 4;
00308          else if (strncmp (input_line_pointer, "data\"", 5) == 0)
00309            input_line_pointer += 5;
00310          else
00311            {
00312              char *p = input_line_pointer;
00313              char c;
00314 
00315              while (*--p != '"')
00316               ;
00317              while (!is_end_of_line[(unsigned char) *input_line_pointer])
00318               if (*input_line_pointer++ == '"')
00319                 break;
00320              c = *input_line_pointer;
00321              *input_line_pointer = '\0';
00322              as_bad (_("bad .common segment %s"), p);
00323              *input_line_pointer = c;
00324              ignore_rest_of_line ();
00325              return NULL;
00326            }
00327          /* ??? Don't ask me why these are always global.  */
00328          is_local = 0;
00329        }
00330       else
00331        {
00332          input_line_pointer = save;
00333          align = parse_align (is_local);
00334          if (align == (addressT) -1)
00335            return NULL;
00336        }
00337     }
00338 
00339   if (is_local)
00340     {
00341       bss_alloc (symbolP, size, align);
00342       S_CLEAR_EXTERNAL (symbolP);
00343     }
00344   else
00345     {
00346       S_SET_VALUE (symbolP, size);
00347       S_SET_ALIGN (symbolP, align);
00348       S_SET_EXTERNAL (symbolP);
00349       S_SET_SEGMENT (symbolP, elf_com_section_ptr);
00350     }
00351 
00352   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
00353 
00354   return symbolP;
00355 }
00356 
00357 void
00358 obj_elf_common (int is_common)
00359 {
00360   if (flag_mri && is_common)
00361     s_mri_common (0);
00362   else
00363     s_comm_internal (0, elf_common_parse);
00364 }
00365 
00366 static void
00367 obj_elf_tls_common (int ignore ATTRIBUTE_UNUSED)
00368 {
00369   symbolS *symbolP = s_comm_internal (0, elf_common_parse);
00370 
00371   if (symbolP)
00372     symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
00373 }
00374 
00375 static void
00376 obj_elf_lcomm (int ignore ATTRIBUTE_UNUSED)
00377 {
00378   symbolS *symbolP = s_comm_internal (0, s_lcomm_internal);
00379 
00380   if (symbolP)
00381     symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
00382 }
00383 
00384 static void
00385 obj_elf_local (int ignore ATTRIBUTE_UNUSED)
00386 {
00387   char *name;
00388   int c;
00389   symbolS *symbolP;
00390 
00391   do
00392     {
00393       name = input_line_pointer;
00394       c = get_symbol_end ();
00395       symbolP = symbol_find_or_make (name);
00396       *input_line_pointer = c;
00397       SKIP_WHITESPACE ();
00398       S_CLEAR_EXTERNAL (symbolP);
00399       symbol_get_obj (symbolP)->local = 1;
00400       if (c == ',')
00401        {
00402          input_line_pointer++;
00403          SKIP_WHITESPACE ();
00404          if (*input_line_pointer == '\n')
00405            c = '\n';
00406        }
00407     }
00408   while (c == ',');
00409   demand_empty_rest_of_line ();
00410 }
00411 
00412 static void
00413 obj_elf_weak (int ignore ATTRIBUTE_UNUSED)
00414 {
00415   char *name;
00416   int c;
00417   symbolS *symbolP;
00418 
00419   do
00420     {
00421       name = input_line_pointer;
00422       c = get_symbol_end ();
00423       symbolP = symbol_find_or_make (name);
00424       *input_line_pointer = c;
00425       SKIP_WHITESPACE ();
00426       S_SET_WEAK (symbolP);
00427       symbol_get_obj (symbolP)->local = 1;
00428       if (c == ',')
00429        {
00430          input_line_pointer++;
00431          SKIP_WHITESPACE ();
00432          if (*input_line_pointer == '\n')
00433            c = '\n';
00434        }
00435     }
00436   while (c == ',');
00437   demand_empty_rest_of_line ();
00438 }
00439 
00440 static void
00441 obj_elf_visibility (int visibility)
00442 {
00443   char *name;
00444   int c;
00445   symbolS *symbolP;
00446   asymbol *bfdsym;
00447   elf_symbol_type *elfsym;
00448 
00449   do
00450     {
00451       name = input_line_pointer;
00452       c = get_symbol_end ();
00453       symbolP = symbol_find_or_make (name);
00454       *input_line_pointer = c;
00455 
00456       SKIP_WHITESPACE ();
00457 
00458       bfdsym = symbol_get_bfdsym (symbolP);
00459       elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
00460 
00461       assert (elfsym);
00462 
00463       elfsym->internal_elf_sym.st_other &= ~3;
00464       elfsym->internal_elf_sym.st_other |= visibility;
00465 
00466       if (c == ',')
00467        {
00468          input_line_pointer ++;
00469 
00470          SKIP_WHITESPACE ();
00471 
00472          if (*input_line_pointer == '\n')
00473            c = '\n';
00474        }
00475     }
00476   while (c == ',');
00477 
00478   demand_empty_rest_of_line ();
00479 }
00480 
00481 static segT previous_section;
00482 static int previous_subsection;
00483 
00484 struct section_stack
00485 {
00486   struct section_stack *next;
00487   segT seg, prev_seg;
00488   int subseg, prev_subseg;
00489 };
00490 
00491 static struct section_stack *section_stack;
00492 
00493 static bfd_boolean
00494 get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
00495 {
00496   const char *gname = inf;
00497   const char *group_name = elf_group_name (sec);
00498   
00499   return (group_name == gname
00500          || (group_name != NULL
00501              && gname != NULL
00502              && strcmp (group_name, gname) == 0));
00503 }
00504 
00505 /* Handle the .section pseudo-op.  This code supports two different
00506    syntaxes.
00507 
00508    The first is found on Solaris, and looks like
00509        .section ".sec1",#alloc,#execinstr,#write
00510    Here the names after '#' are the SHF_* flags to turn on for the
00511    section.  I'm not sure how it determines the SHT_* type (BFD
00512    doesn't really give us control over the type, anyhow).
00513 
00514    The second format is found on UnixWare, and probably most SVR4
00515    machines, and looks like
00516        .section .sec1,"a",@progbits
00517    The quoted string may contain any combination of a, w, x, and
00518    represents the SHF_* flags to turn on for the section.  The string
00519    beginning with '@' can be progbits or nobits.  There should be
00520    other possibilities, but I don't know what they are.  In any case,
00521    BFD doesn't really let us set the section type.  */
00522 
00523 void
00524 obj_elf_change_section (const char *name,
00525                      int type,
00526                      int attr,
00527                      int entsize,
00528                      const char *group_name,
00529                      int linkonce,
00530                      int push)
00531 {
00532   asection *old_sec;
00533   segT sec;
00534   flagword flags;
00535   const struct elf_backend_data *bed;
00536   const struct bfd_elf_special_section *ssect;
00537 
00538 #ifdef md_flush_pending_output
00539   md_flush_pending_output ();
00540 #endif
00541 
00542   /* Switch to the section, creating it if necessary.  */
00543   if (push)
00544     {
00545       struct section_stack *elt;
00546       elt = xmalloc (sizeof (struct section_stack));
00547       elt->next = section_stack;
00548       elt->seg = now_seg;
00549       elt->prev_seg = previous_section;
00550       elt->subseg = now_subseg;
00551       elt->prev_subseg = previous_subsection;
00552       section_stack = elt;
00553     }
00554   previous_section = now_seg;
00555   previous_subsection = now_subseg;
00556 
00557   old_sec = bfd_get_section_by_name_if (stdoutput, name, get_section,
00558                                    (void *) group_name);
00559   if (old_sec)
00560     {
00561       sec = old_sec;
00562       subseg_set (sec, 0);
00563     }
00564   else
00565     sec = subseg_force_new (name, 0);
00566 
00567   bed = get_elf_backend_data (stdoutput);
00568   ssect = (*bed->get_sec_type_attr) (stdoutput, sec);
00569 
00570   if (ssect != NULL)
00571     {
00572       bfd_boolean override = FALSE;
00573 
00574       if (type == SHT_NULL)
00575        type = ssect->type;
00576       else if (type != ssect->type)
00577        {
00578          if (old_sec == NULL
00579              /* FIXME: gcc, as of 2002-10-22, will emit
00580 
00581                .section .init_array,"aw",@progbits
00582 
00583                for __attribute__ ((section (".init_array"))).
00584                "@progbits" is incorrect.  Also for x86-64 large bss
00585                sections, gcc, as of 2005-07-06, will emit
00586 
00587                .section .lbss,"aw",@progbits
00588 
00589                "@progbits" is incorrect.  */
00590 #ifdef TC_I386
00591              && (bed->s->arch_size != 64
00592                 || !(ssect->attr & SHF_X86_64_LARGE))
00593 #endif
00594              && ssect->type != SHT_INIT_ARRAY
00595              && ssect->type != SHT_FINI_ARRAY
00596              && ssect->type != SHT_PREINIT_ARRAY)
00597            {
00598              /* We allow to specify any type for a .note section.  */
00599              if (ssect->type != SHT_NOTE)
00600               as_warn (_("setting incorrect section type for %s"),
00601                       name);
00602            }
00603          else
00604            {
00605              as_warn (_("ignoring incorrect section type for %s"),
00606                      name);
00607              type = ssect->type;
00608            }
00609        }
00610 
00611       if (old_sec == NULL && (attr & ~ssect->attr) != 0)
00612        {
00613          /* As a GNU extension, we permit a .note section to be
00614             allocatable.  If the linker sees an allocatable .note
00615             section, it will create a PT_NOTE segment in the output
00616             file.  We also allow "x" for .note.GNU-stack.  */
00617          if (ssect->type == SHT_NOTE
00618              && (attr == SHF_ALLOC || attr == SHF_EXECINSTR))
00619            ;
00620          /* Allow different SHF_MERGE and SHF_STRINGS if we have
00621             something like .rodata.str.  */
00622          else if (ssect->suffix_length == -2
00623                  && name[ssect->prefix_length] == '.'
00624                  && (attr
00625                      & ~ssect->attr
00626                      & ~SHF_MERGE
00627                      & ~SHF_STRINGS) == 0)
00628            ;
00629          /* .interp, .strtab and .symtab can have SHF_ALLOC.  */
00630          else if (attr == SHF_ALLOC
00631                  && (strcmp (name, ".interp") == 0
00632                      || strcmp (name, ".strtab") == 0
00633                      || strcmp (name, ".symtab") == 0))
00634            override = TRUE;
00635          /* .note.GNU-stack can have SHF_EXECINSTR.  */
00636          else if (attr == SHF_EXECINSTR
00637                  && strcmp (name, ".note.GNU-stack") == 0)
00638            override = TRUE;
00639 #ifdef TC_ALPHA
00640          /* A section on Alpha may have SHF_ALPHA_GPREL.  */
00641          else if ((attr & ~ssect->attr) == SHF_ALPHA_GPREL)
00642            override = TRUE;
00643 #endif
00644          else
00645            {
00646              if (group_name == NULL)
00647               as_warn (_("setting incorrect section attributes for %s"),
00648                       name);
00649              override = TRUE;
00650            }
00651        }
00652       if (!override && old_sec == NULL)
00653        attr |= ssect->attr;
00654     }
00655 
00656   /* Convert ELF type and flags to BFD flags.  */
00657   flags = (SEC_RELOC
00658           | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
00659           | ((attr & SHF_ALLOC) ? SEC_ALLOC : 0)
00660           | (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
00661           | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)
00662           | ((attr & SHF_MERGE) ? SEC_MERGE : 0)
00663           | ((attr & SHF_STRINGS) ? SEC_STRINGS : 0)
00664           | ((attr & SHF_TLS) ? SEC_THREAD_LOCAL : 0));
00665 #ifdef md_elf_section_flags
00666   flags = md_elf_section_flags (flags, attr, type);
00667 #endif
00668 
00669   if (linkonce)
00670     flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
00671 
00672   if (old_sec == NULL)
00673     {
00674       symbolS *secsym;
00675 
00676       elf_section_type (sec) = type;
00677       elf_section_flags (sec) = attr;
00678 
00679       /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
00680       if (type == SHT_NOBITS)
00681        seg_info (sec)->bss = 1;
00682 
00683       bfd_set_section_flags (stdoutput, sec, flags);
00684       if (flags & SEC_MERGE)
00685        sec->entsize = entsize;
00686       elf_group_name (sec) = group_name;
00687 
00688       /* Add a symbol for this section to the symbol table.  */
00689       secsym = symbol_find (name);
00690       if (secsym != NULL)
00691        symbol_set_bfdsym (secsym, sec->symbol);
00692       else
00693        symbol_table_insert (section_symbol (sec));
00694     }
00695   else
00696     {
00697       if (type != SHT_NULL
00698          && (unsigned) type != elf_section_type (old_sec))
00699        as_warn (_("ignoring changed section type for %s"), name);
00700 
00701       if (attr != 0)
00702        {
00703          /* If section attributes are specified the second time we see a
00704             particular section, then check that they are the same as we
00705             saw the first time.  */
00706          if (((old_sec->flags ^ flags)
00707               & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
00708                 | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS
00709                 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
00710                 | SEC_THREAD_LOCAL)))
00711            as_warn (_("ignoring changed section attributes for %s"), name);
00712          if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
00713            as_warn (_("ignoring changed section entity size for %s"), name);
00714        }
00715     }
00716 
00717 #ifdef md_elf_section_change_hook
00718   md_elf_section_change_hook ();
00719 #endif
00720 }
00721 
00722 static int
00723 obj_elf_parse_section_letters (char *str, size_t len)
00724 {
00725   int attr = 0;
00726 
00727   while (len > 0)
00728     {
00729       switch (*str)
00730        {
00731        case 'a':
00732          attr |= SHF_ALLOC;
00733          break;
00734        case 'w':
00735          attr |= SHF_WRITE;
00736          break;
00737        case 'x':
00738          attr |= SHF_EXECINSTR;
00739          break;
00740        case 'M':
00741          attr |= SHF_MERGE;
00742          break;
00743        case 'S':
00744          attr |= SHF_STRINGS;
00745          break;
00746        case 'G':
00747          attr |= SHF_GROUP;
00748          break;
00749        case 'T':
00750          attr |= SHF_TLS;
00751          break;
00752        /* Compatibility.  */
00753        case 'm':
00754          if (*(str - 1) == 'a')
00755            {
00756              attr |= SHF_MERGE;
00757              if (len > 1 && str[1] == 's')
00758               {
00759                 attr |= SHF_STRINGS;
00760                 str++, len--;
00761               }
00762              break;
00763            }
00764        default:
00765          {
00766            char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G,T");
00767 #ifdef md_elf_section_letter
00768            int md_attr = md_elf_section_letter (*str, &bad_msg);
00769            if (md_attr >= 0)
00770              attr |= md_attr;
00771            else
00772 #endif
00773              as_fatal ("%s", bad_msg);
00774          }
00775          break;
00776        }
00777       str++, len--;
00778     }
00779 
00780   return attr;
00781 }
00782 
00783 static int
00784 obj_elf_section_word (char *str, size_t len)
00785 {
00786   if (len == 5 && strncmp (str, "write", 5) == 0)
00787     return SHF_WRITE;
00788   if (len == 5 && strncmp (str, "alloc", 5) == 0)
00789     return SHF_ALLOC;
00790   if (len == 9 && strncmp (str, "execinstr", 9) == 0)
00791     return SHF_EXECINSTR;
00792   if (len == 3 && strncmp (str, "tls", 3) == 0)
00793     return SHF_TLS;
00794 
00795 #ifdef md_elf_section_word
00796   {
00797     int md_attr = md_elf_section_word (str, len);
00798     if (md_attr >= 0)
00799       return md_attr;
00800   }
00801 #endif
00802 
00803   as_warn (_("unrecognized section attribute"));
00804   return 0;
00805 }
00806 
00807 static int
00808 obj_elf_section_type (char *str, size_t len)
00809 {
00810   if (len == 8 && strncmp (str, "progbits", 8) == 0)
00811     return SHT_PROGBITS;
00812   if (len == 6 && strncmp (str, "nobits", 6) == 0)
00813     return SHT_NOBITS;
00814   if (len == 4 && strncmp (str, "note", 4) == 0)
00815     return SHT_NOTE;
00816   if (len == 10 && strncmp (str, "init_array", 10) == 0)
00817     return SHT_INIT_ARRAY;
00818   if (len == 10 && strncmp (str, "fini_array", 10) == 0)
00819     return SHT_FINI_ARRAY;
00820   if (len == 13 && strncmp (str, "preinit_array", 13) == 0)
00821     return SHT_PREINIT_ARRAY;
00822 
00823 #ifdef md_elf_section_type
00824   {
00825     int md_type = md_elf_section_type (str, len);
00826     if (md_type >= 0)
00827       return md_type;
00828   }
00829 #endif
00830 
00831   as_warn (_("unrecognized section type"));
00832   return 0;
00833 }
00834 
00835 /* Get name of section.  */
00836 static char *
00837 obj_elf_section_name (void)
00838 {
00839   char *name;
00840 
00841   SKIP_WHITESPACE ();
00842   if (*input_line_pointer == '"')
00843     {
00844       int dummy;
00845 
00846       name = demand_copy_C_string (&dummy);
00847       if (name == NULL)
00848        {
00849          ignore_rest_of_line ();
00850          return NULL;
00851        }
00852     }
00853   else
00854     {
00855       char *end = input_line_pointer;
00856 
00857       while (0 == strchr ("\n\t,; ", *end))
00858        end++;
00859       if (end == input_line_pointer)
00860        {
00861          as_bad (_("missing name"));
00862          ignore_rest_of_line ();
00863          return NULL;
00864        }
00865 
00866       name = xmalloc (end - input_line_pointer + 1);
00867       memcpy (name, input_line_pointer, end - input_line_pointer);
00868       name[end - input_line_pointer] = '\0';
00869 #ifdef tc_canonicalize_section_name
00870       name = tc_canonicalize_section_name (name);
00871 #endif
00872       input_line_pointer = end;
00873     }
00874   SKIP_WHITESPACE ();
00875   return name;
00876 }
00877 
00878 void
00879 obj_elf_section (int push)
00880 {
00881   char *name, *group_name, *beg;
00882   int type, attr, dummy;
00883   int entsize;
00884   int linkonce;
00885 
00886 #ifndef TC_I370
00887   if (flag_mri)
00888     {
00889       char mri_type;
00890 
00891 #ifdef md_flush_pending_output
00892       md_flush_pending_output ();
00893 #endif
00894 
00895       previous_section = now_seg;
00896       previous_subsection = now_subseg;
00897 
00898       s_mri_sect (&mri_type);
00899 
00900 #ifdef md_elf_section_change_hook
00901       md_elf_section_change_hook ();
00902 #endif
00903 
00904       return;
00905     }
00906 #endif /* ! defined (TC_I370) */
00907 
00908   name = obj_elf_section_name ();
00909   if (name == NULL)
00910     return;
00911   type = SHT_NULL;
00912   attr = 0;
00913   group_name = NULL;
00914   entsize = 0;
00915   linkonce = 0;
00916 
00917   if (*input_line_pointer == ',')
00918     {
00919       /* Skip the comma.  */
00920       ++input_line_pointer;
00921       SKIP_WHITESPACE ();
00922 
00923       if (*input_line_pointer == '"')
00924        {
00925          beg = demand_copy_C_string (&dummy);
00926          if (beg == NULL)
00927            {
00928              ignore_rest_of_line ();
00929              return;
00930            }
00931          attr |= obj_elf_parse_section_letters (beg, strlen (beg));
00932 
00933          SKIP_WHITESPACE ();
00934          if (*input_line_pointer == ',')
00935            {
00936              char c;
00937              char *save = input_line_pointer;
00938 
00939              ++input_line_pointer;
00940              SKIP_WHITESPACE ();
00941              c = *input_line_pointer;
00942              if (c == '"')
00943               {
00944                 beg = demand_copy_C_string (&dummy);
00945                 if (beg == NULL)
00946                   {
00947                     ignore_rest_of_line ();
00948                     return;
00949                   }
00950                 type = obj_elf_section_type (beg, strlen (beg));
00951               }
00952              else if (c == '@' || c == '%')
00953               {
00954                 beg = ++input_line_pointer;
00955                 c = get_symbol_end ();
00956                 *input_line_pointer = c;
00957                 type = obj_elf_section_type (beg, input_line_pointer - beg);
00958               }
00959              else
00960               input_line_pointer = save;
00961            }
00962 
00963          SKIP_WHITESPACE ();
00964          if ((attr & SHF_MERGE) != 0 && *input_line_pointer == ',')
00965            {
00966              ++input_line_pointer;
00967              SKIP_WHITESPACE ();
00968              entsize = get_absolute_expression ();
00969              SKIP_WHITESPACE ();
00970              if (entsize < 0)
00971               {
00972                 as_warn (_("invalid merge entity size"));
00973                 attr &= ~SHF_MERGE;
00974                 entsize = 0;
00975               }
00976            }
00977          else if ((attr & SHF_MERGE) != 0)
00978            {
00979              as_warn (_("entity size for SHF_MERGE not specified"));
00980              attr &= ~SHF_MERGE;
00981            }
00982 
00983          if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
00984            {
00985              ++input_line_pointer;
00986              group_name = obj_elf_section_name ();
00987              if (group_name == NULL)
00988               attr &= ~SHF_GROUP;
00989              else if (strncmp (input_line_pointer, ",comdat", 7) == 0)
00990               {
00991                 input_line_pointer += 7;
00992                 linkonce = 1;
00993               }
00994              else if (strncmp (name, ".gnu.linkonce", 13) == 0)
00995               linkonce = 1;
00996            }
00997          else if ((attr & SHF_GROUP) != 0)
00998            {
00999              as_warn (_("group name for SHF_GROUP not specified"));
01000              attr &= ~SHF_GROUP;
01001            }
01002        }
01003       else
01004        {
01005          do
01006            {
01007              char c;
01008 
01009              SKIP_WHITESPACE ();
01010              if (*input_line_pointer != '#')
01011               {
01012                 as_bad (_("character following name is not '#'"));
01013                 ignore_rest_of_line ();
01014                 return;
01015               }
01016              beg = ++input_line_pointer;
01017              c = get_symbol_end ();
01018              *input_line_pointer = c;
01019 
01020              attr |= obj_elf_section_word (beg, input_line_pointer - beg);
01021 
01022              SKIP_WHITESPACE ();
01023            }
01024          while (*input_line_pointer++ == ',');
01025          --input_line_pointer;
01026        }
01027     }
01028 
01029   demand_empty_rest_of_line ();
01030 
01031   obj_elf_change_section (name, type, attr, entsize, group_name, linkonce, push);
01032 }
01033 
01034 /* Change to the .data section.  */
01035 
01036 void
01037 obj_elf_data (int i)
01038 {
01039 #ifdef md_flush_pending_output
01040   md_flush_pending_output ();
01041 #endif
01042 
01043   previous_section = now_seg;
01044   previous_subsection = now_subseg;
01045   s_data (i);
01046 
01047 #ifdef md_elf_section_change_hook
01048   md_elf_section_change_hook ();
01049 #endif
01050 }
01051 
01052 /* Change to the .text section.  */
01053 
01054 void
01055 obj_elf_text (int i)
01056 {
01057 #ifdef md_flush_pending_output
01058   md_flush_pending_output ();
01059 #endif
01060 
01061   previous_section = now_seg;
01062   previous_subsection = now_subseg;
01063   s_text (i);
01064 
01065 #ifdef md_elf_section_change_hook
01066   md_elf_section_change_hook ();
01067 #endif
01068 }
01069 
01070 /* Change to the *ABS* section.  */
01071 
01072 void
01073 obj_elf_struct (int i)
01074 {
01075 #ifdef md_flush_pending_output
01076   md_flush_pending_output ();
01077 #endif
01078 
01079   previous_section = now_seg;
01080   previous_subsection = now_subseg;
01081   s_struct (i);
01082 
01083 #ifdef md_elf_section_change_hook
01084   md_elf_section_change_hook ();
01085 #endif
01086 }
01087 
01088 static void
01089 obj_elf_subsection (int ignore ATTRIBUTE_UNUSED)
01090 {
01091   register int temp;
01092 
01093 #ifdef md_flush_pending_output
01094   md_flush_pending_output ();
01095 #endif
01096 
01097   previous_section = now_seg;
01098   previous_subsection = now_subseg;
01099 
01100   temp = get_absolute_expression ();
01101   subseg_set (now_seg, (subsegT) temp);
01102   demand_empty_rest_of_line ();
01103 
01104 #ifdef md_elf_section_change_hook
01105   md_elf_section_change_hook ();
01106 #endif
01107 }
01108 
01109 /* This can be called from the processor backends if they change
01110    sections.  */
01111 
01112 void
01113 obj_elf_section_change_hook (void)
01114 {
01115   previous_section = now_seg;
01116   previous_subsection = now_subseg;
01117 }
01118 
01119 void
01120 obj_elf_previous (int ignore ATTRIBUTE_UNUSED)
01121 {
01122   segT new_section;
01123   int new_subsection;
01124 
01125   if (previous_section == 0)
01126     {
01127       as_warn (_(".previous without corresponding .section; ignored"));
01128       return;
01129     }
01130 
01131 #ifdef md_flush_pending_output
01132   md_flush_pending_output ();
01133 #endif
01134 
01135   new_section = previous_section;
01136   new_subsection = previous_subsection;
01137   previous_section = now_seg;
01138   previous_subsection = now_subseg;
01139   subseg_set (new_section, new_subsection);
01140 
01141 #ifdef md_elf_section_change_hook
01142   md_elf_section_change_hook ();
01143 #endif
01144 }
01145 
01146 static void
01147 obj_elf_popsection (int xxx ATTRIBUTE_UNUSED)
01148 {
01149   struct section_stack *top = section_stack;
01150 
01151   if (top == NULL)
01152     {
01153       as_warn (_(".popsection without corresponding .pushsection; ignored"));
01154       return;
01155     }
01156 
01157 #ifdef md_flush_pending_output
01158   md_flush_pending_output ();
01159 #endif
01160 
01161   section_stack = top->next;
01162   previous_section = top->prev_seg;
01163   previous_subsection = top->prev_subseg;
01164   subseg_set (top->seg, top->subseg);
01165   free (top);
01166 
01167 #ifdef md_elf_section_change_hook
01168   md_elf_section_change_hook ();
01169 #endif
01170 }
01171 
01172 static void
01173 obj_elf_line (int ignore ATTRIBUTE_UNUSED)
01174 {
01175   /* Assume delimiter is part of expression.  BSD4.2 as fails with
01176      delightful bug, so we are not being incompatible here.  */
01177   new_logical_line (NULL, get_absolute_expression ());
01178   demand_empty_rest_of_line ();
01179 }
01180 
01181 /* This handles the .symver pseudo-op, which is used to specify a
01182    symbol version.  The syntax is ``.symver NAME,SYMVERNAME''.
01183    SYMVERNAME may contain ELF_VER_CHR ('@') characters.  This
01184    pseudo-op causes the assembler to emit a symbol named SYMVERNAME
01185    with the same value as the symbol NAME.  */
01186 
01187 static void
01188 obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
01189 {
01190   char *name;
01191   char c;
01192   char old_lexat;
01193   symbolS *sym;
01194 
01195   name = input_line_pointer;
01196   c = get_symbol_end ();
01197 
01198   sym = symbol_find_or_make (name);
01199 
01200   *input_line_pointer = c;
01201 
01202   SKIP_WHITESPACE ();
01203   if (*input_line_pointer != ',')
01204     {
01205       as_bad (_("expected comma after name in .symver"));
01206       ignore_rest_of_line ();
01207       return;
01208     }
01209 
01210   ++input_line_pointer;
01211   SKIP_WHITESPACE ();
01212   name = input_line_pointer;
01213 
01214   /* Temporarily include '@' in symbol names.  */
01215   old_lexat = lex_type[(unsigned char) '@'];
01216   lex_type[(unsigned char) '@'] |= LEX_NAME;
01217   c = get_symbol_end ();
01218   lex_type[(unsigned char) '@'] = old_lexat;
01219 
01220   if (symbol_get_obj (sym)->versioned_name == NULL)
01221     {
01222       symbol_get_obj (sym)->versioned_name = xstrdup (name);
01223 
01224       *input_line_pointer = c;
01225 
01226       if (strchr (symbol_get_obj (sym)->versioned_name,
01227                 ELF_VER_CHR) == NULL)
01228        {
01229          as_bad (_("missing version name in `%s' for symbol `%s'"),
01230                 symbol_get_obj (sym)->versioned_name,
01231                 S_GET_NAME (sym));
01232          ignore_rest_of_line ();
01233          return;
01234        }
01235     }
01236   else
01237     {
01238       if (strcmp (symbol_get_obj (sym)->versioned_name, name))
01239        {
01240          as_bad (_("multiple versions [`%s'|`%s'] for symbol `%s'"),
01241                 name, symbol_get_obj (sym)->versioned_name,
01242                 S_GET_NAME (sym));
01243          ignore_rest_of_line ();
01244          return;
01245        }
01246 
01247       *input_line_pointer = c;
01248     }
01249 
01250   demand_empty_rest_of_line ();
01251 }
01252 
01253 /* This handles the .vtable_inherit pseudo-op, which is used to indicate
01254    to the linker the hierarchy in which a particular table resides.  The
01255    syntax is ".vtable_inherit CHILDNAME, PARENTNAME".  */
01256 
01257 struct fix *
01258 obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
01259 {
01260   char *cname, *pname;
01261   symbolS *csym, *psym;
01262   char c, bad = 0;
01263 
01264   if (*input_line_pointer == '#')
01265     ++input_line_pointer;
01266 
01267   cname = input_line_pointer;
01268   c = get_symbol_end ();
01269   csym = symbol_find (cname);
01270 
01271   /* GCFIXME: should check that we don't have two .vtable_inherits for
01272      the same child symbol.  Also, we can currently only do this if the
01273      child symbol is already exists and is placed in a fragment.  */
01274 
01275   if (csym == NULL || symbol_get_frag (csym) == NULL)
01276     {
01277       as_bad ("expected `%s' to have already been set for .vtable_inherit",
01278              cname);
01279       bad = 1;
01280     }
01281 
01282   *input_line_pointer = c;
01283 
01284   SKIP_WHITESPACE ();
01285   if (*input_line_pointer != ',')
01286     {
01287       as_bad ("expected comma after name in .vtable_inherit");
01288       ignore_rest_of_line ();
01289       return NULL;
01290     }
01291 
01292   ++input_line_pointer;
01293   SKIP_WHITESPACE ();
01294 
01295   if (*input_line_pointer == '#')
01296     ++input_line_pointer;
01297 
01298   if (input_line_pointer[0] == '0'
01299       && (input_line_pointer[1] == '\0'
01300          || ISSPACE (input_line_pointer[1])))
01301     {
01302       psym = section_symbol (absolute_section);
01303       ++input_line_pointer;
01304     }
01305   else
01306     {
01307       pname = input_line_pointer;
01308       c = get_symbol_end ();
01309       psym = symbol_find_or_make (pname);
01310       *input_line_pointer = c;
01311     }
01312 
01313   demand_empty_rest_of_line ();
01314 
01315   if (bad)
01316     return NULL;
01317 
01318   assert (symbol_get_value_expression (csym)->X_op == O_constant);
01319   return fix_new (symbol_get_frag (csym),
01320                 symbol_get_value_expression (csym)->X_add_number,
01321                 0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
01322 }
01323 
01324 /* This handles the .vtable_entry pseudo-op, which is used to indicate
01325    to the linker that a vtable slot was used.  The syntax is
01326    ".vtable_entry tablename, offset".  */
01327 
01328 struct fix *
01329 obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
01330 {
01331   char *name;
01332   symbolS *sym;
01333   offsetT offset;
01334   char c;
01335 
01336   if (*input_line_pointer == '#')
01337     ++input_line_pointer;
01338 
01339   name = input_line_pointer;
01340   c = get_symbol_end ();
01341   sym = symbol_find_or_make (name);
01342   *input_line_pointer = c;
01343 
01344   SKIP_WHITESPACE ();
01345   if (*input_line_pointer != ',')
01346     {
01347       as_bad ("expected comma after name in .vtable_entry");
01348       ignore_rest_of_line ();
01349       return NULL;
01350     }
01351 
01352   ++input_line_pointer;
01353   if (*input_line_pointer == '#')
01354     ++input_line_pointer;
01355 
01356   offset = get_absolute_expression ();
01357 
01358   demand_empty_rest_of_line ();
01359 
01360   return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
01361                 BFD_RELOC_VTABLE_ENTRY);
01362 }
01363 
01364 void
01365 elf_obj_read_begin_hook (void)
01366 {
01367 #ifdef NEED_ECOFF_DEBUG
01368   if (ECOFF_DEBUGGING)
01369     ecoff_read_begin_hook ();
01370 #endif
01371 }
01372 
01373 void
01374 elf_obj_symbol_new_hook (symbolS *symbolP)
01375 {
01376   struct elf_obj_sy *sy_obj;
01377 
01378   sy_obj = symbol_get_obj (symbolP);
01379   sy_obj->size = NULL;
01380   sy_obj->versioned_name = NULL;
01381 
01382 #ifdef NEED_ECOFF_DEBUG
01383   if (ECOFF_DEBUGGING)
01384     ecoff_symbol_new_hook (symbolP);
01385 #endif
01386 }
01387 
01388 /* When setting one symbol equal to another, by default we probably
01389    want them to have the same "size", whatever it means in the current
01390    context.  */
01391 
01392 void
01393 elf_copy_symbol_attributes (symbolS *dest, symbolS *src)
01394 {
01395   struct elf_obj_sy *srcelf = symbol_get_obj (src);
01396   struct elf_obj_sy *destelf = symbol_get_obj (dest);
01397   if (srcelf->size)
01398     {
01399       if (destelf->size == NULL)
01400        destelf->size = xmalloc (sizeof (expressionS));
01401       *destelf->size = *srcelf->size;
01402     }
01403   else
01404     {
01405       if (destelf->size != NULL)
01406        free (destelf->size);
01407       destelf->size = NULL;
01408     }
01409   S_SET_SIZE (dest, S_GET_SIZE (src));
01410   /* Don't copy visibility.  */
01411   S_SET_OTHER (dest, (ELF_ST_VISIBILITY (S_GET_OTHER (dest))
01412                     | (S_GET_OTHER (src) & ~ELF_ST_VISIBILITY (-1))));
01413 }
01414 
01415 void
01416 obj_elf_version (int ignore ATTRIBUTE_UNUSED)
01417 {
01418   char *name;
01419   unsigned int c;
01420   char *p;
01421   asection *seg = now_seg;
01422   subsegT subseg = now_subseg;
01423   Elf_Internal_Note i_note;
01424   Elf_External_Note e_note;
01425   asection *note_secp = NULL;
01426 
01427   SKIP_WHITESPACE ();
01428   if (*input_line_pointer == '\"')
01429     {
01430       unsigned int len;
01431 
01432       ++input_line_pointer; /* -> 1st char of string.  */
01433       name = input_line_pointer;
01434 
01435       while (is_a_char (c = next_char_of_string ()))
01436        ;
01437       c = *input_line_pointer;
01438       *input_line_pointer = '\0';
01439       *(input_line_pointer - 1) = '\0';
01440       *input_line_pointer = c;
01441 
01442       /* Create the .note section.  */
01443       note_secp = subseg_new (".note", 0);
01444       bfd_set_section_flags (stdoutput,
01445                           note_secp,
01446                           SEC_HAS_CONTENTS | SEC_READONLY);
01447 
01448       /* Process the version string.  */
01449       len = strlen (name) + 1;
01450 
01451       /* PR 3456: Although the name field is padded out to an 4-byte
01452         boundary, the namesz field should not be adjusted.  */
01453       i_note.namesz = len;
01454       i_note.descsz = 0;    /* No description.  */
01455       i_note.type = NT_VERSION;
01456       p = frag_more (sizeof (e_note.namesz));
01457       md_number_to_chars (p, i_note.namesz, sizeof (e_note.namesz));
01458       p = frag_more (sizeof (e_note.descsz));
01459       md_number_to_chars (p, i_note.descsz, sizeof (e_note.descsz));
01460       p = frag_more (sizeof (e_note.type));
01461       md_number_to_chars (p, i_note.type, sizeof (e_note.type));
01462       p = frag_more (len);
01463       memcpy (p, name, len);
01464 
01465       frag_align (2, 0, 0);
01466 
01467       subseg_set (seg, subseg);
01468     }
01469   else
01470     as_bad (_("expected quoted string"));
01471 
01472   demand_empty_rest_of_line ();
01473 }
01474 
01475 static void
01476 obj_elf_size (int ignore ATTRIBUTE_UNUSED)
01477 {
01478   char *name = input_line_pointer;
01479   char c = get_symbol_end ();
01480   char *p;
01481   expressionS exp;
01482   symbolS *sym;
01483 
01484   p = input_line_pointer;
01485   *p = c;
01486   SKIP_WHITESPACE ();
01487   if (*input_line_pointer != ',')
01488     {
01489       *p = 0;
01490       as_bad (_("expected comma after name `%s' in .size directive"), name);
01491       *p = c;
01492       ignore_rest_of_line ();
01493       return;
01494     }
01495   input_line_pointer++;
01496   expression (&exp);
01497   if (exp.X_op == O_absent)
01498     {
01499       as_bad (_("missing expression in .size directive"));
01500       exp.X_op = O_constant;
01501       exp.X_add_number = 0;
01502     }
01503   *p = 0;
01504   sym = symbol_find_or_make (name);
01505   *p = c;
01506   if (exp.X_op == O_constant)
01507     {
01508       S_SET_SIZE (sym, exp.X_add_number);
01509       if (symbol_get_obj (sym)->size)
01510        {
01511          xfree (symbol_get_obj (sym)->size);
01512          symbol_get_obj (sym)->size = NULL;
01513        }
01514     }
01515   else
01516     {
01517       symbol_get_obj (sym)->size = xmalloc (sizeof (expressionS));
01518       *symbol_get_obj (sym)->size = exp;
01519     }
01520   demand_empty_rest_of_line ();
01521 }
01522 
01523 /* Handle the ELF .type pseudo-op.  This sets the type of a symbol.
01524    There are five syntaxes:
01525 
01526    The first (used on Solaris) is
01527        .type SYM,#function
01528    The second (used on UnixWare) is
01529        .type SYM,@function
01530    The third (reportedly to be used on Irix 6.0) is
01531        .type SYM STT_FUNC
01532    The fourth (used on NetBSD/Arm and Linux/ARM) is
01533        .type SYM,%function
01534    The fifth (used on SVR4/860) is
01535        .type SYM,"function"
01536    */
01537 
01538 static void
01539 obj_elf_type (int ignore ATTRIBUTE_UNUSED)
01540 {
01541   char *name;
01542   char c;
01543   int type;
01544   const char *typename;
01545   symbolS *sym;
01546   elf_symbol_type *elfsym;
01547 
01548   name = input_line_pointer;
01549   c = get_symbol_end ();
01550   sym = symbol_find_or_make (name);
01551   elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
01552   *input_line_pointer = c;
01553 
01554   SKIP_WHITESPACE ();
01555   if (*input_line_pointer == ',')
01556     ++input_line_pointer;
01557 
01558   SKIP_WHITESPACE ();
01559   if (   *input_line_pointer == '#'
01560       || *input_line_pointer == '@'
01561       || *input_line_pointer == '"'
01562       || *input_line_pointer == '%')
01563     ++input_line_pointer;
01564 
01565   typename = input_line_pointer;
01566   c = get_symbol_end ();
01567 
01568   type = 0;
01569   if (strcmp (typename, "function") == 0
01570       || strcmp (typename, "STT_FUNC") == 0)
01571     type = BSF_FUNCTION;
01572   else if (strcmp (typename, "object") == 0
01573           || strcmp (typename, "STT_OBJECT") == 0)
01574     type = BSF_OBJECT;
01575   else if (strcmp (typename, "tls_object") == 0
01576           || strcmp (typename, "STT_TLS") == 0)
01577     type = BSF_OBJECT | BSF_THREAD_LOCAL;
01578   else if (strcmp (typename, "notype") == 0
01579           || strcmp (typename, "STT_NOTYPE") == 0)
01580     ;
01581 #ifdef md_elf_symbol_type
01582   else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
01583     ;
01584 #endif
01585   else
01586     as_bad (_("unrecognized symbol type \"%s\""), typename);
01587 
01588   *input_line_pointer = c;
01589 
01590   if (*input_line_pointer == '"')
01591     ++input_line_pointer;
01592 
01593   elfsym->symbol.flags |= type;
01594 
01595   demand_empty_rest_of_line ();
01596 }
01597 
01598 static void
01599 obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
01600 {
01601   static segT comment_section;
01602   segT old_section = now_seg;
01603   int old_subsection = now_subseg;
01604 
01605 #ifdef md_flush_pending_output
01606   md_flush_pending_output ();
01607 #endif
01608 
01609   if (!comment_section)
01610     {
01611       char *p;
01612       comment_section = subseg_new (".comment", 0);
01613       bfd_set_section_flags (stdoutput, comment_section,
01614                           SEC_READONLY | SEC_HAS_CONTENTS);
01615       p = frag_more (1);
01616       *p = 0;
01617     }
01618   else
01619     subseg_set (comment_section, 0);
01620   stringer (1);
01621   subseg_set (old_section, old_subsection);
01622 }
01623 
01624 #ifdef INIT_STAB_SECTION
01625 
01626 /* The first entry in a .stabs section is special.  */
01627 
01628 void
01629 obj_elf_init_stab_section (segT seg)
01630 {
01631   char *file;
01632   char *p;
01633   char *stabstr_name;
01634   unsigned int stroff;
01635 
01636   /* Force the section to align to a longword boundary.  Without this,
01637      UnixWare ar crashes.  */
01638   bfd_set_section_alignment (stdoutput, seg, 2);
01639 
01640   /* Make space for this first symbol.  */
01641   p = frag_more (12);
01642   /* Zero it out.  */
01643   memset (p, 0, 12);
01644   as_where (&file, NULL);
01645   stabstr_name = xmalloc (strlen (segment_name (seg)) + 4);
01646   strcpy (stabstr_name, segment_name (seg));
01647   strcat (stabstr_name, "str");
01648   stroff = get_stab_string_offset (file, stabstr_name);
01649   know (stroff == 1);
01650   md_number_to_chars (p, stroff, 4);
01651   seg_info (seg)->stabu.p = p;
01652 }
01653 
01654 #endif
01655 
01656 /* Fill in the counts in the first entry in a .stabs section.  */
01657 
01658 static void
01659 adjust_stab_sections (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
01660 {
01661   char *name;
01662   asection *strsec;
01663   char *p;
01664   int strsz, nsyms;
01665 
01666   if (strncmp (".stab", sec->name, 5))
01667     return;
01668   if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
01669     return;
01670 
01671   name = alloca (strlen (sec->name) + 4);
01672   strcpy (name, sec->name);
01673   strcat (name, "str");
01674   strsec = bfd_get_section_by_name (abfd, name);
01675   if (strsec)
01676     strsz = bfd_section_size (abfd, strsec);
01677   else
01678     strsz = 0;
01679   nsyms = bfd_section_size (abfd, sec) / 12 - 1;
01680 
01681   p = seg_info (sec)->stabu.p;
01682   assert (p != 0);
01683 
01684   bfd_h_put_16 (abfd, nsyms, p + 6);
01685   bfd_h_put_32 (abfd, strsz, p + 8);
01686 }
01687 
01688 #ifdef NEED_ECOFF_DEBUG
01689 
01690 /* This function is called by the ECOFF code.  It is supposed to
01691    record the external symbol information so that the backend can
01692    write it out correctly.  The ELF backend doesn't actually handle
01693    this at the moment, so we do it ourselves.  We save the information
01694    in the symbol.  */
01695 
01696 void
01697 elf_ecoff_set_ext (symbolS *sym, struct ecoff_extr *ext)
01698 {
01699   symbol_get_bfdsym (sym)->udata.p = ext;
01700 }
01701 
01702 /* This function is called by bfd_ecoff_debug_externals.  It is
01703    supposed to *EXT to the external symbol information, and return
01704    whether the symbol should be used at all.  */
01705 
01706 static bfd_boolean
01707 elf_get_extr (asymbol *sym, EXTR *ext)
01708 {
01709   if (sym->udata.p == NULL)
01710     return FALSE;
01711   *ext = *(EXTR *) sym->udata.p;
01712   return TRUE;
01713 }
01714 
01715 /* This function is called by bfd_ecoff_debug_externals.  It has
01716    nothing to do for ELF.  */
01717 
01718 static void
01719 elf_set_index (asymbol *sym ATTRIBUTE_UNUSED,
01720               bfd_size_type indx ATTRIBUTE_UNUSED)
01721 {
01722 }
01723 
01724 #endif /* NEED_ECOFF_DEBUG */
01725 
01726 void
01727 elf_frob_symbol (symbolS *symp, int *puntp)
01728 {
01729   struct elf_obj_sy *sy_obj;
01730 
01731 #ifdef NEED_ECOFF_DEBUG
01732   if (ECOFF_DEBUGGING)
01733     ecoff_frob_symbol (symp);
01734 #endif
01735 
01736   sy_obj = symbol_get_obj (symp);
01737 
01738   if (sy_obj->size != NULL)
01739     {
01740       switch (sy_obj->size->X_op)
01741        {
01742        case O_subtract:
01743          S_SET_SIZE (symp,
01744                     (S_GET_VALUE (sy_obj->size->X_add_symbol)
01745                      + sy_obj->size->X_add_number
01746                      - S_GET_VALUE (sy_obj->size->X_op_symbol)));
01747          break;
01748        case O_constant:
01749          S_SET_SIZE (symp,
01750                     (S_GET_VALUE (sy_obj->size->X_add_symbol)
01751                      + sy_obj->size->X_add_number));
01752          break;
01753        default:
01754          as_bad (_(".size expression too complicated to fix up"));
01755          break;
01756        }
01757       free (sy_obj->size);
01758       sy_obj->size = NULL;
01759     }
01760 
01761   if (sy_obj->versioned_name != NULL)
01762     {
01763       char *p;
01764 
01765       p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
01766       know (p != NULL);
01767 
01768       /* This symbol was given a new name with the .symver directive.
01769 
01770         If this is an external reference, just rename the symbol to
01771         include the version string.  This will make the relocs be
01772         against the correct versioned symbol.
01773 
01774         If this is a definition, add an alias.  FIXME: Using an alias
01775         will permit the debugging information to refer to the right
01776         symbol.  However, it's not clear whether it is the best
01777         approach.  */
01778 
01779       if (! S_IS_DEFINED (symp))
01780        {
01781          /* Verify that the name isn't using the @@ syntax--this is
01782             reserved for definitions of the default version to link
01783             against.  */
01784          if (p[1] == ELF_VER_CHR)
01785            {
01786              as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"),
01787                     sy_obj->versioned_name);
01788              *puntp = TRUE;
01789            }
01790          S_SET_NAME (symp, sy_obj->versioned_name);
01791        }
01792       else
01793        {
01794          if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
01795            {
01796              size_t l;
01797 
01798              /* The @@@ syntax is a special case. It renames the
01799                symbol name to versioned_name with one `@' removed.  */
01800              l = strlen (&p[3]) + 1;
01801              memmove (&p[2], &p[3], l);
01802              S_SET_NAME (symp, sy_obj->versioned_name);
01803            }
01804          else
01805            {
01806              symbolS *symp2;
01807 
01808              /* FIXME: Creating a new symbol here is risky.  We're
01809                in the final loop over the symbol table.  We can
01810                get away with it only because the symbol goes to
01811                the end of the list, where the loop will still see
01812                it.  It would probably be better to do this in
01813                obj_frob_file_before_adjust.  */
01814 
01815              symp2 = symbol_find_or_make (sy_obj->versioned_name);
01816 
01817              /* Now we act as though we saw symp2 = sym.  */
01818 
01819              S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
01820 
01821              /* Subtracting out the frag address here is a hack
01822                because we are in the middle of the final loop.  */
01823              S_SET_VALUE (symp2,
01824                         (S_GET_VALUE (symp)
01825                          - symbol_get_frag (symp)->fr_address));
01826 
01827              symbol_set_frag (symp2, symbol_get_frag (symp));
01828 
01829              /* This will copy over the size information.  */
01830              copy_symbol_attributes (symp2, symp);
01831 
01832              S_SET_OTHER (symp2, S_GET_OTHER (symp));
01833 
01834              if (S_IS_WEAK (symp))
01835               S_SET_WEAK (symp2);
01836 
01837              if (S_IS_EXTERNAL (symp))
01838               S_SET_EXTERNAL (symp2);
01839            }
01840        }
01841     }
01842 
01843   /* Double check weak symbols.  */
01844   if (S_IS_WEAK (symp))
01845     {
01846       if (S_IS_COMMON (symp))
01847        as_bad (_("symbol `%s' can not be both weak and common"),
01848               S_GET_NAME (symp));
01849     }
01850 
01851 #ifdef TC_MIPS
01852   /* The Irix 5 and 6 assemblers set the type of any common symbol and
01853      any undefined non-function symbol to STT_OBJECT.  We try to be
01854      compatible, since newer Irix 5 and 6 linkers care.  However, we
01855      only set undefined symbols to be STT_OBJECT if we are on Irix,
01856      because that is the only time gcc will generate the necessary
01857      .global directives to mark functions.  */
01858 
01859   if (S_IS_COMMON (symp))
01860     symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
01861 
01862   if (strstr (TARGET_OS, "irix") != NULL
01863       && ! S_IS_DEFINED (symp)
01864       && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0)
01865     symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
01866 #endif
01867 }
01868 
01869 struct group_list
01870 {
01871   asection **head;          /* Section lists.  */
01872   unsigned int *elt_count;  /* Number of sections in each list.  */
01873   unsigned int num_group;   /* Number of lists.  */
01874 };
01875 
01876 /* Called via bfd_map_over_sections.  If SEC is a member of a group,
01877    add it to a list of sections belonging to the group.  INF is a
01878    pointer to a struct group_list, which is where we store the head of
01879    each list.  */
01880 
01881 static void
01882 build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
01883 {
01884   struct group_list *list = inf;
01885   const char *group_name = elf_group_name (sec);
01886   unsigned int i;
01887 
01888   if (group_name == NULL)
01889     return;
01890 
01891   /* If this group already has a list, add the section to the head of
01892      the list.  */
01893   for (i = 0; i < list->num_group; i++)
01894     {
01895       if (strcmp (group_name, elf_group_name (list->head[i])) == 0)
01896        {
01897          elf_next_in_group (sec) = list->head[i];
01898          list->head[i] = sec;
01899          list->elt_count[i] += 1;
01900          return;
01901        }
01902     }
01903 
01904   /* New group.  Make the arrays bigger in chunks to minimize calls to
01905      realloc.  */
01906   i = list->num_group;
01907   if ((i & 127) == 0)
01908     {
01909       unsigned int newsize = i + 128;
01910       list->head = xrealloc (list->head, newsize * sizeof (*list->head));
01911       list->elt_count = xrealloc (list->elt_count,
01912                               newsize * sizeof (*list->elt_count));
01913     }
01914   list->head[i] = sec;
01915   list->elt_count[i] = 1;
01916   list->num_group += 1;
01917 }
01918 
01919 void
01920 elf_frob_file (void)
01921 {
01922   struct group_list list;
01923   unsigned int i;
01924 
01925   bfd_map_over_sections (stdoutput, adjust_stab_sections, NULL);
01926 
01927   /* Go find section groups.  */
01928   list.num_group = 0;
01929   list.head = NULL;
01930   list.elt_count = NULL;
01931   bfd_map_over_sections (stdoutput, build_group_lists, &list);
01932 
01933   /* Make the SHT_GROUP sections that describe each section group.  We
01934      can't set up the section contents here yet, because elf section
01935      indices have yet to be calculated.  elf.c:set_group_contents does
01936      the rest of the work.  */
01937   for (i = 0; i < list.num_group; i++)
01938     {
01939       const char *group_name = elf_group_name (list.head[i]);
01940       const char *sec_name;
01941       asection *s;
01942       flagword flags;
01943       struct symbol *sy;
01944       int has_sym;
01945       bfd_size_type size;
01946 
01947       flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
01948       for (s = list.head[i]; s != NULL; s = elf_next_in_group (s))
01949        if ((s->flags ^ flags) & SEC_LINK_ONCE)
01950          {
01951            flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
01952            if (s != list.head[i])
01953              {
01954               as_warn (_("assuming all members of group `%s' are COMDAT"),
01955                       group_name);
01956               break;
01957              }
01958          }
01959 
01960       sec_name = group_name;
01961       sy = symbol_find_exact (group_name);
01962       has_sym = 0;
01963       if (sy != NULL
01964          && (sy == symbol_lastP
01965              || (sy->sy_next != NULL
01966                 && sy->sy_next->sy_previous == sy)))
01967        {
01968          has_sym = 1;
01969          sec_name = ".group";
01970        }
01971       s = subseg_force_new (sec_name, 0);
01972       if (s == NULL
01973          || !bfd_set_section_flags (stdoutput, s, flags)
01974          || !bfd_set_section_alignment (stdoutput, s, 2))
01975        {
01976          as_fatal (_("can't create group: %s"),
01977                   bfd_errmsg (bfd_get_error ()));
01978        }
01979       elf_section_type (s) = SHT_GROUP;
01980 
01981       /* Pass a pointer to the first section in this group.  */
01982       elf_next_in_group (s) = list.head[i];
01983       if (has_sym)
01984        elf_group_id (s) = sy->bsym;
01985 
01986       size = 4 * (list.elt_count[i] + 1);
01987       bfd_set_section_size (stdoutput, s, size);
01988       s->contents = (unsigned char *) frag_more (size);
01989       frag_now->fr_fix = frag_now_fix_octets ();
01990       frag_wane (frag_now);
01991     }
01992 
01993 #ifdef elf_tc_final_processing
01994   elf_tc_final_processing ();
01995 #endif
01996 }
01997 
01998 /* It removes any unneeded versioned symbols from the symbol table.  */
01999 
02000 void
02001 elf_frob_file_before_adjust (void)
02002 {
02003   if (symbol_rootP)
02004     {
02005       symbolS *symp;
02006 
02007       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
02008        if (!S_IS_DEFINED (symp))
02009          {
02010            if (symbol_get_obj (symp)->versioned_name)
02011              {
02012               char *p;
02013 
02014               /* The @@@ syntax is a special case. If the symbol is
02015                  not defined, 2 `@'s will be removed from the
02016                  versioned_name.  */
02017 
02018               p = strchr (symbol_get_obj (symp)->versioned_name,
02019                          ELF_VER_CHR);
02020               know (p != NULL);
02021               if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
02022                 {
02023                   size_t l = strlen (&p[3]) + 1;
02024                   memmove (&p[1], &p[3], l);
02025                 }
02026               if (symbol_used_p (symp) == 0
02027                   && symbol_used_in_reloc_p (symp) == 0)
02028                 symbol_remove (symp, &symbol_rootP, &symbol_lastP);
02029              }
02030 
02031            /* If there was .weak foo, but foo was neither defined nor
02032               used anywhere, remove it.  */
02033 
02034            else if (S_IS_WEAK (symp)
02035                    && symbol_used_p (symp) == 0
02036                    && symbol_used_in_reloc_p (symp) == 0)
02037              symbol_remove (symp, &symbol_rootP, &symbol_lastP);
02038          }
02039     }
02040 }
02041 
02042 /* It is required that we let write_relocs have the opportunity to
02043    optimize away fixups before output has begun, since it is possible
02044    to eliminate all fixups for a section and thus we never should
02045    have generated the relocation section.  */
02046 
02047 void
02048 elf_frob_file_after_relocs (void)
02049 {
02050 #ifdef NEED_ECOFF_DEBUG
02051   if (ECOFF_DEBUGGING)
02052     /* Generate the ECOFF debugging information.  */
02053     {
02054       const struct ecoff_debug_swap *debug_swap;
02055       struct ecoff_debug_info debug;
02056       char *buf;
02057       asection *sec;
02058 
02059       debug_swap
02060        = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap;
02061       know (debug_swap != NULL);
02062       ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
02063 
02064       /* Set up the pointers in debug.  */
02065 #define SET(ptr, offset, type) \
02066     debug.ptr = (type) (buf + debug.symbolic_header.offset)
02067 
02068       SET (line, cbLineOffset, unsigned char *);
02069       SET (external_dnr, cbDnOffset, void *);
02070       SET (external_pdr, cbPdOffset, void *);
02071       SET (external_sym, cbSymOffset, void *);
02072       SET (external_opt, cbOptOffset, void *);
02073       SET (external_aux, cbAuxOffset, union aux_ext *);
02074       SET (ss, cbSsOffset, char *);
02075       SET (external_fdr, cbFdOffset, void *);
02076       SET (external_rfd, cbRfdOffset, void *);
02077       /* ssext and external_ext are set up just below.  */
02078 
02079 #undef SET
02080 
02081       /* Set up the external symbols.  */
02082       debug.ssext = debug.ssext_end = NULL;
02083       debug.external_ext = debug.external_ext_end = NULL;
02084       if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, TRUE,
02085                                    elf_get_extr, elf_set_index))
02086        as_fatal (_("failed to set up debugging information: %s"),
02087                 bfd_errmsg (bfd_get_error ()));
02088 
02089       sec = bfd_get_section_by_name (stdoutput, ".mdebug");
02090       assert (sec != NULL);
02091 
02092       know (!stdoutput->output_has_begun);
02093 
02094       /* We set the size of the section, call bfd_set_section_contents
02095         to force the ELF backend to allocate a file position, and then
02096         write out the data.  FIXME: Is this really the best way to do
02097         this?  */
02098       bfd_set_section_size
02099        (stdoutput, sec, bfd_ecoff_debug_size (stdoutput, &debug, debug_swap));
02100 
02101       /* Pass BUF to bfd_set_section_contents because this will
02102         eventually become a call to fwrite, and ISO C prohibits
02103         passing a NULL pointer to a stdio function even if the
02104         pointer will not be used.  */
02105       if (! bfd_set_section_contents (stdoutput, sec, buf, 0, 0))
02106        as_fatal (_("can't start writing .mdebug section: %s"),
02107                 bfd_errmsg (bfd_get_error ()));
02108 
02109       know (stdoutput->output_has_begun);
02110       know (sec->filepos != 0);
02111 
02112       if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
02113                                sec->filepos))
02114        as_fatal (_("could not write .mdebug section: %s"),
02115                 bfd_errmsg (bfd_get_error ()));
02116     }
02117 #endif /* NEED_ECOFF_DEBUG */
02118 }
02119 
02120 #ifdef SCO_ELF
02121 
02122 /* Heavily plagiarized from obj_elf_version.  The idea is to emit the
02123    SCO specific identifier in the .notes section to satisfy the SCO
02124    linker.
02125 
02126    This looks more complicated than it really is.  As opposed to the
02127    "obvious" solution, this should handle the cross dev cases
02128    correctly.  (i.e, hosting on a 64 bit big endian processor, but
02129    generating SCO Elf code) Efficiency isn't a concern, as there
02130    should be exactly one of these sections per object module.
02131 
02132    SCO OpenServer 5 identifies it's ELF modules with a standard ELF
02133    .note section.
02134 
02135    int_32 namesz  = 4 ;  Name size
02136    int_32 descsz  = 12 ; Descriptive information
02137    int_32 type    = 1 ;
02138    char   name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
02139    int_32 version = (major ver # << 16)  | version of tools ;
02140    int_32 source  = (tool_id << 16 ) | 1 ;
02141    int_32 info    = 0 ;    These are set by the SCO tools, but we
02142                         don't know enough about the source
02143                         environment to set them.  SCO ld currently
02144                         ignores them, and recommends we set them
02145                         to zero.  */
02146 
02147 #define SCO_MAJOR_VERSION 0x1
02148 #define SCO_MINOR_VERSION 0x1
02149 
02150 void
02151 sco_id (void)
02152 {
02153 
02154   char *name;
02155   unsigned int c;
02156   char ch;
02157   char *p;
02158   asection *seg = now_seg;
02159   subsegT subseg = now_subseg;
02160   Elf_Internal_Note i_note;
02161   Elf_External_Note e_note;
02162   asection *note_secp = NULL;
02163   int i, len;
02164 
02165   /* create the .note section */
02166 
02167   note_secp = subseg_new (".note", 0);
02168   bfd_set_section_flags (stdoutput,
02169                       note_secp,
02170                       SEC_HAS_CONTENTS | SEC_READONLY);
02171 
02172   /* process the version string */
02173 
02174   i_note.namesz = 4;
02175   i_note.descsz = 12;              /* 12 descriptive bytes */
02176   i_note.type = NT_VERSION; /* Contains a version string */
02177 
02178   p = frag_more (sizeof (i_note.namesz));
02179   md_number_to_chars (p, i_note.namesz, 4);
02180 
02181   p = frag_more (sizeof (i_note.descsz));
02182   md_number_to_chars (p, i_note.descsz, 4);
02183 
02184   p = frag_more (sizeof (i_note.type));
02185   md_number_to_chars (p, i_note.type, 4);
02186 
02187   p = frag_more (4);
02188   strcpy (p, "SCO");
02189 
02190   /* Note: this is the version number of the ELF we're representing */
02191   p = frag_more (4);
02192   md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
02193 
02194   /* Here, we pick a magic number for ourselves (yes, I "registered"
02195      it with SCO.  The bottom bit shows that we are compat with the
02196      SCO ABI.  */
02197   p = frag_more (4);
02198   md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
02199 
02200   /* If we knew (or cared) what the source language options were, we'd
02201      fill them in here.  SCO has given us permission to ignore these
02202      and just set them to zero.  */
02203   p = frag_more (4);
02204   md_number_to_chars (p, 0x0000, 4);
02205 
02206   frag_align (2, 0, 0);
02207 
02208   /* We probably can't restore the current segment, for there likely
02209      isn't one yet...  */
02210   if (seg && subseg)
02211     subseg_set (seg, subseg);
02212 
02213 }
02214 
02215 #endif /* SCO_ELF */
02216 
02217 static int
02218 elf_separate_stab_sections (void)
02219 {
02220 #ifdef NEED_ECOFF_DEBUG
02221   return (!ECOFF_DEBUGGING);
02222 #else
02223   return 1;
02224 #endif
02225 }
02226 
02227 static void
02228 elf_init_stab_section (segT seg)
02229 {
02230 #ifdef NEED_ECOFF_DEBUG
02231   if (!ECOFF_DEBUGGING)
02232 #endif
02233     obj_elf_init_stab_section (seg);
02234 }
02235 
02236 const struct format_ops elf_format_ops =
02237 {
02238   bfd_target_elf_flavour,
02239   0,   /* dfl_leading_underscore */
02240   1,   /* emit_section_symbols */
02241   elf_begin,
02242   elf_file_symbol,
02243   elf_frob_symbol,
02244   elf_frob_file,
02245   elf_frob_file_before_adjust,
02246   0,   /* obj_frob_file_before_fix */
02247   elf_frob_file_after_relocs,
02248   elf_s_get_size, elf_s_set_size,
02249   elf_s_get_align, elf_s_set_align,
02250   elf_s_get_other,
02251   elf_s_set_other,
02252   0,   /* s_get_desc */
02253   0,   /* s_set_desc */
02254   0,   /* s_get_type */
02255   0,   /* s_set_type */
02256   elf_copy_symbol_attributes,
02257 #ifdef NEED_ECOFF_DEBUG
02258   ecoff_generate_asm_lineno,
02259   ecoff_stab,
02260 #else
02261   0,   /* generate_asm_lineno */
02262   0,   /* process_stab */
02263 #endif
02264   elf_separate_stab_sections,
02265   elf_init_stab_section,
02266   elf_sec_sym_ok_for_reloc,
02267   elf_pop_insert,
02268 #ifdef NEED_ECOFF_DEBUG
02269   elf_ecoff_set_ext,
02270 #else
02271   0,   /* ecoff_set_ext */
02272 #endif
02273   elf_obj_read_begin_hook,
02274   elf_obj_symbol_new_hook
02275 };