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