This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/binutils.git] / gas / config / obj-som.c
1 /* SOM object file format.
2    Copyright (C) 1993, 1998 Free Software Foundation, Inc.
3
4    This file is part of GAS, the GNU Assembler.
5
6    GAS is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2,
9    or (at your option) any later version.
10
11    GAS is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14    the GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GAS; see the file COPYING.  If not, write to the Free
18    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.
20
21    Written by the Center for Software Science at the University of Utah
22    and by Cygnus Support.  */
23
24 #include "as.h"
25 #include "subsegs.h"
26 #include "aout/stab_gnu.h"
27 #include "obstack.h"
28
29 static void obj_som_weak PARAMS ((int));
30
31 const pseudo_typeS obj_pseudo_table[] =
32 {
33   {"weak", obj_som_weak, 0},
34   {NULL, NULL, 0}
35 };
36
37 static int version_seen = 0;
38 static int copyright_seen = 0;
39 static int compiler_seen = 0;
40
41 /* Unused by SOM.  */
42 void obj_read_begin_hook () {}
43
44 /* Handle a .compiler directive.   This is intended to create the
45    compilation unit auxiliary header for MPE such that the linkeditor
46    can handle SOM extraction from archives. The format of the quoted
47    string is "sourcefile language version" and is delimited by blanks.*/
48
49 void
50 obj_som_compiler (unused)
51      int unused;
52 {
53   char *buf;
54   char c;
55   char *filename;
56   char *language_name;
57   char *p;
58   char *version_id;
59
60   if (compiler_seen)
61     {
62       as_bad ("Only one .compiler pseudo-op per file!");
63       ignore_rest_of_line ();
64       return;
65     }
66
67   SKIP_WHITESPACE ();
68   if (*input_line_pointer == '\"')
69     {
70       buf = input_line_pointer;
71       ++input_line_pointer;
72       while (is_a_char (next_char_of_string ()))
73         ;
74       c = *input_line_pointer;
75       *input_line_pointer = '\000';
76     }
77   else
78     {
79       as_bad ("Expected quoted string");
80       ignore_rest_of_line ();
81       return;
82     }
83
84   /* Parse the quoted string into its component parts.  Skip the
85      quote.  */
86   filename = buf + 1;
87   p = filename;
88   while (*p != ' ' && *p != '\000')
89     p++;
90   if (*p == '\000')
91     {
92       as_bad (".compiler directive missing language and version");
93       return;
94     }
95   *p = '\000';
96
97   language_name = ++p;
98   while (*p != ' ' && *p != '\000') p++;
99   if (*p == '\000')
100     {
101       as_bad (".compiler directive missing version");
102       return;
103     }
104   *p = '\000';
105
106   version_id    = ++p;
107   while (*p != '\000') p++;
108   /* Remove the trailing quote.  */
109   *(--p) = '\000';
110
111   compiler_seen = 1;
112   if (! bfd_som_attach_compilation_unit (stdoutput, filename, language_name,
113                                          "GNU Tools", version_id))
114     {
115       bfd_perror (stdoutput->filename);
116       as_fatal ("FATAL: Attaching compiler header %s", stdoutput->filename);
117     }
118   *input_line_pointer = c;
119   demand_empty_rest_of_line ();
120 }
121
122 /* Handle a .version directive.  */
123
124 void
125 obj_som_version (unused)
126      int unused;
127 {
128   char *version, c;
129
130   if (version_seen)
131     {
132       as_bad (_("Only one .version pseudo-op per file!"));
133       ignore_rest_of_line ();
134       return;
135     }
136
137   SKIP_WHITESPACE ();
138   if (*input_line_pointer == '\"')
139     {
140       version = input_line_pointer;
141       ++input_line_pointer;
142       while (is_a_char (next_char_of_string ()))
143         ;
144       c = *input_line_pointer;
145       *input_line_pointer = '\000';
146     }
147   else
148     {
149       as_bad (_("Expected quoted string"));
150       ignore_rest_of_line ();
151       return;
152     }
153
154   version_seen = 1;
155   if (bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version) == false)
156     {
157       bfd_perror (stdoutput->filename);
158       as_perror (_("FATAL: Attaching version header %s"), stdoutput->filename);
159       exit (EXIT_FAILURE);
160     }
161   *input_line_pointer = c;
162   demand_empty_rest_of_line ();
163 }
164
165 /* Handle a .copyright directive.   This probably isn't complete, but
166    it's of dubious value anyway and (IMHO) not worth the time to finish.
167    If you care about copyright strings that much, you fix it.  */
168
169 void
170 obj_som_copyright (unused)
171      int unused;
172 {
173   char *copyright, c;
174
175   if (copyright_seen)
176     {
177       as_bad (_("Only one .copyright pseudo-op per file!"));
178       ignore_rest_of_line ();
179       return;
180     }
181
182   SKIP_WHITESPACE ();
183   if (*input_line_pointer == '\"')
184     {
185       copyright = input_line_pointer;
186       ++input_line_pointer;
187       while (is_a_char (next_char_of_string ()))
188         ;
189       c = *input_line_pointer;
190       *input_line_pointer = '\000';
191     }
192   else
193     {
194       as_bad (_("Expected quoted string"));
195       ignore_rest_of_line ();
196       return;
197     }
198
199   copyright_seen = 1;
200   if (bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright) == false)
201     {
202       bfd_perror (stdoutput->filename);
203       as_perror (_("FATAL: Attaching copyright header %s"), stdoutput->filename);
204       exit (EXIT_FAILURE);
205     }
206   *input_line_pointer = c;
207   demand_empty_rest_of_line ();
208 }
209
210 /* Perform any initialization necessary for stabs support.
211
212    For SOM we need to create the space which will contain the
213    two stabs subspaces.  Additionally we need to set up the
214    space/subspace relationships and set space/subspace attributes
215    which BFD does not understand.  */
216
217 void
218 obj_som_init_stab_section (seg)
219      segT seg;
220 {
221   segT saved_seg = now_seg;
222   segT space;
223   subsegT saved_subseg = now_subseg;
224   char *p, *file;
225   unsigned int stroff;
226
227   /* Make the space which will contain the debug subspaces.  */
228   space = bfd_make_section_old_way (stdoutput, "$GDB_DEBUG$");
229
230   /* Set SOM specific attributes for the space.  In particular we set
231      the space "defined", "private", "sort_key", and "spnum" values. 
232
233      Due to a bug in pxdb (called by hpux linker), the sort keys
234      of the various stabs spaces/subspaces need to be "small".  We
235      reserve range 72/73 which appear to work well.  */
236   obj_set_section_attributes (space, 1, 1, 72, 2);
237   bfd_set_section_alignment (stdoutput, space, 2);
238
239   /* Set the containing space for both stab sections to be $GDB_DEBUG$
240      (just created above).  Also set some attributes which BFD does
241      not understand.  In particular, access bits, sort keys, and load
242      quadrant.  */
243   obj_set_subsection_attributes (seg, space, 0x1f, 73, 0);
244   bfd_set_section_alignment (stdoutput, seg, 2);
245
246   /* Make some space for the first special stab entry and zero the memory.
247      It contains information about the length of this file's
248      stab string and the like.  Using it avoids the need to 
249      relocate the stab strings.
250
251      The $GDB_STRINGS$ space will be created as a side effect of
252      the call to get_stab_string_offset.  */
253   p = frag_more (12);
254   memset (p, 0, 12);
255   as_where (&file, (unsigned int *) NULL);
256   stroff = get_stab_string_offset (file, "$GDB_STRINGS$");
257   know (stroff == 1);
258   md_number_to_chars (p, stroff, 4);
259   seg_info (seg)->stabu.p = p;
260
261   /* Set the containing space for both stab sections to be $GDB_DEBUG$
262      (just created above).  Also set some attributes which BFD does
263      not understand.  In particular, access bits, sort keys, and load
264      quadrant.  */
265   seg = bfd_get_section_by_name (stdoutput, "$GDB_STRINGS$");
266   obj_set_subsection_attributes (seg, space, 0x1f, 72, 0);
267   bfd_set_section_alignment (stdoutput, seg, 2);
268
269   subseg_set (saved_seg, saved_subseg);
270 }
271
272 /* Fill in the counts in the first entry in a .stabs section.  */
273
274 static void
275 adjust_stab_sections (abfd, sec, xxx)
276      bfd *abfd;
277      asection *sec;
278      PTR xxx;
279 {
280   asection *strsec;
281   char *p;
282   int strsz, nsyms;
283
284   if (strcmp ("$GDB_SYMBOLS$", sec->name))
285     return;
286
287   strsec = bfd_get_section_by_name (abfd, "$GDB_STRINGS$");
288   if (strsec)
289     strsz = bfd_section_size (abfd, strsec);
290   else
291     strsz = 0;
292   nsyms = bfd_section_size (abfd, sec) / 12 - 1;
293
294   p = seg_info (sec)->stabu.p;
295   assert (p != 0);
296
297   bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
298   bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
299 }
300
301 /* Called late in the asssembly phase to adjust the special
302    stab entry and to set the starting address for each code subspace.  */
303
304 void
305 som_frob_file ()
306 {
307   bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
308 }
309
310 static void
311 obj_som_weak (ignore)
312      int ignore ATTRIBUTE_UNUSED;
313 {
314   char *name;
315   int c;
316   symbolS *symbolP;
317  
318   do
319     {
320       name = input_line_pointer;
321       c = get_symbol_end ();
322       symbolP = symbol_find_or_make (name);
323       *input_line_pointer = c;
324       SKIP_WHITESPACE ();
325       S_SET_WEAK (symbolP);
326 #if 0
327       symbol_get_obj (symbolP)->local = 1;
328 #endif
329       if (c == ',')
330         {
331           input_line_pointer++;
332           SKIP_WHITESPACE ();
333           if (*input_line_pointer == '\n')
334             c = '\n';
335         }
336     }
337   while (c == ',');
338   demand_empty_rest_of_line ();
339 }
340