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