Back to index

cell-binutils  2.17cvs20070401
obj-som.c
Go to the documentation of this file.
00001 /* SOM object file format.
00002    Copyright 1993, 1994, 1998, 2000, 2002, 2003, 2004, 2005, 2006
00003    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    Written by the Center for Software Science at the University of Utah
00023    and by Cygnus Support.  */
00024 
00025 #include "as.h"
00026 #include "subsegs.h"
00027 #include "aout/stab_gnu.h"
00028 #include "obstack.h"
00029 
00030 static int version_seen = 0;
00031 static int copyright_seen = 0;
00032 static int compiler_seen = 0;
00033 
00034 /* Unused by SOM.  */
00035 
00036 void
00037 obj_read_begin_hook (void)
00038 {
00039 }
00040 
00041 /* Handle a .compiler directive.   This is intended to create the
00042    compilation unit auxiliary header for MPE such that the linkeditor
00043    can handle SOM extraction from archives. The format of the quoted
00044    string is "sourcefile language version" and is delimited by blanks.  */
00045 
00046 void
00047 obj_som_compiler (int unused ATTRIBUTE_UNUSED)
00048 {
00049   char *buf;
00050   char c;
00051   char *filename;
00052   char *language_name;
00053   char *p;
00054   char *version_id;
00055 
00056   if (compiler_seen)
00057     {
00058       as_bad ("Only one .compiler pseudo-op per file!");
00059       ignore_rest_of_line ();
00060       return;
00061     }
00062 
00063   SKIP_WHITESPACE ();
00064   if (*input_line_pointer == '\"')
00065     {
00066       buf = input_line_pointer;
00067       ++input_line_pointer;
00068       while (is_a_char (next_char_of_string ()))
00069        ;
00070       c = *input_line_pointer;
00071       *input_line_pointer = '\000';
00072     }
00073   else
00074     {
00075       as_bad ("Expected quoted string");
00076       ignore_rest_of_line ();
00077       return;
00078     }
00079 
00080   /* Parse the quoted string into its component parts.  Skip the
00081      quote.  */
00082   filename = buf + 1;
00083   p = filename;
00084   while (*p != ' ' && *p != '\000')
00085     p++;
00086   if (*p == '\000')
00087     {
00088       as_bad (".compiler directive missing language and version");
00089       return;
00090     }
00091   *p = '\000';
00092 
00093   language_name = ++p;
00094   while (*p != ' ' && *p != '\000')
00095     p++;
00096   if (*p == '\000')
00097     {
00098       as_bad (".compiler directive missing version");
00099       return;
00100     }
00101   *p = '\000';
00102 
00103   version_id = ++p;
00104   while (*p != '\000')
00105     p++;
00106   /* Remove the trailing quote.  */
00107   *(--p) = '\000';
00108 
00109   compiler_seen = 1;
00110   if (! bfd_som_attach_compilation_unit (stdoutput, filename, language_name,
00111                                     "GNU Tools", version_id))
00112     {
00113       bfd_perror (stdoutput->filename);
00114       as_fatal ("FATAL: Attaching compiler header %s", stdoutput->filename);
00115     }
00116   *input_line_pointer = c;
00117   demand_empty_rest_of_line ();
00118 }
00119 
00120 /* Handle a .version directive.  */
00121 
00122 void
00123 obj_som_version (int unused ATTRIBUTE_UNUSED)
00124 {
00125   char *version, c;
00126 
00127   if (version_seen)
00128     {
00129       as_bad (_("Only one .version pseudo-op per file!"));
00130       ignore_rest_of_line ();
00131       return;
00132     }
00133 
00134   SKIP_WHITESPACE ();
00135   if (*input_line_pointer == '\"')
00136     {
00137       version = input_line_pointer;
00138       ++input_line_pointer;
00139       while (is_a_char (next_char_of_string ()))
00140        ;
00141       c = *input_line_pointer;
00142       *input_line_pointer = '\000';
00143     }
00144   else
00145     {
00146       as_bad (_("Expected quoted string"));
00147       ignore_rest_of_line ();
00148       return;
00149     }
00150 
00151   version_seen = 1;
00152   if (!bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version))
00153     as_fatal (_("attaching version header %s: %s"),
00154              stdoutput->filename, bfd_errmsg (bfd_get_error ()));
00155 
00156   *input_line_pointer = c;
00157   demand_empty_rest_of_line ();
00158 }
00159 
00160 /* Handle a .copyright directive.   This probably isn't complete, but
00161    it's of dubious value anyway and (IMHO) not worth the time to finish.
00162    If you care about copyright strings that much, you fix it.  */
00163 
00164 void
00165 obj_som_copyright (int unused ATTRIBUTE_UNUSED)
00166 {
00167   char *copyright, c;
00168 
00169   if (copyright_seen)
00170     {
00171       as_bad (_("Only one .copyright pseudo-op per file!"));
00172       ignore_rest_of_line ();
00173       return;
00174     }
00175 
00176   SKIP_WHITESPACE ();
00177   if (*input_line_pointer == '\"')
00178     {
00179       copyright = input_line_pointer;
00180       ++input_line_pointer;
00181       while (is_a_char (next_char_of_string ()))
00182        ;
00183       c = *input_line_pointer;
00184       *input_line_pointer = '\000';
00185     }
00186   else
00187     {
00188       as_bad (_("Expected quoted string"));
00189       ignore_rest_of_line ();
00190       return;
00191     }
00192 
00193   copyright_seen = 1;
00194   if (!bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright))
00195     as_fatal (_("attaching copyright header %s: %s"),
00196              stdoutput->filename, bfd_errmsg (bfd_get_error ()));
00197 
00198   *input_line_pointer = c;
00199   demand_empty_rest_of_line ();
00200 }
00201 
00202 /* Perform any initialization necessary for stabs support.
00203 
00204    For SOM we need to create the space which will contain the
00205    two stabs subspaces.  Additionally we need to set up the
00206    space/subspace relationships and set space/subspace attributes
00207    which BFD does not understand.  */
00208 
00209 void
00210 obj_som_init_stab_section (segT seg)
00211 {
00212   segT saved_seg = now_seg;
00213   segT space;
00214   subsegT saved_subseg = now_subseg;
00215   char *p, *file;
00216   unsigned int stroff;
00217 
00218   /* Make the space which will contain the debug subspaces.  */
00219   space = bfd_make_section_old_way (stdoutput, "$GDB_DEBUG$");
00220 
00221   /* Set SOM specific attributes for the space.  In particular we set
00222      the space "defined", "private", "sort_key", and "spnum" values.
00223 
00224      Due to a bug in pxdb (called by hpux linker), the sort keys
00225      of the various stabs spaces/subspaces need to be "small".  We
00226      reserve range 72/73 which appear to work well.  */
00227   obj_set_section_attributes (space, 1, 1, 72, 2);
00228   bfd_set_section_alignment (stdoutput, space, 2);
00229 
00230   /* Set the containing space for both stab sections to be $GDB_DEBUG$
00231      (just created above).  Also set some attributes which BFD does
00232      not understand.  In particular, access bits, sort keys, and load
00233      quadrant.  */
00234   obj_set_subsection_attributes (seg, space, 0x1f, 73, 0, 0, 0, 0);
00235   bfd_set_section_alignment (stdoutput, seg, 2);
00236 
00237   /* Make some space for the first special stab entry and zero the memory.
00238      It contains information about the length of this file's
00239      stab string and the like.  Using it avoids the need to
00240      relocate the stab strings.
00241 
00242      The $GDB_STRINGS$ space will be created as a side effect of
00243      the call to get_stab_string_offset.  */
00244   p = frag_more (12);
00245   memset (p, 0, 12);
00246   as_where (&file, (unsigned int *) NULL);
00247   stroff = get_stab_string_offset (file, "$GDB_STRINGS$");
00248   know (stroff == 1);
00249   md_number_to_chars (p, stroff, 4);
00250   seg_info (seg)->stabu.p = p;
00251 
00252   /* Set the containing space for both stab sections to be $GDB_DEBUG$
00253      (just created above).  Also set some attributes which BFD does
00254      not understand.  In particular, access bits, sort keys, and load
00255      quadrant.  */
00256   seg = bfd_get_section_by_name (stdoutput, "$GDB_STRINGS$");
00257   obj_set_subsection_attributes (seg, space, 0x1f, 72, 0, 0, 0, 0);
00258   bfd_set_section_alignment (stdoutput, seg, 2);
00259 
00260   subseg_set (saved_seg, saved_subseg);
00261 }
00262 
00263 /* Fill in the counts in the first entry in a .stabs section.  */
00264 
00265 static void
00266 adjust_stab_sections (bfd *abfd, asection *sec, PTR xxx ATTRIBUTE_UNUSED)
00267 {
00268   asection *strsec;
00269   char *p;
00270   int strsz, nsyms;
00271 
00272   if (strcmp ("$GDB_SYMBOLS$", sec->name))
00273     return;
00274 
00275   strsec = bfd_get_section_by_name (abfd, "$GDB_STRINGS$");
00276   if (strsec)
00277     strsz = bfd_section_size (abfd, strsec);
00278   else
00279     strsz = 0;
00280   nsyms = bfd_section_size (abfd, sec) / 12 - 1;
00281 
00282   p = seg_info (sec)->stabu.p;
00283   assert (p != 0);
00284 
00285   bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
00286   bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
00287 }
00288 
00289 /* Called late in the assembly phase to adjust the special
00290    stab entry and to set the starting address for each code subspace.  */
00291 
00292 void
00293 som_frob_file (void)
00294 {
00295   bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
00296 }
00297 
00298 static void
00299 obj_som_weak (int ignore ATTRIBUTE_UNUSED)
00300 {
00301   char *name;
00302   int c;
00303   symbolS *symbolP;
00304 
00305   do
00306     {
00307       name = input_line_pointer;
00308       c = get_symbol_end ();
00309       symbolP = symbol_find_or_make (name);
00310       *input_line_pointer = c;
00311       SKIP_WHITESPACE ();
00312       S_SET_WEAK (symbolP);
00313       if (c == ',')
00314        {
00315          input_line_pointer++;
00316          SKIP_WHITESPACE ();
00317          if (*input_line_pointer == '\n')
00318            c = '\n';
00319        }
00320     }
00321   while (c == ',');
00322   demand_empty_rest_of_line ();
00323 }
00324 
00325 const pseudo_typeS obj_pseudo_table[] =
00326 {
00327   {"weak", obj_som_weak, 0},
00328   {NULL, NULL, 0}
00329 };