| 1 | /* coff object file format
 | 
|---|
| 2 |    Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 | 
|---|
| 3 |    1999, 2000, 2001, 2002
 | 
|---|
| 4 |    Free Software Foundation, Inc.
 | 
|---|
| 5 | 
 | 
|---|
| 6 |    This file is part of GAS.
 | 
|---|
| 7 | 
 | 
|---|
| 8 |    GAS is free software; you can redistribute it and/or modify
 | 
|---|
| 9 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 10 |    the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
| 11 |    any later version.
 | 
|---|
| 12 | 
 | 
|---|
| 13 |    GAS is distributed in the hope that it will be useful,
 | 
|---|
| 14 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 15 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 16 |    GNU General Public License for more details.
 | 
|---|
| 17 | 
 | 
|---|
| 18 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 19 |    along with GAS; see the file COPYING.  If not, write to the Free
 | 
|---|
| 20 |    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 | 
|---|
| 21 |    02111-1307, USA.  */
 | 
|---|
| 22 | 
 | 
|---|
| 23 | #define OBJ_HEADER "obj-coff.h"
 | 
|---|
| 24 | 
 | 
|---|
| 25 | #include "as.h"
 | 
|---|
| 26 | #include "obstack.h"
 | 
|---|
| 27 | #include "subsegs.h"
 | 
|---|
| 28 | 
 | 
|---|
| 29 | /* I think this is probably always correct.  */
 | 
|---|
| 30 | #ifndef KEEP_RELOC_INFO
 | 
|---|
| 31 | #define KEEP_RELOC_INFO
 | 
|---|
| 32 | #endif
 | 
|---|
| 33 | 
 | 
|---|
| 34 | /* The BFD_ASSEMBLER version of obj_coff_section will use this macro to set
 | 
|---|
| 35 |    a new section's attributes when a directive has no valid flags or the
 | 
|---|
| 36 |    "w" flag is used. This default should be appropriate for most.  */
 | 
|---|
| 37 | #ifndef TC_COFF_SECTION_DEFAULT_ATTRIBUTES
 | 
|---|
| 38 | #define TC_COFF_SECTION_DEFAULT_ATTRIBUTES (SEC_LOAD | SEC_DATA)
 | 
|---|
| 39 | #endif
 | 
|---|
| 40 | 
 | 
|---|
| 41 | /* This is used to hold the symbol built by a sequence of pseudo-ops
 | 
|---|
| 42 |    from .def and .endef.  */
 | 
|---|
| 43 | static symbolS *def_symbol_in_progress;
 | 
|---|
| 44 | 
 | 
|---|
| 45 | typedef struct
 | 
|---|
| 46 |   {
 | 
|---|
| 47 |     unsigned long chunk_size;
 | 
|---|
| 48 |     unsigned long element_size;
 | 
|---|
| 49 |     unsigned long size;
 | 
|---|
| 50 |     char *data;
 | 
|---|
| 51 |     unsigned long pointer;
 | 
|---|
| 52 |   }
 | 
|---|
| 53 | stack;
 | 
|---|
| 54 | 
 | 
|---|
| 55 | static stack *stack_init PARAMS ((unsigned long, unsigned long));
 | 
|---|
| 56 | static char *stack_push PARAMS ((stack *, char *));
 | 
|---|
| 57 | static char *stack_pop PARAMS ((stack *));
 | 
|---|
| 58 | static void tag_init PARAMS ((void));
 | 
|---|
| 59 | static void tag_insert PARAMS ((const char *, symbolS *));
 | 
|---|
| 60 | static symbolS *tag_find PARAMS ((char *));
 | 
|---|
| 61 | static symbolS *tag_find_or_make PARAMS ((char *));
 | 
|---|
| 62 | static void obj_coff_bss PARAMS ((int));
 | 
|---|
| 63 | static void obj_coff_weak PARAMS ((int));
 | 
|---|
| 64 | const char *s_get_name PARAMS ((symbolS * s));
 | 
|---|
| 65 | static void obj_coff_ln PARAMS ((int));
 | 
|---|
| 66 | static void obj_coff_def PARAMS ((int));
 | 
|---|
| 67 | static void obj_coff_endef PARAMS ((int));
 | 
|---|
| 68 | static void obj_coff_dim PARAMS ((int));
 | 
|---|
| 69 | static void obj_coff_line PARAMS ((int));
 | 
|---|
| 70 | static void obj_coff_size PARAMS ((int));
 | 
|---|
| 71 | static void obj_coff_scl PARAMS ((int));
 | 
|---|
| 72 | static void obj_coff_tag PARAMS ((int));
 | 
|---|
| 73 | static void obj_coff_val PARAMS ((int));
 | 
|---|
| 74 | static void obj_coff_type PARAMS ((int));
 | 
|---|
| 75 | static void obj_coff_ident PARAMS ((int));
 | 
|---|
| 76 | #ifdef BFD_ASSEMBLER
 | 
|---|
| 77 | static void obj_coff_loc PARAMS((int));
 | 
|---|
| 78 | #endif
 | 
|---|
| 79 |  | 
|---|
| 80 | 
 | 
|---|
| 81 | /* stack stuff */
 | 
|---|
| 82 | 
 | 
|---|
| 83 | static stack *
 | 
|---|
| 84 | stack_init (chunk_size, element_size)
 | 
|---|
| 85 |      unsigned long chunk_size;
 | 
|---|
| 86 |      unsigned long element_size;
 | 
|---|
| 87 | {
 | 
|---|
| 88 |   stack *st;
 | 
|---|
| 89 | 
 | 
|---|
| 90 |   st = (stack *) malloc (sizeof (stack));
 | 
|---|
| 91 |   if (!st)
 | 
|---|
| 92 |     return 0;
 | 
|---|
| 93 |   st->data = malloc (chunk_size);
 | 
|---|
| 94 |   if (!st->data)
 | 
|---|
| 95 |     {
 | 
|---|
| 96 |       free (st);
 | 
|---|
| 97 |       return 0;
 | 
|---|
| 98 |     }
 | 
|---|
| 99 |   st->pointer = 0;
 | 
|---|
| 100 |   st->size = chunk_size;
 | 
|---|
| 101 |   st->chunk_size = chunk_size;
 | 
|---|
| 102 |   st->element_size = element_size;
 | 
|---|
| 103 |   return st;
 | 
|---|
| 104 | }
 | 
|---|
| 105 | 
 | 
|---|
| 106 | #if 0
 | 
|---|
| 107 | /* Not currently used.  */
 | 
|---|
| 108 | static void
 | 
|---|
| 109 | stack_delete (st)
 | 
|---|
| 110 |      stack *st;
 | 
|---|
| 111 | {
 | 
|---|
| 112 |   free (st->data);
 | 
|---|
| 113 |   free (st);
 | 
|---|
| 114 | }
 | 
|---|
| 115 | #endif
 | 
|---|
| 116 | 
 | 
|---|
| 117 | static char *
 | 
|---|
| 118 | stack_push (st, element)
 | 
|---|
| 119 |      stack *st;
 | 
|---|
| 120 |      char *element;
 | 
|---|
| 121 | {
 | 
|---|
| 122 |   if (st->pointer + st->element_size >= st->size)
 | 
|---|
| 123 |     {
 | 
|---|
| 124 |       st->size += st->chunk_size;
 | 
|---|
| 125 |       if ((st->data = xrealloc (st->data, st->size)) == (char *) 0)
 | 
|---|
| 126 |         return (char *) 0;
 | 
|---|
| 127 |     }
 | 
|---|
| 128 |   memcpy (st->data + st->pointer, element, st->element_size);
 | 
|---|
| 129 |   st->pointer += st->element_size;
 | 
|---|
| 130 |   return st->data + st->pointer;
 | 
|---|
| 131 | }
 | 
|---|
| 132 | 
 | 
|---|
| 133 | static char *
 | 
|---|
| 134 | stack_pop (st)
 | 
|---|
| 135 |      stack *st;
 | 
|---|
| 136 | {
 | 
|---|
| 137 |   if (st->pointer < st->element_size)
 | 
|---|
| 138 |     {
 | 
|---|
| 139 |       st->pointer = 0;
 | 
|---|
| 140 |       return (char *) 0;
 | 
|---|
| 141 |     }
 | 
|---|
| 142 |   st->pointer -= st->element_size;
 | 
|---|
| 143 |   return st->data + st->pointer;
 | 
|---|
| 144 | }
 | 
|---|
| 145 |  | 
|---|
| 146 | 
 | 
|---|
| 147 | /*
 | 
|---|
| 148 |  * Maintain a list of the tagnames of the structres.
 | 
|---|
| 149 |  */
 | 
|---|
| 150 | 
 | 
|---|
| 151 | static struct hash_control *tag_hash;
 | 
|---|
| 152 | 
 | 
|---|
| 153 | static void
 | 
|---|
| 154 | tag_init ()
 | 
|---|
| 155 | {
 | 
|---|
| 156 |   tag_hash = hash_new ();
 | 
|---|
| 157 | }
 | 
|---|
| 158 | 
 | 
|---|
| 159 | static void
 | 
|---|
| 160 | tag_insert (name, symbolP)
 | 
|---|
| 161 |      const char *name;
 | 
|---|
| 162 |      symbolS *symbolP;
 | 
|---|
| 163 | {
 | 
|---|
| 164 |   const char *error_string;
 | 
|---|
| 165 | 
 | 
|---|
| 166 |   if ((error_string = hash_jam (tag_hash, name, (char *) symbolP)))
 | 
|---|
| 167 |     {
 | 
|---|
| 168 |       as_fatal (_("Inserting \"%s\" into structure table failed: %s"),
 | 
|---|
| 169 |                 name, error_string);
 | 
|---|
| 170 |     }
 | 
|---|
| 171 | }
 | 
|---|
| 172 | 
 | 
|---|
| 173 | static symbolS *
 | 
|---|
| 174 | tag_find (name)
 | 
|---|
| 175 |      char *name;
 | 
|---|
| 176 | {
 | 
|---|
| 177 | #ifdef STRIP_UNDERSCORE
 | 
|---|
| 178 |   if (*name == '_')
 | 
|---|
| 179 |     name++;
 | 
|---|
| 180 | #endif /* STRIP_UNDERSCORE */
 | 
|---|
| 181 |   return (symbolS *) hash_find (tag_hash, name);
 | 
|---|
| 182 | }
 | 
|---|
| 183 | 
 | 
|---|
| 184 | static symbolS *
 | 
|---|
| 185 | tag_find_or_make (name)
 | 
|---|
| 186 |      char *name;
 | 
|---|
| 187 | {
 | 
|---|
| 188 |   symbolS *symbolP;
 | 
|---|
| 189 | 
 | 
|---|
| 190 |   if ((symbolP = tag_find (name)) == NULL)
 | 
|---|
| 191 |     {
 | 
|---|
| 192 |       symbolP = symbol_new (name, undefined_section,
 | 
|---|
| 193 |                             0, &zero_address_frag);
 | 
|---|
| 194 | 
 | 
|---|
| 195 |       tag_insert (S_GET_NAME (symbolP), symbolP);
 | 
|---|
| 196 | #ifdef BFD_ASSEMBLER
 | 
|---|
| 197 |       symbol_table_insert (symbolP);
 | 
|---|
| 198 | #endif
 | 
|---|
| 199 |     }                           /* not found */
 | 
|---|
| 200 | 
 | 
|---|
| 201 |   return symbolP;
 | 
|---|
| 202 | }
 | 
|---|
| 203 | 
 | 
|---|
| 204 | /* We accept the .bss directive to set the section for backward
 | 
|---|
| 205 |    compatibility with earlier versions of gas.  */
 | 
|---|
| 206 | 
 | 
|---|
| 207 | static void
 | 
|---|
| 208 | obj_coff_bss (ignore)
 | 
|---|
| 209 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 210 | {
 | 
|---|
| 211 |   if (*input_line_pointer == '\n')
 | 
|---|
| 212 |     subseg_new (".bss", get_absolute_expression ());
 | 
|---|
| 213 |   else
 | 
|---|
| 214 |     s_lcomm (0);
 | 
|---|
| 215 | }
 | 
|---|
| 216 | 
 | 
|---|
| 217 | /* Handle .weak.  This is a GNU extension.  */
 | 
|---|
| 218 | 
 | 
|---|
| 219 | static void
 | 
|---|
| 220 | obj_coff_weak (ignore)
 | 
|---|
| 221 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 222 | {
 | 
|---|
| 223 |   char *name;
 | 
|---|
| 224 |   int c;
 | 
|---|
| 225 |   symbolS *symbolP;
 | 
|---|
| 226 | 
 | 
|---|
| 227 |   do
 | 
|---|
| 228 |     {
 | 
|---|
| 229 |       name = input_line_pointer;
 | 
|---|
| 230 |       c = get_symbol_end ();
 | 
|---|
| 231 |       symbolP = symbol_find_or_make (name);
 | 
|---|
| 232 |       *input_line_pointer = c;
 | 
|---|
| 233 |       SKIP_WHITESPACE ();
 | 
|---|
| 234 | 
 | 
|---|
| 235 | #if defined BFD_ASSEMBLER || defined S_SET_WEAK
 | 
|---|
| 236 |       S_SET_WEAK (symbolP);
 | 
|---|
| 237 | #endif
 | 
|---|
| 238 | 
 | 
|---|
| 239 | #ifdef TE_PE
 | 
|---|
| 240 |       S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
 | 
|---|
| 241 | #else
 | 
|---|
| 242 |       S_SET_STORAGE_CLASS (symbolP, C_WEAKEXT);
 | 
|---|
| 243 | #endif
 | 
|---|
| 244 | 
 | 
|---|
| 245 |       if (c == ',')
 | 
|---|
| 246 |         {
 | 
|---|
| 247 |           input_line_pointer++;
 | 
|---|
| 248 |           SKIP_WHITESPACE ();
 | 
|---|
| 249 |           if (*input_line_pointer == '\n')
 | 
|---|
| 250 |             c = '\n';
 | 
|---|
| 251 |         }
 | 
|---|
| 252 |     }
 | 
|---|
| 253 |   while (c == ',');
 | 
|---|
| 254 | 
 | 
|---|
| 255 |   demand_empty_rest_of_line ();
 | 
|---|
| 256 | }
 | 
|---|
| 257 | 
 | 
|---|
| 258 | #ifdef BFD_ASSEMBLER
 | 
|---|
| 259 | 
 | 
|---|
| 260 | static segT fetch_coff_debug_section PARAMS ((void));
 | 
|---|
| 261 | static void SA_SET_SYM_TAGNDX PARAMS ((symbolS *, symbolS *));
 | 
|---|
| 262 | static int S_GET_DATA_TYPE PARAMS ((symbolS *));
 | 
|---|
| 263 | void c_symbol_merge PARAMS ((symbolS *, symbolS *));
 | 
|---|
| 264 | static void add_lineno PARAMS ((fragS *, addressT, int));
 | 
|---|
| 265 | 
 | 
|---|
| 266 | #define GET_FILENAME_STRING(X) \
 | 
|---|
| 267 | ((char*) (&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
 | 
|---|
| 268 | 
 | 
|---|
| 269 | /* @@ Ick.  */
 | 
|---|
| 270 | static segT
 | 
|---|
| 271 | fetch_coff_debug_section ()
 | 
|---|
| 272 | {
 | 
|---|
| 273 |   static segT debug_section;
 | 
|---|
| 274 |   if (!debug_section)
 | 
|---|
| 275 |     {
 | 
|---|
| 276 |       const asymbol *s;
 | 
|---|
| 277 |       s = bfd_make_debug_symbol (stdoutput, (char *) 0, 0);
 | 
|---|
| 278 |       assert (s != 0);
 | 
|---|
| 279 |       debug_section = s->section;
 | 
|---|
| 280 |     }
 | 
|---|
| 281 |   return debug_section;
 | 
|---|
| 282 | }
 | 
|---|
| 283 | 
 | 
|---|
| 284 | void
 | 
|---|
| 285 | SA_SET_SYM_ENDNDX (sym, val)
 | 
|---|
| 286 |      symbolS *sym;
 | 
|---|
| 287 |      symbolS *val;
 | 
|---|
| 288 | {
 | 
|---|
| 289 |   combined_entry_type *entry, *p;
 | 
|---|
| 290 | 
 | 
|---|
| 291 |   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
 | 
|---|
| 292 |   p = coffsymbol (symbol_get_bfdsym (val))->native;
 | 
|---|
| 293 |   entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p;
 | 
|---|
| 294 |   entry->fix_end = 1;
 | 
|---|
| 295 | }
 | 
|---|
| 296 | 
 | 
|---|
| 297 | static void
 | 
|---|
| 298 | SA_SET_SYM_TAGNDX (sym, val)
 | 
|---|
| 299 |      symbolS *sym;
 | 
|---|
| 300 |      symbolS *val;
 | 
|---|
| 301 | {
 | 
|---|
| 302 |   combined_entry_type *entry, *p;
 | 
|---|
| 303 | 
 | 
|---|
| 304 |   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
 | 
|---|
| 305 |   p = coffsymbol (symbol_get_bfdsym (val))->native;
 | 
|---|
| 306 |   entry->u.auxent.x_sym.x_tagndx.p = p;
 | 
|---|
| 307 |   entry->fix_tag = 1;
 | 
|---|
| 308 | }
 | 
|---|
| 309 | 
 | 
|---|
| 310 | static int
 | 
|---|
| 311 | S_GET_DATA_TYPE (sym)
 | 
|---|
| 312 |      symbolS *sym;
 | 
|---|
| 313 | {
 | 
|---|
| 314 |   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type;
 | 
|---|
| 315 | }
 | 
|---|
| 316 | 
 | 
|---|
| 317 | int
 | 
|---|
| 318 | S_SET_DATA_TYPE (sym, val)
 | 
|---|
| 319 |      symbolS *sym;
 | 
|---|
| 320 |      int val;
 | 
|---|
| 321 | {
 | 
|---|
| 322 |   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type = val;
 | 
|---|
| 323 |   return val;
 | 
|---|
| 324 | }
 | 
|---|
| 325 | 
 | 
|---|
| 326 | int
 | 
|---|
| 327 | S_GET_STORAGE_CLASS (sym)
 | 
|---|
| 328 |      symbolS *sym;
 | 
|---|
| 329 | {
 | 
|---|
| 330 |   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass;
 | 
|---|
| 331 | }
 | 
|---|
| 332 | 
 | 
|---|
| 333 | int
 | 
|---|
| 334 | S_SET_STORAGE_CLASS (sym, val)
 | 
|---|
| 335 |      symbolS *sym;
 | 
|---|
| 336 |      int val;
 | 
|---|
| 337 | {
 | 
|---|
| 338 |   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass = val;
 | 
|---|
| 339 |   return val;
 | 
|---|
| 340 | }
 | 
|---|
| 341 | 
 | 
|---|
| 342 | /* Merge a debug symbol containing debug information into a normal symbol.  */
 | 
|---|
| 343 | 
 | 
|---|
| 344 | void
 | 
|---|
| 345 | c_symbol_merge (debug, normal)
 | 
|---|
| 346 |      symbolS *debug;
 | 
|---|
| 347 |      symbolS *normal;
 | 
|---|
| 348 | {
 | 
|---|
| 349 |   S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
 | 
|---|
| 350 |   S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
 | 
|---|
| 351 | 
 | 
|---|
| 352 |   if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
 | 
|---|
| 353 |     {
 | 
|---|
| 354 |       /* take the most we have */
 | 
|---|
| 355 |       S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
 | 
|---|
| 356 |     }
 | 
|---|
| 357 | 
 | 
|---|
| 358 |   if (S_GET_NUMBER_AUXILIARY (debug) > 0)
 | 
|---|
| 359 |     {
 | 
|---|
| 360 |       /* Move all the auxiliary information.  */
 | 
|---|
| 361 |       memcpy (SYM_AUXINFO (normal), SYM_AUXINFO (debug),
 | 
|---|
| 362 |               (S_GET_NUMBER_AUXILIARY (debug)
 | 
|---|
| 363 |                * sizeof (*SYM_AUXINFO (debug))));
 | 
|---|
| 364 |     }
 | 
|---|
| 365 | 
 | 
|---|
| 366 |   /* Move the debug flags.  */
 | 
|---|
| 367 |   SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
 | 
|---|
| 368 | }
 | 
|---|
| 369 | 
 | 
|---|
| 370 | void
 | 
|---|
| 371 | c_dot_file_symbol (filename)
 | 
|---|
| 372 |      const char *filename;
 | 
|---|
| 373 | {
 | 
|---|
| 374 |   symbolS *symbolP;
 | 
|---|
| 375 | 
 | 
|---|
| 376 |   /* BFD converts filename to a .file symbol with an aux entry.  It
 | 
|---|
| 377 |      also handles chaining.  */
 | 
|---|
| 378 |   symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag);
 | 
|---|
| 379 | 
 | 
|---|
| 380 |   S_SET_STORAGE_CLASS (symbolP, C_FILE);
 | 
|---|
| 381 |   S_SET_NUMBER_AUXILIARY (symbolP, 1);
 | 
|---|
| 382 | 
 | 
|---|
| 383 |   symbol_get_bfdsym (symbolP)->flags = BSF_DEBUGGING;
 | 
|---|
| 384 | 
 | 
|---|
| 385 | #ifndef NO_LISTING
 | 
|---|
| 386 |   {
 | 
|---|
| 387 |     extern int listing;
 | 
|---|
| 388 |     if (listing)
 | 
|---|
| 389 |       {
 | 
|---|
| 390 |         listing_source_file (filename);
 | 
|---|
| 391 |       }
 | 
|---|
| 392 |   }
 | 
|---|
| 393 | #endif
 | 
|---|
| 394 | 
 | 
|---|
| 395 |   /* Make sure that the symbol is first on the symbol chain */
 | 
|---|
| 396 |   if (symbol_rootP != symbolP)
 | 
|---|
| 397 |     {
 | 
|---|
| 398 |       symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 399 |       symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 400 |     }                           /* if not first on the list */
 | 
|---|
| 401 | }
 | 
|---|
| 402 | 
 | 
|---|
| 403 | /* Line number handling */
 | 
|---|
| 404 | 
 | 
|---|
| 405 | struct line_no {
 | 
|---|
| 406 |   struct line_no *next;
 | 
|---|
| 407 |   fragS *frag;
 | 
|---|
| 408 |   alent l;
 | 
|---|
| 409 | };
 | 
|---|
| 410 | 
 | 
|---|
| 411 | int coff_line_base;
 | 
|---|
| 412 | 
 | 
|---|
| 413 | /* Symbol of last function, which we should hang line#s off of.  */
 | 
|---|
| 414 | static symbolS *line_fsym;
 | 
|---|
| 415 | 
 | 
|---|
| 416 | #define in_function()           (line_fsym != 0)
 | 
|---|
| 417 | #define clear_function()        (line_fsym = 0)
 | 
|---|
| 418 | #define set_function(F)         (line_fsym = (F), coff_add_linesym (F))
 | 
|---|
| 419 | 
 | 
|---|
| 420 |  | 
|---|
| 421 | 
 | 
|---|
| 422 | void
 | 
|---|
| 423 | coff_obj_symbol_new_hook (symbolP)
 | 
|---|
| 424 |      symbolS *symbolP;
 | 
|---|
| 425 | {
 | 
|---|
| 426 |   long   sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
 | 
|---|
| 427 |   char * s  = (char *) xmalloc (sz);
 | 
|---|
| 428 | 
 | 
|---|
| 429 |   memset (s, 0, sz);
 | 
|---|
| 430 |   coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s;
 | 
|---|
| 431 | 
 | 
|---|
| 432 |   S_SET_DATA_TYPE (symbolP, T_NULL);
 | 
|---|
| 433 |   S_SET_STORAGE_CLASS (symbolP, 0);
 | 
|---|
| 434 |   S_SET_NUMBER_AUXILIARY (symbolP, 0);
 | 
|---|
| 435 | 
 | 
|---|
| 436 |   if (S_IS_STRING (symbolP))
 | 
|---|
| 437 |     SF_SET_STRING (symbolP);
 | 
|---|
| 438 | 
 | 
|---|
| 439 |   if (S_IS_LOCAL (symbolP))
 | 
|---|
| 440 |     SF_SET_LOCAL (symbolP);
 | 
|---|
| 441 | }
 | 
|---|
| 442 | 
 | 
|---|
| 443 |  | 
|---|
| 444 | 
 | 
|---|
| 445 | /*
 | 
|---|
| 446 |  * Handle .ln directives.
 | 
|---|
| 447 |  */
 | 
|---|
| 448 | 
 | 
|---|
| 449 | static symbolS *current_lineno_sym;
 | 
|---|
| 450 | static struct line_no *line_nos;
 | 
|---|
| 451 | /* @@ Blindly assume all .ln directives will be in the .text section...  */
 | 
|---|
| 452 | int coff_n_line_nos;
 | 
|---|
| 453 | 
 | 
|---|
| 454 | static void
 | 
|---|
| 455 | add_lineno (frag, offset, num)
 | 
|---|
| 456 |      fragS *frag;
 | 
|---|
| 457 |      addressT offset;
 | 
|---|
| 458 |      int num;
 | 
|---|
| 459 | {
 | 
|---|
| 460 |   struct line_no *new_line =
 | 
|---|
| 461 |     (struct line_no *) xmalloc (sizeof (struct line_no));
 | 
|---|
| 462 |   if (!current_lineno_sym)
 | 
|---|
| 463 |     {
 | 
|---|
| 464 |       abort ();
 | 
|---|
| 465 |     }
 | 
|---|
| 466 | 
 | 
|---|
| 467 | #ifndef OBJ_XCOFF
 | 
|---|
| 468 |   /* The native aix assembler accepts negative line number */
 | 
|---|
| 469 | 
 | 
|---|
| 470 |   if (num <= 0)
 | 
|---|
| 471 |     {
 | 
|---|
| 472 |       /* Zero is used as an end marker in the file.  */
 | 
|---|
| 473 |       as_warn (_("Line numbers must be positive integers\n"));
 | 
|---|
| 474 |       num = 1;
 | 
|---|
| 475 |     }
 | 
|---|
| 476 | #endif /* OBJ_XCOFF */
 | 
|---|
| 477 |   new_line->next = line_nos;
 | 
|---|
| 478 |   new_line->frag = frag;
 | 
|---|
| 479 |   new_line->l.line_number = num;
 | 
|---|
| 480 |   new_line->l.u.offset = offset;
 | 
|---|
| 481 |   line_nos = new_line;
 | 
|---|
| 482 |   coff_n_line_nos++;
 | 
|---|
| 483 | }
 | 
|---|
| 484 | 
 | 
|---|
| 485 | void
 | 
|---|
| 486 | coff_add_linesym (sym)
 | 
|---|
| 487 |      symbolS *sym;
 | 
|---|
| 488 | {
 | 
|---|
| 489 |   if (line_nos)
 | 
|---|
| 490 |     {
 | 
|---|
| 491 |       coffsymbol (symbol_get_bfdsym (current_lineno_sym))->lineno =
 | 
|---|
| 492 |         (alent *) line_nos;
 | 
|---|
| 493 |       coff_n_line_nos++;
 | 
|---|
| 494 |       line_nos = 0;
 | 
|---|
| 495 |     }
 | 
|---|
| 496 |   current_lineno_sym = sym;
 | 
|---|
| 497 | }
 | 
|---|
| 498 | 
 | 
|---|
| 499 | static void
 | 
|---|
| 500 | obj_coff_ln (appline)
 | 
|---|
| 501 |      int appline;
 | 
|---|
| 502 | {
 | 
|---|
| 503 |   int l;
 | 
|---|
| 504 | 
 | 
|---|
| 505 |   if (! appline && def_symbol_in_progress != NULL)
 | 
|---|
| 506 |     {
 | 
|---|
| 507 |       as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
 | 
|---|
| 508 |       demand_empty_rest_of_line ();
 | 
|---|
| 509 |       return;
 | 
|---|
| 510 |     }
 | 
|---|
| 511 | 
 | 
|---|
| 512 |   l = get_absolute_expression ();
 | 
|---|
| 513 | 
 | 
|---|
| 514 |   /* If there is no lineno symbol, treat a .ln
 | 
|---|
| 515 |      directive as if it were a .appline directive.  */
 | 
|---|
| 516 |   if (appline || current_lineno_sym == NULL)
 | 
|---|
| 517 |     new_logical_line ((char *) NULL, l - 1);
 | 
|---|
| 518 |   else
 | 
|---|
| 519 |     add_lineno (frag_now, frag_now_fix (), l);
 | 
|---|
| 520 | 
 | 
|---|
| 521 | #ifndef NO_LISTING
 | 
|---|
| 522 |   {
 | 
|---|
| 523 |     extern int listing;
 | 
|---|
| 524 | 
 | 
|---|
| 525 |     if (listing)
 | 
|---|
| 526 |       {
 | 
|---|
| 527 |         if (! appline)
 | 
|---|
| 528 |           l += coff_line_base - 1;
 | 
|---|
| 529 |         listing_source_line (l);
 | 
|---|
| 530 |       }
 | 
|---|
| 531 |   }
 | 
|---|
| 532 | #endif
 | 
|---|
| 533 | 
 | 
|---|
| 534 |   demand_empty_rest_of_line ();
 | 
|---|
| 535 | }
 | 
|---|
| 536 | 
 | 
|---|
| 537 | /* .loc is essentially the same as .ln; parse it for assembler
 | 
|---|
| 538 |    compatibility.  */
 | 
|---|
| 539 | 
 | 
|---|
| 540 | static void
 | 
|---|
| 541 | obj_coff_loc (ignore)
 | 
|---|
| 542 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 543 | {
 | 
|---|
| 544 |   int lineno;
 | 
|---|
| 545 | 
 | 
|---|
| 546 |   /* FIXME: Why do we need this check?  We need it for ECOFF, but why
 | 
|---|
| 547 |      do we need it for COFF?  */
 | 
|---|
| 548 |   if (now_seg != text_section)
 | 
|---|
| 549 |     {
 | 
|---|
| 550 |       as_warn (_(".loc outside of .text"));
 | 
|---|
| 551 |       demand_empty_rest_of_line ();
 | 
|---|
| 552 |       return;
 | 
|---|
| 553 |     }
 | 
|---|
| 554 | 
 | 
|---|
| 555 |   if (def_symbol_in_progress != NULL)
 | 
|---|
| 556 |     {
 | 
|---|
| 557 |       as_warn (_(".loc pseudo-op inside .def/.endef: ignored."));
 | 
|---|
| 558 |       demand_empty_rest_of_line ();
 | 
|---|
| 559 |       return;
 | 
|---|
| 560 |     }
 | 
|---|
| 561 | 
 | 
|---|
| 562 |   /* Skip the file number.  */
 | 
|---|
| 563 |   SKIP_WHITESPACE ();
 | 
|---|
| 564 |   get_absolute_expression ();
 | 
|---|
| 565 |   SKIP_WHITESPACE ();
 | 
|---|
| 566 | 
 | 
|---|
| 567 |   lineno = get_absolute_expression ();
 | 
|---|
| 568 | 
 | 
|---|
| 569 | #ifndef NO_LISTING
 | 
|---|
| 570 |   {
 | 
|---|
| 571 |     extern int listing;
 | 
|---|
| 572 | 
 | 
|---|
| 573 |     if (listing)
 | 
|---|
| 574 |       {
 | 
|---|
| 575 |         lineno += coff_line_base - 1;
 | 
|---|
| 576 |         listing_source_line (lineno);
 | 
|---|
| 577 |       }
 | 
|---|
| 578 |   }
 | 
|---|
| 579 | #endif
 | 
|---|
| 580 | 
 | 
|---|
| 581 |   demand_empty_rest_of_line ();
 | 
|---|
| 582 | 
 | 
|---|
| 583 |   add_lineno (frag_now, frag_now_fix (), lineno);
 | 
|---|
| 584 | }
 | 
|---|
| 585 | 
 | 
|---|
| 586 | /* Handle the .ident pseudo-op.  */
 | 
|---|
| 587 | 
 | 
|---|
| 588 | static void
 | 
|---|
| 589 | obj_coff_ident (ignore)
 | 
|---|
| 590 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 591 | {
 | 
|---|
| 592 |   segT current_seg = now_seg;
 | 
|---|
| 593 |   subsegT current_subseg = now_subseg;
 | 
|---|
| 594 | 
 | 
|---|
| 595 | #ifdef TE_PE
 | 
|---|
| 596 |   {
 | 
|---|
| 597 |     segT sec;
 | 
|---|
| 598 | 
 | 
|---|
| 599 |     /* We could put it in .comment, but that creates an extra section
 | 
|---|
| 600 |        that shouldn't be loaded into memory, which requires linker
 | 
|---|
| 601 |        changes...  For now, until proven otherwise, use .rdata.  */
 | 
|---|
| 602 |     sec = subseg_new (".rdata$zzz", 0);
 | 
|---|
| 603 |     bfd_set_section_flags (stdoutput, sec,
 | 
|---|
| 604 |                            ((SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA)
 | 
|---|
| 605 |                             & bfd_applicable_section_flags (stdoutput)));
 | 
|---|
| 606 |   }
 | 
|---|
| 607 | #else
 | 
|---|
| 608 |   subseg_new (".comment", 0);
 | 
|---|
| 609 | #endif
 | 
|---|
| 610 | 
 | 
|---|
| 611 |   stringer (1);
 | 
|---|
| 612 |   subseg_set (current_seg, current_subseg);
 | 
|---|
| 613 | }
 | 
|---|
| 614 | 
 | 
|---|
| 615 | /*
 | 
|---|
| 616 |  *                      def()
 | 
|---|
| 617 |  *
 | 
|---|
| 618 |  * Handle .def directives.
 | 
|---|
| 619 |  *
 | 
|---|
| 620 |  * One might ask : why can't we symbol_new if the symbol does not
 | 
|---|
| 621 |  * already exist and fill it with debug information.  Because of
 | 
|---|
| 622 |  * the C_EFCN special symbol. It would clobber the value of the
 | 
|---|
| 623 |  * function symbol before we have a chance to notice that it is
 | 
|---|
| 624 |  * a C_EFCN. And a second reason is that the code is more clear this
 | 
|---|
| 625 |  * way. (at least I think it is :-).
 | 
|---|
| 626 |  *
 | 
|---|
| 627 |  */
 | 
|---|
| 628 | 
 | 
|---|
| 629 | #define SKIP_SEMI_COLON()       while (*input_line_pointer++ != ';')
 | 
|---|
| 630 | #define SKIP_WHITESPACES()      while (*input_line_pointer == ' ' || \
 | 
|---|
| 631 |                                        *input_line_pointer == '\t') \
 | 
|---|
| 632 |     input_line_pointer++;
 | 
|---|
| 633 | 
 | 
|---|
| 634 | static void
 | 
|---|
| 635 | obj_coff_def (what)
 | 
|---|
| 636 |      int what ATTRIBUTE_UNUSED;
 | 
|---|
| 637 | {
 | 
|---|
| 638 |   char name_end;                /* Char after the end of name */
 | 
|---|
| 639 |   char *symbol_name;            /* Name of the debug symbol */
 | 
|---|
| 640 |   char *symbol_name_copy;       /* Temporary copy of the name */
 | 
|---|
| 641 |   unsigned int symbol_name_length;
 | 
|---|
| 642 | 
 | 
|---|
| 643 |   if (def_symbol_in_progress != NULL)
 | 
|---|
| 644 |     {
 | 
|---|
| 645 |       as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
 | 
|---|
| 646 |       demand_empty_rest_of_line ();
 | 
|---|
| 647 |       return;
 | 
|---|
| 648 |     }                           /* if not inside .def/.endef */
 | 
|---|
| 649 | 
 | 
|---|
| 650 |   SKIP_WHITESPACES ();
 | 
|---|
| 651 | 
 | 
|---|
| 652 |   symbol_name = input_line_pointer;
 | 
|---|
| 653 | #ifdef STRIP_UNDERSCORE
 | 
|---|
| 654 |   if (symbol_name[0] == '_' && symbol_name[1] != 0)
 | 
|---|
| 655 |     symbol_name++;
 | 
|---|
| 656 | #endif /* STRIP_UNDERSCORE */
 | 
|---|
| 657 | 
 | 
|---|
| 658 |   name_end = get_symbol_end ();
 | 
|---|
| 659 |   symbol_name_length = strlen (symbol_name);
 | 
|---|
| 660 |   symbol_name_copy = xmalloc (symbol_name_length + 1);
 | 
|---|
| 661 |   strcpy (symbol_name_copy, symbol_name);
 | 
|---|
| 662 | #ifdef tc_canonicalize_symbol_name
 | 
|---|
| 663 |   symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
 | 
|---|
| 664 | #endif
 | 
|---|
| 665 | 
 | 
|---|
| 666 |   /* Initialize the new symbol */
 | 
|---|
| 667 |   def_symbol_in_progress = symbol_make (symbol_name_copy);
 | 
|---|
| 668 |   symbol_set_frag (def_symbol_in_progress, &zero_address_frag);
 | 
|---|
| 669 |   S_SET_VALUE (def_symbol_in_progress, 0);
 | 
|---|
| 670 | 
 | 
|---|
| 671 |   if (S_IS_STRING (def_symbol_in_progress))
 | 
|---|
| 672 |     SF_SET_STRING (def_symbol_in_progress);
 | 
|---|
| 673 | 
 | 
|---|
| 674 |   *input_line_pointer = name_end;
 | 
|---|
| 675 | 
 | 
|---|
| 676 |   demand_empty_rest_of_line ();
 | 
|---|
| 677 | }
 | 
|---|
| 678 | 
 | 
|---|
| 679 | unsigned int dim_index;
 | 
|---|
| 680 | 
 | 
|---|
| 681 | static void
 | 
|---|
| 682 | obj_coff_endef (ignore)
 | 
|---|
| 683 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 684 | {
 | 
|---|
| 685 |   symbolS *symbolP = NULL;
 | 
|---|
| 686 | 
 | 
|---|
| 687 |   /* DIM BUG FIX sac@cygnus.com */
 | 
|---|
| 688 |   dim_index = 0;
 | 
|---|
| 689 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 690 |     {
 | 
|---|
| 691 |       as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
 | 
|---|
| 692 |       demand_empty_rest_of_line ();
 | 
|---|
| 693 |       return;
 | 
|---|
| 694 |     }                           /* if not inside .def/.endef */
 | 
|---|
| 695 | 
 | 
|---|
| 696 |   /* Set the section number according to storage class.  */
 | 
|---|
| 697 |   switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
 | 
|---|
| 698 |     {
 | 
|---|
| 699 |     case C_STRTAG:
 | 
|---|
| 700 |     case C_ENTAG:
 | 
|---|
| 701 |     case C_UNTAG:
 | 
|---|
| 702 |       SF_SET_TAG (def_symbol_in_progress);
 | 
|---|
| 703 |       /* intentional fallthrough */
 | 
|---|
| 704 |     case C_FILE:
 | 
|---|
| 705 |     case C_TPDEF:
 | 
|---|
| 706 |       SF_SET_DEBUG (def_symbol_in_progress);
 | 
|---|
| 707 |       S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
 | 
|---|
| 708 |       break;
 | 
|---|
| 709 | 
 | 
|---|
| 710 |     case C_EFCN:
 | 
|---|
| 711 |       SF_SET_LOCAL (def_symbol_in_progress);    /* Do not emit this symbol.  */
 | 
|---|
| 712 |       /* intentional fallthrough */
 | 
|---|
| 713 |     case C_BLOCK:
 | 
|---|
| 714 |       SF_SET_PROCESS (def_symbol_in_progress);  /* Will need processing before writing */
 | 
|---|
| 715 |       /* intentional fallthrough */
 | 
|---|
| 716 |     case C_FCN:
 | 
|---|
| 717 |       {
 | 
|---|
| 718 |         const char *name;
 | 
|---|
| 719 |         S_SET_SEGMENT (def_symbol_in_progress, text_section);
 | 
|---|
| 720 | 
 | 
|---|
| 721 |         name = S_GET_NAME (def_symbol_in_progress);
 | 
|---|
| 722 |         if (name[0] == '.' && name[2] == 'f' && name[3] == '\0')
 | 
|---|
| 723 |           {
 | 
|---|
| 724 |             switch (name[1])
 | 
|---|
| 725 |               {
 | 
|---|
| 726 |               case 'b':
 | 
|---|
| 727 |                 /* .bf */
 | 
|---|
| 728 |                 if (! in_function ())
 | 
|---|
| 729 |                   as_warn (_("`%s' symbol without preceding function"), name);
 | 
|---|
| 730 |                 /* Will need relocating.  */
 | 
|---|
| 731 |                 SF_SET_PROCESS (def_symbol_in_progress);
 | 
|---|
| 732 |                 clear_function ();
 | 
|---|
| 733 |                 break;
 | 
|---|
| 734 | #ifdef TE_PE
 | 
|---|
| 735 |               case 'e':
 | 
|---|
| 736 |                 /* .ef */
 | 
|---|
| 737 |                 /* The MS compilers output the actual endline, not the
 | 
|---|
| 738 |                    function-relative one... we want to match without
 | 
|---|
| 739 |                    changing the assembler input.  */
 | 
|---|
| 740 |                 SA_SET_SYM_LNNO (def_symbol_in_progress,
 | 
|---|
| 741 |                                  (SA_GET_SYM_LNNO (def_symbol_in_progress)
 | 
|---|
| 742 |                                   + coff_line_base));
 | 
|---|
| 743 |                 break;
 | 
|---|
| 744 | #endif
 | 
|---|
| 745 |               }
 | 
|---|
| 746 |           }
 | 
|---|
| 747 |       }
 | 
|---|
| 748 |       break;
 | 
|---|
| 749 | 
 | 
|---|
| 750 | #ifdef C_AUTOARG
 | 
|---|
| 751 |     case C_AUTOARG:
 | 
|---|
| 752 | #endif /* C_AUTOARG */
 | 
|---|
| 753 |     case C_AUTO:
 | 
|---|
| 754 |     case C_REG:
 | 
|---|
| 755 |     case C_ARG:
 | 
|---|
| 756 |     case C_REGPARM:
 | 
|---|
| 757 |     case C_FIELD:
 | 
|---|
| 758 | 
 | 
|---|
| 759 |     /* According to the COFF documentation:
 | 
|---|
| 760 | 
 | 
|---|
| 761 |        http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html
 | 
|---|
| 762 | 
 | 
|---|
| 763 |        A special section number (-2) marks symbolic debugging symbols,
 | 
|---|
| 764 |        including structure/union/enumeration tag names, typedefs, and
 | 
|---|
| 765 |        the name of the file. A section number of -1 indicates that the
 | 
|---|
| 766 |        symbol has a value but is not relocatable. Examples of
 | 
|---|
| 767 |        absolute-valued symbols include automatic and register variables,
 | 
|---|
| 768 |        function arguments, and .eos symbols.
 | 
|---|
| 769 | 
 | 
|---|
| 770 |        But from Ian Lance Taylor:
 | 
|---|
| 771 | 
 | 
|---|
| 772 |        http://sources.redhat.com/ml/binutils/2000-08/msg00202.html
 | 
|---|
| 773 | 
 | 
|---|
| 774 |        the actual tools all marked them as section -1. So the GNU COFF
 | 
|---|
| 775 |        assembler follows historical COFF assemblers.
 | 
|---|
| 776 | 
 | 
|---|
| 777 |        However, it causes problems for djgpp
 | 
|---|
| 778 | 
 | 
|---|
| 779 |        http://sources.redhat.com/ml/binutils/2000-08/msg00210.html
 | 
|---|
| 780 | 
 | 
|---|
| 781 |        By defining STRICTCOFF, a COFF port can make the assembler to
 | 
|---|
| 782 |        follow the documented behavior.  */
 | 
|---|
| 783 | #ifdef STRICTCOFF
 | 
|---|
| 784 |     case C_MOS:
 | 
|---|
| 785 |     case C_MOE:
 | 
|---|
| 786 |     case C_MOU:
 | 
|---|
| 787 |     case C_EOS:
 | 
|---|
| 788 | #endif
 | 
|---|
| 789 |       SF_SET_DEBUG (def_symbol_in_progress);
 | 
|---|
| 790 |       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
 | 
|---|
| 791 |       break;
 | 
|---|
| 792 | 
 | 
|---|
| 793 | #ifndef STRICTCOFF
 | 
|---|
| 794 |     case C_MOS:
 | 
|---|
| 795 |     case C_MOE:
 | 
|---|
| 796 |     case C_MOU:
 | 
|---|
| 797 |     case C_EOS:
 | 
|---|
| 798 |       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
 | 
|---|
| 799 |       break;
 | 
|---|
| 800 | #endif
 | 
|---|
| 801 | 
 | 
|---|
| 802 |     case C_EXT:
 | 
|---|
| 803 |     case C_WEAKEXT:
 | 
|---|
| 804 | #ifdef TE_PE
 | 
|---|
| 805 |     case C_NT_WEAK:
 | 
|---|
| 806 | #endif
 | 
|---|
| 807 |     case C_STAT:
 | 
|---|
| 808 |     case C_LABEL:
 | 
|---|
| 809 |       /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
 | 
|---|
| 810 |       break;
 | 
|---|
| 811 | 
 | 
|---|
| 812 |     default:
 | 
|---|
| 813 |     case C_USTATIC:
 | 
|---|
| 814 |     case C_EXTDEF:
 | 
|---|
| 815 |     case C_ULABEL:
 | 
|---|
| 816 |       as_warn (_("unexpected storage class %d"),
 | 
|---|
| 817 |                S_GET_STORAGE_CLASS (def_symbol_in_progress));
 | 
|---|
| 818 |       break;
 | 
|---|
| 819 |     }                           /* switch on storage class */
 | 
|---|
| 820 | 
 | 
|---|
| 821 |   /* Now that we have built a debug symbol, try to find if we should
 | 
|---|
| 822 |      merge with an existing symbol or not.  If a symbol is C_EFCN or
 | 
|---|
| 823 |      absolute_section or untagged SEG_DEBUG it never merges.  We also
 | 
|---|
| 824 |      don't merge labels, which are in a different namespace, nor
 | 
|---|
| 825 |      symbols which have not yet been defined since they are typically
 | 
|---|
| 826 |      unique, nor do we merge tags with non-tags.  */
 | 
|---|
| 827 | 
 | 
|---|
| 828 |   /* Two cases for functions.  Either debug followed by definition or
 | 
|---|
| 829 |      definition followed by debug.  For definition first, we will
 | 
|---|
| 830 |      merge the debug symbol into the definition.  For debug first, the
 | 
|---|
| 831 |      lineno entry MUST point to the definition function or else it
 | 
|---|
| 832 |      will point off into space when obj_crawl_symbol_chain() merges
 | 
|---|
| 833 |      the debug symbol into the real symbol.  Therefor, let's presume
 | 
|---|
| 834 |      the debug symbol is a real function reference.  */
 | 
|---|
| 835 | 
 | 
|---|
| 836 |   /* FIXME-SOON If for some reason the definition label/symbol is
 | 
|---|
| 837 |      never seen, this will probably leave an undefined symbol at link
 | 
|---|
| 838 |      time.  */
 | 
|---|
| 839 | 
 | 
|---|
| 840 |   if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
 | 
|---|
| 841 |       || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
 | 
|---|
| 842 |       || (!strcmp (bfd_get_section_name (stdoutput,
 | 
|---|
| 843 |                                          S_GET_SEGMENT (def_symbol_in_progress)),
 | 
|---|
| 844 |                    "*DEBUG*")
 | 
|---|
| 845 |           && !SF_GET_TAG (def_symbol_in_progress))
 | 
|---|
| 846 |       || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
 | 
|---|
| 847 |       || ! symbol_constant_p (def_symbol_in_progress)
 | 
|---|
| 848 |       || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress),
 | 
|---|
| 849 |                                       DO_NOT_STRIP)) == NULL
 | 
|---|
| 850 |       || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))
 | 
|---|
| 851 |     {
 | 
|---|
| 852 |       /* If it already is at the end of the symbol list, do nothing */
 | 
|---|
| 853 |       if (def_symbol_in_progress != symbol_lastP)
 | 
|---|
| 854 |         {
 | 
|---|
| 855 |           symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 856 |           symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
 | 
|---|
| 857 |                          &symbol_lastP);
 | 
|---|
| 858 |         }
 | 
|---|
| 859 |     }
 | 
|---|
| 860 |   else
 | 
|---|
| 861 |     {
 | 
|---|
| 862 |       /* This symbol already exists, merge the newly created symbol
 | 
|---|
| 863 |          into the old one.  This is not mandatory. The linker can
 | 
|---|
| 864 |          handle duplicate symbols correctly. But I guess that it save
 | 
|---|
| 865 |          a *lot* of space if the assembly file defines a lot of
 | 
|---|
| 866 |          symbols. [loic] */
 | 
|---|
| 867 | 
 | 
|---|
| 868 |       /* The debug entry (def_symbol_in_progress) is merged into the
 | 
|---|
| 869 |          previous definition.  */
 | 
|---|
| 870 | 
 | 
|---|
| 871 |       c_symbol_merge (def_symbol_in_progress, symbolP);
 | 
|---|
| 872 |       symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 873 | 
 | 
|---|
| 874 |       def_symbol_in_progress = symbolP;
 | 
|---|
| 875 | 
 | 
|---|
| 876 |       if (SF_GET_FUNCTION (def_symbol_in_progress)
 | 
|---|
| 877 |           || SF_GET_TAG (def_symbol_in_progress)
 | 
|---|
| 878 |           || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
 | 
|---|
| 879 |         {
 | 
|---|
| 880 |           /* For functions, and tags, and static symbols, the symbol
 | 
|---|
| 881 |              *must* be where the debug symbol appears.  Move the
 | 
|---|
| 882 |              existing symbol to the current place.  */
 | 
|---|
| 883 |           /* If it already is at the end of the symbol list, do nothing */
 | 
|---|
| 884 |           if (def_symbol_in_progress != symbol_lastP)
 | 
|---|
| 885 |             {
 | 
|---|
| 886 |               symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 887 |               symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 888 |             }
 | 
|---|
| 889 |         }
 | 
|---|
| 890 |     }
 | 
|---|
| 891 | 
 | 
|---|
| 892 |   if (SF_GET_TAG (def_symbol_in_progress))
 | 
|---|
| 893 |     {
 | 
|---|
| 894 |       symbolS *oldtag;
 | 
|---|
| 895 | 
 | 
|---|
| 896 |       oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress),
 | 
|---|
| 897 |                                  DO_NOT_STRIP);
 | 
|---|
| 898 |       if (oldtag == NULL || ! SF_GET_TAG (oldtag))
 | 
|---|
| 899 |         tag_insert (S_GET_NAME (def_symbol_in_progress),
 | 
|---|
| 900 |                     def_symbol_in_progress);
 | 
|---|
| 901 |     }
 | 
|---|
| 902 | 
 | 
|---|
| 903 |   if (SF_GET_FUNCTION (def_symbol_in_progress))
 | 
|---|
| 904 |     {
 | 
|---|
| 905 |       know (sizeof (def_symbol_in_progress) <= sizeof (long));
 | 
|---|
| 906 |       set_function (def_symbol_in_progress);
 | 
|---|
| 907 |       SF_SET_PROCESS (def_symbol_in_progress);
 | 
|---|
| 908 | 
 | 
|---|
| 909 |       if (symbolP == NULL)
 | 
|---|
| 910 |         {
 | 
|---|
| 911 |           /* That is, if this is the first time we've seen the
 | 
|---|
| 912 |              function...  */
 | 
|---|
| 913 |           symbol_table_insert (def_symbol_in_progress);
 | 
|---|
| 914 |         } /* definition follows debug */
 | 
|---|
| 915 |     } /* Create the line number entry pointing to the function being defined */
 | 
|---|
| 916 | 
 | 
|---|
| 917 |   def_symbol_in_progress = NULL;
 | 
|---|
| 918 |   demand_empty_rest_of_line ();
 | 
|---|
| 919 | }
 | 
|---|
| 920 | 
 | 
|---|
| 921 | static void
 | 
|---|
| 922 | obj_coff_dim (ignore)
 | 
|---|
| 923 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 924 | {
 | 
|---|
| 925 |   int dim_index;
 | 
|---|
| 926 | 
 | 
|---|
| 927 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 928 |     {
 | 
|---|
| 929 |       as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
 | 
|---|
| 930 |       demand_empty_rest_of_line ();
 | 
|---|
| 931 |       return;
 | 
|---|
| 932 |     }                           /* if not inside .def/.endef */
 | 
|---|
| 933 | 
 | 
|---|
| 934 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 935 | 
 | 
|---|
| 936 |   for (dim_index = 0; dim_index < DIMNUM; dim_index++)
 | 
|---|
| 937 |     {
 | 
|---|
| 938 |       SKIP_WHITESPACES ();
 | 
|---|
| 939 |       SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
 | 
|---|
| 940 |                         get_absolute_expression ());
 | 
|---|
| 941 | 
 | 
|---|
| 942 |       switch (*input_line_pointer)
 | 
|---|
| 943 |         {
 | 
|---|
| 944 |         case ',':
 | 
|---|
| 945 |           input_line_pointer++;
 | 
|---|
| 946 |           break;
 | 
|---|
| 947 | 
 | 
|---|
| 948 |         default:
 | 
|---|
| 949 |           as_warn (_("badly formed .dim directive ignored"));
 | 
|---|
| 950 |           /* intentional fallthrough */
 | 
|---|
| 951 |         case '\n':
 | 
|---|
| 952 |         case ';':
 | 
|---|
| 953 |           dim_index = DIMNUM;
 | 
|---|
| 954 |           break;
 | 
|---|
| 955 |         }
 | 
|---|
| 956 |     }
 | 
|---|
| 957 | 
 | 
|---|
| 958 |   demand_empty_rest_of_line ();
 | 
|---|
| 959 | }
 | 
|---|
| 960 | 
 | 
|---|
| 961 | static void
 | 
|---|
| 962 | obj_coff_line (ignore)
 | 
|---|
| 963 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 964 | {
 | 
|---|
| 965 |   int this_base;
 | 
|---|
| 966 | 
 | 
|---|
| 967 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 968 |     {
 | 
|---|
| 969 |       /* Probably stabs-style line?  */
 | 
|---|
| 970 |       obj_coff_ln (0);
 | 
|---|
| 971 |       return;
 | 
|---|
| 972 |     }
 | 
|---|
| 973 | 
 | 
|---|
| 974 |   this_base = get_absolute_expression ();
 | 
|---|
| 975 |   if (!strcmp (".bf", S_GET_NAME (def_symbol_in_progress)))
 | 
|---|
| 976 |     coff_line_base = this_base;
 | 
|---|
| 977 | 
 | 
|---|
| 978 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 979 |   SA_SET_SYM_LNNO (def_symbol_in_progress, this_base);
 | 
|---|
| 980 | 
 | 
|---|
| 981 |   demand_empty_rest_of_line ();
 | 
|---|
| 982 | 
 | 
|---|
| 983 | #ifndef NO_LISTING
 | 
|---|
| 984 |   if (strcmp (".bf", S_GET_NAME (def_symbol_in_progress)) == 0)
 | 
|---|
| 985 |     {
 | 
|---|
| 986 |       extern int listing;
 | 
|---|
| 987 | 
 | 
|---|
| 988 |       if (listing)
 | 
|---|
| 989 |         listing_source_line ((unsigned int) this_base);
 | 
|---|
| 990 |     }
 | 
|---|
| 991 | #endif
 | 
|---|
| 992 | }
 | 
|---|
| 993 | 
 | 
|---|
| 994 | static void
 | 
|---|
| 995 | obj_coff_size (ignore)
 | 
|---|
| 996 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 997 | {
 | 
|---|
| 998 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 999 |     {
 | 
|---|
| 1000 |       as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 1001 |       demand_empty_rest_of_line ();
 | 
|---|
| 1002 |       return;
 | 
|---|
| 1003 |     }                           /* if not inside .def/.endef */
 | 
|---|
| 1004 | 
 | 
|---|
| 1005 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 1006 |   SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
 | 
|---|
| 1007 |   demand_empty_rest_of_line ();
 | 
|---|
| 1008 | }
 | 
|---|
| 1009 | 
 | 
|---|
| 1010 | static void
 | 
|---|
| 1011 | obj_coff_scl (ignore)
 | 
|---|
| 1012 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1013 | {
 | 
|---|
| 1014 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 1015 |     {
 | 
|---|
| 1016 |       as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 1017 |       demand_empty_rest_of_line ();
 | 
|---|
| 1018 |       return;
 | 
|---|
| 1019 |     }                           /* if not inside .def/.endef */
 | 
|---|
| 1020 | 
 | 
|---|
| 1021 |   S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
 | 
|---|
| 1022 |   demand_empty_rest_of_line ();
 | 
|---|
| 1023 | }
 | 
|---|
| 1024 | 
 | 
|---|
| 1025 | static void
 | 
|---|
| 1026 | obj_coff_tag (ignore)
 | 
|---|
| 1027 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1028 | {
 | 
|---|
| 1029 |   char *symbol_name;
 | 
|---|
| 1030 |   char name_end;
 | 
|---|
| 1031 | 
 | 
|---|
| 1032 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 1033 |     {
 | 
|---|
| 1034 |       as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 1035 |       demand_empty_rest_of_line ();
 | 
|---|
| 1036 |       return;
 | 
|---|
| 1037 |     }
 | 
|---|
| 1038 | 
 | 
|---|
| 1039 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 1040 |   symbol_name = input_line_pointer;
 | 
|---|
| 1041 |   name_end = get_symbol_end ();
 | 
|---|
| 1042 | 
 | 
|---|
| 1043 | #ifdef tc_canonicalize_symbol_name
 | 
|---|
| 1044 |   symbol_name = tc_canonicalize_symbol_name (symbol_name);
 | 
|---|
| 1045 | #endif
 | 
|---|
| 1046 | 
 | 
|---|
| 1047 |   /* Assume that the symbol referred to by .tag is always defined.
 | 
|---|
| 1048 |      This was a bad assumption.  I've added find_or_make. xoxorich.  */
 | 
|---|
| 1049 |   SA_SET_SYM_TAGNDX (def_symbol_in_progress,
 | 
|---|
| 1050 |                      tag_find_or_make (symbol_name));
 | 
|---|
| 1051 |   if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
 | 
|---|
| 1052 |     {
 | 
|---|
| 1053 |       as_warn (_("tag not found for .tag %s"), symbol_name);
 | 
|---|
| 1054 |     }                           /* not defined */
 | 
|---|
| 1055 | 
 | 
|---|
| 1056 |   SF_SET_TAGGED (def_symbol_in_progress);
 | 
|---|
| 1057 |   *input_line_pointer = name_end;
 | 
|---|
| 1058 | 
 | 
|---|
| 1059 |   demand_empty_rest_of_line ();
 | 
|---|
| 1060 | }
 | 
|---|
| 1061 | 
 | 
|---|
| 1062 | static void
 | 
|---|
| 1063 | obj_coff_type (ignore)
 | 
|---|
| 1064 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1065 | {
 | 
|---|
| 1066 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 1067 |     {
 | 
|---|
| 1068 |       as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 1069 |       demand_empty_rest_of_line ();
 | 
|---|
| 1070 |       return;
 | 
|---|
| 1071 |     }                           /* if not inside .def/.endef */
 | 
|---|
| 1072 | 
 | 
|---|
| 1073 |   S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
 | 
|---|
| 1074 | 
 | 
|---|
| 1075 |   if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
 | 
|---|
| 1076 |       S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
 | 
|---|
| 1077 |     {
 | 
|---|
| 1078 |       SF_SET_FUNCTION (def_symbol_in_progress);
 | 
|---|
| 1079 |     }                           /* is a function */
 | 
|---|
| 1080 | 
 | 
|---|
| 1081 |   demand_empty_rest_of_line ();
 | 
|---|
| 1082 | }
 | 
|---|
| 1083 | 
 | 
|---|
| 1084 | static void
 | 
|---|
| 1085 | obj_coff_val (ignore)
 | 
|---|
| 1086 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1087 | {
 | 
|---|
| 1088 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 1089 |     {
 | 
|---|
| 1090 |       as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 1091 |       demand_empty_rest_of_line ();
 | 
|---|
| 1092 |       return;
 | 
|---|
| 1093 |     }                           /* if not inside .def/.endef */
 | 
|---|
| 1094 | 
 | 
|---|
| 1095 |   if (is_name_beginner (*input_line_pointer))
 | 
|---|
| 1096 |     {
 | 
|---|
| 1097 |       char *symbol_name = input_line_pointer;
 | 
|---|
| 1098 |       char name_end = get_symbol_end ();
 | 
|---|
| 1099 | 
 | 
|---|
| 1100 | #ifdef tc_canonicalize_symbol_name
 | 
|---|
| 1101 |   symbol_name = tc_canonicalize_symbol_name (symbol_name);
 | 
|---|
| 1102 | #endif
 | 
|---|
| 1103 |       if (!strcmp (symbol_name, "."))
 | 
|---|
| 1104 |         {
 | 
|---|
| 1105 |           symbol_set_frag (def_symbol_in_progress, frag_now);
 | 
|---|
| 1106 |           S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
 | 
|---|
| 1107 |           /* If the .val is != from the .def (e.g. statics) */
 | 
|---|
| 1108 |         }
 | 
|---|
| 1109 |       else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
 | 
|---|
| 1110 |         {
 | 
|---|
| 1111 |           expressionS exp;
 | 
|---|
| 1112 | 
 | 
|---|
| 1113 |           exp.X_op = O_symbol;
 | 
|---|
| 1114 |           exp.X_add_symbol = symbol_find_or_make (symbol_name);
 | 
|---|
| 1115 |           exp.X_op_symbol = NULL;
 | 
|---|
| 1116 |           exp.X_add_number = 0;
 | 
|---|
| 1117 |           symbol_set_value_expression (def_symbol_in_progress, &exp);
 | 
|---|
| 1118 | 
 | 
|---|
| 1119 |           /* If the segment is undefined when the forward reference is
 | 
|---|
| 1120 |              resolved, then copy the segment id from the forward
 | 
|---|
| 1121 |              symbol.  */
 | 
|---|
| 1122 |           SF_SET_GET_SEGMENT (def_symbol_in_progress);
 | 
|---|
| 1123 | 
 | 
|---|
| 1124 |           /* FIXME: gcc can generate address expressions here in
 | 
|---|
| 1125 |              unusual cases (search for "obscure" in sdbout.c).  We
 | 
|---|
| 1126 |              just ignore the offset here, thus generating incorrect
 | 
|---|
| 1127 |              debugging information.  We ignore the rest of the line
 | 
|---|
| 1128 |              just below.  */
 | 
|---|
| 1129 |         }
 | 
|---|
| 1130 |       /* Otherwise, it is the name of a non debug symbol and its value
 | 
|---|
| 1131 |          will be calculated later.  */
 | 
|---|
| 1132 |       *input_line_pointer = name_end;
 | 
|---|
| 1133 |     }
 | 
|---|
| 1134 |   else
 | 
|---|
| 1135 |     {
 | 
|---|
| 1136 |       S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
 | 
|---|
| 1137 |     }                           /* if symbol based */
 | 
|---|
| 1138 | 
 | 
|---|
| 1139 |   demand_empty_rest_of_line ();
 | 
|---|
| 1140 | }
 | 
|---|
| 1141 | 
 | 
|---|
| 1142 | void
 | 
|---|
| 1143 | coff_obj_read_begin_hook ()
 | 
|---|
| 1144 | {
 | 
|---|
| 1145 |   /* These had better be the same.  Usually 18 bytes.  */
 | 
|---|
| 1146 | #ifndef BFD_HEADERS
 | 
|---|
| 1147 |   know (sizeof (SYMENT) == sizeof (AUXENT));
 | 
|---|
| 1148 |   know (SYMESZ == AUXESZ);
 | 
|---|
| 1149 | #endif
 | 
|---|
| 1150 |   tag_init ();
 | 
|---|
| 1151 | }
 | 
|---|
| 1152 | 
 | 
|---|
| 1153 | symbolS *coff_last_function;
 | 
|---|
| 1154 | #ifndef OBJ_XCOFF
 | 
|---|
| 1155 | static symbolS *coff_last_bf;
 | 
|---|
| 1156 | #endif
 | 
|---|
| 1157 | 
 | 
|---|
| 1158 | void
 | 
|---|
| 1159 | coff_frob_symbol (symp, punt)
 | 
|---|
| 1160 |      symbolS *symp;
 | 
|---|
| 1161 |      int *punt;
 | 
|---|
| 1162 | {
 | 
|---|
| 1163 |   static symbolS *last_tagP;
 | 
|---|
| 1164 |   static stack *block_stack;
 | 
|---|
| 1165 |   static symbolS *set_end;
 | 
|---|
| 1166 |   symbolS *next_set_end = NULL;
 | 
|---|
| 1167 | 
 | 
|---|
| 1168 |   if (symp == &abs_symbol)
 | 
|---|
| 1169 |     {
 | 
|---|
| 1170 |       *punt = 1;
 | 
|---|
| 1171 |       return;
 | 
|---|
| 1172 |     }
 | 
|---|
| 1173 | 
 | 
|---|
| 1174 |   if (current_lineno_sym)
 | 
|---|
| 1175 |     coff_add_linesym ((symbolS *) 0);
 | 
|---|
| 1176 | 
 | 
|---|
| 1177 |   if (!block_stack)
 | 
|---|
| 1178 |     block_stack = stack_init (512, sizeof (symbolS*));
 | 
|---|
| 1179 | 
 | 
|---|
| 1180 |   if (S_IS_WEAK (symp))
 | 
|---|
| 1181 |     {
 | 
|---|
| 1182 | #ifdef TE_PE
 | 
|---|
| 1183 |       S_SET_STORAGE_CLASS (symp, C_NT_WEAK);
 | 
|---|
| 1184 | #else
 | 
|---|
| 1185 |       S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
 | 
|---|
| 1186 | #endif
 | 
|---|
| 1187 |     }
 | 
|---|
| 1188 | 
 | 
|---|
| 1189 |   if (!S_IS_DEFINED (symp)
 | 
|---|
| 1190 |       && !S_IS_WEAK (symp)
 | 
|---|
| 1191 |       && S_GET_STORAGE_CLASS (symp) != C_STAT)
 | 
|---|
| 1192 |     S_SET_STORAGE_CLASS (symp, C_EXT);
 | 
|---|
| 1193 | 
 | 
|---|
| 1194 |   if (!SF_GET_DEBUG (symp))
 | 
|---|
| 1195 |     {
 | 
|---|
| 1196 |       symbolS * real;
 | 
|---|
| 1197 | 
 | 
|---|
| 1198 |       if (!SF_GET_LOCAL (symp)
 | 
|---|
| 1199 |           && !SF_GET_STATICS (symp)
 | 
|---|
| 1200 |           && S_GET_STORAGE_CLASS (symp) != C_LABEL
 | 
|---|
| 1201 |           && symbol_constant_p(symp)
 | 
|---|
| 1202 |           && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP))
 | 
|---|
| 1203 |           && S_GET_STORAGE_CLASS (real) == C_NULL
 | 
|---|
| 1204 |           && real != symp)
 | 
|---|
| 1205 |         {
 | 
|---|
| 1206 |           c_symbol_merge (symp, real);
 | 
|---|
| 1207 |           *punt = 1;
 | 
|---|
| 1208 |           return;
 | 
|---|
| 1209 |         }
 | 
|---|
| 1210 | 
 | 
|---|
| 1211 |       if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
 | 
|---|
| 1212 |         {
 | 
|---|
| 1213 |           assert (S_GET_VALUE (symp) == 0);
 | 
|---|
| 1214 |           S_SET_EXTERNAL (symp);
 | 
|---|
| 1215 |         }
 | 
|---|
| 1216 |       else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
 | 
|---|
| 1217 |         {
 | 
|---|
| 1218 |           if (S_GET_SEGMENT (symp) == text_section
 | 
|---|
| 1219 |               && symp != seg_info (text_section)->sym)
 | 
|---|
| 1220 |             S_SET_STORAGE_CLASS (symp, C_LABEL);
 | 
|---|
| 1221 |           else
 | 
|---|
| 1222 |             S_SET_STORAGE_CLASS (symp, C_STAT);
 | 
|---|
| 1223 |         }
 | 
|---|
| 1224 | 
 | 
|---|
| 1225 |       if (SF_GET_PROCESS (symp))
 | 
|---|
| 1226 |         {
 | 
|---|
| 1227 |           if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
 | 
|---|
| 1228 |             {
 | 
|---|
| 1229 |               if (!strcmp (S_GET_NAME (symp), ".bb"))
 | 
|---|
| 1230 |                 stack_push (block_stack, (char *) &symp);
 | 
|---|
| 1231 |               else
 | 
|---|
| 1232 |                 {
 | 
|---|
| 1233 |                   symbolS *begin;
 | 
|---|
| 1234 | 
 | 
|---|
| 1235 |                   begin = *(symbolS **) stack_pop (block_stack);
 | 
|---|
| 1236 |                   if (begin == 0)
 | 
|---|
| 1237 |                     as_warn (_("mismatched .eb"));
 | 
|---|
| 1238 |                   else
 | 
|---|
| 1239 |                     next_set_end = begin;
 | 
|---|
| 1240 |                 }
 | 
|---|
| 1241 |             }
 | 
|---|
| 1242 | 
 | 
|---|
| 1243 |           if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
 | 
|---|
| 1244 |             {
 | 
|---|
| 1245 |               union internal_auxent *auxp;
 | 
|---|
| 1246 | 
 | 
|---|
| 1247 |               coff_last_function = symp;
 | 
|---|
| 1248 |               if (S_GET_NUMBER_AUXILIARY (symp) < 1)
 | 
|---|
| 1249 |                 S_SET_NUMBER_AUXILIARY (symp, 1);
 | 
|---|
| 1250 |               auxp = SYM_AUXENT (symp);
 | 
|---|
| 1251 |               memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
 | 
|---|
| 1252 |                       sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
 | 
|---|
| 1253 |             }
 | 
|---|
| 1254 | 
 | 
|---|
| 1255 |           if (S_GET_STORAGE_CLASS (symp) == C_EFCN)
 | 
|---|
| 1256 |             {
 | 
|---|
| 1257 |               if (coff_last_function == 0)
 | 
|---|
| 1258 |                 as_fatal (_("C_EFCN symbol out of scope"));
 | 
|---|
| 1259 |               SA_SET_SYM_FSIZE (coff_last_function,
 | 
|---|
| 1260 |                                 (long) (S_GET_VALUE (symp)
 | 
|---|
| 1261 |                                         - S_GET_VALUE (coff_last_function)));
 | 
|---|
| 1262 |               next_set_end = coff_last_function;
 | 
|---|
| 1263 |               coff_last_function = 0;
 | 
|---|
| 1264 |             }
 | 
|---|
| 1265 |         }
 | 
|---|
| 1266 | 
 | 
|---|
| 1267 |       if (S_IS_EXTERNAL (symp))
 | 
|---|
| 1268 |         S_SET_STORAGE_CLASS (symp, C_EXT);
 | 
|---|
| 1269 |       else if (SF_GET_LOCAL (symp))
 | 
|---|
| 1270 |         *punt = 1;
 | 
|---|
| 1271 | 
 | 
|---|
| 1272 |       if (SF_GET_FUNCTION (symp))
 | 
|---|
| 1273 |         symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION;
 | 
|---|
| 1274 | 
 | 
|---|
| 1275 |       /* more ...  */
 | 
|---|
| 1276 |     }
 | 
|---|
| 1277 | 
 | 
|---|
| 1278 |   /* Double check weak symbols.  */
 | 
|---|
| 1279 |   if (S_IS_WEAK (symp) && S_IS_COMMON (symp))
 | 
|---|
| 1280 |     as_bad (_("Symbol `%s' can not be both weak and common"),
 | 
|---|
| 1281 |             S_GET_NAME (symp));
 | 
|---|
| 1282 | 
 | 
|---|
| 1283 |   if (SF_GET_TAG (symp))
 | 
|---|
| 1284 |     last_tagP = symp;
 | 
|---|
| 1285 |   else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
 | 
|---|
| 1286 |     next_set_end = last_tagP;
 | 
|---|
| 1287 | 
 | 
|---|
| 1288 | #ifdef OBJ_XCOFF
 | 
|---|
| 1289 |   /* This is pretty horrible, but we have to set *punt correctly in
 | 
|---|
| 1290 |      order to call SA_SET_SYM_ENDNDX correctly.  */
 | 
|---|
| 1291 |   if (! symbol_used_in_reloc_p (symp)
 | 
|---|
| 1292 |       && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0
 | 
|---|
| 1293 |           || (! S_IS_EXTERNAL (symp)
 | 
|---|
| 1294 |               && ! symbol_get_tc (symp)->output
 | 
|---|
| 1295 |               && S_GET_STORAGE_CLASS (symp) != C_FILE)))
 | 
|---|
| 1296 |     *punt = 1;
 | 
|---|
| 1297 | #endif
 | 
|---|
| 1298 | 
 | 
|---|
| 1299 |   if (set_end != (symbolS *) NULL
 | 
|---|
| 1300 |       && ! *punt
 | 
|---|
| 1301 |       && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0
 | 
|---|
| 1302 |           || (S_IS_DEFINED (symp)
 | 
|---|
| 1303 |               && ! S_IS_COMMON (symp)
 | 
|---|
| 1304 |               && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
 | 
|---|
| 1305 |     {
 | 
|---|
| 1306 |       SA_SET_SYM_ENDNDX (set_end, symp);
 | 
|---|
| 1307 |       set_end = NULL;
 | 
|---|
| 1308 |     }
 | 
|---|
| 1309 | 
 | 
|---|
| 1310 |   if (next_set_end != NULL)
 | 
|---|
| 1311 |     {
 | 
|---|
| 1312 |       if (set_end != NULL)
 | 
|---|
| 1313 |         as_warn ("Warning: internal error: forgetting to set endndx of %s",
 | 
|---|
| 1314 |                  S_GET_NAME (set_end));
 | 
|---|
| 1315 |       set_end = next_set_end;
 | 
|---|
| 1316 |     }
 | 
|---|
| 1317 | 
 | 
|---|
| 1318 | #ifndef OBJ_XCOFF
 | 
|---|
| 1319 |   if (! *punt
 | 
|---|
| 1320 |       && S_GET_STORAGE_CLASS (symp) == C_FCN
 | 
|---|
| 1321 |       && strcmp (S_GET_NAME (symp), ".bf") == 0)
 | 
|---|
| 1322 |     {
 | 
|---|
| 1323 |       if (coff_last_bf != NULL)
 | 
|---|
| 1324 |         SA_SET_SYM_ENDNDX (coff_last_bf, symp);
 | 
|---|
| 1325 |       coff_last_bf = symp;
 | 
|---|
| 1326 |     }
 | 
|---|
| 1327 | #endif
 | 
|---|
| 1328 |   if (coffsymbol (symbol_get_bfdsym (symp))->lineno)
 | 
|---|
| 1329 |     {
 | 
|---|
| 1330 |       int i;
 | 
|---|
| 1331 |       struct line_no *lptr;
 | 
|---|
| 1332 |       alent *l;
 | 
|---|
| 1333 | 
 | 
|---|
| 1334 |       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
 | 
|---|
| 1335 |       for (i = 0; lptr; lptr = lptr->next)
 | 
|---|
| 1336 |         i++;
 | 
|---|
| 1337 |       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
 | 
|---|
| 1338 | 
 | 
|---|
| 1339 |       /* We need i entries for line numbers, plus 1 for the first
 | 
|---|
| 1340 |          entry which BFD will override, plus 1 for the last zero
 | 
|---|
| 1341 |          entry (a marker for BFD).  */
 | 
|---|
| 1342 |       l = (alent *) xmalloc ((i + 2) * sizeof (alent));
 | 
|---|
| 1343 |       coffsymbol (symbol_get_bfdsym (symp))->lineno = l;
 | 
|---|
| 1344 |       l[i + 1].line_number = 0;
 | 
|---|
| 1345 |       l[i + 1].u.sym = NULL;
 | 
|---|
| 1346 |       for (; i > 0; i--)
 | 
|---|
| 1347 |         {
 | 
|---|
| 1348 |           if (lptr->frag)
 | 
|---|
| 1349 |             lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE;
 | 
|---|
| 1350 |           l[i] = lptr->l;
 | 
|---|
| 1351 |           lptr = lptr->next;
 | 
|---|
| 1352 |         }
 | 
|---|
| 1353 |     }
 | 
|---|
| 1354 | }
 | 
|---|
| 1355 | 
 | 
|---|
| 1356 | void
 | 
|---|
| 1357 | coff_adjust_section_syms (abfd, sec, x)
 | 
|---|
| 1358 |      bfd *abfd ATTRIBUTE_UNUSED;
 | 
|---|
| 1359 |      asection *sec;
 | 
|---|
| 1360 |      PTR x ATTRIBUTE_UNUSED;
 | 
|---|
| 1361 | {
 | 
|---|
| 1362 |   symbolS *secsym;
 | 
|---|
| 1363 |   segment_info_type *seginfo = seg_info (sec);
 | 
|---|
| 1364 |   int nlnno, nrelocs = 0;
 | 
|---|
| 1365 | 
 | 
|---|
| 1366 |   /* RS/6000 gas creates a .debug section manually in ppc_frob_file in
 | 
|---|
| 1367 |      tc-ppc.c.  Do not get confused by it.  */
 | 
|---|
| 1368 |   if (seginfo == NULL)
 | 
|---|
| 1369 |     return;
 | 
|---|
| 1370 | 
 | 
|---|
| 1371 |   if (!strcmp (sec->name, ".text"))
 | 
|---|
| 1372 |     nlnno = coff_n_line_nos;
 | 
|---|
| 1373 |   else
 | 
|---|
| 1374 |     nlnno = 0;
 | 
|---|
| 1375 |   {
 | 
|---|
| 1376 |     /* @@ Hope that none of the fixups expand to more than one reloc
 | 
|---|
| 1377 |        entry...  */
 | 
|---|
| 1378 |     fixS *fixp = seginfo->fix_root;
 | 
|---|
| 1379 |     while (fixp)
 | 
|---|
| 1380 |       {
 | 
|---|
| 1381 |         if (! fixp->fx_done)
 | 
|---|
| 1382 |           nrelocs++;
 | 
|---|
| 1383 |         fixp = fixp->fx_next;
 | 
|---|
| 1384 |       }
 | 
|---|
| 1385 |   }
 | 
|---|
| 1386 |   if (bfd_get_section_size_before_reloc (sec) == 0
 | 
|---|
| 1387 |       && nrelocs == 0
 | 
|---|
| 1388 |       && nlnno == 0
 | 
|---|
| 1389 |       && sec != text_section
 | 
|---|
| 1390 |       && sec != data_section
 | 
|---|
| 1391 |       && sec != bss_section)
 | 
|---|
| 1392 |     return;
 | 
|---|
| 1393 |   secsym = section_symbol (sec);
 | 
|---|
| 1394 |   /* This is an estimate; we'll plug in the real value using
 | 
|---|
| 1395 |      SET_SECTION_RELOCS later */
 | 
|---|
| 1396 |   SA_SET_SCN_NRELOC (secsym, nrelocs);
 | 
|---|
| 1397 |   SA_SET_SCN_NLINNO (secsym, nlnno);
 | 
|---|
| 1398 | }
 | 
|---|
| 1399 | 
 | 
|---|
| 1400 | void
 | 
|---|
| 1401 | coff_frob_file_after_relocs ()
 | 
|---|
| 1402 | {
 | 
|---|
| 1403 |   bfd_map_over_sections (stdoutput, coff_adjust_section_syms, (char*) 0);
 | 
|---|
| 1404 | }
 | 
|---|
| 1405 | 
 | 
|---|
| 1406 | /* Implement the .section pseudo op:
 | 
|---|
| 1407 |         .section name {, "flags"}
 | 
|---|
| 1408 |                   ^         ^
 | 
|---|
| 1409 |                   |         +--- optional flags: 'b' for bss
 | 
|---|
| 1410 |                   |                              'i' for info
 | 
|---|
| 1411 |                   +-- section name               'l' for lib
 | 
|---|
| 1412 |                                                  'n' for noload
 | 
|---|
| 1413 |                                                  'o' for over
 | 
|---|
| 1414 |                                                  'w' for data
 | 
|---|
| 1415 |                                                  'd' (apparently m88k for data)
 | 
|---|
| 1416 |                                                  'x' for text
 | 
|---|
| 1417 |                                                  'r' for read-only data
 | 
|---|
| 1418 |                                                  's' for shared data (PE)
 | 
|---|
| 1419 |    But if the argument is not a quoted string, treat it as a
 | 
|---|
| 1420 |    subsegment number.
 | 
|---|
| 1421 | 
 | 
|---|
| 1422 |    Note the 'a' flag is silently ignored.  This allows the same
 | 
|---|
| 1423 |    .section directive to be parsed in both ELF and COFF formats.  */
 | 
|---|
| 1424 | 
 | 
|---|
| 1425 | void
 | 
|---|
| 1426 | obj_coff_section (ignore)
 | 
|---|
| 1427 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1428 | {
 | 
|---|
| 1429 |   /* Strip out the section name */
 | 
|---|
| 1430 |   char *section_name;
 | 
|---|
| 1431 |   char c;
 | 
|---|
| 1432 |   char *name;
 | 
|---|
| 1433 |   unsigned int exp;
 | 
|---|
| 1434 |   flagword flags, oldflags;
 | 
|---|
| 1435 |   asection *sec;
 | 
|---|
| 1436 | 
 | 
|---|
| 1437 |   if (flag_mri)
 | 
|---|
| 1438 |     {
 | 
|---|
| 1439 |       char type;
 | 
|---|
| 1440 | 
 | 
|---|
| 1441 |       s_mri_sect (&type);
 | 
|---|
| 1442 |       return;
 | 
|---|
| 1443 |     }
 | 
|---|
| 1444 | 
 | 
|---|
| 1445 |   section_name = input_line_pointer;
 | 
|---|
| 1446 |   c = get_symbol_end ();
 | 
|---|
| 1447 | 
 | 
|---|
| 1448 |   name = xmalloc (input_line_pointer - section_name + 1);
 | 
|---|
| 1449 |   strcpy (name, section_name);
 | 
|---|
| 1450 | 
 | 
|---|
| 1451 |   *input_line_pointer = c;
 | 
|---|
| 1452 | 
 | 
|---|
| 1453 |   SKIP_WHITESPACE ();
 | 
|---|
| 1454 | 
 | 
|---|
| 1455 |   exp = 0;
 | 
|---|
| 1456 |   flags = SEC_NO_FLAGS;
 | 
|---|
| 1457 | 
 | 
|---|
| 1458 |   if (*input_line_pointer == ',')
 | 
|---|
| 1459 |     {
 | 
|---|
| 1460 |       ++input_line_pointer;
 | 
|---|
| 1461 |       SKIP_WHITESPACE ();
 | 
|---|
| 1462 |       if (*input_line_pointer != '"')
 | 
|---|
| 1463 |         exp = get_absolute_expression ();
 | 
|---|
| 1464 |       else
 | 
|---|
| 1465 |         {
 | 
|---|
| 1466 |           ++input_line_pointer;
 | 
|---|
| 1467 |           while (*input_line_pointer != '"'
 | 
|---|
| 1468 |                  && ! is_end_of_line[(unsigned char) *input_line_pointer])
 | 
|---|
| 1469 |             {
 | 
|---|
| 1470 |               switch (*input_line_pointer)
 | 
|---|
| 1471 |                 {
 | 
|---|
| 1472 |                 case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break;
 | 
|---|
| 1473 |                 case 'n': flags &=~ SEC_LOAD; flags |= SEC_NEVER_LOAD; break;
 | 
|---|
| 1474 | 
 | 
|---|
| 1475 |                 case 's': flags |= SEC_SHARED; /* fall through */
 | 
|---|
| 1476 |                 case 'd': flags |= SEC_DATA | SEC_LOAD; /* fall through */
 | 
|---|
| 1477 |                 case 'w': flags &=~ SEC_READONLY; break;
 | 
|---|
| 1478 | 
 | 
|---|
| 1479 |                 case 'a': break; /* For compatability with ELF.  */
 | 
|---|
| 1480 |                 case 'x': flags |= SEC_CODE | SEC_LOAD; break;
 | 
|---|
| 1481 |                 case 'r': flags |= SEC_READONLY; break;
 | 
|---|
| 1482 | 
 | 
|---|
| 1483 |                 case 'i': /* STYP_INFO */
 | 
|---|
| 1484 |                 case 'l': /* STYP_LIB */
 | 
|---|
| 1485 |                 case 'o': /* STYP_OVER */
 | 
|---|
| 1486 |                   as_warn (_("unsupported section attribute '%c'"),
 | 
|---|
| 1487 |                            *input_line_pointer);
 | 
|---|
| 1488 |                   break;
 | 
|---|
| 1489 | 
 | 
|---|
| 1490 |                 default:
 | 
|---|
| 1491 |                   as_warn(_("unknown section attribute '%c'"),
 | 
|---|
| 1492 |                           *input_line_pointer);
 | 
|---|
| 1493 |                   break;
 | 
|---|
| 1494 |                 }
 | 
|---|
| 1495 |               ++input_line_pointer;
 | 
|---|
| 1496 |             }
 | 
|---|
| 1497 |           if (*input_line_pointer == '"')
 | 
|---|
| 1498 |             ++input_line_pointer;
 | 
|---|
| 1499 |         }
 | 
|---|
| 1500 |     }
 | 
|---|
| 1501 | 
 | 
|---|
| 1502 |   sec = subseg_new (name, (subsegT) exp);
 | 
|---|
| 1503 | 
 | 
|---|
| 1504 |   oldflags = bfd_get_section_flags (stdoutput, sec);
 | 
|---|
| 1505 |   if (oldflags == SEC_NO_FLAGS)
 | 
|---|
| 1506 |     {
 | 
|---|
| 1507 |       /* Set section flags for a new section just created by subseg_new.
 | 
|---|
| 1508 |          Provide a default if no flags were parsed.  */
 | 
|---|
| 1509 |       if (flags == SEC_NO_FLAGS)
 | 
|---|
| 1510 |         flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES;
 | 
|---|
| 1511 | 
 | 
|---|
| 1512 | #ifdef COFF_LONG_SECTION_NAMES
 | 
|---|
| 1513 |       /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce
 | 
|---|
| 1514 |          sections so adjust_reloc_syms in write.c will correctly handle
 | 
|---|
| 1515 |          relocs which refer to non-local symbols in these sections.  */
 | 
|---|
| 1516 |       if (strncmp (name, ".gnu.linkonce", sizeof (".gnu.linkonce") - 1) == 0)
 | 
|---|
| 1517 |         flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 | 
|---|
| 1518 | #endif
 | 
|---|
| 1519 | 
 | 
|---|
| 1520 |       if (! bfd_set_section_flags (stdoutput, sec, flags))
 | 
|---|
| 1521 |         as_warn (_("error setting flags for \"%s\": %s"),
 | 
|---|
| 1522 |                  bfd_section_name (stdoutput, sec),
 | 
|---|
| 1523 |                  bfd_errmsg (bfd_get_error ()));
 | 
|---|
| 1524 |     }
 | 
|---|
| 1525 |   else if (flags != SEC_NO_FLAGS)
 | 
|---|
| 1526 |     {
 | 
|---|
| 1527 |       /* This section's attributes have already been set. Warn if the
 | 
|---|
| 1528 |          attributes don't match.  */
 | 
|---|
| 1529 |       flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
 | 
|---|
| 1530 |                              | SEC_DATA | SEC_SHARED | SEC_NEVER_LOAD);
 | 
|---|
| 1531 |       if ((flags ^ oldflags) & matchflags)
 | 
|---|
| 1532 |         as_warn (_("Ignoring changed section attributes for %s"), name);
 | 
|---|
| 1533 |     }
 | 
|---|
| 1534 | 
 | 
|---|
| 1535 |   demand_empty_rest_of_line ();
 | 
|---|
| 1536 | }
 | 
|---|
| 1537 | 
 | 
|---|
| 1538 | void
 | 
|---|
| 1539 | coff_adjust_symtab ()
 | 
|---|
| 1540 | {
 | 
|---|
| 1541 |   if (symbol_rootP == NULL
 | 
|---|
| 1542 |       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
 | 
|---|
| 1543 |     c_dot_file_symbol ("fake");
 | 
|---|
| 1544 | }
 | 
|---|
| 1545 | 
 | 
|---|
| 1546 | void
 | 
|---|
| 1547 | coff_frob_section (sec)
 | 
|---|
| 1548 |      segT sec;
 | 
|---|
| 1549 | {
 | 
|---|
| 1550 |   segT strsec;
 | 
|---|
| 1551 |   char *p;
 | 
|---|
| 1552 |   fragS *fragp;
 | 
|---|
| 1553 |   bfd_vma size, n_entries, mask;
 | 
|---|
| 1554 |   bfd_vma align_power = (bfd_vma)sec->alignment_power + OCTETS_PER_BYTE_POWER;
 | 
|---|
| 1555 | 
 | 
|---|
| 1556 |   /* The COFF back end in BFD requires that all section sizes be
 | 
|---|
| 1557 |      rounded up to multiples of the corresponding section alignments,
 | 
|---|
| 1558 |      supposedly because standard COFF has no other way of encoding alignment
 | 
|---|
| 1559 |      for sections.  If your COFF flavor has a different way of encoding
 | 
|---|
| 1560 |      section alignment, then skip this step, as TICOFF does.  */
 | 
|---|
| 1561 |   size = bfd_get_section_size_before_reloc (sec);
 | 
|---|
| 1562 |   mask = ((bfd_vma) 1 << align_power) - 1;
 | 
|---|
| 1563 | #if !defined(TICOFF)
 | 
|---|
| 1564 |   if (size & mask)
 | 
|---|
| 1565 |     {
 | 
|---|
| 1566 |       bfd_vma new_size;
 | 
|---|
| 1567 |       fragS *last;
 | 
|---|
| 1568 | 
 | 
|---|
| 1569 |       new_size = (size + mask) & ~mask;
 | 
|---|
| 1570 |       bfd_set_section_size (stdoutput, sec, new_size);
 | 
|---|
| 1571 | 
 | 
|---|
| 1572 |       /* If the size had to be rounded up, add some padding in
 | 
|---|
| 1573 |          the last non-empty frag.  */
 | 
|---|
| 1574 |       fragp = seg_info (sec)->frchainP->frch_root;
 | 
|---|
| 1575 |       last = seg_info (sec)->frchainP->frch_last;
 | 
|---|
| 1576 |       while (fragp->fr_next != last)
 | 
|---|
| 1577 |         fragp = fragp->fr_next;
 | 
|---|
| 1578 |       last->fr_address = size;
 | 
|---|
| 1579 |       fragp->fr_offset += new_size - size;
 | 
|---|
| 1580 |     }
 | 
|---|
| 1581 | #endif
 | 
|---|
| 1582 | 
 | 
|---|
| 1583 |   /* If the section size is non-zero, the section symbol needs an aux
 | 
|---|
| 1584 |      entry associated with it, indicating the size.  We don't know
 | 
|---|
| 1585 |      all the values yet; coff_frob_symbol will fill them in later.  */
 | 
|---|
| 1586 | #ifndef TICOFF
 | 
|---|
| 1587 |   if (size != 0
 | 
|---|
| 1588 |       || sec == text_section
 | 
|---|
| 1589 |       || sec == data_section
 | 
|---|
| 1590 |       || sec == bss_section)
 | 
|---|
| 1591 | #endif
 | 
|---|
| 1592 |     {
 | 
|---|
| 1593 |       symbolS *secsym = section_symbol (sec);
 | 
|---|
| 1594 | 
 | 
|---|
| 1595 |       S_SET_STORAGE_CLASS (secsym, C_STAT);
 | 
|---|
| 1596 |       S_SET_NUMBER_AUXILIARY (secsym, 1);
 | 
|---|
| 1597 |       SF_SET_STATICS (secsym);
 | 
|---|
| 1598 |       SA_SET_SCN_SCNLEN (secsym, size);
 | 
|---|
| 1599 |     }
 | 
|---|
| 1600 | 
 | 
|---|
| 1601 |   /* @@ these should be in a "stabs.h" file, or maybe as.h */
 | 
|---|
| 1602 | #ifndef STAB_SECTION_NAME
 | 
|---|
| 1603 | #define STAB_SECTION_NAME ".stab"
 | 
|---|
| 1604 | #endif
 | 
|---|
| 1605 | #ifndef STAB_STRING_SECTION_NAME
 | 
|---|
| 1606 | #define STAB_STRING_SECTION_NAME ".stabstr"
 | 
|---|
| 1607 | #endif
 | 
|---|
| 1608 |   if (strcmp (STAB_STRING_SECTION_NAME, sec->name))
 | 
|---|
| 1609 |     return;
 | 
|---|
| 1610 | 
 | 
|---|
| 1611 |   strsec = sec;
 | 
|---|
| 1612 |   sec = subseg_get (STAB_SECTION_NAME, 0);
 | 
|---|
| 1613 |   /* size is already rounded up, since other section will be listed first */
 | 
|---|
| 1614 |   size = bfd_get_section_size_before_reloc (strsec);
 | 
|---|
| 1615 | 
 | 
|---|
| 1616 |   n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1;
 | 
|---|
| 1617 | 
 | 
|---|
| 1618 |   /* Find first non-empty frag.  It should be large enough.  */
 | 
|---|
| 1619 |   fragp = seg_info (sec)->frchainP->frch_root;
 | 
|---|
| 1620 |   while (fragp && fragp->fr_fix == 0)
 | 
|---|
| 1621 |     fragp = fragp->fr_next;
 | 
|---|
| 1622 |   assert (fragp != 0 && fragp->fr_fix >= 12);
 | 
|---|
| 1623 | 
 | 
|---|
| 1624 |   /* Store the values.  */
 | 
|---|
| 1625 |   p = fragp->fr_literal;
 | 
|---|
| 1626 |   bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
 | 
|---|
| 1627 |   bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
 | 
|---|
| 1628 | }
 | 
|---|
| 1629 | 
 | 
|---|
| 1630 | void
 | 
|---|
| 1631 | obj_coff_init_stab_section (seg)
 | 
|---|
| 1632 |      segT seg;
 | 
|---|
| 1633 | {
 | 
|---|
| 1634 |   char *file;
 | 
|---|
| 1635 |   char *p;
 | 
|---|
| 1636 |   char *stabstr_name;
 | 
|---|
| 1637 |   unsigned int stroff;
 | 
|---|
| 1638 | 
 | 
|---|
| 1639 |   /* Make space for this first symbol.  */
 | 
|---|
| 1640 |   p = frag_more (12);
 | 
|---|
| 1641 |   /* Zero it out.  */
 | 
|---|
| 1642 |   memset (p, 0, 12);
 | 
|---|
| 1643 |   as_where (&file, (unsigned int *) NULL);
 | 
|---|
| 1644 |   stabstr_name = (char *) xmalloc (strlen (seg->name) + 4);
 | 
|---|
| 1645 |   strcpy (stabstr_name, seg->name);
 | 
|---|
| 1646 |   strcat (stabstr_name, "str");
 | 
|---|
| 1647 |   stroff = get_stab_string_offset (file, stabstr_name);
 | 
|---|
| 1648 |   know (stroff == 1);
 | 
|---|
| 1649 |   md_number_to_chars (p, stroff, 4);
 | 
|---|
| 1650 | }
 | 
|---|
| 1651 | 
 | 
|---|
| 1652 | #ifdef DEBUG
 | 
|---|
| 1653 | /* for debugging */
 | 
|---|
| 1654 | const char *
 | 
|---|
| 1655 | s_get_name (s)
 | 
|---|
| 1656 |      symbolS *s;
 | 
|---|
| 1657 | {
 | 
|---|
| 1658 |   return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
 | 
|---|
| 1659 | }
 | 
|---|
| 1660 | 
 | 
|---|
| 1661 | void
 | 
|---|
| 1662 | symbol_dump ()
 | 
|---|
| 1663 | {
 | 
|---|
| 1664 |   symbolS *symbolP;
 | 
|---|
| 1665 | 
 | 
|---|
| 1666 |   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
 | 
|---|
| 1667 |     {
 | 
|---|
| 1668 |       printf (_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"),
 | 
|---|
| 1669 |              (unsigned long) symbolP,
 | 
|---|
| 1670 |              S_GET_NAME(symbolP),
 | 
|---|
| 1671 |              (long) S_GET_DATA_TYPE(symbolP),
 | 
|---|
| 1672 |              S_GET_STORAGE_CLASS(symbolP),
 | 
|---|
| 1673 |              (int) S_GET_SEGMENT(symbolP));
 | 
|---|
| 1674 |     }
 | 
|---|
| 1675 | }
 | 
|---|
| 1676 | 
 | 
|---|
| 1677 | #endif /* DEBUG */
 | 
|---|
| 1678 | 
 | 
|---|
| 1679 | #else /* not BFD_ASSEMBLER */
 | 
|---|
| 1680 | 
 | 
|---|
| 1681 | #include "frags.h"
 | 
|---|
| 1682 | /* This is needed because we include internal bfd things.  */
 | 
|---|
| 1683 | #include <time.h>
 | 
|---|
| 1684 | 
 | 
|---|
| 1685 | #include "libbfd.h"
 | 
|---|
| 1686 | #include "libcoff.h"
 | 
|---|
| 1687 | 
 | 
|---|
| 1688 | #ifdef TE_PE
 | 
|---|
| 1689 | #include "coff/pe.h"
 | 
|---|
| 1690 | #endif
 | 
|---|
| 1691 | 
 | 
|---|
| 1692 | /* The NOP_OPCODE is for the alignment fill value.  Fill with nop so
 | 
|---|
| 1693 |    that we can stick sections together without causing trouble.  */
 | 
|---|
| 1694 | #ifndef NOP_OPCODE
 | 
|---|
| 1695 | #define NOP_OPCODE 0x00
 | 
|---|
| 1696 | #endif
 | 
|---|
| 1697 | 
 | 
|---|
| 1698 | /* The zeroes if symbol name is longer than 8 chars */
 | 
|---|
| 1699 | #define S_SET_ZEROES(s,v)               ((s)->sy_symbol.ost_entry.n_zeroes = (v))
 | 
|---|
| 1700 | 
 | 
|---|
| 1701 | #define MIN(a,b) ((a) < (b)? (a) : (b))
 | 
|---|
| 1702 | 
 | 
|---|
| 1703 | /* This vector is used to turn a gas internal segment number into a
 | 
|---|
| 1704 |    section number suitable for insertion into a coff symbol table.
 | 
|---|
| 1705 |    This must correspond to seg_info_off_by_4.  */
 | 
|---|
| 1706 | 
 | 
|---|
| 1707 | const short seg_N_TYPE[] =
 | 
|---|
| 1708 | {                               /* in: segT   out: N_TYPE bits */
 | 
|---|
| 1709 |   C_ABS_SECTION,
 | 
|---|
| 1710 |   1,    2,  3,   4,    5,   6,   7,   8,   9,  10,
 | 
|---|
| 1711 |   11,  12,  13,  14,  15,  16,  17,  18,  19,  20,
 | 
|---|
| 1712 |   21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
 | 
|---|
| 1713 |   31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
 | 
|---|
| 1714 |   C_UNDEF_SECTION,              /* SEG_UNKNOWN */
 | 
|---|
| 1715 |   C_UNDEF_SECTION,              /* SEG_GOOF */
 | 
|---|
| 1716 |   C_UNDEF_SECTION,              /* SEG_EXPR */
 | 
|---|
| 1717 |   C_DEBUG_SECTION,              /* SEG_DEBUG */
 | 
|---|
| 1718 |   C_NTV_SECTION,                /* SEG_NTV */
 | 
|---|
| 1719 |   C_PTV_SECTION,                /* SEG_PTV */
 | 
|---|
| 1720 |   C_REGISTER_SECTION,           /* SEG_REGISTER */
 | 
|---|
| 1721 | };
 | 
|---|
| 1722 | 
 | 
|---|
| 1723 | int function_lineoff = -1;      /* Offset in line#s where the last function
 | 
|---|
| 1724 |                                    started (the odd entry for line #0) */
 | 
|---|
| 1725 | 
 | 
|---|
| 1726 | /* Structure used to keep the filenames which
 | 
|---|
| 1727 |    are too long around so that we can stick them
 | 
|---|
| 1728 |    into the string table.  */
 | 
|---|
| 1729 | struct filename_list
 | 
|---|
| 1730 | {
 | 
|---|
| 1731 |   char *filename;
 | 
|---|
| 1732 |   struct filename_list *next;
 | 
|---|
| 1733 | };
 | 
|---|
| 1734 | 
 | 
|---|
| 1735 | static struct filename_list *filename_list_head;
 | 
|---|
| 1736 | static struct filename_list *filename_list_tail;
 | 
|---|
| 1737 | 
 | 
|---|
| 1738 | static symbolS *last_line_symbol;
 | 
|---|
| 1739 | 
 | 
|---|
| 1740 | /* Add 4 to the real value to get the index and compensate the
 | 
|---|
| 1741 |    negatives. This vector is used by S_GET_SEGMENT to turn a coff
 | 
|---|
| 1742 |    section number into a segment number.  */
 | 
|---|
| 1743 | 
 | 
|---|
| 1744 | bfd *abfd;
 | 
|---|
| 1745 | static symbolS *previous_file_symbol;
 | 
|---|
| 1746 | static int line_base;
 | 
|---|
| 1747 | 
 | 
|---|
| 1748 | void c_symbol_merge PARAMS ((symbolS *, symbolS *));
 | 
|---|
| 1749 | symbolS *c_section_symbol PARAMS ((char *, int));
 | 
|---|
| 1750 | void obj_coff_section PARAMS ((int));
 | 
|---|
| 1751 | void do_relocs_for PARAMS ((bfd *, object_headers *, unsigned long *));
 | 
|---|
| 1752 | char * symbol_to_chars PARAMS ((bfd *, char *, symbolS *));
 | 
|---|
| 1753 | void w_strings PARAMS ((char *));
 | 
|---|
| 1754 | 
 | 
|---|
| 1755 | static void fixup_segment PARAMS ((segment_info_type *, segT));
 | 
|---|
| 1756 | static void fixup_mdeps PARAMS ((fragS *, object_headers *, segT));
 | 
|---|
| 1757 | static void fill_section PARAMS ((bfd *,  object_headers *, unsigned long *));
 | 
|---|
| 1758 | static int c_line_new PARAMS ((symbolS *, long, int, fragS *));
 | 
|---|
| 1759 | static void w_symbols PARAMS ((bfd *, char *, symbolS *));
 | 
|---|
| 1760 | static void adjust_stab_section PARAMS ((bfd *, segT));
 | 
|---|
| 1761 | static void obj_coff_lcomm PARAMS ((int));
 | 
|---|
| 1762 | static void obj_coff_text PARAMS ((int));
 | 
|---|
| 1763 | static void obj_coff_data PARAMS ((int));
 | 
|---|
| 1764 | static unsigned int count_entries_in_chain PARAMS ((unsigned int));
 | 
|---|
| 1765 | static void coff_header_append PARAMS ((bfd *, object_headers *));
 | 
|---|
| 1766 | static unsigned int yank_symbols PARAMS ((void));
 | 
|---|
| 1767 | static unsigned int glue_symbols PARAMS ((symbolS **, symbolS **));
 | 
|---|
| 1768 | static unsigned int tie_tags PARAMS ((void));
 | 
|---|
| 1769 | static void crawl_symbols PARAMS ((object_headers *, bfd *));
 | 
|---|
| 1770 | static void do_linenos_for PARAMS ((bfd *, object_headers *, unsigned long *));
 | 
|---|
| 1771 | static void remove_subsegs PARAMS ((void));
 | 
|---|
| 1772 | 
 | 
|---|
| 1773 | 
 | 
|---|
| 1774 | 
 | 
|---|
| 1775 | /* When not using BFD_ASSEMBLER, we permit up to 40 sections.
 | 
|---|
| 1776 | 
 | 
|---|
| 1777 |    This array maps a COFF section number into a gas section number.
 | 
|---|
| 1778 |    Because COFF uses negative section numbers, you must add 4 to the
 | 
|---|
| 1779 |    COFF section number when indexing into this array; this is done via
 | 
|---|
| 1780 |    the SEG_INFO_FROM_SECTION_NUMBER macro.  This must correspond to
 | 
|---|
| 1781 |    seg_N_TYPE.  */
 | 
|---|
| 1782 | 
 | 
|---|
| 1783 | static const segT seg_info_off_by_4[] =
 | 
|---|
| 1784 | {
 | 
|---|
| 1785 |  SEG_PTV,
 | 
|---|
| 1786 |  SEG_NTV,
 | 
|---|
| 1787 |  SEG_DEBUG,
 | 
|---|
| 1788 |  SEG_ABSOLUTE,
 | 
|---|
| 1789 |  SEG_UNKNOWN,
 | 
|---|
| 1790 |  SEG_E0,  SEG_E1,  SEG_E2,  SEG_E3,  SEG_E4,
 | 
|---|
| 1791 |  SEG_E5,  SEG_E6,  SEG_E7,  SEG_E8,  SEG_E9,
 | 
|---|
| 1792 |  SEG_E10, SEG_E11, SEG_E12, SEG_E13, SEG_E14,
 | 
|---|
| 1793 |  SEG_E15, SEG_E16, SEG_E17, SEG_E18, SEG_E19,
 | 
|---|
| 1794 |  SEG_E20, SEG_E21, SEG_E22, SEG_E23, SEG_E24,
 | 
|---|
| 1795 |  SEG_E25, SEG_E26, SEG_E27, SEG_E28, SEG_E29,
 | 
|---|
| 1796 |  SEG_E30, SEG_E31, SEG_E32, SEG_E33, SEG_E34,
 | 
|---|
| 1797 |  SEG_E35, SEG_E36, SEG_E37, SEG_E38, SEG_E39,
 | 
|---|
| 1798 |  (segT) 40,
 | 
|---|
| 1799 |  (segT) 41,
 | 
|---|
| 1800 |  (segT) 42,
 | 
|---|
| 1801 |  (segT) 43,
 | 
|---|
| 1802 |  (segT) 44,
 | 
|---|
| 1803 |  (segT) 45,
 | 
|---|
| 1804 |  (segT) 0,
 | 
|---|
| 1805 |  (segT) 0,
 | 
|---|
| 1806 |  (segT) 0,
 | 
|---|
| 1807 |  SEG_REGISTER
 | 
|---|
| 1808 | };
 | 
|---|
| 1809 | 
 | 
|---|
| 1810 | #define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
 | 
|---|
| 1811 | 
 | 
|---|
| 1812 | static relax_addressT relax_align PARAMS ((relax_addressT, long));
 | 
|---|
| 1813 | 
 | 
|---|
| 1814 | static relax_addressT
 | 
|---|
| 1815 | relax_align (address, alignment)
 | 
|---|
| 1816 |      relax_addressT address;
 | 
|---|
| 1817 |      long alignment;
 | 
|---|
| 1818 | {
 | 
|---|
| 1819 |   relax_addressT mask;
 | 
|---|
| 1820 |   relax_addressT new_address;
 | 
|---|
| 1821 | 
 | 
|---|
| 1822 |   mask = ~((~0) << alignment);
 | 
|---|
| 1823 |   new_address = (address + mask) & (~mask);
 | 
|---|
| 1824 |   return (new_address - address);
 | 
|---|
| 1825 | }
 | 
|---|
| 1826 | 
 | 
|---|
| 1827 | segT
 | 
|---|
| 1828 | s_get_segment (x)
 | 
|---|
| 1829 |      symbolS * x;
 | 
|---|
| 1830 | {
 | 
|---|
| 1831 |   return SEG_INFO_FROM_SECTION_NUMBER (x->sy_symbol.ost_entry.n_scnum);
 | 
|---|
| 1832 | }
 | 
|---|
| 1833 | 
 | 
|---|
| 1834 | static unsigned int size_section PARAMS ((bfd *, unsigned int));
 | 
|---|
| 1835 | 
 | 
|---|
| 1836 | /* Calculate the size of the frag chain and fill in the section header
 | 
|---|
| 1837 |    to contain all of it, also fill in the addr of the sections.  */
 | 
|---|
| 1838 | 
 | 
|---|
| 1839 | static unsigned int
 | 
|---|
| 1840 | size_section (abfd, idx)
 | 
|---|
| 1841 |      bfd *abfd ATTRIBUTE_UNUSED;
 | 
|---|
| 1842 |      unsigned int idx;
 | 
|---|
| 1843 | {
 | 
|---|
| 1844 | 
 | 
|---|
| 1845 |   unsigned int size = 0;
 | 
|---|
| 1846 |   fragS *frag = segment_info[idx].frchainP->frch_root;
 | 
|---|
| 1847 | 
 | 
|---|
| 1848 |   while (frag)
 | 
|---|
| 1849 |     {
 | 
|---|
| 1850 |       size = frag->fr_address;
 | 
|---|
| 1851 |       if (frag->fr_address != size)
 | 
|---|
| 1852 |         {
 | 
|---|
| 1853 |           fprintf (stderr, _("Out of step\n"));
 | 
|---|
| 1854 |           size = frag->fr_address;
 | 
|---|
| 1855 |         }
 | 
|---|
| 1856 | 
 | 
|---|
| 1857 |       switch (frag->fr_type)
 | 
|---|
| 1858 |         {
 | 
|---|
| 1859 | #ifdef TC_COFF_SIZEMACHDEP
 | 
|---|
| 1860 |         case rs_machine_dependent:
 | 
|---|
| 1861 |           size += TC_COFF_SIZEMACHDEP (frag);
 | 
|---|
| 1862 |           break;
 | 
|---|
| 1863 | #endif
 | 
|---|
| 1864 |         case rs_space:
 | 
|---|
| 1865 |         case rs_fill:
 | 
|---|
| 1866 |         case rs_org:
 | 
|---|
| 1867 |           size += frag->fr_fix;
 | 
|---|
| 1868 |           size += frag->fr_offset * frag->fr_var;
 | 
|---|
| 1869 |           break;
 | 
|---|
| 1870 |         case rs_align:
 | 
|---|
| 1871 |         case rs_align_code:
 | 
|---|
| 1872 |         case rs_align_test:
 | 
|---|
| 1873 |           {
 | 
|---|
| 1874 |             addressT off;
 | 
|---|
| 1875 | 
 | 
|---|
| 1876 |             size += frag->fr_fix;
 | 
|---|
| 1877 |             off = relax_align (size, frag->fr_offset);
 | 
|---|
| 1878 |             if (frag->fr_subtype != 0 && off > frag->fr_subtype)
 | 
|---|
| 1879 |               off = 0;
 | 
|---|
| 1880 |             size += off;
 | 
|---|
| 1881 |           }
 | 
|---|
| 1882 |           break;
 | 
|---|
| 1883 |         default:
 | 
|---|
| 1884 |           BAD_CASE (frag->fr_type);
 | 
|---|
| 1885 |           break;
 | 
|---|
| 1886 |         }
 | 
|---|
| 1887 |       frag = frag->fr_next;
 | 
|---|
| 1888 |     }
 | 
|---|
| 1889 |   segment_info[idx].scnhdr.s_size = size;
 | 
|---|
| 1890 |   return size;
 | 
|---|
| 1891 | }
 | 
|---|
| 1892 | 
 | 
|---|
| 1893 | static unsigned int
 | 
|---|
| 1894 | count_entries_in_chain (idx)
 | 
|---|
| 1895 |      unsigned int idx;
 | 
|---|
| 1896 | {
 | 
|---|
| 1897 |   unsigned int nrelocs;
 | 
|---|
| 1898 |   fixS *fixup_ptr;
 | 
|---|
| 1899 | 
 | 
|---|
| 1900 |   /* Count the relocations.  */
 | 
|---|
| 1901 |   fixup_ptr = segment_info[idx].fix_root;
 | 
|---|
| 1902 |   nrelocs = 0;
 | 
|---|
| 1903 |   while (fixup_ptr != (fixS *) NULL)
 | 
|---|
| 1904 |     {
 | 
|---|
| 1905 |       if (fixup_ptr->fx_done == 0 && TC_COUNT_RELOC (fixup_ptr))
 | 
|---|
| 1906 |         {
 | 
|---|
| 1907 | #if defined(TC_A29K) || defined(TC_OR32)
 | 
|---|
| 1908 |           if (fixup_ptr->fx_r_type == RELOC_CONSTH)
 | 
|---|
| 1909 |             nrelocs += 2;
 | 
|---|
| 1910 |           else
 | 
|---|
| 1911 |             nrelocs++;
 | 
|---|
| 1912 | #else
 | 
|---|
| 1913 |           nrelocs++;
 | 
|---|
| 1914 | #endif
 | 
|---|
| 1915 |         }
 | 
|---|
| 1916 | 
 | 
|---|
| 1917 |       fixup_ptr = fixup_ptr->fx_next;
 | 
|---|
| 1918 |     }
 | 
|---|
| 1919 |   return nrelocs;
 | 
|---|
| 1920 | }
 | 
|---|
| 1921 | 
 | 
|---|
| 1922 | #ifdef TE_AUX
 | 
|---|
| 1923 | 
 | 
|---|
| 1924 | static int compare_external_relocs PARAMS ((const PTR, const PTR));
 | 
|---|
| 1925 | 
 | 
|---|
| 1926 | /* AUX's ld expects relocations to be sorted.  */
 | 
|---|
| 1927 | 
 | 
|---|
| 1928 | static int
 | 
|---|
| 1929 | compare_external_relocs (x, y)
 | 
|---|
| 1930 |      const PTR x;
 | 
|---|
| 1931 |      const PTR y;
 | 
|---|
| 1932 | {
 | 
|---|
| 1933 |   struct external_reloc *a = (struct external_reloc *) x;
 | 
|---|
| 1934 |   struct external_reloc *b = (struct external_reloc *) y;
 | 
|---|
| 1935 |   bfd_vma aadr = bfd_getb32 (a->r_vaddr);
 | 
|---|
| 1936 |   bfd_vma badr = bfd_getb32 (b->r_vaddr);
 | 
|---|
| 1937 |   return (aadr < badr ? -1 : badr < aadr ? 1 : 0);
 | 
|---|
| 1938 | }
 | 
|---|
| 1939 | 
 | 
|---|
| 1940 | #endif
 | 
|---|
| 1941 | 
 | 
|---|
| 1942 | /* Output all the relocations for a section.  */
 | 
|---|
| 1943 | 
 | 
|---|
| 1944 | void
 | 
|---|
| 1945 | do_relocs_for (abfd, h, file_cursor)
 | 
|---|
| 1946 |      bfd * abfd;
 | 
|---|
| 1947 |      object_headers * h;
 | 
|---|
| 1948 |      unsigned long *file_cursor;
 | 
|---|
| 1949 | {
 | 
|---|
| 1950 |   unsigned int nrelocs;
 | 
|---|
| 1951 |   unsigned int idx;
 | 
|---|
| 1952 |   unsigned long reloc_start = *file_cursor;
 | 
|---|
| 1953 | 
 | 
|---|
| 1954 |   for (idx = SEG_E0; idx < SEG_LAST; idx++)
 | 
|---|
| 1955 |     {
 | 
|---|
| 1956 |       if (segment_info[idx].scnhdr.s_name[0])
 | 
|---|
| 1957 |         {
 | 
|---|
| 1958 |           struct external_reloc *ext_ptr;
 | 
|---|
| 1959 |           struct external_reloc *external_reloc_vec;
 | 
|---|
| 1960 |           unsigned int external_reloc_size;
 | 
|---|
| 1961 |           unsigned int base = segment_info[idx].scnhdr.s_paddr;
 | 
|---|
| 1962 |           fixS *fix_ptr = segment_info[idx].fix_root;
 | 
|---|
| 1963 |           nrelocs = count_entries_in_chain (idx);
 | 
|---|
| 1964 | 
 | 
|---|
| 1965 |           if (nrelocs)
 | 
|---|
| 1966 |             /* Bypass this stuff if no relocs.  This also incidentally
 | 
|---|
| 1967 |                avoids a SCO bug, where free(malloc(0)) tends to crash.  */
 | 
|---|
| 1968 |             {
 | 
|---|
| 1969 |               external_reloc_size = nrelocs * RELSZ;
 | 
|---|
| 1970 |               external_reloc_vec =
 | 
|---|
| 1971 |                 (struct external_reloc *) malloc (external_reloc_size);
 | 
|---|
| 1972 | 
 | 
|---|
| 1973 |               ext_ptr = external_reloc_vec;
 | 
|---|
| 1974 | 
 | 
|---|
| 1975 |               /* Fill in the internal coff style reloc struct from the
 | 
|---|
| 1976 |                  internal fix list.  */
 | 
|---|
| 1977 |               while (fix_ptr)
 | 
|---|
| 1978 |                 {
 | 
|---|
| 1979 |                   struct internal_reloc intr;
 | 
|---|
| 1980 | 
 | 
|---|
| 1981 |                   /* Only output some of the relocations.  */
 | 
|---|
| 1982 |                   if (fix_ptr->fx_done == 0 && TC_COUNT_RELOC (fix_ptr))
 | 
|---|
| 1983 |                     {
 | 
|---|
| 1984 | #ifdef TC_RELOC_MANGLE
 | 
|---|
| 1985 |                       TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr,
 | 
|---|
| 1986 |                                        base);
 | 
|---|
| 1987 | #else
 | 
|---|
| 1988 |                       symbolS *dot;
 | 
|---|
| 1989 |                       symbolS *symbol_ptr = fix_ptr->fx_addsy;
 | 
|---|
| 1990 | 
 | 
|---|
| 1991 |                       intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
 | 
|---|
| 1992 |                       intr.r_vaddr =
 | 
|---|
| 1993 |                         base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
 | 
|---|
| 1994 | 
 | 
|---|
| 1995 | #ifdef TC_KEEP_FX_OFFSET
 | 
|---|
| 1996 |                       intr.r_offset = fix_ptr->fx_offset;
 | 
|---|
| 1997 | #else
 | 
|---|
| 1998 |                       intr.r_offset = 0;
 | 
|---|
| 1999 | #endif
 | 
|---|
| 2000 | 
 | 
|---|
| 2001 |                       while (symbol_ptr->sy_value.X_op == O_symbol
 | 
|---|
| 2002 |                              && (! S_IS_DEFINED (symbol_ptr)
 | 
|---|
| 2003 |                                  || S_IS_COMMON (symbol_ptr)))
 | 
|---|
| 2004 |                         {
 | 
|---|
| 2005 |                           symbolS *n;
 | 
|---|
| 2006 | 
 | 
|---|
| 2007 |                           /* We must avoid looping, as that can occur
 | 
|---|
| 2008 |                              with a badly written program.  */
 | 
|---|
| 2009 |                           n = symbol_ptr->sy_value.X_add_symbol;
 | 
|---|
| 2010 |                           if (n == symbol_ptr)
 | 
|---|
| 2011 |                             break;
 | 
|---|
| 2012 |                           symbol_ptr = n;
 | 
|---|
| 2013 |                         }
 | 
|---|
| 2014 | 
 | 
|---|
| 2015 |                       /* Turn the segment of the symbol into an offset.  */
 | 
|---|
| 2016 |                       if (symbol_ptr)
 | 
|---|
| 2017 |                         {
 | 
|---|
| 2018 |                           resolve_symbol_value (symbol_ptr);
 | 
|---|
| 2019 |                           if (! symbol_ptr->sy_resolved)
 | 
|---|
| 2020 |                             {
 | 
|---|
| 2021 |                               char *file;
 | 
|---|
| 2022 |                               unsigned int line;
 | 
|---|
| 2023 | 
 | 
|---|
| 2024 |                               if (expr_symbol_where (symbol_ptr, &file, &line))
 | 
|---|
| 2025 |                                 as_bad_where (file, line,
 | 
|---|
| 2026 |                                               _("unresolved relocation"));
 | 
|---|
| 2027 |                               else
 | 
|---|
| 2028 |                                 as_bad (_("bad relocation: symbol `%s' not in symbol table"),
 | 
|---|
| 2029 |                                         S_GET_NAME (symbol_ptr));
 | 
|---|
| 2030 |                             }
 | 
|---|
| 2031 | 
 | 
|---|
| 2032 |                           dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
 | 
|---|
| 2033 |                           if (dot)
 | 
|---|
| 2034 |                             intr.r_symndx = dot->sy_number;
 | 
|---|
| 2035 |                           else
 | 
|---|
| 2036 |                             intr.r_symndx = symbol_ptr->sy_number;
 | 
|---|
| 2037 |                         }
 | 
|---|
| 2038 |                       else
 | 
|---|
| 2039 |                         intr.r_symndx = -1;
 | 
|---|
| 2040 | #endif
 | 
|---|
| 2041 |                       (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
 | 
|---|
| 2042 |                       ext_ptr++;
 | 
|---|
| 2043 | #if defined(TC_A29K)
 | 
|---|
| 2044 |                       /* The 29k has a special kludge for the high 16 bit
 | 
|---|
| 2045 |                          reloc.  Two relocations are emited, R_IHIHALF,
 | 
|---|
| 2046 |                          and R_IHCONST. The second one doesn't contain a
 | 
|---|
| 2047 |                          symbol, but uses the value for offset.  */
 | 
|---|
| 2048 |                       if (intr.r_type == R_IHIHALF)
 | 
|---|
| 2049 |                         {
 | 
|---|
| 2050 |                           /* Now emit the second bit.  */
 | 
|---|
| 2051 |                           intr.r_type = R_IHCONST;
 | 
|---|
| 2052 |                           intr.r_symndx = fix_ptr->fx_addnumber;
 | 
|---|
| 2053 |                           (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
 | 
|---|
| 2054 |                           ext_ptr++;
 | 
|---|
| 2055 |                         }
 | 
|---|
| 2056 | #endif
 | 
|---|
| 2057 | #if defined(TC_OR32)
 | 
|---|
| 2058 |                       /* The or32 has a special kludge for the high 16 bit
 | 
|---|
| 2059 |                          reloc.  Two relocations are emited, R_IHIHALF,
 | 
|---|
| 2060 |                          and R_IHCONST. The second one doesn't contain a
 | 
|---|
| 2061 |                          symbol, but uses the value for offset.  */
 | 
|---|
| 2062 |                       if (intr.r_type == R_IHIHALF)
 | 
|---|
| 2063 |                         {
 | 
|---|
| 2064 |                           /* Now emit the second bit.  */
 | 
|---|
| 2065 |                           intr.r_type = R_IHCONST;
 | 
|---|
| 2066 |                           intr.r_symndx = fix_ptr->fx_addnumber;
 | 
|---|
| 2067 |                           (void) bfd_coff_swap_reloc_out (abfd, & intr, ext_ptr);
 | 
|---|
| 2068 |                           ext_ptr ++;
 | 
|---|
| 2069 |                         }
 | 
|---|
| 2070 | #endif
 | 
|---|
| 2071 |                     }
 | 
|---|
| 2072 | 
 | 
|---|
| 2073 |                   fix_ptr = fix_ptr->fx_next;
 | 
|---|
| 2074 |                 }
 | 
|---|
| 2075 | #ifdef TE_AUX
 | 
|---|
| 2076 |               /* Sort the reloc table.  */
 | 
|---|
| 2077 |               qsort ((PTR) external_reloc_vec, nrelocs,
 | 
|---|
| 2078 |                      sizeof (struct external_reloc), compare_external_relocs);
 | 
|---|
| 2079 | #endif
 | 
|---|
| 2080 |               /* Write out the reloc table.  */
 | 
|---|
| 2081 |               bfd_bwrite ((PTR) external_reloc_vec,
 | 
|---|
| 2082 |                           (bfd_size_type) external_reloc_size, abfd);
 | 
|---|
| 2083 |               free (external_reloc_vec);
 | 
|---|
| 2084 | 
 | 
|---|
| 2085 |               /* Fill in section header info.  */
 | 
|---|
| 2086 |               segment_info[idx].scnhdr.s_relptr = *file_cursor;
 | 
|---|
| 2087 |               *file_cursor += external_reloc_size;
 | 
|---|
| 2088 |               segment_info[idx].scnhdr.s_nreloc = nrelocs;
 | 
|---|
| 2089 |             }
 | 
|---|
| 2090 |           else
 | 
|---|
| 2091 |             {
 | 
|---|
| 2092 |               /* No relocs.  */
 | 
|---|
| 2093 |               segment_info[idx].scnhdr.s_relptr = 0;
 | 
|---|
| 2094 |             }
 | 
|---|
| 2095 |         }
 | 
|---|
| 2096 |     }
 | 
|---|
| 2097 | 
 | 
|---|
| 2098 |   /* Set relocation_size field in file headers.  */
 | 
|---|
| 2099 |   H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0);
 | 
|---|
| 2100 | }
 | 
|---|
| 2101 | 
 | 
|---|
| 2102 | /* Run through a frag chain and write out the data to go with it, fill
 | 
|---|
| 2103 |    in the scnhdrs with the info on the file postions.  */
 | 
|---|
| 2104 | 
 | 
|---|
| 2105 | static void
 | 
|---|
| 2106 | fill_section (abfd, h, file_cursor)
 | 
|---|
| 2107 |      bfd * abfd;
 | 
|---|
| 2108 |      object_headers *h ATTRIBUTE_UNUSED;
 | 
|---|
| 2109 |      unsigned long *file_cursor;
 | 
|---|
| 2110 | {
 | 
|---|
| 2111 |   unsigned int i;
 | 
|---|
| 2112 |   unsigned int paddr = 0;
 | 
|---|
| 2113 | 
 | 
|---|
| 2114 |   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
 | 
|---|
| 2115 |     {
 | 
|---|
| 2116 |       unsigned int offset = 0;
 | 
|---|
| 2117 |       struct internal_scnhdr *s = &(segment_info[i].scnhdr);
 | 
|---|
| 2118 | 
 | 
|---|
| 2119 |       PROGRESS (1);
 | 
|---|
| 2120 | 
 | 
|---|
| 2121 |       if (s->s_name[0])
 | 
|---|
| 2122 |         {
 | 
|---|
| 2123 |           fragS *frag = segment_info[i].frchainP->frch_root;
 | 
|---|
| 2124 |           char *buffer = NULL;
 | 
|---|
| 2125 | 
 | 
|---|
| 2126 |           if (s->s_size == 0)
 | 
|---|
| 2127 |             s->s_scnptr = 0;
 | 
|---|
| 2128 |           else
 | 
|---|
| 2129 |             {
 | 
|---|
| 2130 |               buffer = xmalloc (s->s_size);
 | 
|---|
| 2131 |               s->s_scnptr = *file_cursor;
 | 
|---|
| 2132 |             }
 | 
|---|
| 2133 |           know (s->s_paddr == paddr);
 | 
|---|
| 2134 | 
 | 
|---|
| 2135 |           if (strcmp (s->s_name, ".text") == 0)
 | 
|---|
| 2136 |             s->s_flags |= STYP_TEXT;
 | 
|---|
| 2137 |           else if (strcmp (s->s_name, ".data") == 0)
 | 
|---|
| 2138 |             s->s_flags |= STYP_DATA;
 | 
|---|
| 2139 |           else if (strcmp (s->s_name, ".bss") == 0)
 | 
|---|
| 2140 |             {
 | 
|---|
| 2141 |               s->s_scnptr = 0;
 | 
|---|
| 2142 |               s->s_flags |= STYP_BSS;
 | 
|---|
| 2143 | 
 | 
|---|
| 2144 |               /* @@ Should make the i386 and a29k coff targets define
 | 
|---|
| 2145 |                  COFF_NOLOAD_PROBLEM, and have only one test here.  */
 | 
|---|
| 2146 | #ifndef TC_I386
 | 
|---|
| 2147 | #ifndef TC_A29K
 | 
|---|
| 2148 | #ifndef TC_OR32
 | 
|---|
| 2149 | #ifndef COFF_NOLOAD_PROBLEM
 | 
|---|
| 2150 |               /* Apparently the SVR3 linker (and exec syscall) and UDI
 | 
|---|
| 2151 |                  mondfe progrem are confused by noload sections.  */
 | 
|---|
| 2152 |               s->s_flags |= STYP_NOLOAD;
 | 
|---|
| 2153 | #endif
 | 
|---|
| 2154 | #endif
 | 
|---|
| 2155 | #endif
 | 
|---|
| 2156 | #endif
 | 
|---|
| 2157 |             }
 | 
|---|
| 2158 |           else if (strcmp (s->s_name, ".lit") == 0)
 | 
|---|
| 2159 |             s->s_flags = STYP_LIT | STYP_TEXT;
 | 
|---|
| 2160 |           else if (strcmp (s->s_name, ".init") == 0)
 | 
|---|
| 2161 |             s->s_flags |= STYP_TEXT;
 | 
|---|
| 2162 |           else if (strcmp (s->s_name, ".fini") == 0)
 | 
|---|
| 2163 |             s->s_flags |= STYP_TEXT;
 | 
|---|
| 2164 |           else if (strncmp (s->s_name, ".comment", 8) == 0)
 | 
|---|
| 2165 |             s->s_flags |= STYP_INFO;
 | 
|---|
| 2166 | 
 | 
|---|
| 2167 |           while (frag)
 | 
|---|
| 2168 |             {
 | 
|---|
| 2169 |               unsigned int fill_size;
 | 
|---|
| 2170 |               switch (frag->fr_type)
 | 
|---|
| 2171 |                 {
 | 
|---|
| 2172 |                 case rs_machine_dependent:
 | 
|---|
| 2173 |                   if (frag->fr_fix)
 | 
|---|
| 2174 |                     {
 | 
|---|
| 2175 |                       memcpy (buffer + frag->fr_address,
 | 
|---|
| 2176 |                               frag->fr_literal,
 | 
|---|
| 2177 |                               (unsigned int) frag->fr_fix);
 | 
|---|
| 2178 |                       offset += frag->fr_fix;
 | 
|---|
| 2179 |                     }
 | 
|---|
| 2180 | 
 | 
|---|
| 2181 |                   break;
 | 
|---|
| 2182 |                 case rs_space:
 | 
|---|
| 2183 |                 case rs_fill:
 | 
|---|
| 2184 |                 case rs_align:
 | 
|---|
| 2185 |                 case rs_align_code:
 | 
|---|
| 2186 |                 case rs_align_test:
 | 
|---|
| 2187 |                 case rs_org:
 | 
|---|
| 2188 |                   if (frag->fr_fix)
 | 
|---|
| 2189 |                     {
 | 
|---|
| 2190 |                       memcpy (buffer + frag->fr_address,
 | 
|---|
| 2191 |                               frag->fr_literal,
 | 
|---|
| 2192 |                               (unsigned int) frag->fr_fix);
 | 
|---|
| 2193 |                       offset += frag->fr_fix;
 | 
|---|
| 2194 |                     }
 | 
|---|
| 2195 | 
 | 
|---|
| 2196 |                   fill_size = frag->fr_var;
 | 
|---|
| 2197 |                   if (fill_size && frag->fr_offset > 0)
 | 
|---|
| 2198 |                     {
 | 
|---|
| 2199 |                       unsigned int count;
 | 
|---|
| 2200 |                       unsigned int off = frag->fr_fix;
 | 
|---|
| 2201 |                       for (count = frag->fr_offset; count; count--)
 | 
|---|
| 2202 |                         {
 | 
|---|
| 2203 |                           if (fill_size + frag->fr_address + off <= s->s_size)
 | 
|---|
| 2204 |                             {
 | 
|---|
| 2205 |                               memcpy (buffer + frag->fr_address + off,
 | 
|---|
| 2206 |                                       frag->fr_literal + frag->fr_fix,
 | 
|---|
| 2207 |                                       fill_size);
 | 
|---|
| 2208 |                               off += fill_size;
 | 
|---|
| 2209 |                               offset += fill_size;
 | 
|---|
| 2210 |                             }
 | 
|---|
| 2211 |                         }
 | 
|---|
| 2212 |                     }
 | 
|---|
| 2213 |                   break;
 | 
|---|
| 2214 |                 case rs_broken_word:
 | 
|---|
| 2215 |                   break;
 | 
|---|
| 2216 |                 default:
 | 
|---|
| 2217 |                   abort ();
 | 
|---|
| 2218 |                 }
 | 
|---|
| 2219 |               frag = frag->fr_next;
 | 
|---|
| 2220 |             }
 | 
|---|
| 2221 | 
 | 
|---|
| 2222 |           if (s->s_size != 0)
 | 
|---|
| 2223 |             {
 | 
|---|
| 2224 |               if (s->s_scnptr != 0)
 | 
|---|
| 2225 |                 {
 | 
|---|
| 2226 |                   bfd_bwrite (buffer, s->s_size, abfd);
 | 
|---|
| 2227 |                   *file_cursor += s->s_size;
 | 
|---|
| 2228 |                 }
 | 
|---|
| 2229 |               free (buffer);
 | 
|---|
| 2230 |             }
 | 
|---|
| 2231 |           paddr += s->s_size;
 | 
|---|
| 2232 |         }
 | 
|---|
| 2233 |     }
 | 
|---|
| 2234 | }
 | 
|---|
| 2235 | 
 | 
|---|
| 2236 | /* Coff file generation & utilities.  */
 | 
|---|
| 2237 | 
 | 
|---|
| 2238 | static void
 | 
|---|
| 2239 | coff_header_append (abfd, h)
 | 
|---|
| 2240 |      bfd * abfd;
 | 
|---|
| 2241 |      object_headers * h;
 | 
|---|
| 2242 | {
 | 
|---|
| 2243 |   unsigned int i;
 | 
|---|
| 2244 |   char buffer[1000];
 | 
|---|
| 2245 |   char buffero[1000];
 | 
|---|
| 2246 | #ifdef COFF_LONG_SECTION_NAMES
 | 
|---|
| 2247 |   unsigned long string_size = 4;
 | 
|---|
| 2248 | #endif
 | 
|---|
| 2249 | 
 | 
|---|
| 2250 |   bfd_seek (abfd, (file_ptr) 0, 0);
 | 
|---|
| 2251 | 
 | 
|---|
| 2252 | #ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
 | 
|---|
| 2253 |   H_SET_MAGIC_NUMBER (h, COFF_MAGIC);
 | 
|---|
| 2254 |   H_SET_VERSION_STAMP (h, 0);
 | 
|---|
| 2255 |   H_SET_ENTRY_POINT (h, 0);
 | 
|---|
| 2256 |   H_SET_TEXT_START (h, segment_info[SEG_E0].frchainP->frch_root->fr_address);
 | 
|---|
| 2257 |   H_SET_DATA_START (h, segment_info[SEG_E1].frchainP->frch_root->fr_address);
 | 
|---|
| 2258 |   H_SET_SIZEOF_OPTIONAL_HEADER (h, bfd_coff_swap_aouthdr_out(abfd, &h->aouthdr,
 | 
|---|
| 2259 |                                                              buffero));
 | 
|---|
| 2260 | #else /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */
 | 
|---|
| 2261 |   H_SET_SIZEOF_OPTIONAL_HEADER (h, 0);
 | 
|---|
| 2262 | #endif /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */
 | 
|---|
| 2263 | 
 | 
|---|
| 2264 |   i = bfd_coff_swap_filehdr_out (abfd, &h->filehdr, buffer);
 | 
|---|
| 2265 | 
 | 
|---|
| 2266 |   bfd_bwrite (buffer, (bfd_size_type) i, abfd);
 | 
|---|
| 2267 |   bfd_bwrite (buffero, (bfd_size_type) H_GET_SIZEOF_OPTIONAL_HEADER (h), abfd);
 | 
|---|
| 2268 | 
 | 
|---|
| 2269 |   for (i = SEG_E0; i < SEG_LAST; i++)
 | 
|---|
| 2270 |     {
 | 
|---|
| 2271 |       if (segment_info[i].scnhdr.s_name[0])
 | 
|---|
| 2272 |         {
 | 
|---|
| 2273 |           unsigned int size;
 | 
|---|
| 2274 | 
 | 
|---|
| 2275 | #ifdef COFF_LONG_SECTION_NAMES
 | 
|---|
| 2276 |           /* Support long section names as found in PE.  This code
 | 
|---|
| 2277 |              must coordinate with that in write_object_file and
 | 
|---|
| 2278 |              w_strings.  */
 | 
|---|
| 2279 |           if (strlen (segment_info[i].name) > SCNNMLEN)
 | 
|---|
| 2280 |             {
 | 
|---|
| 2281 |               memset (segment_info[i].scnhdr.s_name, 0, SCNNMLEN);
 | 
|---|
| 2282 |               sprintf (segment_info[i].scnhdr.s_name, "/%lu", string_size);
 | 
|---|
| 2283 |               string_size += strlen (segment_info[i].name) + 1;
 | 
|---|
| 2284 |             }
 | 
|---|
| 2285 | #endif
 | 
|---|
| 2286 |           size = bfd_coff_swap_scnhdr_out (abfd,
 | 
|---|
| 2287 |                                            &(segment_info[i].scnhdr),
 | 
|---|
| 2288 |                                            buffer);
 | 
|---|
| 2289 |           if (size == 0)
 | 
|---|
| 2290 |             as_bad (_("bfd_coff_swap_scnhdr_out failed"));
 | 
|---|
| 2291 |           bfd_bwrite (buffer, (bfd_size_type) size, abfd);
 | 
|---|
| 2292 |         }
 | 
|---|
| 2293 |     }
 | 
|---|
| 2294 | }
 | 
|---|
| 2295 | 
 | 
|---|
| 2296 | char *
 | 
|---|
| 2297 | symbol_to_chars (abfd, where, symbolP)
 | 
|---|
| 2298 |      bfd * abfd;
 | 
|---|
| 2299 |      char *where;
 | 
|---|
| 2300 |      symbolS * symbolP;
 | 
|---|
| 2301 | {
 | 
|---|
| 2302 |   unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
 | 
|---|
| 2303 |   unsigned int i;
 | 
|---|
| 2304 |   valueT val;
 | 
|---|
| 2305 | 
 | 
|---|
| 2306 |   /* Turn any symbols with register attributes into abs symbols.  */
 | 
|---|
| 2307 |   if (S_GET_SEGMENT (symbolP) == reg_section)
 | 
|---|
| 2308 |     S_SET_SEGMENT (symbolP, absolute_section);
 | 
|---|
| 2309 | 
 | 
|---|
| 2310 |   /* At the same time, relocate all symbols to their output value.  */
 | 
|---|
| 2311 | #ifndef TE_PE
 | 
|---|
| 2312 |   val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr
 | 
|---|
| 2313 |          + S_GET_VALUE (symbolP));
 | 
|---|
| 2314 | #else
 | 
|---|
| 2315 |   val = S_GET_VALUE (symbolP);
 | 
|---|
| 2316 | #endif
 | 
|---|
| 2317 | 
 | 
|---|
| 2318 |   S_SET_VALUE (symbolP, val);
 | 
|---|
| 2319 | 
 | 
|---|
| 2320 |   symbolP->sy_symbol.ost_entry.n_value = val;
 | 
|---|
| 2321 | 
 | 
|---|
| 2322 |   where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry,
 | 
|---|
| 2323 |                                   where);
 | 
|---|
| 2324 | 
 | 
|---|
| 2325 |   for (i = 0; i < numaux; i++)
 | 
|---|
| 2326 |     {
 | 
|---|
| 2327 |       where += bfd_coff_swap_aux_out (abfd,
 | 
|---|
| 2328 |                                       &symbolP->sy_symbol.ost_auxent[i],
 | 
|---|
| 2329 |                                       S_GET_DATA_TYPE (symbolP),
 | 
|---|
| 2330 |                                       S_GET_STORAGE_CLASS (symbolP),
 | 
|---|
| 2331 |                                       i, numaux, where);
 | 
|---|
| 2332 |     }
 | 
|---|
| 2333 | 
 | 
|---|
| 2334 |   return where;
 | 
|---|
| 2335 | }
 | 
|---|
| 2336 | 
 | 
|---|
| 2337 | void
 | 
|---|
| 2338 | coff_obj_symbol_new_hook (symbolP)
 | 
|---|
| 2339 |      symbolS *symbolP;
 | 
|---|
| 2340 | {
 | 
|---|
| 2341 |   char underscore = 0;          /* Symbol has leading _  */
 | 
|---|
| 2342 | 
 | 
|---|
| 2343 |   /* Effective symbol.  */
 | 
|---|
| 2344 |   /* Store the pointer in the offset.  */
 | 
|---|
| 2345 |   S_SET_ZEROES (symbolP, 0L);
 | 
|---|
| 2346 |   S_SET_DATA_TYPE (symbolP, T_NULL);
 | 
|---|
| 2347 |   S_SET_STORAGE_CLASS (symbolP, 0);
 | 
|---|
| 2348 |   S_SET_NUMBER_AUXILIARY (symbolP, 0);
 | 
|---|
| 2349 |   /* Additional information.  */
 | 
|---|
| 2350 |   symbolP->sy_symbol.ost_flags = 0;
 | 
|---|
| 2351 |   /* Auxiliary entries.  */
 | 
|---|
| 2352 |   memset ((char *) &symbolP->sy_symbol.ost_auxent[0], 0, AUXESZ);
 | 
|---|
| 2353 | 
 | 
|---|
| 2354 |   if (S_IS_STRING (symbolP))
 | 
|---|
| 2355 |     SF_SET_STRING (symbolP);
 | 
|---|
| 2356 |   if (!underscore && S_IS_LOCAL (symbolP))
 | 
|---|
| 2357 |     SF_SET_LOCAL (symbolP);
 | 
|---|
| 2358 | }
 | 
|---|
| 2359 | 
 | 
|---|
| 2360 | /* Handle .ln directives.  */
 | 
|---|
| 2361 | 
 | 
|---|
| 2362 | static void
 | 
|---|
| 2363 | obj_coff_ln (appline)
 | 
|---|
| 2364 |      int appline;
 | 
|---|
| 2365 | {
 | 
|---|
| 2366 |   int l;
 | 
|---|
| 2367 | 
 | 
|---|
| 2368 |   if (! appline && def_symbol_in_progress != NULL)
 | 
|---|
| 2369 |     {
 | 
|---|
| 2370 |       /* Wrong context.  */
 | 
|---|
| 2371 |       as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
 | 
|---|
| 2372 |       demand_empty_rest_of_line ();
 | 
|---|
| 2373 |       return;
 | 
|---|
| 2374 |     }
 | 
|---|
| 2375 | 
 | 
|---|
| 2376 |   l = get_absolute_expression ();
 | 
|---|
| 2377 |   c_line_new (0, frag_now_fix (), l, frag_now);
 | 
|---|
| 2378 | 
 | 
|---|
| 2379 |   if (appline)
 | 
|---|
| 2380 |     new_logical_line ((char *) NULL, l - 1);
 | 
|---|
| 2381 | 
 | 
|---|
| 2382 | #ifndef NO_LISTING
 | 
|---|
| 2383 |   {
 | 
|---|
| 2384 |     extern int listing;
 | 
|---|
| 2385 | 
 | 
|---|
| 2386 |     if (listing)
 | 
|---|
| 2387 |       {
 | 
|---|
| 2388 |         if (! appline)
 | 
|---|
| 2389 |           l += line_base - 1;
 | 
|---|
| 2390 |         listing_source_line ((unsigned int) l);
 | 
|---|
| 2391 |       }
 | 
|---|
| 2392 | 
 | 
|---|
| 2393 |   }
 | 
|---|
| 2394 | #endif
 | 
|---|
| 2395 |   demand_empty_rest_of_line ();
 | 
|---|
| 2396 | }
 | 
|---|
| 2397 | 
 | 
|---|
| 2398 | /* Handle .def directives.
 | 
|---|
| 2399 |  
 | 
|---|
| 2400 |   One might ask : why can't we symbol_new if the symbol does not
 | 
|---|
| 2401 |   already exist and fill it with debug information.  Because of
 | 
|---|
| 2402 |   the C_EFCN special symbol. It would clobber the value of the
 | 
|---|
| 2403 |   function symbol before we have a chance to notice that it is
 | 
|---|
| 2404 |   a C_EFCN. And a second reason is that the code is more clear this
 | 
|---|
| 2405 |   way. (at least I think it is :-).  */
 | 
|---|
| 2406 | 
 | 
|---|
| 2407 | #define SKIP_SEMI_COLON()       while (*input_line_pointer++ != ';')
 | 
|---|
| 2408 | #define SKIP_WHITESPACES()      while (*input_line_pointer == ' ' || \
 | 
|---|
| 2409 |                                       *input_line_pointer == '\t') \
 | 
|---|
| 2410 |                                          input_line_pointer++;
 | 
|---|
| 2411 | 
 | 
|---|
| 2412 | static void
 | 
|---|
| 2413 | obj_coff_def (what)
 | 
|---|
| 2414 |      int what ATTRIBUTE_UNUSED;
 | 
|---|
| 2415 | {
 | 
|---|
| 2416 |   char name_end;                /* Char after the end of name.  */
 | 
|---|
| 2417 |   char *symbol_name;            /* Name of the debug symbol.  */
 | 
|---|
| 2418 |   char *symbol_name_copy;       /* Temporary copy of the name.  */
 | 
|---|
| 2419 |   unsigned int symbol_name_length;
 | 
|---|
| 2420 | 
 | 
|---|
| 2421 |   if (def_symbol_in_progress != NULL)
 | 
|---|
| 2422 |     {
 | 
|---|
| 2423 |       as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
 | 
|---|
| 2424 |       demand_empty_rest_of_line ();
 | 
|---|
| 2425 |       return;
 | 
|---|
| 2426 |     }
 | 
|---|
| 2427 | 
 | 
|---|
| 2428 |   SKIP_WHITESPACES ();
 | 
|---|
| 2429 | 
 | 
|---|
| 2430 |   def_symbol_in_progress = (symbolS *) obstack_alloc (¬es, sizeof (*def_symbol_in_progress));
 | 
|---|
| 2431 |   memset (def_symbol_in_progress, 0, sizeof (*def_symbol_in_progress));
 | 
|---|
| 2432 | 
 | 
|---|
| 2433 |   symbol_name = input_line_pointer;
 | 
|---|
| 2434 |   name_end = get_symbol_end ();
 | 
|---|
| 2435 |   symbol_name_length = strlen (symbol_name);
 | 
|---|
| 2436 |   symbol_name_copy = xmalloc (symbol_name_length + 1);
 | 
|---|
| 2437 |   strcpy (symbol_name_copy, symbol_name);
 | 
|---|
| 2438 | #ifdef tc_canonicalize_symbol_name
 | 
|---|
| 2439 |   symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
 | 
|---|
| 2440 | #endif
 | 
|---|
| 2441 | 
 | 
|---|
| 2442 |   /* Initialize the new symbol.  */
 | 
|---|
| 2443 | #ifdef STRIP_UNDERSCORE
 | 
|---|
| 2444 |   S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_'
 | 
|---|
| 2445 |                                        ? symbol_name_copy + 1
 | 
|---|
| 2446 |                                        : symbol_name_copy));
 | 
|---|
| 2447 | #else /* STRIP_UNDERSCORE */
 | 
|---|
| 2448 |   S_SET_NAME (def_symbol_in_progress, symbol_name_copy);
 | 
|---|
| 2449 | #endif /* STRIP_UNDERSCORE */
 | 
|---|
| 2450 |   /* free(symbol_name_copy); */
 | 
|---|
| 2451 |   def_symbol_in_progress->sy_name_offset = (unsigned long) ~0;
 | 
|---|
| 2452 |   def_symbol_in_progress->sy_number = ~0;
 | 
|---|
| 2453 |   def_symbol_in_progress->sy_frag = &zero_address_frag;
 | 
|---|
| 2454 |   S_SET_VALUE (def_symbol_in_progress, 0);
 | 
|---|
| 2455 | 
 | 
|---|
| 2456 |   if (S_IS_STRING (def_symbol_in_progress))
 | 
|---|
| 2457 |     SF_SET_STRING (def_symbol_in_progress);
 | 
|---|
| 2458 | 
 | 
|---|
| 2459 |   *input_line_pointer = name_end;
 | 
|---|
| 2460 | 
 | 
|---|
| 2461 |   demand_empty_rest_of_line ();
 | 
|---|
| 2462 | }
 | 
|---|
| 2463 | 
 | 
|---|
| 2464 | unsigned int dim_index;
 | 
|---|
| 2465 | 
 | 
|---|
| 2466 | static void
 | 
|---|
| 2467 | obj_coff_endef (ignore)
 | 
|---|
| 2468 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2469 | {
 | 
|---|
| 2470 |   symbolS *symbolP = 0;
 | 
|---|
| 2471 |   /* DIM BUG FIX sac@cygnus.com */
 | 
|---|
| 2472 |   dim_index = 0;
 | 
|---|
| 2473 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2474 |     {
 | 
|---|
| 2475 |       as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
 | 
|---|
| 2476 |       demand_empty_rest_of_line ();
 | 
|---|
| 2477 |       return;
 | 
|---|
| 2478 |     }
 | 
|---|
| 2479 | 
 | 
|---|
| 2480 |   /* Set the section number according to storage class.  */
 | 
|---|
| 2481 |   switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
 | 
|---|
| 2482 |     {
 | 
|---|
| 2483 |     case C_STRTAG:
 | 
|---|
| 2484 |     case C_ENTAG:
 | 
|---|
| 2485 |     case C_UNTAG:
 | 
|---|
| 2486 |       SF_SET_TAG (def_symbol_in_progress);
 | 
|---|
| 2487 |       /* Intentional fallthrough.  */
 | 
|---|
| 2488 | 
 | 
|---|
| 2489 |     case C_FILE:
 | 
|---|
| 2490 |     case C_TPDEF:
 | 
|---|
| 2491 |       SF_SET_DEBUG (def_symbol_in_progress);
 | 
|---|
| 2492 |       S_SET_SEGMENT (def_symbol_in_progress, SEG_DEBUG);
 | 
|---|
| 2493 |       break;
 | 
|---|
| 2494 | 
 | 
|---|
| 2495 |     case C_EFCN:
 | 
|---|
| 2496 |       /* Do not emit this symbol.  */
 | 
|---|
| 2497 |       SF_SET_LOCAL (def_symbol_in_progress);
 | 
|---|
| 2498 |       /* Intentional fallthrough. */
 | 
|---|
| 2499 |       
 | 
|---|
| 2500 |     case C_BLOCK:
 | 
|---|
| 2501 |       /* Will need processing before writing.  */
 | 
|---|
| 2502 |       SF_SET_PROCESS (def_symbol_in_progress);
 | 
|---|
| 2503 |       /* Intentional fallthrough.  */
 | 
|---|
| 2504 | 
 | 
|---|
| 2505 |     case C_FCN:
 | 
|---|
| 2506 |       S_SET_SEGMENT (def_symbol_in_progress, SEG_E0);
 | 
|---|
| 2507 | 
 | 
|---|
| 2508 |       if (strcmp (S_GET_NAME (def_symbol_in_progress), ".bf") == 0)
 | 
|---|
| 2509 |         {                       /* .bf */
 | 
|---|
| 2510 |           if (function_lineoff < 0)
 | 
|---|
| 2511 |             fprintf (stderr, _("`.bf' symbol without preceding function\n"));
 | 
|---|
| 2512 | 
 | 
|---|
| 2513 |           SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff;
 | 
|---|
| 2514 | 
 | 
|---|
| 2515 |           SF_SET_PROCESS (last_line_symbol);
 | 
|---|
| 2516 |           SF_SET_ADJ_LNNOPTR (last_line_symbol);
 | 
|---|
| 2517 |           SF_SET_PROCESS (def_symbol_in_progress);
 | 
|---|
| 2518 |           function_lineoff = -1;
 | 
|---|
| 2519 |         }
 | 
|---|
| 2520 | 
 | 
|---|
| 2521 |       /* Value is always set to .  */
 | 
|---|
| 2522 |       def_symbol_in_progress->sy_frag = frag_now;
 | 
|---|
| 2523 |       S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
 | 
|---|
| 2524 |       break;
 | 
|---|
| 2525 | 
 | 
|---|
| 2526 | #ifdef C_AUTOARG
 | 
|---|
| 2527 |     case C_AUTOARG:
 | 
|---|
| 2528 | #endif /* C_AUTOARG */
 | 
|---|
| 2529 |     case C_AUTO:
 | 
|---|
| 2530 |     case C_REG:
 | 
|---|
| 2531 |     case C_MOS:
 | 
|---|
| 2532 |     case C_MOE:
 | 
|---|
| 2533 |     case C_MOU:
 | 
|---|
| 2534 |     case C_ARG:
 | 
|---|
| 2535 |     case C_REGPARM:
 | 
|---|
| 2536 |     case C_FIELD:
 | 
|---|
| 2537 |     case C_EOS:
 | 
|---|
| 2538 |       SF_SET_DEBUG (def_symbol_in_progress);
 | 
|---|
| 2539 |       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
 | 
|---|
| 2540 |       break;
 | 
|---|
| 2541 | 
 | 
|---|
| 2542 |     case C_EXT:
 | 
|---|
| 2543 |     case C_WEAKEXT:
 | 
|---|
| 2544 | #ifdef TE_PE
 | 
|---|
| 2545 |     case C_NT_WEAK:
 | 
|---|
| 2546 | #endif
 | 
|---|
| 2547 |     case C_STAT:
 | 
|---|
| 2548 |     case C_LABEL:
 | 
|---|
| 2549 |       /* Valid but set somewhere else (s_comm, s_lcomm, colon).  */
 | 
|---|
| 2550 |       break;
 | 
|---|
| 2551 | 
 | 
|---|
| 2552 |     case C_USTATIC:
 | 
|---|
| 2553 |     case C_EXTDEF:
 | 
|---|
| 2554 |     case C_ULABEL:
 | 
|---|
| 2555 |       as_warn (_("unexpected storage class %d"), S_GET_STORAGE_CLASS (def_symbol_in_progress));
 | 
|---|
| 2556 |       break;
 | 
|---|
| 2557 |     }
 | 
|---|
| 2558 | 
 | 
|---|
| 2559 |   /* Now that we have built a debug symbol, try to find if we should
 | 
|---|
| 2560 |      merge with an existing symbol or not.  If a symbol is C_EFCN or
 | 
|---|
| 2561 |      absolute_section or untagged SEG_DEBUG it never merges.  We also
 | 
|---|
| 2562 |      don't merge labels, which are in a different namespace, nor
 | 
|---|
| 2563 |      symbols which have not yet been defined since they are typically
 | 
|---|
| 2564 |      unique, nor do we merge tags with non-tags.  */
 | 
|---|
| 2565 | 
 | 
|---|
| 2566 |   /* Two cases for functions.  Either debug followed by definition or
 | 
|---|
| 2567 |      definition followed by debug.  For definition first, we will
 | 
|---|
| 2568 |      merge the debug symbol into the definition.  For debug first, the
 | 
|---|
| 2569 |      lineno entry MUST point to the definition function or else it
 | 
|---|
| 2570 |      will point off into space when crawl_symbols() merges the debug
 | 
|---|
| 2571 |      symbol into the real symbol.  Therefor, let's presume the debug
 | 
|---|
| 2572 |      symbol is a real function reference.  */
 | 
|---|
| 2573 | 
 | 
|---|
| 2574 |   /* FIXME-SOON If for some reason the definition label/symbol is
 | 
|---|
| 2575 |      never seen, this will probably leave an undefined symbol at link
 | 
|---|
| 2576 |      time.  */
 | 
|---|
| 2577 | 
 | 
|---|
| 2578 |   if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
 | 
|---|
| 2579 |       || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
 | 
|---|
| 2580 |       || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG
 | 
|---|
| 2581 |           && !SF_GET_TAG (def_symbol_in_progress))
 | 
|---|
| 2582 |       || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
 | 
|---|
| 2583 |       || def_symbol_in_progress->sy_value.X_op != O_constant
 | 
|---|
| 2584 |       || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL
 | 
|---|
| 2585 |       || (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP)))
 | 
|---|
| 2586 |     {
 | 
|---|
| 2587 |       symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
 | 
|---|
| 2588 |                      &symbol_lastP);
 | 
|---|
| 2589 |     }
 | 
|---|
| 2590 |   else
 | 
|---|
| 2591 |     {
 | 
|---|
| 2592 |       /* This symbol already exists, merge the newly created symbol
 | 
|---|
| 2593 |          into the old one.  This is not mandatory. The linker can
 | 
|---|
| 2594 |          handle duplicate symbols correctly. But I guess that it save
 | 
|---|
| 2595 |          a *lot* of space if the assembly file defines a lot of
 | 
|---|
| 2596 |          symbols. [loic] */
 | 
|---|
| 2597 | 
 | 
|---|
| 2598 |       /* The debug entry (def_symbol_in_progress) is merged into the
 | 
|---|
| 2599 |          previous definition.  */
 | 
|---|
| 2600 | 
 | 
|---|
| 2601 |       c_symbol_merge (def_symbol_in_progress, symbolP);
 | 
|---|
| 2602 |       /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich.  */
 | 
|---|
| 2603 |       def_symbol_in_progress = symbolP;
 | 
|---|
| 2604 | 
 | 
|---|
| 2605 |       if (SF_GET_FUNCTION (def_symbol_in_progress)
 | 
|---|
| 2606 |           || SF_GET_TAG (def_symbol_in_progress)
 | 
|---|
| 2607 |           || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
 | 
|---|
| 2608 |         {
 | 
|---|
| 2609 |           /* For functions, and tags, and static symbols, the symbol
 | 
|---|
| 2610 |              *must* be where the debug symbol appears.  Move the
 | 
|---|
| 2611 |              existing symbol to the current place.  */
 | 
|---|
| 2612 |           /* If it already is at the end of the symbol list, do nothing.  */
 | 
|---|
| 2613 |           if (def_symbol_in_progress != symbol_lastP)
 | 
|---|
| 2614 |             {
 | 
|---|
| 2615 |               symbol_remove (def_symbol_in_progress, &symbol_rootP,
 | 
|---|
| 2616 |                              &symbol_lastP);
 | 
|---|
| 2617 |               symbol_append (def_symbol_in_progress, symbol_lastP,
 | 
|---|
| 2618 |                              &symbol_rootP, &symbol_lastP);
 | 
|---|
| 2619 |             }
 | 
|---|
| 2620 |         }
 | 
|---|
| 2621 |     }
 | 
|---|
| 2622 | 
 | 
|---|
| 2623 |   if (SF_GET_TAG (def_symbol_in_progress))
 | 
|---|
| 2624 |     {
 | 
|---|
| 2625 |       symbolS *oldtag;
 | 
|---|
| 2626 | 
 | 
|---|
| 2627 |       oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress),
 | 
|---|
| 2628 |                                  DO_NOT_STRIP);
 | 
|---|
| 2629 |       if (oldtag == NULL || ! SF_GET_TAG (oldtag))
 | 
|---|
| 2630 |         tag_insert (S_GET_NAME (def_symbol_in_progress),
 | 
|---|
| 2631 |                     def_symbol_in_progress);
 | 
|---|
| 2632 |     }
 | 
|---|
| 2633 | 
 | 
|---|
| 2634 |   if (SF_GET_FUNCTION (def_symbol_in_progress))
 | 
|---|
| 2635 |     {
 | 
|---|
| 2636 |       know (sizeof (def_symbol_in_progress) <= sizeof (long));
 | 
|---|
| 2637 |       function_lineoff
 | 
|---|
| 2638 |         = c_line_new (def_symbol_in_progress, 0, 0, &zero_address_frag);
 | 
|---|
| 2639 | 
 | 
|---|
| 2640 |       SF_SET_PROCESS (def_symbol_in_progress);
 | 
|---|
| 2641 | 
 | 
|---|
| 2642 |       if (symbolP == NULL)
 | 
|---|
| 2643 |         {
 | 
|---|
| 2644 |           /* That is, if this is the first time we've seen the
 | 
|---|
| 2645 |              function...  */
 | 
|---|
| 2646 |           symbol_table_insert (def_symbol_in_progress);
 | 
|---|
| 2647 |         }
 | 
|---|
| 2648 |     }
 | 
|---|
| 2649 | 
 | 
|---|
| 2650 |   def_symbol_in_progress = NULL;
 | 
|---|
| 2651 |   demand_empty_rest_of_line ();
 | 
|---|
| 2652 | }
 | 
|---|
| 2653 | 
 | 
|---|
| 2654 | static void
 | 
|---|
| 2655 | obj_coff_dim (ignore)
 | 
|---|
| 2656 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2657 | {
 | 
|---|
| 2658 |   int dim_index;
 | 
|---|
| 2659 | 
 | 
|---|
| 2660 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2661 |     {
 | 
|---|
| 2662 |       as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
 | 
|---|
| 2663 |       demand_empty_rest_of_line ();
 | 
|---|
| 2664 |       return;
 | 
|---|
| 2665 |     }
 | 
|---|
| 2666 | 
 | 
|---|
| 2667 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 2668 | 
 | 
|---|
| 2669 |   for (dim_index = 0; dim_index < DIMNUM; dim_index++)
 | 
|---|
| 2670 |     {
 | 
|---|
| 2671 |       SKIP_WHITESPACES ();
 | 
|---|
| 2672 |       SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
 | 
|---|
| 2673 |                         get_absolute_expression ());
 | 
|---|
| 2674 | 
 | 
|---|
| 2675 |       switch (*input_line_pointer)
 | 
|---|
| 2676 |         {
 | 
|---|
| 2677 |         case ',':
 | 
|---|
| 2678 |           input_line_pointer++;
 | 
|---|
| 2679 |           break;
 | 
|---|
| 2680 | 
 | 
|---|
| 2681 |         default:
 | 
|---|
| 2682 |           as_warn (_("badly formed .dim directive ignored"));
 | 
|---|
| 2683 |           /* Intentional fallthrough.  */
 | 
|---|
| 2684 | 
 | 
|---|
| 2685 |         case '\n':
 | 
|---|
| 2686 |         case ';':
 | 
|---|
| 2687 |           dim_index = DIMNUM;
 | 
|---|
| 2688 |           break;
 | 
|---|
| 2689 |         }
 | 
|---|
| 2690 |     }
 | 
|---|
| 2691 | 
 | 
|---|
| 2692 |   demand_empty_rest_of_line ();
 | 
|---|
| 2693 | }
 | 
|---|
| 2694 | 
 | 
|---|
| 2695 | static void
 | 
|---|
| 2696 | obj_coff_line (ignore)
 | 
|---|
| 2697 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2698 | {
 | 
|---|
| 2699 |   int this_base;
 | 
|---|
| 2700 |   const char *name;
 | 
|---|
| 2701 | 
 | 
|---|
| 2702 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2703 |     {
 | 
|---|
| 2704 |       obj_coff_ln (0);
 | 
|---|
| 2705 |       return;
 | 
|---|
| 2706 |     }
 | 
|---|
| 2707 | 
 | 
|---|
| 2708 |   name = S_GET_NAME (def_symbol_in_progress);
 | 
|---|
| 2709 |   this_base = get_absolute_expression ();
 | 
|---|
| 2710 | 
 | 
|---|
| 2711 |   /* Only .bf symbols indicate the use of a new base line number; the
 | 
|---|
| 2712 |      line numbers associated with .ef, .bb, .eb are relative to the
 | 
|---|
| 2713 |      start of the containing function.  */
 | 
|---|
| 2714 |   if (!strcmp (".bf", name))
 | 
|---|
| 2715 |     {
 | 
|---|
| 2716 | #if 0 /* XXX Can we ever have line numbers going backwards?  */
 | 
|---|
| 2717 |       if (this_base > line_base)
 | 
|---|
| 2718 | #endif
 | 
|---|
| 2719 |         line_base = this_base;
 | 
|---|
| 2720 | 
 | 
|---|
| 2721 | #ifndef NO_LISTING
 | 
|---|
| 2722 |       {
 | 
|---|
| 2723 |         extern int listing;
 | 
|---|
| 2724 |         if (listing)
 | 
|---|
| 2725 |           listing_source_line ((unsigned int) line_base);
 | 
|---|
| 2726 |       }
 | 
|---|
| 2727 | #endif
 | 
|---|
| 2728 |     }
 | 
|---|
| 2729 | 
 | 
|---|
| 2730 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 2731 |   SA_SET_SYM_LNNO (def_symbol_in_progress, this_base);
 | 
|---|
| 2732 | 
 | 
|---|
| 2733 |   demand_empty_rest_of_line ();
 | 
|---|
| 2734 | }
 | 
|---|
| 2735 | 
 | 
|---|
| 2736 | static void
 | 
|---|
| 2737 | obj_coff_size (ignore)
 | 
|---|
| 2738 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2739 | {
 | 
|---|
| 2740 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2741 |     {
 | 
|---|
| 2742 |       as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 2743 |       demand_empty_rest_of_line ();
 | 
|---|
| 2744 |       return;
 | 
|---|
| 2745 |     }
 | 
|---|
| 2746 | 
 | 
|---|
| 2747 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 2748 |   SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
 | 
|---|
| 2749 |   demand_empty_rest_of_line ();
 | 
|---|
| 2750 | }
 | 
|---|
| 2751 | 
 | 
|---|
| 2752 | static void
 | 
|---|
| 2753 | obj_coff_scl (ignore)
 | 
|---|
| 2754 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2755 | {
 | 
|---|
| 2756 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2757 |     {
 | 
|---|
| 2758 |       as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 2759 |       demand_empty_rest_of_line ();
 | 
|---|
| 2760 |       return;
 | 
|---|
| 2761 |     }
 | 
|---|
| 2762 | 
 | 
|---|
| 2763 |   S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
 | 
|---|
| 2764 |   demand_empty_rest_of_line ();
 | 
|---|
| 2765 | }
 | 
|---|
| 2766 | 
 | 
|---|
| 2767 | static void
 | 
|---|
| 2768 | obj_coff_tag (ignore)
 | 
|---|
| 2769 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2770 | {
 | 
|---|
| 2771 |   char *symbol_name;
 | 
|---|
| 2772 |   char name_end;
 | 
|---|
| 2773 | 
 | 
|---|
| 2774 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2775 |     {
 | 
|---|
| 2776 |       as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 2777 |       demand_empty_rest_of_line ();
 | 
|---|
| 2778 |       return;
 | 
|---|
| 2779 |     }
 | 
|---|
| 2780 | 
 | 
|---|
| 2781 |   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
 | 
|---|
| 2782 |   symbol_name = input_line_pointer;
 | 
|---|
| 2783 |   name_end = get_symbol_end ();
 | 
|---|
| 2784 | #ifdef tc_canonicalize_symbol_name
 | 
|---|
| 2785 |   symbol_name = tc_canonicalize_symbol_name (symbol_name);
 | 
|---|
| 2786 | #endif
 | 
|---|
| 2787 | 
 | 
|---|
| 2788 |   /* Assume that the symbol referred to by .tag is always defined.
 | 
|---|
| 2789 |      This was a bad assumption.  I've added find_or_make. xoxorich.  */
 | 
|---|
| 2790 |   SA_SET_SYM_TAGNDX (def_symbol_in_progress,
 | 
|---|
| 2791 |                      (long) tag_find_or_make (symbol_name));
 | 
|---|
| 2792 |   if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
 | 
|---|
| 2793 |     as_warn (_("tag not found for .tag %s"), symbol_name);
 | 
|---|
| 2794 | 
 | 
|---|
| 2795 |   SF_SET_TAGGED (def_symbol_in_progress);
 | 
|---|
| 2796 |   *input_line_pointer = name_end;
 | 
|---|
| 2797 | 
 | 
|---|
| 2798 |   demand_empty_rest_of_line ();
 | 
|---|
| 2799 | }
 | 
|---|
| 2800 | 
 | 
|---|
| 2801 | static void
 | 
|---|
| 2802 | obj_coff_type (ignore)
 | 
|---|
| 2803 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2804 | {
 | 
|---|
| 2805 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2806 |     {
 | 
|---|
| 2807 |       as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 2808 |       demand_empty_rest_of_line ();
 | 
|---|
| 2809 |       return;
 | 
|---|
| 2810 |     }
 | 
|---|
| 2811 | 
 | 
|---|
| 2812 |   S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
 | 
|---|
| 2813 | 
 | 
|---|
| 2814 |   if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
 | 
|---|
| 2815 |       S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
 | 
|---|
| 2816 |     SF_SET_FUNCTION (def_symbol_in_progress);
 | 
|---|
| 2817 | 
 | 
|---|
| 2818 |   demand_empty_rest_of_line ();
 | 
|---|
| 2819 | }
 | 
|---|
| 2820 | 
 | 
|---|
| 2821 | static void
 | 
|---|
| 2822 | obj_coff_val (ignore)
 | 
|---|
| 2823 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 2824 | {
 | 
|---|
| 2825 |   if (def_symbol_in_progress == NULL)
 | 
|---|
| 2826 |     {
 | 
|---|
| 2827 |       as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
 | 
|---|
| 2828 |       demand_empty_rest_of_line ();
 | 
|---|
| 2829 |       return;
 | 
|---|
| 2830 |     }
 | 
|---|
| 2831 | 
 | 
|---|
| 2832 |   if (is_name_beginner (*input_line_pointer))
 | 
|---|
| 2833 |     {
 | 
|---|
| 2834 |       char *symbol_name = input_line_pointer;
 | 
|---|
| 2835 |       char name_end = get_symbol_end ();
 | 
|---|
| 2836 | 
 | 
|---|
| 2837 | #ifdef tc_canonicalize_symbol_name
 | 
|---|
| 2838 |   symbol_name = tc_canonicalize_symbol_name (symbol_name);
 | 
|---|
| 2839 | #endif
 | 
|---|
| 2840 | 
 | 
|---|
| 2841 |       if (!strcmp (symbol_name, "."))
 | 
|---|
| 2842 |         {
 | 
|---|
| 2843 |           def_symbol_in_progress->sy_frag = frag_now;
 | 
|---|
| 2844 |           S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
 | 
|---|
| 2845 |           /* If the .val is != from the .def (e.g. statics).  */
 | 
|---|
| 2846 |         }
 | 
|---|
| 2847 |       else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
 | 
|---|
| 2848 |         {
 | 
|---|
| 2849 |           def_symbol_in_progress->sy_value.X_op = O_symbol;
 | 
|---|
| 2850 |           def_symbol_in_progress->sy_value.X_add_symbol =
 | 
|---|
| 2851 |             symbol_find_or_make (symbol_name);
 | 
|---|
| 2852 |           def_symbol_in_progress->sy_value.X_op_symbol = NULL;
 | 
|---|
| 2853 |           def_symbol_in_progress->sy_value.X_add_number = 0;
 | 
|---|
| 2854 | 
 | 
|---|
| 2855 |           /* If the segment is undefined when the forward reference is
 | 
|---|
| 2856 |              resolved, then copy the segment id from the forward
 | 
|---|
| 2857 |              symbol.  */
 | 
|---|
| 2858 |           SF_SET_GET_SEGMENT (def_symbol_in_progress);
 | 
|---|
| 2859 | 
 | 
|---|
| 2860 |           /* FIXME: gcc can generate address expressions here in
 | 
|---|
| 2861 |              unusual cases (search for "obscure" in sdbout.c).  We
 | 
|---|
| 2862 |              just ignore the offset here, thus generating incorrect
 | 
|---|
| 2863 |              debugging information.  We ignore the rest of the line
 | 
|---|
| 2864 |              just below.  */
 | 
|---|
| 2865 |         }
 | 
|---|
| 2866 |       /* Otherwise, it is the name of a non debug symbol and
 | 
|---|
| 2867 |          its value will be calculated later.  */
 | 
|---|
| 2868 |       *input_line_pointer = name_end;
 | 
|---|
| 2869 | 
 | 
|---|
| 2870 |       /* FIXME: this is to avoid an error message in the
 | 
|---|
| 2871 |          FIXME case mentioned just above.  */
 | 
|---|
| 2872 |       while (! is_end_of_line[(unsigned char) *input_line_pointer])
 | 
|---|
| 2873 |         ++input_line_pointer;
 | 
|---|
| 2874 |     }
 | 
|---|
| 2875 |   else
 | 
|---|
| 2876 |     {
 | 
|---|
| 2877 |       S_SET_VALUE (def_symbol_in_progress,
 | 
|---|
| 2878 |                    (valueT) get_absolute_expression ());
 | 
|---|
| 2879 |     }                           /* if symbol based */
 | 
|---|
| 2880 | 
 | 
|---|
| 2881 |   demand_empty_rest_of_line ();
 | 
|---|
| 2882 | }
 | 
|---|
| 2883 | 
 | 
|---|
| 2884 | #ifdef TE_PE
 | 
|---|
| 2885 | 
 | 
|---|
| 2886 | /* Handle the .linkonce pseudo-op.  This is parsed by s_linkonce in
 | 
|---|
| 2887 |    read.c, which then calls this object file format specific routine.  */
 | 
|---|
| 2888 | 
 | 
|---|
| 2889 | void
 | 
|---|
| 2890 | obj_coff_pe_handle_link_once (type)
 | 
|---|
| 2891 |      enum linkonce_type type;
 | 
|---|
| 2892 | {
 | 
|---|
| 2893 |   seg_info (now_seg)->scnhdr.s_flags |= IMAGE_SCN_LNK_COMDAT;
 | 
|---|
| 2894 | 
 | 
|---|
| 2895 |   /* We store the type in the seg_info structure, and use it to set up
 | 
|---|
| 2896 |      the auxiliary entry for the section symbol in c_section_symbol.  */
 | 
|---|
| 2897 |   seg_info (now_seg)->linkonce = type;
 | 
|---|
| 2898 | }
 | 
|---|
| 2899 | 
 | 
|---|
| 2900 | #endif /* TE_PE */
 | 
|---|
| 2901 | 
 | 
|---|
| 2902 | void
 | 
|---|
| 2903 | coff_obj_read_begin_hook ()
 | 
|---|
| 2904 | {
 | 
|---|
| 2905 |   /* These had better be the same.  Usually 18 bytes.  */
 | 
|---|
| 2906 | #ifndef BFD_HEADERS
 | 
|---|
| 2907 |   know (sizeof (SYMENT) == sizeof (AUXENT));
 | 
|---|
| 2908 |   know (SYMESZ == AUXESZ);
 | 
|---|
| 2909 | #endif
 | 
|---|
| 2910 |   tag_init ();
 | 
|---|
| 2911 | }
 | 
|---|
| 2912 | 
 | 
|---|
| 2913 | /* This function runs through the symbol table and puts all the
 | 
|---|
| 2914 |    externals onto another chain.  */
 | 
|---|
| 2915 | 
 | 
|---|
| 2916 | /* The chain of globals.  */
 | 
|---|
| 2917 | symbolS *symbol_globalP;
 | 
|---|
| 2918 | symbolS *symbol_global_lastP;
 | 
|---|
| 2919 | 
 | 
|---|
| 2920 | /* The chain of externals.  */
 | 
|---|
| 2921 | symbolS *symbol_externP;
 | 
|---|
| 2922 | symbolS *symbol_extern_lastP;
 | 
|---|
| 2923 | 
 | 
|---|
| 2924 | stack *block_stack;
 | 
|---|
| 2925 | symbolS *last_functionP;
 | 
|---|
| 2926 | static symbolS *last_bfP;
 | 
|---|
| 2927 | symbolS *last_tagP;
 | 
|---|
| 2928 | 
 | 
|---|
| 2929 | static unsigned int
 | 
|---|
| 2930 | yank_symbols ()
 | 
|---|
| 2931 | {
 | 
|---|
| 2932 |   symbolS *symbolP;
 | 
|---|
| 2933 |   unsigned int symbol_number = 0;
 | 
|---|
| 2934 |   unsigned int last_file_symno = 0;
 | 
|---|
| 2935 | 
 | 
|---|
| 2936 |   struct filename_list *filename_list_scan = filename_list_head;
 | 
|---|
| 2937 | 
 | 
|---|
| 2938 |   for (symbolP = symbol_rootP;
 | 
|---|
| 2939 |        symbolP;
 | 
|---|
| 2940 |        symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP)
 | 
|---|
| 2941 |     {
 | 
|---|
| 2942 |       if (symbolP->sy_mri_common)
 | 
|---|
| 2943 |         {
 | 
|---|
| 2944 |           if (S_GET_STORAGE_CLASS (symbolP) == C_EXT
 | 
|---|
| 2945 | #ifdef TE_PE
 | 
|---|
| 2946 |               || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK
 | 
|---|
| 2947 | #endif
 | 
|---|
| 2948 |               || S_GET_STORAGE_CLASS (symbolP) == C_WEAKEXT)
 | 
|---|
| 2949 |             as_bad (_("%s: global symbols not supported in common sections"),
 | 
|---|
| 2950 |                     S_GET_NAME (symbolP));
 | 
|---|
| 2951 |           symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 2952 |           continue;
 | 
|---|
| 2953 |         }
 | 
|---|
| 2954 | 
 | 
|---|
| 2955 |       if (!SF_GET_DEBUG (symbolP))
 | 
|---|
| 2956 |         {
 | 
|---|
| 2957 |           /* Debug symbols do not need all this rubbish.  */
 | 
|---|
| 2958 |           symbolS *real_symbolP;
 | 
|---|
| 2959 | 
 | 
|---|
| 2960 |           /* L* and C_EFCN symbols never merge.  */
 | 
|---|
| 2961 |           if (!SF_GET_LOCAL (symbolP)
 | 
|---|
| 2962 |               && !SF_GET_STATICS (symbolP)
 | 
|---|
| 2963 |               && S_GET_STORAGE_CLASS (symbolP) != C_LABEL
 | 
|---|
| 2964 |               && symbolP->sy_value.X_op == O_constant
 | 
|---|
| 2965 |               && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP))
 | 
|---|
| 2966 |               && real_symbolP != symbolP)
 | 
|---|
| 2967 |             {
 | 
|---|
| 2968 |               /* FIXME-SOON: where do dups come from?
 | 
|---|
| 2969 |                  Maybe tag references before definitions? xoxorich.  */
 | 
|---|
| 2970 |               /* Move the debug data from the debug symbol to the
 | 
|---|
| 2971 |                  real symbol. Do NOT do the oposite (i.e. move from
 | 
|---|
| 2972 |                  real symbol to debug symbol and remove real symbol from the
 | 
|---|
| 2973 |                  list.) Because some pointers refer to the real symbol
 | 
|---|
| 2974 |                  whereas no pointers refer to the debug symbol.  */
 | 
|---|
| 2975 |               c_symbol_merge (symbolP, real_symbolP);
 | 
|---|
| 2976 |               /* Replace the current symbol by the real one.  */
 | 
|---|
| 2977 |               /* The symbols will never be the last or the first
 | 
|---|
| 2978 |                  because : 1st symbol is .file and 3 last symbols are
 | 
|---|
| 2979 |                  .text, .data, .bss.  */
 | 
|---|
| 2980 |               symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 2981 |               symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 2982 |               symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 2983 |               symbolP = real_symbolP;
 | 
|---|
| 2984 |             }
 | 
|---|
| 2985 | 
 | 
|---|
| 2986 |           if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_E1))
 | 
|---|
| 2987 |             S_SET_SEGMENT (symbolP, SEG_E0);
 | 
|---|
| 2988 | 
 | 
|---|
| 2989 |           resolve_symbol_value (symbolP);
 | 
|---|
| 2990 | 
 | 
|---|
| 2991 |           if (S_GET_STORAGE_CLASS (symbolP) == C_NULL)
 | 
|---|
| 2992 |             {
 | 
|---|
| 2993 |               if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP))
 | 
|---|
| 2994 |                 {
 | 
|---|
| 2995 |                   S_SET_EXTERNAL (symbolP);
 | 
|---|
| 2996 |                 }
 | 
|---|
| 2997 | 
 | 
|---|
| 2998 |               else if (S_GET_SEGMENT (symbolP) == SEG_E0)
 | 
|---|
| 2999 |                 S_SET_STORAGE_CLASS (symbolP, C_LABEL);
 | 
|---|
| 3000 | 
 | 
|---|
| 3001 |               else
 | 
|---|
| 3002 |                 S_SET_STORAGE_CLASS (symbolP, C_STAT);
 | 
|---|
| 3003 |             }
 | 
|---|
| 3004 | 
 | 
|---|
| 3005 |           /* Mainly to speed up if not -g.  */
 | 
|---|
| 3006 |           if (SF_GET_PROCESS (symbolP))
 | 
|---|
| 3007 |             {
 | 
|---|
| 3008 |               /* Handle the nested blocks auxiliary info.  */
 | 
|---|
| 3009 |               if (S_GET_STORAGE_CLASS (symbolP) == C_BLOCK)
 | 
|---|
| 3010 |                 {
 | 
|---|
| 3011 |                   if (!strcmp (S_GET_NAME (symbolP), ".bb"))
 | 
|---|
| 3012 |                     stack_push (block_stack, (char *) &symbolP);
 | 
|---|
| 3013 |                   else
 | 
|---|
| 3014 |                     {
 | 
|---|
| 3015 |                       /* .eb */
 | 
|---|
| 3016 |                       symbolS *begin_symbolP;
 | 
|---|
| 3017 | 
 | 
|---|
| 3018 |                       begin_symbolP = *(symbolS **) stack_pop (block_stack);
 | 
|---|
| 3019 |                       if (begin_symbolP == (symbolS *) 0)
 | 
|---|
| 3020 |                         as_warn (_("mismatched .eb"));
 | 
|---|
| 3021 |                       else
 | 
|---|
| 3022 |                         SA_SET_SYM_ENDNDX (begin_symbolP, symbol_number + 2);
 | 
|---|
| 3023 |                     }
 | 
|---|
| 3024 |                 }
 | 
|---|
| 3025 |               /* If we are able to identify the type of a function, and we
 | 
|---|
| 3026 |                are out of a function (last_functionP == 0) then, the
 | 
|---|
| 3027 |                function symbol will be associated with an auxiliary
 | 
|---|
| 3028 |                entry.  */
 | 
|---|
| 3029 |               if (last_functionP == (symbolS *) 0 &&
 | 
|---|
| 3030 |                   SF_GET_FUNCTION (symbolP))
 | 
|---|
| 3031 |                 {
 | 
|---|
| 3032 |                   last_functionP = symbolP;
 | 
|---|
| 3033 | 
 | 
|---|
| 3034 |                   if (S_GET_NUMBER_AUXILIARY (symbolP) < 1)
 | 
|---|
| 3035 |                     S_SET_NUMBER_AUXILIARY (symbolP, 1);
 | 
|---|
| 3036 | 
 | 
|---|
| 3037 |                   /* Clobber possible stale .dim information.  */
 | 
|---|
| 3038 | #if 0
 | 
|---|
| 3039 |                   /* Iffed out by steve - this fries the lnnoptr info too.  */
 | 
|---|
| 3040 |                   bzero (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
 | 
|---|
| 3041 |                          sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
 | 
|---|
| 3042 | #endif
 | 
|---|
| 3043 |                 }
 | 
|---|
| 3044 |               if (S_GET_STORAGE_CLASS (symbolP) == C_FCN)
 | 
|---|
| 3045 |                 {
 | 
|---|
| 3046 |                   if (strcmp (S_GET_NAME (symbolP), ".bf") == 0)
 | 
|---|
| 3047 |                     {
 | 
|---|
| 3048 |                       if (last_bfP != NULL)
 | 
|---|
| 3049 |                         SA_SET_SYM_ENDNDX (last_bfP, symbol_number);
 | 
|---|
| 3050 |                       last_bfP = symbolP;
 | 
|---|
| 3051 |                     }
 | 
|---|
| 3052 |                 }
 | 
|---|
| 3053 |               else if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN)
 | 
|---|
| 3054 |                 {
 | 
|---|
| 3055 |                   /* I don't even know if this is needed for sdb. But
 | 
|---|
| 3056 |                      the standard assembler generates it, so...  */
 | 
|---|
| 3057 |                   if (last_functionP == (symbolS *) 0)
 | 
|---|
| 3058 |                     as_fatal (_("C_EFCN symbol out of scope"));
 | 
|---|
| 3059 |                   SA_SET_SYM_FSIZE (last_functionP,
 | 
|---|
| 3060 |                                     (long) (S_GET_VALUE (symbolP) -
 | 
|---|
| 3061 |                                             S_GET_VALUE (last_functionP)));
 | 
|---|
| 3062 |                   SA_SET_SYM_ENDNDX (last_functionP, symbol_number);
 | 
|---|
| 3063 |                  last_functionP = (symbolS *) 0;
 | 
|---|
| 3064 |                 }
 | 
|---|
| 3065 |             }
 | 
|---|
| 3066 |         }
 | 
|---|
| 3067 |       else if (SF_GET_TAG (symbolP))
 | 
|---|
| 3068 |         {
 | 
|---|
| 3069 |           /* First descriptor of a structure must point to
 | 
|---|
| 3070 |              the first slot after the structure description.  */
 | 
|---|
| 3071 |           last_tagP = symbolP;
 | 
|---|
| 3072 | 
 | 
|---|
| 3073 |         }
 | 
|---|
| 3074 |       else if (S_GET_STORAGE_CLASS (symbolP) == C_EOS)
 | 
|---|
| 3075 |         {
 | 
|---|
| 3076 |           /* +2 take in account the current symbol.  */
 | 
|---|
| 3077 |           SA_SET_SYM_ENDNDX (last_tagP, symbol_number + 2);
 | 
|---|
| 3078 |         }
 | 
|---|
| 3079 |       else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE)
 | 
|---|
| 3080 |         {
 | 
|---|
| 3081 |           /* If the filename was too long to fit in the
 | 
|---|
| 3082 |              auxent, put it in the string table.  */
 | 
|---|
| 3083 |           if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0
 | 
|---|
| 3084 |               && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0)
 | 
|---|
| 3085 |             {
 | 
|---|
| 3086 |               SA_SET_FILE_FNAME_OFFSET (symbolP, string_byte_count);
 | 
|---|
| 3087 |               string_byte_count += strlen (filename_list_scan->filename) + 1;
 | 
|---|
| 3088 |               filename_list_scan = filename_list_scan->next;
 | 
|---|
| 3089 |             }
 | 
|---|
| 3090 |           if (S_GET_VALUE (symbolP))
 | 
|---|
| 3091 |             {
 | 
|---|
| 3092 |               S_SET_VALUE (symbolP, last_file_symno);
 | 
|---|
| 3093 |               last_file_symno = symbol_number;
 | 
|---|
| 3094 |             }
 | 
|---|
| 3095 |         }
 | 
|---|
| 3096 | 
 | 
|---|
| 3097 | #ifdef tc_frob_coff_symbol
 | 
|---|
| 3098 |       tc_frob_coff_symbol (symbolP);
 | 
|---|
| 3099 | #endif
 | 
|---|
| 3100 | 
 | 
|---|
| 3101 |       /* We must put the external symbols apart. The loader
 | 
|---|
| 3102 |          does not bomb if we do not. But the references in
 | 
|---|
| 3103 |          the endndx field for a .bb symbol are not corrected
 | 
|---|
| 3104 |          if an external symbol is removed between .bb and .be.
 | 
|---|
| 3105 |          I.e in the following case :
 | 
|---|
| 3106 |          [20] .bb endndx = 22
 | 
|---|
| 3107 |          [21] foo external
 | 
|---|
| 3108 |          [22] .be
 | 
|---|
| 3109 |          ld will move the symbol 21 to the end of the list but
 | 
|---|
| 3110 |          endndx will still be 22 instead of 21.  */
 | 
|---|
| 3111 | 
 | 
|---|
| 3112 |       if (SF_GET_LOCAL (symbolP))
 | 
|---|
| 3113 |         {
 | 
|---|
| 3114 |           /* Remove C_EFCN and LOCAL (L...) symbols.  */
 | 
|---|
| 3115 |           /* Next pointer remains valid.  */
 | 
|---|
| 3116 |           symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 3117 | 
 | 
|---|
| 3118 |         }
 | 
|---|
| 3119 |       else if (symbolP->sy_value.X_op == O_symbol
 | 
|---|
| 3120 |                && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
 | 
|---|
| 3121 |         {
 | 
|---|
| 3122 |           /* Skip symbols which were equated to undefined or common
 | 
|---|
| 3123 |              symbols.  */
 | 
|---|
| 3124 |           symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 3125 |         }
 | 
|---|
| 3126 |       else if (!S_IS_DEFINED (symbolP)
 | 
|---|
| 3127 |                && !S_IS_DEBUG (symbolP)
 | 
|---|
| 3128 |                && !SF_GET_STATICS (symbolP)
 | 
|---|
| 3129 |                && (S_GET_STORAGE_CLASS (symbolP) == C_EXT
 | 
|---|
| 3130 | #ifdef TE_PE
 | 
|---|
| 3131 |                    || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK
 | 
|---|
| 3132 | #endif
 | 
|---|
| 3133 |                    || S_GET_STORAGE_CLASS (symbolP) == C_WEAKEXT))
 | 
|---|
| 3134 |         {
 | 
|---|
| 3135 |           /* If external, Remove from the list.  */
 | 
|---|
| 3136 |           symbolS *hold = symbol_previous (symbolP);
 | 
|---|
| 3137 | 
 | 
|---|
| 3138 |           symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 3139 |           symbol_clear_list_pointers (symbolP);
 | 
|---|
| 3140 |           symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
 | 
|---|
| 3141 |           symbolP = hold;
 | 
|---|
| 3142 |         }
 | 
|---|
| 3143 |       else if (! S_IS_DEBUG (symbolP)
 | 
|---|
| 3144 |                && ! SF_GET_STATICS (symbolP)
 | 
|---|
| 3145 |                && ! SF_GET_FUNCTION (symbolP)
 | 
|---|
| 3146 |                && (S_GET_STORAGE_CLASS (symbolP) == C_EXT
 | 
|---|
| 3147 | #ifdef TE_PE
 | 
|---|
| 3148 |                    || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK
 | 
|---|
| 3149 | #endif
 | 
|---|
| 3150 |                    || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK))
 | 
|---|
| 3151 |         {
 | 
|---|
| 3152 |           symbolS *hold = symbol_previous (symbolP);
 | 
|---|
| 3153 | 
 | 
|---|
| 3154 |           /* The O'Reilly COFF book says that defined global symbols
 | 
|---|
| 3155 |              come at the end of the symbol table, just before
 | 
|---|
| 3156 |              undefined global symbols.  */
 | 
|---|
| 3157 |           symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 3158 |           symbol_clear_list_pointers (symbolP);
 | 
|---|
| 3159 |           symbol_append (symbolP, symbol_global_lastP, &symbol_globalP,
 | 
|---|
| 3160 |                          &symbol_global_lastP);
 | 
|---|
| 3161 |           symbolP = hold;
 | 
|---|
| 3162 |         }
 | 
|---|
| 3163 |       else
 | 
|---|
| 3164 |         {
 | 
|---|
| 3165 |           if (SF_GET_STRING (symbolP))
 | 
|---|
| 3166 |             {
 | 
|---|
| 3167 |               symbolP->sy_name_offset = string_byte_count;
 | 
|---|
| 3168 |               string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
 | 
|---|
| 3169 |             }
 | 
|---|
| 3170 |           else
 | 
|---|
| 3171 |             {
 | 
|---|
| 3172 |               symbolP->sy_name_offset = 0;
 | 
|---|
| 3173 |             }
 | 
|---|
| 3174 | 
 | 
|---|
| 3175 |           symbolP->sy_number = symbol_number;
 | 
|---|
| 3176 |           symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP);
 | 
|---|
| 3177 |         }
 | 
|---|
| 3178 |     }
 | 
|---|
| 3179 | 
 | 
|---|
| 3180 |   return symbol_number;
 | 
|---|
| 3181 | }
 | 
|---|
| 3182 | 
 | 
|---|
| 3183 | static unsigned int
 | 
|---|
| 3184 | glue_symbols (head, tail)
 | 
|---|
| 3185 |      symbolS **head;
 | 
|---|
| 3186 |      symbolS **tail;
 | 
|---|
| 3187 | {
 | 
|---|
| 3188 |   unsigned int symbol_number = 0;
 | 
|---|
| 3189 | 
 | 
|---|
| 3190 |   while (*head != NULL)
 | 
|---|
| 3191 |     {
 | 
|---|
| 3192 |       symbolS *tmp = *head;
 | 
|---|
| 3193 | 
 | 
|---|
| 3194 |       /* Append.  */
 | 
|---|
| 3195 |       symbol_remove (tmp, head, tail);
 | 
|---|
| 3196 |       symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 3197 | 
 | 
|---|
| 3198 |       /* Process.  */
 | 
|---|
| 3199 |       if (SF_GET_STRING (tmp))
 | 
|---|
| 3200 |         {
 | 
|---|
| 3201 |           tmp->sy_name_offset = string_byte_count;
 | 
|---|
| 3202 |           string_byte_count += strlen (S_GET_NAME (tmp)) + 1;
 | 
|---|
| 3203 |         }
 | 
|---|
| 3204 |       else
 | 
|---|
| 3205 |         {
 | 
|---|
| 3206 |           /* Fix "long" names.  */
 | 
|---|
| 3207 |           tmp->sy_name_offset = 0;
 | 
|---|
| 3208 |         }
 | 
|---|
| 3209 | 
 | 
|---|
| 3210 |       tmp->sy_number = symbol_number;
 | 
|---|
| 3211 |       symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp);
 | 
|---|
| 3212 |     }
 | 
|---|
| 3213 | 
 | 
|---|
| 3214 |   return symbol_number;
 | 
|---|
| 3215 | }
 | 
|---|
| 3216 | 
 | 
|---|
| 3217 | static unsigned int
 | 
|---|
| 3218 | tie_tags ()
 | 
|---|
| 3219 | {
 | 
|---|
| 3220 |   unsigned int symbol_number = 0;
 | 
|---|
| 3221 |   symbolS *symbolP;
 | 
|---|
| 3222 | 
 | 
|---|
| 3223 |   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
 | 
|---|
| 3224 |     {
 | 
|---|
| 3225 |       symbolP->sy_number = symbol_number;
 | 
|---|
| 3226 | 
 | 
|---|
| 3227 |       if (SF_GET_TAGGED (symbolP))
 | 
|---|
| 3228 |         {
 | 
|---|
| 3229 |           SA_SET_SYM_TAGNDX
 | 
|---|
| 3230 |             (symbolP,
 | 
|---|
| 3231 |              ((symbolS *) SA_GET_SYM_TAGNDX (symbolP))->sy_number);
 | 
|---|
| 3232 |         }
 | 
|---|
| 3233 | 
 | 
|---|
| 3234 |       symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP);
 | 
|---|
| 3235 |     }
 | 
|---|
| 3236 | 
 | 
|---|
| 3237 |   return symbol_number;
 | 
|---|
| 3238 | }
 | 
|---|
| 3239 | 
 | 
|---|
| 3240 | 
 | 
|---|
| 3241 | static void
 | 
|---|
| 3242 | crawl_symbols (h, abfd)
 | 
|---|
| 3243 |      object_headers *h;
 | 
|---|
| 3244 |      bfd *abfd ATTRIBUTE_UNUSED;
 | 
|---|
| 3245 | {
 | 
|---|
| 3246 |   unsigned int i;
 | 
|---|
| 3247 | 
 | 
|---|
| 3248 |   /* Initialize the stack used to keep track of the matching .bb .be.  */
 | 
|---|
| 3249 | 
 | 
|---|
| 3250 |   block_stack = stack_init (512, sizeof (symbolS *));
 | 
|---|
| 3251 | 
 | 
|---|
| 3252 |   /* The symbol list should be ordered according to the following sequence
 | 
|---|
| 3253 |      order :
 | 
|---|
| 3254 |      . .file symbol
 | 
|---|
| 3255 |      . debug entries for functions
 | 
|---|
| 3256 |      . fake symbols for the sections, including .text .data and .bss
 | 
|---|
| 3257 |      . defined symbols
 | 
|---|
| 3258 |      . undefined symbols
 | 
|---|
| 3259 |      But this is not mandatory. The only important point is to put the
 | 
|---|
| 3260 |      undefined symbols at the end of the list.  */
 | 
|---|
| 3261 | 
 | 
|---|
| 3262 |   /* Is there a .file symbol ? If not insert one at the beginning.  */
 | 
|---|
| 3263 |   if (symbol_rootP == NULL
 | 
|---|
| 3264 |       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
 | 
|---|
| 3265 |     c_dot_file_symbol ("fake");
 | 
|---|
| 3266 | 
 | 
|---|
| 3267 |   /* Build up static symbols for the sections, they are filled in later.  */
 | 
|---|
| 3268 | 
 | 
|---|
| 3269 |   for (i = SEG_E0; i < SEG_LAST; i++)
 | 
|---|
| 3270 |     if (segment_info[i].scnhdr.s_name[0])
 | 
|---|
| 3271 |       segment_info[i].dot = c_section_symbol ((char *) segment_info[i].name,
 | 
|---|
| 3272 |                                               i - SEG_E0 + 1);
 | 
|---|
| 3273 | 
 | 
|---|
| 3274 |   /* Take all the externals out and put them into another chain.  */
 | 
|---|
| 3275 |   H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ());
 | 
|---|
| 3276 |   /* Take the externals and glue them onto the end.  */
 | 
|---|
| 3277 |   H_SET_SYMBOL_TABLE_SIZE (h,
 | 
|---|
| 3278 |                            (H_GET_SYMBOL_COUNT (h)
 | 
|---|
| 3279 |                             + glue_symbols (&symbol_globalP,
 | 
|---|
| 3280 |                                             &symbol_global_lastP)
 | 
|---|
| 3281 |                             + glue_symbols (&symbol_externP,
 | 
|---|
| 3282 |                                             &symbol_extern_lastP)));
 | 
|---|
| 3283 | 
 | 
|---|
| 3284 |   H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ());
 | 
|---|
| 3285 |   know (symbol_globalP == NULL);
 | 
|---|
| 3286 |   know (symbol_global_lastP == NULL);
 | 
|---|
| 3287 |   know (symbol_externP == NULL);
 | 
|---|
| 3288 |   know (symbol_extern_lastP == NULL);
 | 
|---|
| 3289 | }
 | 
|---|
| 3290 | 
 | 
|---|
| 3291 | /* Find strings by crawling along symbol table chain.  */
 | 
|---|
| 3292 | 
 | 
|---|
| 3293 | void
 | 
|---|
| 3294 | w_strings (where)
 | 
|---|
| 3295 |      char *where;
 | 
|---|
| 3296 | {
 | 
|---|
| 3297 |   symbolS *symbolP;
 | 
|---|
| 3298 |   struct filename_list *filename_list_scan = filename_list_head;
 | 
|---|
| 3299 | 
 | 
|---|
| 3300 |   /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK.  */
 | 
|---|
| 3301 |   md_number_to_chars (where, (valueT) string_byte_count, 4);
 | 
|---|
| 3302 |   where += 4;
 | 
|---|
| 3303 | 
 | 
|---|
| 3304 | #ifdef COFF_LONG_SECTION_NAMES
 | 
|---|
| 3305 |   /* Support long section names as found in PE.  This code must
 | 
|---|
| 3306 |      coordinate with that in coff_header_append and write_object_file.  */
 | 
|---|
| 3307 |   {
 | 
|---|
| 3308 |     unsigned int i;
 | 
|---|
| 3309 | 
 | 
|---|
| 3310 |     for (i = SEG_E0; i < SEG_LAST; i++)
 | 
|---|
| 3311 |       {
 | 
|---|
| 3312 |         if (segment_info[i].scnhdr.s_name[0]
 | 
|---|
| 3313 |             && strlen (segment_info[i].name) > SCNNMLEN)
 | 
|---|
| 3314 |           {
 | 
|---|
| 3315 |             unsigned int size;
 | 
|---|
| 3316 | 
 | 
|---|
| 3317 |             size = strlen (segment_info[i].name) + 1;
 | 
|---|
| 3318 |             memcpy (where, segment_info[i].name, size);
 | 
|---|
| 3319 |             where += size;
 | 
|---|
| 3320 |           }
 | 
|---|
| 3321 |       }
 | 
|---|
| 3322 |   }
 | 
|---|
| 3323 | #endif /* COFF_LONG_SECTION_NAMES */
 | 
|---|
| 3324 | 
 | 
|---|
| 3325 |   for (symbolP = symbol_rootP;
 | 
|---|
| 3326 |        symbolP;
 | 
|---|
| 3327 |        symbolP = symbol_next (symbolP))
 | 
|---|
| 3328 |     {
 | 
|---|
| 3329 |       unsigned int size;
 | 
|---|
| 3330 | 
 | 
|---|
| 3331 |       if (SF_GET_STRING (symbolP))
 | 
|---|
| 3332 |         {
 | 
|---|
| 3333 |           size = strlen (S_GET_NAME (symbolP)) + 1;
 | 
|---|
| 3334 |           memcpy (where, S_GET_NAME (symbolP), size);
 | 
|---|
| 3335 |           where += size;
 | 
|---|
| 3336 |         }
 | 
|---|
| 3337 |       if (S_GET_STORAGE_CLASS (symbolP) == C_FILE
 | 
|---|
| 3338 |           && SA_GET_FILE_FNAME_ZEROS (symbolP) == 0
 | 
|---|
| 3339 |           && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0)
 | 
|---|
| 3340 |         {
 | 
|---|
| 3341 |           size = strlen (filename_list_scan->filename) + 1;
 | 
|---|
| 3342 |           memcpy (where, filename_list_scan->filename, size);
 | 
|---|
| 3343 |           filename_list_scan = filename_list_scan ->next;
 | 
|---|
| 3344 |           where += size;
 | 
|---|
| 3345 |         }
 | 
|---|
| 3346 |     }
 | 
|---|
| 3347 | }
 | 
|---|
| 3348 | 
 | 
|---|
| 3349 | static void
 | 
|---|
| 3350 | do_linenos_for (abfd, h, file_cursor)
 | 
|---|
| 3351 |      bfd * abfd;
 | 
|---|
| 3352 |      object_headers * h;
 | 
|---|
| 3353 |      unsigned long *file_cursor;
 | 
|---|
| 3354 | {
 | 
|---|
| 3355 |   unsigned int idx;
 | 
|---|
| 3356 |   unsigned long start = *file_cursor;
 | 
|---|
| 3357 | 
 | 
|---|
| 3358 |   for (idx = SEG_E0; idx < SEG_LAST; idx++)
 | 
|---|
| 3359 |     {
 | 
|---|
| 3360 |       segment_info_type *s = segment_info + idx;
 | 
|---|
| 3361 | 
 | 
|---|
| 3362 |       if (s->scnhdr.s_nlnno != 0)
 | 
|---|
| 3363 |         {
 | 
|---|
| 3364 |           struct lineno_list *line_ptr;
 | 
|---|
| 3365 | 
 | 
|---|
| 3366 |           struct external_lineno *buffer =
 | 
|---|
| 3367 |           (struct external_lineno *) xmalloc (s->scnhdr.s_nlnno * LINESZ);
 | 
|---|
| 3368 | 
 | 
|---|
| 3369 |           struct external_lineno *dst = buffer;
 | 
|---|
| 3370 | 
 | 
|---|
| 3371 |           /* Run through the table we've built and turn it into its external
 | 
|---|
| 3372 |              form, take this chance to remove duplicates.  */
 | 
|---|
| 3373 | 
 | 
|---|
| 3374 |           for (line_ptr = s->lineno_list_head;
 | 
|---|
| 3375 |                line_ptr != (struct lineno_list *) NULL;
 | 
|---|
| 3376 |                line_ptr = line_ptr->next)
 | 
|---|
| 3377 |             {
 | 
|---|
| 3378 |               if (line_ptr->line.l_lnno == 0)
 | 
|---|
| 3379 |                 {
 | 
|---|
| 3380 |                   /* Turn a pointer to a symbol into the symbols' index,
 | 
|---|
| 3381 |                      provided that it has been initialised.  */
 | 
|---|
| 3382 |                   if (line_ptr->line.l_addr.l_symndx)
 | 
|---|
| 3383 |                     line_ptr->line.l_addr.l_symndx =
 | 
|---|
| 3384 |                       ((symbolS *) line_ptr->line.l_addr.l_symndx)->sy_number;
 | 
|---|
| 3385 |                 }
 | 
|---|
| 3386 |               else
 | 
|---|
| 3387 |                 line_ptr->line.l_addr.l_paddr += ((struct frag *) (line_ptr->frag))->fr_address;
 | 
|---|
| 3388 | 
 | 
|---|
| 3389 |               (void) bfd_coff_swap_lineno_out (abfd, &(line_ptr->line), dst);
 | 
|---|
| 3390 |               dst++;
 | 
|---|
| 3391 |             }
 | 
|---|
| 3392 | 
 | 
|---|
| 3393 |           s->scnhdr.s_lnnoptr = *file_cursor;
 | 
|---|
| 3394 | 
 | 
|---|
| 3395 |           bfd_bwrite (buffer, (bfd_size_type) s->scnhdr.s_nlnno * LINESZ, abfd);
 | 
|---|
| 3396 |           free (buffer);
 | 
|---|
| 3397 | 
 | 
|---|
| 3398 |           *file_cursor += s->scnhdr.s_nlnno * LINESZ;
 | 
|---|
| 3399 |         }
 | 
|---|
| 3400 |     }
 | 
|---|
| 3401 | 
 | 
|---|
| 3402 |   H_SET_LINENO_SIZE (h, *file_cursor - start);
 | 
|---|
| 3403 | }
 | 
|---|
| 3404 | 
 | 
|---|
| 3405 | /* Now we run through the list of frag chains in a segment and
 | 
|---|
| 3406 |    make all the subsegment frags appear at the end of the
 | 
|---|
| 3407 |    list, as if the seg 0 was extra long.  */
 | 
|---|
| 3408 | 
 | 
|---|
| 3409 | static void
 | 
|---|
| 3410 | remove_subsegs ()
 | 
|---|
| 3411 | {
 | 
|---|
| 3412 |   unsigned int i;
 | 
|---|
| 3413 | 
 | 
|---|
| 3414 |   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
 | 
|---|
| 3415 |     {
 | 
|---|
| 3416 |       frchainS *head = segment_info[i].frchainP;
 | 
|---|
| 3417 |       fragS dummy;
 | 
|---|
| 3418 |       fragS *prev_frag = &dummy;
 | 
|---|
| 3419 | 
 | 
|---|
| 3420 |       while (head && head->frch_seg == i)
 | 
|---|
| 3421 |         {
 | 
|---|
| 3422 |           prev_frag->fr_next = head->frch_root;
 | 
|---|
| 3423 |           prev_frag = head->frch_last;
 | 
|---|
| 3424 |           head = head->frch_next;
 | 
|---|
| 3425 |         }
 | 
|---|
| 3426 |       prev_frag->fr_next = 0;
 | 
|---|
| 3427 |     }
 | 
|---|
| 3428 | }
 | 
|---|
| 3429 | 
 | 
|---|
| 3430 | unsigned long machine;
 | 
|---|
| 3431 | int coff_flags;
 | 
|---|
| 3432 | 
 | 
|---|
| 3433 | #ifndef SUB_SEGMENT_ALIGN
 | 
|---|
| 3434 | #ifdef HANDLE_ALIGN
 | 
|---|
| 3435 | /* The last subsegment gets an aligment corresponding to the alignment
 | 
|---|
| 3436 |    of the section.  This allows proper nop-filling at the end of
 | 
|---|
| 3437 |    code-bearing sections.  */
 | 
|---|
| 3438 | #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN)                                 \
 | 
|---|
| 3439 |   (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG)     \
 | 
|---|
| 3440 |    ? get_recorded_alignment (SEG) : 0)
 | 
|---|
| 3441 | #else
 | 
|---|
| 3442 | #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 1
 | 
|---|
| 3443 | #endif
 | 
|---|
| 3444 | #endif
 | 
|---|
| 3445 | 
 | 
|---|
| 3446 | extern void
 | 
|---|
| 3447 | write_object_file ()
 | 
|---|
| 3448 | {
 | 
|---|
| 3449 |   int i;
 | 
|---|
| 3450 |   const char *name;
 | 
|---|
| 3451 |   struct frchain *frchain_ptr;
 | 
|---|
| 3452 | 
 | 
|---|
| 3453 |   object_headers headers;
 | 
|---|
| 3454 |   unsigned long file_cursor;
 | 
|---|
| 3455 |   bfd *abfd;
 | 
|---|
| 3456 |   unsigned int addr;
 | 
|---|
| 3457 |   abfd = bfd_openw (out_file_name, TARGET_FORMAT);
 | 
|---|
| 3458 | 
 | 
|---|
| 3459 |   if (abfd == 0)
 | 
|---|
| 3460 |     {
 | 
|---|
| 3461 |       as_perror (_("FATAL: Can't create %s"), out_file_name);
 | 
|---|
| 3462 |       exit (EXIT_FAILURE);
 | 
|---|
| 3463 |     }
 | 
|---|
| 3464 |   bfd_set_format (abfd, bfd_object);
 | 
|---|
| 3465 |   bfd_set_arch_mach (abfd, BFD_ARCH, machine);
 | 
|---|
| 3466 | 
 | 
|---|
| 3467 |   string_byte_count = 4;
 | 
|---|
| 3468 | 
 | 
|---|
| 3469 |   /* Run through all the sub-segments and align them up.  Also
 | 
|---|
| 3470 |      close any open frags.  We tack a .fill onto the end of the
 | 
|---|
| 3471 |      frag chain so that any .align's size can be worked by looking
 | 
|---|
| 3472 |      at the next frag.  */
 | 
|---|
| 3473 |   for (frchain_ptr = frchain_root;
 | 
|---|
| 3474 |        frchain_ptr != (struct frchain *) NULL;
 | 
|---|
| 3475 |        frchain_ptr = frchain_ptr->frch_next)
 | 
|---|
| 3476 |     {
 | 
|---|
| 3477 |       int alignment;
 | 
|---|
| 3478 | 
 | 
|---|
| 3479 |       subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
 | 
|---|
| 3480 | 
 | 
|---|
| 3481 |       alignment = SUB_SEGMENT_ALIGN (now_seg, frchain_ptr);
 | 
|---|
| 3482 | 
 | 
|---|
| 3483 | #ifdef md_do_align
 | 
|---|
| 3484 |       md_do_align (alignment, (char *) NULL, 0, 0, alignment_done);
 | 
|---|
| 3485 | #endif
 | 
|---|
| 3486 |       if (subseg_text_p (now_seg))
 | 
|---|
| 3487 |         frag_align_code (alignment, 0);
 | 
|---|
| 3488 |       else
 | 
|---|
| 3489 |         frag_align (alignment, 0, 0);
 | 
|---|
| 3490 | 
 | 
|---|
| 3491 | #ifdef md_do_align
 | 
|---|
| 3492 |     alignment_done:
 | 
|---|
| 3493 | #endif
 | 
|---|
| 3494 | 
 | 
|---|
| 3495 |       frag_wane (frag_now);
 | 
|---|
| 3496 |       frag_now->fr_fix = 0;
 | 
|---|
| 3497 |       know (frag_now->fr_next == NULL);
 | 
|---|
| 3498 |     }
 | 
|---|
| 3499 | 
 | 
|---|
| 3500 |   remove_subsegs ();
 | 
|---|
| 3501 | 
 | 
|---|
| 3502 |   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
 | 
|---|
| 3503 |     relax_segment (segment_info[i].frchainP->frch_root, i);
 | 
|---|
| 3504 | 
 | 
|---|
| 3505 |   /* Relaxation has completed.  Freeze all syms.  */
 | 
|---|
| 3506 |   finalize_syms = 1;
 | 
|---|
| 3507 | 
 | 
|---|
| 3508 |   H_SET_NUMBER_OF_SECTIONS (&headers, 0);
 | 
|---|
| 3509 | 
 | 
|---|
| 3510 |   /* Find out how big the sections are, and set the addresses.  */
 | 
|---|
| 3511 |   addr = 0;
 | 
|---|
| 3512 |   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
 | 
|---|
| 3513 |     {
 | 
|---|
| 3514 |       long size;
 | 
|---|
| 3515 | 
 | 
|---|
| 3516 |       segment_info[i].scnhdr.s_paddr = addr;
 | 
|---|
| 3517 |       segment_info[i].scnhdr.s_vaddr = addr;
 | 
|---|
| 3518 | 
 | 
|---|
| 3519 |       if (segment_info[i].scnhdr.s_name[0])
 | 
|---|
| 3520 |         {
 | 
|---|
| 3521 |           H_SET_NUMBER_OF_SECTIONS (&headers,
 | 
|---|
| 3522 |                                     H_GET_NUMBER_OF_SECTIONS (&headers) + 1);
 | 
|---|
| 3523 | 
 | 
|---|
| 3524 | #ifdef COFF_LONG_SECTION_NAMES
 | 
|---|
| 3525 |           /* Support long section names as found in PE.  This code
 | 
|---|
| 3526 |              must coordinate with that in coff_header_append and
 | 
|---|
| 3527 |              w_strings.  */
 | 
|---|
| 3528 |           {
 | 
|---|
| 3529 |             unsigned int len;
 | 
|---|
| 3530 | 
 | 
|---|
| 3531 |             len = strlen (segment_info[i].name);
 | 
|---|
| 3532 |             if (len > SCNNMLEN)
 | 
|---|
| 3533 |               string_byte_count += len + 1;
 | 
|---|
| 3534 |           }
 | 
|---|
| 3535 | #endif /* COFF_LONG_SECTION_NAMES */
 | 
|---|
| 3536 |         }
 | 
|---|
| 3537 | 
 | 
|---|
| 3538 |       size = size_section (abfd, (unsigned int) i);
 | 
|---|
| 3539 |       addr += size;
 | 
|---|
| 3540 | 
 | 
|---|
| 3541 |       /* I think the section alignment is only used on the i960; the
 | 
|---|
| 3542 |          i960 needs it, and it should do no harm on other targets.  */
 | 
|---|
| 3543 | #ifdef ALIGNMENT_IN_S_FLAGS
 | 
|---|
| 3544 |       segment_info[i].scnhdr.s_flags |= (section_alignment[i] & 0xF) << 8;
 | 
|---|
| 3545 | #else
 | 
|---|
| 3546 |       segment_info[i].scnhdr.s_align = 1 << section_alignment[i];
 | 
|---|
| 3547 | #endif
 | 
|---|
| 3548 | 
 | 
|---|
| 3549 |       if (i == SEG_E0)
 | 
|---|
| 3550 |         H_SET_TEXT_SIZE (&headers, size);
 | 
|---|
| 3551 |       else if (i == SEG_E1)
 | 
|---|
| 3552 |         H_SET_DATA_SIZE (&headers, size);
 | 
|---|
| 3553 |       else if (i == SEG_E2)
 | 
|---|
| 3554 |         H_SET_BSS_SIZE (&headers, size);
 | 
|---|
| 3555 |     }
 | 
|---|
| 3556 | 
 | 
|---|
| 3557 |   /* Turn the gas native symbol table shape into a coff symbol table.  */
 | 
|---|
| 3558 |   crawl_symbols (&headers, abfd);
 | 
|---|
| 3559 | 
 | 
|---|
| 3560 |   if (string_byte_count == 4)
 | 
|---|
| 3561 |     string_byte_count = 0;
 | 
|---|
| 3562 | 
 | 
|---|
| 3563 |   H_SET_STRING_SIZE (&headers, string_byte_count);
 | 
|---|
| 3564 | 
 | 
|---|
| 3565 | #ifdef tc_frob_file
 | 
|---|
| 3566 |   tc_frob_file ();
 | 
|---|
| 3567 | #endif
 | 
|---|
| 3568 | 
 | 
|---|
| 3569 |   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
 | 
|---|
| 3570 |     {
 | 
|---|
| 3571 |       fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i);
 | 
|---|
| 3572 |       fixup_segment (&segment_info[i], i);
 | 
|---|
| 3573 |     }
 | 
|---|
| 3574 | 
 | 
|---|
| 3575 |   /* Look for ".stab" segments and fill in their initial symbols
 | 
|---|
| 3576 |      correctly.  */
 | 
|---|
| 3577 |   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
 | 
|---|
| 3578 |     {
 | 
|---|
| 3579 |       name = segment_info[i].name;
 | 
|---|
| 3580 | 
 | 
|---|
| 3581 |       if (name != NULL
 | 
|---|
| 3582 |           && strncmp (".stab", name, 5) == 0
 | 
|---|
| 3583 |           && strncmp (".stabstr", name, 8) != 0)
 | 
|---|
| 3584 |         adjust_stab_section (abfd, i);
 | 
|---|
| 3585 |     }
 | 
|---|
| 3586 | 
 | 
|---|
| 3587 |   file_cursor = H_GET_TEXT_FILE_OFFSET (&headers);
 | 
|---|
| 3588 | 
 | 
|---|
| 3589 |   bfd_seek (abfd, (file_ptr) file_cursor, 0);
 | 
|---|
| 3590 | 
 | 
|---|
| 3591 |   /* Plant the data.  */
 | 
|---|
| 3592 |   fill_section (abfd, &headers, &file_cursor);
 | 
|---|
| 3593 | 
 | 
|---|
| 3594 |   do_relocs_for (abfd, &headers, &file_cursor);
 | 
|---|
| 3595 | 
 | 
|---|
| 3596 |   do_linenos_for (abfd, &headers, &file_cursor);
 | 
|---|
| 3597 | 
 | 
|---|
| 3598 |   H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC);
 | 
|---|
| 3599 | #ifndef OBJ_COFF_OMIT_TIMESTAMP
 | 
|---|
| 3600 |   H_SET_TIME_STAMP (&headers, (long)time((time_t *)0));
 | 
|---|
| 3601 | #else
 | 
|---|
| 3602 |   H_SET_TIME_STAMP (&headers, 0);
 | 
|---|
| 3603 | #endif
 | 
|---|
| 3604 | #ifdef TC_COFF_SET_MACHINE
 | 
|---|
| 3605 |   TC_COFF_SET_MACHINE (&headers);
 | 
|---|
| 3606 | #endif
 | 
|---|
| 3607 | 
 | 
|---|
| 3608 | #ifndef COFF_FLAGS
 | 
|---|
| 3609 | #define COFF_FLAGS 0
 | 
|---|
| 3610 | #endif
 | 
|---|
| 3611 | 
 | 
|---|
| 3612 | #ifdef KEEP_RELOC_INFO
 | 
|---|
| 3613 |   H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) |
 | 
|---|
| 3614 |                           COFF_FLAGS | coff_flags));
 | 
|---|
| 3615 | #else
 | 
|---|
| 3616 |   H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers)     ? 0 : F_LNNO)   |
 | 
|---|
| 3617 |                           (H_GET_RELOCATION_SIZE(&headers) ? 0 : F_RELFLG) |
 | 
|---|
| 3618 |                           COFF_FLAGS | coff_flags));
 | 
|---|
| 3619 | #endif
 | 
|---|
| 3620 | 
 | 
|---|
| 3621 |   {
 | 
|---|
| 3622 |     unsigned int symtable_size = H_GET_SYMBOL_TABLE_SIZE (&headers);
 | 
|---|
| 3623 |     char *buffer1 = xmalloc (symtable_size + string_byte_count + 1);
 | 
|---|
| 3624 | 
 | 
|---|
| 3625 |     H_SET_SYMBOL_TABLE_POINTER (&headers, bfd_tell (abfd));
 | 
|---|
| 3626 |     w_symbols (abfd, buffer1, symbol_rootP);
 | 
|---|
| 3627 |     if (string_byte_count > 0)
 | 
|---|
| 3628 |       w_strings (buffer1 + symtable_size);
 | 
|---|
| 3629 |     bfd_bwrite (buffer1, (bfd_size_type) symtable_size + string_byte_count,
 | 
|---|
| 3630 |                 abfd);
 | 
|---|
| 3631 |     free (buffer1);
 | 
|---|
| 3632 |   }
 | 
|---|
| 3633 | 
 | 
|---|
| 3634 |   coff_header_append (abfd, &headers);
 | 
|---|
| 3635 | #if 0
 | 
|---|
| 3636 |   /* Recent changes to write need this, but where it should
 | 
|---|
| 3637 |      go is up to Ken..  */
 | 
|---|
| 3638 |   if (!bfd_close_all_done (abfd))
 | 
|---|
| 3639 |     as_fatal (_("Can't close %s: %s"), out_file_name,
 | 
|---|
| 3640 |               bfd_errmsg (bfd_get_error ()));
 | 
|---|
| 3641 | #else
 | 
|---|
| 3642 |   {
 | 
|---|
| 3643 |     extern bfd *stdoutput;
 | 
|---|
| 3644 |     stdoutput = abfd;
 | 
|---|
| 3645 |   }
 | 
|---|
| 3646 | #endif
 | 
|---|
| 3647 | 
 | 
|---|
| 3648 | }
 | 
|---|
| 3649 | 
 | 
|---|
| 3650 | /* Add a new segment.  This is called from subseg_new via the
 | 
|---|
| 3651 |    obj_new_segment macro.  */
 | 
|---|
| 3652 | 
 | 
|---|
| 3653 | segT
 | 
|---|
| 3654 | obj_coff_add_segment (name)
 | 
|---|
| 3655 |      const char *name;
 | 
|---|
| 3656 | {
 | 
|---|
| 3657 |   unsigned int i;
 | 
|---|
| 3658 | 
 | 
|---|
| 3659 | #ifndef COFF_LONG_SECTION_NAMES
 | 
|---|
| 3660 |   char buf[SCNNMLEN + 1];
 | 
|---|
| 3661 | 
 | 
|---|
| 3662 |   strncpy (buf, name, SCNNMLEN);
 | 
|---|
| 3663 |   buf[SCNNMLEN] = '\0';
 | 
|---|
| 3664 |   name = buf;
 | 
|---|
| 3665 | #endif
 | 
|---|
| 3666 | 
 | 
|---|
| 3667 |   for (i = SEG_E0; i < SEG_LAST && segment_info[i].scnhdr.s_name[0]; i++)
 | 
|---|
| 3668 |     if (strcmp (name, segment_info[i].name) == 0)
 | 
|---|
| 3669 |       return (segT) i;
 | 
|---|
| 3670 | 
 | 
|---|
| 3671 |   if (i == SEG_LAST)
 | 
|---|
| 3672 |     {
 | 
|---|
| 3673 |       as_bad (_("Too many new sections; can't add \"%s\""), name);
 | 
|---|
| 3674 |       return now_seg;
 | 
|---|
| 3675 |     }
 | 
|---|
| 3676 | 
 | 
|---|
| 3677 |   /* Add a new section.  */
 | 
|---|
| 3678 |   strncpy (segment_info[i].scnhdr.s_name, name,
 | 
|---|
| 3679 |            sizeof (segment_info[i].scnhdr.s_name));
 | 
|---|
| 3680 |   segment_info[i].scnhdr.s_flags = STYP_REG;
 | 
|---|
| 3681 |   segment_info[i].name = xstrdup (name);
 | 
|---|
| 3682 | 
 | 
|---|
| 3683 |   return (segT) i;
 | 
|---|
| 3684 | }
 | 
|---|
| 3685 | 
 | 
|---|
| 3686 | /* Implement the .section pseudo op:
 | 
|---|
| 3687 |         .section name {, "flags"}
 | 
|---|
| 3688 |                   ^         ^
 | 
|---|
| 3689 |                   |         +--- optional flags: 'b' for bss
 | 
|---|
| 3690 |                   |                              'i' for info
 | 
|---|
| 3691 |                   +-- section name               'l' for lib
 | 
|---|
| 3692 |                                                  'n' for noload
 | 
|---|
| 3693 |                                                  'o' for over
 | 
|---|
| 3694 |                                                  'w' for data
 | 
|---|
| 3695 |                                                  'd' (apparently m88k for data)
 | 
|---|
| 3696 |                                                  'x' for text
 | 
|---|
| 3697 |                                                  'r' for read-only data
 | 
|---|
| 3698 |    But if the argument is not a quoted string, treat it as a
 | 
|---|
| 3699 |    subsegment number.  */
 | 
|---|
| 3700 | 
 | 
|---|
| 3701 | void
 | 
|---|
| 3702 | obj_coff_section (ignore)
 | 
|---|
| 3703 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 3704 | {
 | 
|---|
| 3705 |   /* Strip out the section name.  */
 | 
|---|
| 3706 |   char *section_name, *name;
 | 
|---|
| 3707 |   char c;
 | 
|---|
| 3708 |   unsigned int exp;
 | 
|---|
| 3709 |   long flags;
 | 
|---|
| 3710 | 
 | 
|---|
| 3711 |   if (flag_mri)
 | 
|---|
| 3712 |     {
 | 
|---|
| 3713 |       char type;
 | 
|---|
| 3714 | 
 | 
|---|
| 3715 |       s_mri_sect (&type);
 | 
|---|
| 3716 |       flags = 0;
 | 
|---|
| 3717 |       if (type == 'C')
 | 
|---|
| 3718 |         flags = STYP_TEXT;
 | 
|---|
| 3719 |       else if (type == 'D')
 | 
|---|
| 3720 |         flags = STYP_DATA;
 | 
|---|
| 3721 |       segment_info[now_seg].scnhdr.s_flags |= flags;
 | 
|---|
| 3722 | 
 | 
|---|
| 3723 |       return;
 | 
|---|
| 3724 |     }
 | 
|---|
| 3725 | 
 | 
|---|
| 3726 |   section_name = input_line_pointer;
 | 
|---|
| 3727 |   c = get_symbol_end ();
 | 
|---|
| 3728 | 
 | 
|---|
| 3729 |   name = xmalloc (input_line_pointer - section_name + 1);
 | 
|---|
| 3730 |   strcpy (name, section_name);
 | 
|---|
| 3731 | 
 | 
|---|
| 3732 |   *input_line_pointer = c;
 | 
|---|
| 3733 | 
 | 
|---|
| 3734 |   exp = 0;
 | 
|---|
| 3735 |   flags = 0;
 | 
|---|
| 3736 | 
 | 
|---|
| 3737 |   SKIP_WHITESPACE ();
 | 
|---|
| 3738 |   if (*input_line_pointer == ',')
 | 
|---|
| 3739 |     {
 | 
|---|
| 3740 |       ++input_line_pointer;
 | 
|---|
| 3741 |       SKIP_WHITESPACE ();
 | 
|---|
| 3742 | 
 | 
|---|
| 3743 |       if (*input_line_pointer != '"')
 | 
|---|
| 3744 |         exp = get_absolute_expression ();
 | 
|---|
| 3745 |       else
 | 
|---|
| 3746 |         {
 | 
|---|
| 3747 |           ++input_line_pointer;
 | 
|---|
| 3748 |           while (*input_line_pointer != '"'
 | 
|---|
| 3749 |                  && ! is_end_of_line[(unsigned char) *input_line_pointer])
 | 
|---|
| 3750 |             {
 | 
|---|
| 3751 |               switch (*input_line_pointer)
 | 
|---|
| 3752 |                 {
 | 
|---|
| 3753 |                 case 'b': flags |= STYP_BSS;    break;
 | 
|---|
| 3754 |                 case 'i': flags |= STYP_INFO;   break;
 | 
|---|
| 3755 |                 case 'l': flags |= STYP_LIB;    break;
 | 
|---|
| 3756 |                 case 'n': flags |= STYP_NOLOAD; break;
 | 
|---|
| 3757 |                 case 'o': flags |= STYP_OVER;   break;
 | 
|---|
| 3758 |                 case 'd':
 | 
|---|
| 3759 |                 case 'w': flags |= STYP_DATA;   break;
 | 
|---|
| 3760 |                 case 'x': flags |= STYP_TEXT;   break;
 | 
|---|
| 3761 |                 case 'r': flags |= STYP_LIT;    break;
 | 
|---|
| 3762 |                 default:
 | 
|---|
| 3763 |                   as_warn(_("unknown section attribute '%c'"),
 | 
|---|
| 3764 |                           *input_line_pointer);
 | 
|---|
| 3765 |                   break;
 | 
|---|
| 3766 |                 }
 | 
|---|
| 3767 |               ++input_line_pointer;
 | 
|---|
| 3768 |             }
 | 
|---|
| 3769 |           if (*input_line_pointer == '"')
 | 
|---|
| 3770 |             ++input_line_pointer;
 | 
|---|
| 3771 |         }
 | 
|---|
| 3772 |     }
 | 
|---|
| 3773 | 
 | 
|---|
| 3774 |   subseg_new (name, (subsegT) exp);
 | 
|---|
| 3775 | 
 | 
|---|
| 3776 |   segment_info[now_seg].scnhdr.s_flags |= flags;
 | 
|---|
| 3777 | 
 | 
|---|
| 3778 |   demand_empty_rest_of_line ();
 | 
|---|
| 3779 | }
 | 
|---|
| 3780 | 
 | 
|---|
| 3781 | static void
 | 
|---|
| 3782 | obj_coff_text (ignore)
 | 
|---|
| 3783 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 3784 | {
 | 
|---|
| 3785 |   subseg_new (".text", get_absolute_expression ());
 | 
|---|
| 3786 | }
 | 
|---|
| 3787 | 
 | 
|---|
| 3788 | static void
 | 
|---|
| 3789 | obj_coff_data (ignore)
 | 
|---|
| 3790 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 3791 | {
 | 
|---|
| 3792 |   if (flag_readonly_data_in_text)
 | 
|---|
| 3793 |     subseg_new (".text", get_absolute_expression () + 1000);
 | 
|---|
| 3794 |   else
 | 
|---|
| 3795 |     subseg_new (".data", get_absolute_expression ());
 | 
|---|
| 3796 | }
 | 
|---|
| 3797 | 
 | 
|---|
| 3798 | static void
 | 
|---|
| 3799 | obj_coff_ident (ignore)
 | 
|---|
| 3800 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 3801 | {
 | 
|---|
| 3802 |   segT current_seg = now_seg;           /* Save current seg.  */
 | 
|---|
| 3803 |   subsegT current_subseg = now_subseg;
 | 
|---|
| 3804 | 
 | 
|---|
| 3805 |   subseg_new (".comment", 0);           /* .comment seg.  */
 | 
|---|
| 3806 |   stringer (1);                         /* Read string.  */
 | 
|---|
| 3807 |   subseg_set (current_seg, current_subseg);     /* Restore current seg.  */
 | 
|---|
| 3808 | }
 | 
|---|
| 3809 | 
 | 
|---|
| 3810 | void
 | 
|---|
| 3811 | c_symbol_merge (debug, normal)
 | 
|---|
| 3812 |      symbolS *debug;
 | 
|---|
| 3813 |      symbolS *normal;
 | 
|---|
| 3814 | {
 | 
|---|
| 3815 |   S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
 | 
|---|
| 3816 |   S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
 | 
|---|
| 3817 | 
 | 
|---|
| 3818 |   if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
 | 
|---|
| 3819 |     S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
 | 
|---|
| 3820 | 
 | 
|---|
| 3821 |   if (S_GET_NUMBER_AUXILIARY (debug) > 0)
 | 
|---|
| 3822 |     memcpy ((char *) &normal->sy_symbol.ost_auxent[0],
 | 
|---|
| 3823 |             (char *) &debug->sy_symbol.ost_auxent[0],
 | 
|---|
| 3824 |             (unsigned int) (S_GET_NUMBER_AUXILIARY (debug) * AUXESZ));
 | 
|---|
| 3825 | 
 | 
|---|
| 3826 |   /* Move the debug flags.  */
 | 
|---|
| 3827 |   SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
 | 
|---|
| 3828 | }
 | 
|---|
| 3829 | 
 | 
|---|
| 3830 | static int
 | 
|---|
| 3831 | c_line_new (symbol, paddr, line_number, frag)
 | 
|---|
| 3832 |      symbolS * symbol;
 | 
|---|
| 3833 |      long paddr;
 | 
|---|
| 3834 |      int line_number;
 | 
|---|
| 3835 |      fragS * frag;
 | 
|---|
| 3836 | {
 | 
|---|
| 3837 |   struct lineno_list *new_line =
 | 
|---|
| 3838 |   (struct lineno_list *) xmalloc (sizeof (struct lineno_list));
 | 
|---|
| 3839 | 
 | 
|---|
| 3840 |   segment_info_type *s = segment_info + now_seg;
 | 
|---|
| 3841 |   new_line->line.l_lnno = line_number;
 | 
|---|
| 3842 | 
 | 
|---|
| 3843 |   if (line_number == 0)
 | 
|---|
| 3844 |     {
 | 
|---|
| 3845 |       last_line_symbol = symbol;
 | 
|---|
| 3846 |       new_line->line.l_addr.l_symndx = (long) symbol;
 | 
|---|
| 3847 |     }
 | 
|---|
| 3848 |   else
 | 
|---|
| 3849 |     {
 | 
|---|
| 3850 |       new_line->line.l_addr.l_paddr = paddr;
 | 
|---|
| 3851 |     }
 | 
|---|
| 3852 | 
 | 
|---|
| 3853 |   new_line->frag = (char *) frag;
 | 
|---|
| 3854 |   new_line->next = (struct lineno_list *) NULL;
 | 
|---|
| 3855 | 
 | 
|---|
| 3856 |   if (s->lineno_list_head == (struct lineno_list *) NULL)
 | 
|---|
| 3857 |     s->lineno_list_head = new_line;
 | 
|---|
| 3858 |   else
 | 
|---|
| 3859 |     s->lineno_list_tail->next = new_line;
 | 
|---|
| 3860 | 
 | 
|---|
| 3861 |   s->lineno_list_tail = new_line;
 | 
|---|
| 3862 |   return LINESZ * s->scnhdr.s_nlnno++;
 | 
|---|
| 3863 | }
 | 
|---|
| 3864 | 
 | 
|---|
| 3865 | void
 | 
|---|
| 3866 | c_dot_file_symbol (filename)
 | 
|---|
| 3867 |      char *filename;
 | 
|---|
| 3868 | {
 | 
|---|
| 3869 |   symbolS *symbolP;
 | 
|---|
| 3870 | 
 | 
|---|
| 3871 |   symbolP = symbol_new (".file",
 | 
|---|
| 3872 |                         SEG_DEBUG,
 | 
|---|
| 3873 |                         0,
 | 
|---|
| 3874 |                         &zero_address_frag);
 | 
|---|
| 3875 | 
 | 
|---|
| 3876 |   S_SET_STORAGE_CLASS (symbolP, C_FILE);
 | 
|---|
| 3877 |   S_SET_NUMBER_AUXILIARY (symbolP, 1);
 | 
|---|
| 3878 | 
 | 
|---|
| 3879 |   if (strlen (filename) > FILNMLEN)
 | 
|---|
| 3880 |     {
 | 
|---|
| 3881 |       /* Filename is too long to fit into an auxent,
 | 
|---|
| 3882 |          we stick it into the string table instead.  We keep
 | 
|---|
| 3883 |          a linked list of the filenames we find so we can emit
 | 
|---|
| 3884 |          them later.  */
 | 
|---|
| 3885 |       struct filename_list *f = ((struct filename_list *)
 | 
|---|
| 3886 |                                  xmalloc (sizeof (struct filename_list)));
 | 
|---|
| 3887 | 
 | 
|---|
| 3888 |       f->filename = filename;
 | 
|---|
| 3889 |       f->next = 0;
 | 
|---|
| 3890 | 
 | 
|---|
| 3891 |       SA_SET_FILE_FNAME_ZEROS (symbolP, 0);
 | 
|---|
| 3892 |       SA_SET_FILE_FNAME_OFFSET (symbolP, 1);
 | 
|---|
| 3893 | 
 | 
|---|
| 3894 |       if (filename_list_tail)
 | 
|---|
| 3895 |         filename_list_tail->next = f;
 | 
|---|
| 3896 |       else
 | 
|---|
| 3897 |         filename_list_head = f;
 | 
|---|
| 3898 |       filename_list_tail = f;
 | 
|---|
| 3899 |     }
 | 
|---|
| 3900 |   else
 | 
|---|
| 3901 |     {
 | 
|---|
| 3902 |       SA_SET_FILE_FNAME (symbolP, filename);
 | 
|---|
| 3903 |     }
 | 
|---|
| 3904 | #ifndef NO_LISTING
 | 
|---|
| 3905 |   {
 | 
|---|
| 3906 |     extern int listing;
 | 
|---|
| 3907 |     if (listing)
 | 
|---|
| 3908 |       listing_source_file (filename);
 | 
|---|
| 3909 |   }
 | 
|---|
| 3910 | #endif
 | 
|---|
| 3911 |   SF_SET_DEBUG (symbolP);
 | 
|---|
| 3912 |   S_SET_VALUE (symbolP, (valueT) previous_file_symbol);
 | 
|---|
| 3913 | 
 | 
|---|
| 3914 |   previous_file_symbol = symbolP;
 | 
|---|
| 3915 | 
 | 
|---|
| 3916 |   /* Make sure that the symbol is first on the symbol chain.  */
 | 
|---|
| 3917 |   if (symbol_rootP != symbolP)
 | 
|---|
| 3918 |     {
 | 
|---|
| 3919 |       symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 3920 |       symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
 | 
|---|
| 3921 |     }
 | 
|---|
| 3922 | }
 | 
|---|
| 3923 | 
 | 
|---|
| 3924 | /* Build a 'section static' symbol.  */
 | 
|---|
| 3925 | 
 | 
|---|
| 3926 | symbolS *
 | 
|---|
| 3927 | c_section_symbol (name, idx)
 | 
|---|
| 3928 |      char *name;
 | 
|---|
| 3929 |      int idx;
 | 
|---|
| 3930 | {
 | 
|---|
| 3931 |   symbolS *symbolP;
 | 
|---|
| 3932 | 
 | 
|---|
| 3933 |   symbolP = symbol_find_base (name, DO_NOT_STRIP);
 | 
|---|
| 3934 |   if (symbolP == NULL)
 | 
|---|
| 3935 |     symbolP = symbol_new (name, idx, 0, &zero_address_frag);
 | 
|---|
| 3936 |   else
 | 
|---|
| 3937 |     {
 | 
|---|
| 3938 |       /* Mmmm.  I just love violating interfaces.  Makes me feel...dirty.  */
 | 
|---|
| 3939 |       S_SET_SEGMENT (symbolP, idx);
 | 
|---|
| 3940 |       symbolP->sy_frag = &zero_address_frag;
 | 
|---|
| 3941 |     }
 | 
|---|
| 3942 | 
 | 
|---|
| 3943 |   S_SET_STORAGE_CLASS (symbolP, C_STAT);
 | 
|---|
| 3944 |   S_SET_NUMBER_AUXILIARY (symbolP, 1);
 | 
|---|
| 3945 | 
 | 
|---|
| 3946 |   SF_SET_STATICS (symbolP);
 | 
|---|
| 3947 | 
 | 
|---|
| 3948 | #ifdef TE_DELTA
 | 
|---|
| 3949 |   /* manfred@s-direktnet.de: section symbols *must* have the LOCAL bit cleared,
 | 
|---|
| 3950 |      which is set by the new definition of LOCAL_LABEL in tc-m68k.h.  */
 | 
|---|
| 3951 |   SF_CLEAR_LOCAL (symbolP);
 | 
|---|
| 3952 | #endif
 | 
|---|
| 3953 | #ifdef TE_PE
 | 
|---|
| 3954 |   /* If the .linkonce pseudo-op was used for this section, we must
 | 
|---|
| 3955 |      store the information in the auxiliary entry for the section
 | 
|---|
| 3956 |      symbol.  */
 | 
|---|
| 3957 |   if (segment_info[idx].linkonce != LINKONCE_UNSET)
 | 
|---|
| 3958 |     {
 | 
|---|
| 3959 |       int type;
 | 
|---|
| 3960 | 
 | 
|---|
| 3961 |       switch (segment_info[idx].linkonce)
 | 
|---|
| 3962 |         {
 | 
|---|
| 3963 |         default:
 | 
|---|
| 3964 |           abort ();
 | 
|---|
| 3965 |         case LINKONCE_DISCARD:
 | 
|---|
| 3966 |           type = IMAGE_COMDAT_SELECT_ANY;
 | 
|---|
| 3967 |           break;
 | 
|---|
| 3968 |         case LINKONCE_ONE_ONLY:
 | 
|---|
| 3969 |           type = IMAGE_COMDAT_SELECT_NODUPLICATES;
 | 
|---|
| 3970 |           break;
 | 
|---|
| 3971 |         case LINKONCE_SAME_SIZE:
 | 
|---|
| 3972 |           type = IMAGE_COMDAT_SELECT_SAME_SIZE;
 | 
|---|
| 3973 |           break;
 | 
|---|
| 3974 |         case LINKONCE_SAME_CONTENTS:
 | 
|---|
| 3975 |           type = IMAGE_COMDAT_SELECT_EXACT_MATCH;
 | 
|---|
| 3976 |           break;
 | 
|---|
| 3977 |         }
 | 
|---|
| 3978 | 
 | 
|---|
| 3979 |       SYM_AUXENT (symbolP)->x_scn.x_comdat = type;
 | 
|---|
| 3980 |     }
 | 
|---|
| 3981 | #endif /* TE_PE */
 | 
|---|
| 3982 | 
 | 
|---|
| 3983 |   return symbolP;
 | 
|---|
| 3984 | }
 | 
|---|
| 3985 | 
 | 
|---|
| 3986 | static void
 | 
|---|
| 3987 | w_symbols (abfd, where, symbol_rootP)
 | 
|---|
| 3988 |      bfd * abfd;
 | 
|---|
| 3989 |      char *where;
 | 
|---|
| 3990 |      symbolS * symbol_rootP;
 | 
|---|
| 3991 | {
 | 
|---|
| 3992 |   symbolS *symbolP;
 | 
|---|
| 3993 |   unsigned int i;
 | 
|---|
| 3994 | 
 | 
|---|
| 3995 |   /* First fill in those values we have only just worked out.  */
 | 
|---|
| 3996 |   for (i = SEG_E0; i < SEG_LAST; i++)
 | 
|---|
| 3997 |     {
 | 
|---|
| 3998 |       symbolP = segment_info[i].dot;
 | 
|---|
| 3999 |       if (symbolP)
 | 
|---|
| 4000 |         {
 | 
|---|
| 4001 |           SA_SET_SCN_SCNLEN (symbolP, segment_info[i].scnhdr.s_size);
 | 
|---|
| 4002 |           SA_SET_SCN_NRELOC (symbolP, segment_info[i].scnhdr.s_nreloc);
 | 
|---|
| 4003 |           SA_SET_SCN_NLINNO (symbolP, segment_info[i].scnhdr.s_nlnno);
 | 
|---|
| 4004 |         }
 | 
|---|
| 4005 |     }
 | 
|---|
| 4006 | 
 | 
|---|
| 4007 |   /* Emit all symbols left in the symbol chain.  */
 | 
|---|
| 4008 |   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
 | 
|---|
| 4009 |     {
 | 
|---|
| 4010 |       /* Used to save the offset of the name. It is used to point
 | 
|---|
| 4011 |          to the string in memory but must be a file offset.  */
 | 
|---|
| 4012 |       char *temp;
 | 
|---|
| 4013 | 
 | 
|---|
| 4014 |       /* We can't fix the lnnoptr field in yank_symbols with the other
 | 
|---|
| 4015 |          adjustments, because we have to wait until we know where they
 | 
|---|
| 4016 |          go in the file.  */
 | 
|---|
| 4017 |       if (SF_GET_ADJ_LNNOPTR (symbolP))
 | 
|---|
| 4018 |         SA_GET_SYM_LNNOPTR (symbolP) +=
 | 
|---|
| 4019 |           segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_lnnoptr;
 | 
|---|
| 4020 | 
 | 
|---|
| 4021 |       tc_coff_symbol_emit_hook (symbolP);
 | 
|---|
| 4022 | 
 | 
|---|
| 4023 |       temp = S_GET_NAME (symbolP);
 | 
|---|
| 4024 |       if (SF_GET_STRING (symbolP))
 | 
|---|
| 4025 |         {
 | 
|---|
| 4026 |           S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
 | 
|---|
| 4027 |           S_SET_ZEROES (symbolP, 0);
 | 
|---|
| 4028 |         }
 | 
|---|
| 4029 |       else
 | 
|---|
| 4030 |         {
 | 
|---|
| 4031 |           memset (symbolP->sy_symbol.ost_entry.n_name, 0, SYMNMLEN);
 | 
|---|
| 4032 |           strncpy (symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
 | 
|---|
| 4033 |         }
 | 
|---|
| 4034 |       where = symbol_to_chars (abfd, where, symbolP);
 | 
|---|
| 4035 |       S_SET_NAME (symbolP, temp);
 | 
|---|
| 4036 |     }
 | 
|---|
| 4037 | }
 | 
|---|
| 4038 | 
 | 
|---|
| 4039 | static void
 | 
|---|
| 4040 | obj_coff_lcomm (ignore)
 | 
|---|
| 4041 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 4042 | {
 | 
|---|
| 4043 |   s_lcomm(0);
 | 
|---|
| 4044 |   return;
 | 
|---|
| 4045 | #if 0
 | 
|---|
| 4046 |   char *name;
 | 
|---|
| 4047 |   char c;
 | 
|---|
| 4048 |   int temp;
 | 
|---|
| 4049 |   char *p;
 | 
|---|
| 4050 | 
 | 
|---|
| 4051 |   symbolS *symbolP;
 | 
|---|
| 4052 | 
 | 
|---|
| 4053 |   name = input_line_pointer;
 | 
|---|
| 4054 | 
 | 
|---|
| 4055 |   c = get_symbol_end ();
 | 
|---|
| 4056 |   p = input_line_pointer;
 | 
|---|
| 4057 |   *p = c;
 | 
|---|
| 4058 |   SKIP_WHITESPACE ();
 | 
|---|
| 4059 |   if (*input_line_pointer != ',')
 | 
|---|
| 4060 |     {
 | 
|---|
| 4061 |       as_bad (_("Expected comma after name"));
 | 
|---|
| 4062 |       ignore_rest_of_line ();
 | 
|---|
| 4063 |       return;
 | 
|---|
| 4064 |     }
 | 
|---|
| 4065 |   if (*input_line_pointer == '\n')
 | 
|---|
| 4066 |     {
 | 
|---|
| 4067 |       as_bad (_("Missing size expression"));
 | 
|---|
| 4068 |       return;
 | 
|---|
| 4069 |     }
 | 
|---|
| 4070 |   input_line_pointer++;
 | 
|---|
| 4071 |   if ((temp = get_absolute_expression ()) < 0)
 | 
|---|
| 4072 |     {
 | 
|---|
| 4073 |       as_warn (_("lcomm length (%d.) <0! Ignored."), temp);
 | 
|---|
| 4074 |       ignore_rest_of_line ();
 | 
|---|
| 4075 |       return;
 | 
|---|
| 4076 |     }
 | 
|---|
| 4077 |   *p = 0;
 | 
|---|
| 4078 | 
 | 
|---|
| 4079 |   symbolP = symbol_find_or_make (name);
 | 
|---|
| 4080 | 
 | 
|---|
| 4081 |   if (S_GET_SEGMENT (symbolP) == SEG_UNKNOWN &&
 | 
|---|
| 4082 |       S_GET_VALUE (symbolP) == 0)
 | 
|---|
| 4083 |     {
 | 
|---|
| 4084 |       if (! need_pass_2)
 | 
|---|
| 4085 |         {
 | 
|---|
| 4086 |           char *p;
 | 
|---|
| 4087 |           segT current_seg = now_seg;   /* Save current seg.  */
 | 
|---|
| 4088 |           subsegT current_subseg = now_subseg;
 | 
|---|
| 4089 | 
 | 
|---|
| 4090 |           subseg_set (SEG_E2, 1);
 | 
|---|
| 4091 |           symbolP->sy_frag = frag_now;
 | 
|---|
| 4092 |           p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP,
 | 
|---|
| 4093 |                        (offsetT) temp, (char *) 0);
 | 
|---|
| 4094 |           *p = 0;
 | 
|---|
| 4095 |           subseg_set (current_seg, current_subseg); /* Restore current seg.  */
 | 
|---|
| 4096 |           S_SET_SEGMENT (symbolP, SEG_E2);
 | 
|---|
| 4097 |           S_SET_STORAGE_CLASS (symbolP, C_STAT);
 | 
|---|
| 4098 |         }
 | 
|---|
| 4099 |     }
 | 
|---|
| 4100 |   else
 | 
|---|
| 4101 |     as_bad (_("Symbol %s already defined"), name);
 | 
|---|
| 4102 | 
 | 
|---|
| 4103 |   demand_empty_rest_of_line ();
 | 
|---|
| 4104 | #endif
 | 
|---|
| 4105 | }
 | 
|---|
| 4106 | 
 | 
|---|
| 4107 | static void
 | 
|---|
| 4108 | fixup_mdeps (frags, h, this_segment)
 | 
|---|
| 4109 |      fragS *frags;
 | 
|---|
| 4110 |      object_headers *h ATTRIBUTE_UNUSED;
 | 
|---|
| 4111 |      segT this_segment;
 | 
|---|
| 4112 | {
 | 
|---|
| 4113 |   subseg_change (this_segment, 0);
 | 
|---|
| 4114 | 
 | 
|---|
| 4115 |   while (frags)
 | 
|---|
| 4116 |     {
 | 
|---|
| 4117 |       switch (frags->fr_type)
 | 
|---|
| 4118 |         {
 | 
|---|
| 4119 |         case rs_align:
 | 
|---|
| 4120 |         case rs_align_code:
 | 
|---|
| 4121 |         case rs_align_test:
 | 
|---|
| 4122 |         case rs_org:
 | 
|---|
| 4123 | #ifdef HANDLE_ALIGN
 | 
|---|
| 4124 |           HANDLE_ALIGN (frags);
 | 
|---|
| 4125 | #endif
 | 
|---|
| 4126 |           frags->fr_type = rs_fill;
 | 
|---|
| 4127 |           frags->fr_offset =
 | 
|---|
| 4128 |             ((frags->fr_next->fr_address - frags->fr_address - frags->fr_fix)
 | 
|---|
| 4129 |              / frags->fr_var);
 | 
|---|
| 4130 |           break;
 | 
|---|
| 4131 |         case rs_machine_dependent:
 | 
|---|
| 4132 |           md_convert_frag (h, this_segment, frags);
 | 
|---|
| 4133 |           frag_wane (frags);
 | 
|---|
| 4134 |           break;
 | 
|---|
| 4135 |         default:
 | 
|---|
| 4136 |           ;
 | 
|---|
| 4137 |         }
 | 
|---|
| 4138 |       frags = frags->fr_next;
 | 
|---|
| 4139 |     }
 | 
|---|
| 4140 | }
 | 
|---|
| 4141 | 
 | 
|---|
| 4142 | #if 1
 | 
|---|
| 4143 | 
 | 
|---|
| 4144 | #ifndef TC_FORCE_RELOCATION
 | 
|---|
| 4145 | #define TC_FORCE_RELOCATION(fix) 0
 | 
|---|
| 4146 | #endif
 | 
|---|
| 4147 | 
 | 
|---|
| 4148 | static void
 | 
|---|
| 4149 | fixup_segment (segP, this_segment_type)
 | 
|---|
| 4150 |      segment_info_type * segP;
 | 
|---|
| 4151 |      segT this_segment_type;
 | 
|---|
| 4152 | {
 | 
|---|
| 4153 |   fixS * fixP;
 | 
|---|
| 4154 |   symbolS *add_symbolP;
 | 
|---|
| 4155 |   symbolS *sub_symbolP;
 | 
|---|
| 4156 |   long add_number;
 | 
|---|
| 4157 |   int size;
 | 
|---|
| 4158 |   char *place;
 | 
|---|
| 4159 |   long where;
 | 
|---|
| 4160 |   char pcrel;
 | 
|---|
| 4161 |   fragS *fragP;
 | 
|---|
| 4162 |   segT add_symbol_segment = absolute_section;
 | 
|---|
| 4163 | 
 | 
|---|
| 4164 |   for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next)
 | 
|---|
| 4165 |     {
 | 
|---|
| 4166 |       fragP = fixP->fx_frag;
 | 
|---|
| 4167 |       know (fragP);
 | 
|---|
| 4168 |       where = fixP->fx_where;
 | 
|---|
| 4169 |       place = fragP->fr_literal + where;
 | 
|---|
| 4170 |       size = fixP->fx_size;
 | 
|---|
| 4171 |       add_symbolP = fixP->fx_addsy;
 | 
|---|
| 4172 |       sub_symbolP = fixP->fx_subsy;
 | 
|---|
| 4173 |       add_number = fixP->fx_offset;
 | 
|---|
| 4174 |       pcrel = fixP->fx_pcrel;
 | 
|---|
| 4175 | 
 | 
|---|
| 4176 |       /* We want function-relative stabs to work on systems which
 | 
|---|
| 4177 |          may use a relaxing linker; thus we must handle the sym1-sym2
 | 
|---|
| 4178 |          fixups function-relative stabs generates.
 | 
|---|
| 4179 | 
 | 
|---|
| 4180 |          Of course, if you actually enable relaxing in the linker, the
 | 
|---|
| 4181 |          line and block scoping information is going to be incorrect
 | 
|---|
| 4182 |          in some cases.  The only way to really fix this is to support
 | 
|---|
| 4183 |          a reloc involving the difference of two symbols.  */
 | 
|---|
| 4184 |       if (linkrelax
 | 
|---|
| 4185 |           && (!sub_symbolP || pcrel))
 | 
|---|
| 4186 |         continue;
 | 
|---|
| 4187 | 
 | 
|---|
| 4188 | #ifdef TC_I960
 | 
|---|
| 4189 |       if (fixP->fx_tcbit && SF_GET_CALLNAME (add_symbolP))
 | 
|---|
| 4190 |         {
 | 
|---|
| 4191 |           /* Relocation should be done via the associated 'bal' entry
 | 
|---|
| 4192 |              point symbol.  */
 | 
|---|
| 4193 | 
 | 
|---|
| 4194 |           if (!SF_GET_BALNAME (tc_get_bal_of_call (add_symbolP)))
 | 
|---|
| 4195 |             {
 | 
|---|
| 4196 |               as_bad_where (fixP->fx_file, fixP->fx_line,
 | 
|---|
| 4197 |                             _("No 'bal' entry point for leafproc %s"),
 | 
|---|
| 4198 |                             S_GET_NAME (add_symbolP));
 | 
|---|
| 4199 |               continue;
 | 
|---|
| 4200 |             }
 | 
|---|
| 4201 |           fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP);
 | 
|---|
| 4202 |         }
 | 
|---|
| 4203 | #endif
 | 
|---|
| 4204 | 
 | 
|---|
| 4205 |       /* Make sure the symbols have been resolved; this may not have
 | 
|---|
| 4206 |          happened if these are expression symbols.  */
 | 
|---|
| 4207 |       if (add_symbolP != NULL && ! add_symbolP->sy_resolved)
 | 
|---|
| 4208 |         resolve_symbol_value (add_symbolP);
 | 
|---|
| 4209 | 
 | 
|---|
| 4210 |       if (add_symbolP != NULL)
 | 
|---|
| 4211 |         {
 | 
|---|
| 4212 |           /* If this fixup is against a symbol which has been equated
 | 
|---|
| 4213 |              to another symbol, convert it to the other symbol.  */
 | 
|---|
| 4214 |           if (add_symbolP->sy_value.X_op == O_symbol
 | 
|---|
| 4215 |               && (! S_IS_DEFINED (add_symbolP)
 | 
|---|
| 4216 |                   || S_IS_COMMON (add_symbolP)))
 | 
|---|
| 4217 |             {
 | 
|---|
| 4218 |               while (add_symbolP->sy_value.X_op == O_symbol
 | 
|---|
| 4219 |                      && (! S_IS_DEFINED (add_symbolP)
 | 
|---|
| 4220 |                          || S_IS_COMMON (add_symbolP)))
 | 
|---|
| 4221 |                 {
 | 
|---|
| 4222 |                   symbolS *n;
 | 
|---|
| 4223 | 
 | 
|---|
| 4224 |                   /* We must avoid looping, as that can occur with a
 | 
|---|
| 4225 |                      badly written program.  */
 | 
|---|
| 4226 |                   n = add_symbolP->sy_value.X_add_symbol;
 | 
|---|
| 4227 |                   if (n == add_symbolP)
 | 
|---|
| 4228 |                     break;
 | 
|---|
| 4229 |                   add_number += add_symbolP->sy_value.X_add_number;
 | 
|---|
| 4230 |                   add_symbolP = n;
 | 
|---|
| 4231 |                 }
 | 
|---|
| 4232 |               fixP->fx_addsy = add_symbolP;
 | 
|---|
| 4233 |               fixP->fx_offset = add_number;
 | 
|---|
| 4234 |             }
 | 
|---|
| 4235 |         }
 | 
|---|
| 4236 | 
 | 
|---|
| 4237 |       if (sub_symbolP != NULL && ! sub_symbolP->sy_resolved)
 | 
|---|
| 4238 |         resolve_symbol_value (sub_symbolP);
 | 
|---|
| 4239 | 
 | 
|---|
| 4240 |       if (add_symbolP != NULL
 | 
|---|
| 4241 |           && add_symbolP->sy_mri_common)
 | 
|---|
| 4242 |         {
 | 
|---|
| 4243 |           know (add_symbolP->sy_value.X_op == O_symbol);
 | 
|---|
| 4244 |           add_number += S_GET_VALUE (add_symbolP);
 | 
|---|
| 4245 |           fixP->fx_offset = add_number;
 | 
|---|
| 4246 |           add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
 | 
|---|
| 4247 |         }
 | 
|---|
| 4248 | 
 | 
|---|
| 4249 |       if (add_symbolP)
 | 
|---|
| 4250 |         add_symbol_segment = S_GET_SEGMENT (add_symbolP);
 | 
|---|
| 4251 | 
 | 
|---|
| 4252 |       if (sub_symbolP)
 | 
|---|
| 4253 |         {
 | 
|---|
| 4254 |           if (add_symbolP == NULL || add_symbol_segment == absolute_section)
 | 
|---|
| 4255 |             {
 | 
|---|
| 4256 |               if (add_symbolP != NULL)
 | 
|---|
| 4257 |                 {
 | 
|---|
| 4258 |                   add_number += S_GET_VALUE (add_symbolP);
 | 
|---|
| 4259 |                   add_symbolP = NULL;
 | 
|---|
| 4260 |                   fixP->fx_addsy = NULL;
 | 
|---|
| 4261 |                 }
 | 
|---|
| 4262 | 
 | 
|---|
| 4263 |               /* It's just -sym.  */
 | 
|---|
| 4264 |               if (S_GET_SEGMENT (sub_symbolP) == absolute_section)
 | 
|---|
| 4265 |                 {
 | 
|---|
| 4266 |                   add_number -= S_GET_VALUE (sub_symbolP);
 | 
|---|
| 4267 |                   fixP->fx_subsy = 0;
 | 
|---|
| 4268 |                   fixP->fx_done = 1;
 | 
|---|
| 4269 |                 }
 | 
|---|
| 4270 |               else
 | 
|---|
| 4271 |                 {
 | 
|---|
| 4272 | #ifndef TC_M68K
 | 
|---|
| 4273 |                   as_bad_where (fixP->fx_file, fixP->fx_line,
 | 
|---|
| 4274 |                                 _("Negative of non-absolute symbol %s"),
 | 
|---|
| 4275 |                                 S_GET_NAME (sub_symbolP));
 | 
|---|
| 4276 | #endif
 | 
|---|
| 4277 |                   add_number -= S_GET_VALUE (sub_symbolP);
 | 
|---|
| 4278 |                 }               /* not absolute */
 | 
|---|
| 4279 | 
 | 
|---|
| 4280 |               /* if sub_symbol is in the same segment that add_symbol
 | 
|---|
| 4281 |                  and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE.  */
 | 
|---|
| 4282 |             }
 | 
|---|
| 4283 |           else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
 | 
|---|
| 4284 |                    && SEG_NORMAL (add_symbol_segment))
 | 
|---|
| 4285 |             {
 | 
|---|
| 4286 |               /* Difference of 2 symbols from same segment.  Can't
 | 
|---|
| 4287 |                  make difference of 2 undefineds: 'value' means
 | 
|---|
| 4288 |                  something different for N_UNDF.  */
 | 
|---|
| 4289 | #ifdef TC_I960
 | 
|---|
| 4290 |               /* Makes no sense to use the difference of 2 arbitrary symbols
 | 
|---|
| 4291 |                  as the target of a call instruction.  */
 | 
|---|
| 4292 |               if (fixP->fx_tcbit)
 | 
|---|
| 4293 |                 as_bad_where (fixP->fx_file, fixP->fx_line,
 | 
|---|
| 4294 |                               _("callj to difference of 2 symbols"));
 | 
|---|
| 4295 | #endif /* TC_I960 */
 | 
|---|
| 4296 |               add_number += S_GET_VALUE (add_symbolP) -
 | 
|---|
| 4297 |                 S_GET_VALUE (sub_symbolP);
 | 
|---|
| 4298 |               add_symbolP = NULL;
 | 
|---|
| 4299 | 
 | 
|---|
| 4300 |               if (!TC_FORCE_RELOCATION (fixP))
 | 
|---|
| 4301 |                 {
 | 
|---|
| 4302 |                   fixP->fx_addsy = NULL;
 | 
|---|
| 4303 |                   fixP->fx_subsy = NULL;
 | 
|---|
| 4304 |                   fixP->fx_done = 1;
 | 
|---|
| 4305 | #ifdef TC_M68K /* is this right? */
 | 
|---|
| 4306 |                   pcrel = 0;
 | 
|---|
| 4307 |                   fixP->fx_pcrel = 0;
 | 
|---|
| 4308 | #endif
 | 
|---|
| 4309 |                 }
 | 
|---|
| 4310 |             }
 | 
|---|
| 4311 |           else
 | 
|---|
| 4312 |             {
 | 
|---|
| 4313 |               /* Different segments in subtraction.  */
 | 
|---|
| 4314 |               know (!(S_IS_EXTERNAL (sub_symbolP) && (S_GET_SEGMENT (sub_symbolP) == absolute_section)));
 | 
|---|
| 4315 | 
 | 
|---|
| 4316 |               if ((S_GET_SEGMENT (sub_symbolP) == absolute_section))
 | 
|---|
| 4317 |                 add_number -= S_GET_VALUE (sub_symbolP);
 | 
|---|
| 4318 | 
 | 
|---|
| 4319 | #ifdef DIFF_EXPR_OK
 | 
|---|
| 4320 |               else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type
 | 
|---|
| 4321 | #if 0 /* Okay for 68k, at least...  */
 | 
|---|
| 4322 |                        && !pcrel
 | 
|---|
| 4323 | #endif
 | 
|---|
| 4324 |                        )
 | 
|---|
| 4325 |                 {
 | 
|---|
| 4326 |                   /* Make it pc-relative.  */
 | 
|---|
| 4327 |                   add_number += (md_pcrel_from (fixP)
 | 
|---|
| 4328 |                                  - S_GET_VALUE (sub_symbolP));
 | 
|---|
| 4329 |                   pcrel = 1;
 | 
|---|
| 4330 |                   fixP->fx_pcrel = 1;
 | 
|---|
| 4331 |                   sub_symbolP = 0;
 | 
|---|
| 4332 |                   fixP->fx_subsy = 0;
 | 
|---|
| 4333 |                 }
 | 
|---|
| 4334 | #endif
 | 
|---|
| 4335 |               else
 | 
|---|
| 4336 |                 {
 | 
|---|
| 4337 |                   as_bad_where (fixP->fx_file, fixP->fx_line,
 | 
|---|
| 4338 |                                 _("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %ld."),
 | 
|---|
| 4339 |                                 segment_name (S_GET_SEGMENT (sub_symbolP)),
 | 
|---|
| 4340 |                                 S_GET_NAME (sub_symbolP),
 | 
|---|
| 4341 |                                 (long) (fragP->fr_address + where));
 | 
|---|
| 4342 |                 }
 | 
|---|
| 4343 |             }
 | 
|---|
| 4344 |         }
 | 
|---|
| 4345 | 
 | 
|---|
| 4346 |       if (add_symbolP)
 | 
|---|
| 4347 |         {
 | 
|---|
| 4348 |           if (add_symbol_segment == this_segment_type && pcrel)
 | 
|---|
| 4349 |             {
 | 
|---|
| 4350 |               /* This fixup was made when the symbol's segment was
 | 
|---|
| 4351 |                  SEG_UNKNOWN, but it is now in the local segment.
 | 
|---|
| 4352 |                  So we know how to do the address without relocation.  */
 | 
|---|
| 4353 | #ifdef TC_I960
 | 
|---|
| 4354 |               /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
 | 
|---|
| 4355 |                  in which cases it modifies *fixP as appropriate.  In the case
 | 
|---|
| 4356 |                  of a 'calls', no further work is required, and *fixP has been
 | 
|---|
| 4357 |                  set up to make the rest of the code below a no-op.  */
 | 
|---|
| 4358 |               reloc_callj (fixP);
 | 
|---|
| 4359 | #endif /* TC_I960 */
 | 
|---|
| 4360 | 
 | 
|---|
| 4361 |               add_number += S_GET_VALUE (add_symbolP);
 | 
|---|
| 4362 |               add_number -= md_pcrel_from (fixP);
 | 
|---|
| 4363 | 
 | 
|---|
| 4364 |               /* We used to do
 | 
|---|
| 4365 |                    add_number -= segP->scnhdr.s_vaddr;
 | 
|---|
| 4366 |                  if defined (TC_I386) || defined (TE_LYNX).  I now
 | 
|---|
| 4367 |                  think that was an error propagated from the case when
 | 
|---|
| 4368 |                  we are going to emit the relocation.  If we are not
 | 
|---|
| 4369 |                  going to emit the relocation, then we just want to
 | 
|---|
| 4370 |                  set add_number to the difference between the symbols.
 | 
|---|
| 4371 |                  This is a case that would only arise when there is a
 | 
|---|
| 4372 |                  PC relative reference from a section other than .text
 | 
|---|
| 4373 |                  to a symbol defined in the same section, and the
 | 
|---|
| 4374 |                  reference is not relaxed.  Since jump instructions on
 | 
|---|
| 4375 |                  the i386 are relaxed, this could only arise with a
 | 
|---|
| 4376 |                  call instruction.  */
 | 
|---|
| 4377 | 
 | 
|---|
| 4378 |               pcrel = 0;        /* Lie. Don't want further pcrel processing.  */
 | 
|---|
| 4379 |               if (!TC_FORCE_RELOCATION (fixP))
 | 
|---|
| 4380 |                 {
 | 
|---|
| 4381 |                   fixP->fx_addsy = NULL;
 | 
|---|
| 4382 |                   fixP->fx_done = 1;
 | 
|---|
| 4383 |                 }
 | 
|---|
| 4384 |             }
 | 
|---|
| 4385 |           else
 | 
|---|
| 4386 |             {
 | 
|---|
| 4387 |               switch (add_symbol_segment)
 | 
|---|
| 4388 |                 {
 | 
|---|
| 4389 |                 case absolute_section:
 | 
|---|
| 4390 | #ifdef TC_I960
 | 
|---|
| 4391 |                   /* See comment about reloc_callj() above.  */
 | 
|---|
| 4392 |                   reloc_callj (fixP);
 | 
|---|
| 4393 | #endif /* TC_I960 */
 | 
|---|
| 4394 |                   add_number += S_GET_VALUE (add_symbolP);
 | 
|---|
| 4395 |                   add_symbolP = NULL;
 | 
|---|
| 4396 | 
 | 
|---|
| 4397 |                   if (!TC_FORCE_RELOCATION (fixP))
 | 
|---|
| 4398 |                     {
 | 
|---|
| 4399 |                       fixP->fx_addsy = NULL;
 | 
|---|
| 4400 |                       fixP->fx_done = 1;
 | 
|---|
| 4401 |                     }
 | 
|---|
| 4402 |                   break;
 | 
|---|
| 4403 |                 default:
 | 
|---|
| 4404 | 
 | 
|---|
| 4405 | #if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386)) || defined(TC_M88K) || defined(TC_OR32)
 | 
|---|
| 4406 |                   /* This really should be handled in the linker, but
 | 
|---|
| 4407 |                      backward compatibility forbids.  */
 | 
|---|
| 4408 |                   add_number += S_GET_VALUE (add_symbolP);
 | 
|---|
| 4409 | #else
 | 
|---|
| 4410 |                   add_number += S_GET_VALUE (add_symbolP) +
 | 
|---|
| 4411 |                     segment_info[S_GET_SEGMENT (add_symbolP)].scnhdr.s_paddr;
 | 
|---|
| 4412 | #endif
 | 
|---|
| 4413 |                   break;
 | 
|---|
| 4414 | 
 | 
|---|
| 4415 |                 case SEG_UNKNOWN:
 | 
|---|
| 4416 | #ifdef TC_I960
 | 
|---|
| 4417 |                   if ((int) fixP->fx_bit_fixP == 13)
 | 
|---|
| 4418 |                     {
 | 
|---|
| 4419 |                       /* This is a COBR instruction.  They have only a
 | 
|---|
| 4420 |                          13-bit displacement and are only to be used
 | 
|---|
| 4421 |                          for local branches: flag as error, don't generate
 | 
|---|
| 4422 |                          relocation.  */
 | 
|---|
| 4423 |                       as_bad_where (fixP->fx_file, fixP->fx_line,
 | 
|---|
| 4424 |                                     _("can't use COBR format with external label"));
 | 
|---|
| 4425 |                       fixP->fx_addsy = NULL;
 | 
|---|
| 4426 |                       fixP->fx_done = 1;
 | 
|---|
| 4427 |                       continue;
 | 
|---|
| 4428 |                     }
 | 
|---|
| 4429 | #endif /* TC_I960 */
 | 
|---|
| 4430 | #if ((defined (TC_I386) || defined (TE_LYNX) || defined (TE_AUX)) && !defined(TE_PE)) || defined (COFF_COMMON_ADDEND)
 | 
|---|
| 4431 |                   /* 386 COFF uses a peculiar format in which the
 | 
|---|
| 4432 |                      value of a common symbol is stored in the .text
 | 
|---|
| 4433 |                      segment (I've checked this on SVR3.2 and SCO
 | 
|---|
| 4434 |                      3.2.2) Ian Taylor <ian@cygnus.com>.  */
 | 
|---|
| 4435 |                   /* This is also true for 68k COFF on sysv machines
 | 
|---|
| 4436 |                      (Checked on Motorola sysv68 R3V6 and R3V7.1, and also on
 | 
|---|
| 4437 |                      UNIX System V/M68000, Release 1.0 from ATT/Bell Labs)
 | 
|---|
| 4438 |                      Philippe De Muyter <phdm@info.ucl.ac.be>.  */
 | 
|---|
| 4439 |                   if (S_IS_COMMON (add_symbolP))
 | 
|---|
| 4440 |                     add_number += S_GET_VALUE (add_symbolP);
 | 
|---|
| 4441 | #endif
 | 
|---|
| 4442 |                   break;
 | 
|---|
| 4443 | 
 | 
|---|
| 4444 |                 }
 | 
|---|
| 4445 |             }
 | 
|---|
| 4446 |         }
 | 
|---|
| 4447 | 
 | 
|---|
| 4448 |       if (pcrel)
 | 
|---|
| 4449 |         {
 | 
|---|
| 4450 | #if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386)) && !defined(TC_A29K) && !defined(TC_OR32)
 | 
|---|
| 4451 |           /* This adjustment is not correct on the m88k, for which the
 | 
|---|
| 4452 |              linker does all the computation.  */
 | 
|---|
| 4453 |           add_number -= md_pcrel_from (fixP);
 | 
|---|
| 4454 | #endif
 | 
|---|
| 4455 |           if (add_symbolP == 0)
 | 
|---|
| 4456 |             fixP->fx_addsy = &abs_symbol;
 | 
|---|
| 4457 | #if defined (TC_I386) || defined (TE_LYNX) || defined (TC_I960) || defined (TC_M68K)
 | 
|---|
| 4458 |           /* On the 386 we must adjust by the segment vaddr as well.
 | 
|---|
| 4459 |              Ian Taylor.
 | 
|---|
| 4460 | 
 | 
|---|
| 4461 |              I changed the i960 to work this way as well.  This is
 | 
|---|
| 4462 |              compatible with the current GNU linker behaviour.  I do
 | 
|---|
| 4463 |              not know what other i960 COFF assemblers do.  This is not
 | 
|---|
| 4464 |              a common case: normally, only assembler code will contain
 | 
|---|
| 4465 |              a PC relative reloc, and only branches which do not
 | 
|---|
| 4466 |              originate in the .text section will have a non-zero
 | 
|---|
| 4467 |              address.
 | 
|---|
| 4468 | 
 | 
|---|
| 4469 |              I changed the m68k to work this way as well.  This will
 | 
|---|
| 4470 |              break existing PC relative relocs from sections which do
 | 
|---|
| 4471 |              not start at address 0, but it will make ld -r work.
 | 
|---|
| 4472 |              Ian Taylor, 4 Oct 96.  */
 | 
|---|
| 4473 | 
 | 
|---|
| 4474 |           add_number -= segP->scnhdr.s_vaddr;
 | 
|---|
| 4475 | #endif
 | 
|---|
| 4476 |         }
 | 
|---|
| 4477 | 
 | 
|---|
| 4478 |       md_apply_fix3 (fixP, (valueT *) & add_number, this_segment_type);
 | 
|---|
| 4479 | 
 | 
|---|
| 4480 |       if (!fixP->fx_bit_fixP && ! fixP->fx_no_overflow)
 | 
|---|
| 4481 |         {
 | 
|---|
| 4482 | #ifndef TC_M88K
 | 
|---|
| 4483 |           /* The m88k uses the offset field of the reloc to get around
 | 
|---|
| 4484 |              this problem.  */
 | 
|---|
| 4485 |           if ((size == 1
 | 
|---|
| 4486 |                && ((add_number & ~0xFF)
 | 
|---|
| 4487 |                    || (fixP->fx_signed && (add_number & 0x80)))
 | 
|---|
| 4488 |                && ((add_number & ~0xFF) != (-1 & ~0xFF)
 | 
|---|
| 4489 |                    || (add_number & 0x80) == 0))
 | 
|---|
| 4490 |               || (size == 2
 | 
|---|
| 4491 |                   && ((add_number & ~0xFFFF)
 | 
|---|
| 4492 |                       || (fixP->fx_signed && (add_number & 0x8000)))
 | 
|---|
| 4493 |                   && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF)
 | 
|---|
| 4494 |                       || (add_number & 0x8000) == 0)))
 | 
|---|
| 4495 |             {
 | 
|---|
| 4496 |               as_bad_where (fixP->fx_file, fixP->fx_line,
 | 
|---|
| 4497 |                             _("Value of %ld too large for field of %d bytes at 0x%lx"),
 | 
|---|
| 4498 |                             (long) add_number, size,
 | 
|---|
| 4499 |                             (unsigned long) (fragP->fr_address + where));
 | 
|---|
| 4500 |             }
 | 
|---|
| 4501 | #endif
 | 
|---|
| 4502 | #ifdef WARN_SIGNED_OVERFLOW_WORD
 | 
|---|
| 4503 |           /* Warn if a .word value is too large when treated as a
 | 
|---|
| 4504 |              signed number.  We already know it is not too negative.
 | 
|---|
| 4505 |              This is to catch over-large switches generated by gcc on
 | 
|---|
| 4506 |              the 68k.  */
 | 
|---|
| 4507 |           if (!flag_signed_overflow_ok
 | 
|---|
| 4508 |               && size == 2
 | 
|---|
| 4509 |               && add_number > 0x7fff)
 | 
|---|
| 4510 |             as_bad_where (fixP->fx_file, fixP->fx_line,
 | 
|---|
| 4511 |                           _("Signed .word overflow; switch may be too large; %ld at 0x%lx"),
 | 
|---|
| 4512 |                           (long) add_number,
 | 
|---|
| 4513 |                           (unsigned long) (fragP->fr_address + where));
 | 
|---|
| 4514 | #endif
 | 
|---|
| 4515 |         }
 | 
|---|
| 4516 |     }
 | 
|---|
| 4517 | }
 | 
|---|
| 4518 | 
 | 
|---|
| 4519 | #endif
 | 
|---|
| 4520 | 
 | 
|---|
| 4521 | /* The first entry in a .stab section is special.  */
 | 
|---|
| 4522 | 
 | 
|---|
| 4523 | void
 | 
|---|
| 4524 | obj_coff_init_stab_section (seg)
 | 
|---|
| 4525 |      segT seg;
 | 
|---|
| 4526 | {
 | 
|---|
| 4527 |   char *file;
 | 
|---|
| 4528 |   char *p;
 | 
|---|
| 4529 |   char *stabstr_name;
 | 
|---|
| 4530 |   unsigned int stroff;
 | 
|---|
| 4531 | 
 | 
|---|
| 4532 |   /* Make space for this first symbol.  */
 | 
|---|
| 4533 |   p = frag_more (12);
 | 
|---|
| 4534 |   /* Zero it out.  */
 | 
|---|
| 4535 |   memset (p, 0, 12);
 | 
|---|
| 4536 |   as_where (&file, (unsigned int *) NULL);
 | 
|---|
| 4537 |   stabstr_name = (char *) alloca (strlen (segment_info[seg].name) + 4);
 | 
|---|
| 4538 |   strcpy (stabstr_name, segment_info[seg].name);
 | 
|---|
| 4539 |   strcat (stabstr_name, "str");
 | 
|---|
| 4540 |   stroff = get_stab_string_offset (file, stabstr_name);
 | 
|---|
| 4541 |   know (stroff == 1);
 | 
|---|
| 4542 |   md_number_to_chars (p, stroff, 4);
 | 
|---|
| 4543 | }
 | 
|---|
| 4544 | 
 | 
|---|
| 4545 | /* Fill in the counts in the first entry in a .stab section.  */
 | 
|---|
| 4546 | 
 | 
|---|
| 4547 | static void
 | 
|---|
| 4548 | adjust_stab_section(abfd, seg)
 | 
|---|
| 4549 |      bfd *abfd;
 | 
|---|
| 4550 |      segT seg;
 | 
|---|
| 4551 | {
 | 
|---|
| 4552 |   segT stabstrseg = SEG_UNKNOWN;
 | 
|---|
| 4553 |   const char *secname, *name2;
 | 
|---|
| 4554 |   char *name;
 | 
|---|
| 4555 |   char *p = NULL;
 | 
|---|
| 4556 |   int i, strsz = 0, nsyms;
 | 
|---|
| 4557 |   fragS *frag = segment_info[seg].frchainP->frch_root;
 | 
|---|
| 4558 | 
 | 
|---|
| 4559 |   /* Look for the associated string table section.  */
 | 
|---|
| 4560 | 
 | 
|---|
| 4561 |   secname = segment_info[seg].name;
 | 
|---|
| 4562 |   name = (char *) alloca (strlen (secname) + 4);
 | 
|---|
| 4563 |   strcpy (name, secname);
 | 
|---|
| 4564 |   strcat (name, "str");
 | 
|---|
| 4565 | 
 | 
|---|
| 4566 |   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
 | 
|---|
| 4567 |     {
 | 
|---|
| 4568 |       name2 = segment_info[i].name;
 | 
|---|
| 4569 |       if (name2 != NULL && strncmp(name2, name, 8) == 0)
 | 
|---|
| 4570 |         {
 | 
|---|
| 4571 |           stabstrseg = i;
 | 
|---|
| 4572 |           break;
 | 
|---|
| 4573 |         }
 | 
|---|
| 4574 |     }
 | 
|---|
| 4575 | 
 | 
|---|
| 4576 |   /* If we found the section, get its size.  */
 | 
|---|
| 4577 |   if (stabstrseg != SEG_UNKNOWN)
 | 
|---|
| 4578 |     strsz = size_section (abfd, stabstrseg);
 | 
|---|
| 4579 | 
 | 
|---|
| 4580 |   nsyms = size_section (abfd, seg) / 12 - 1;
 | 
|---|
| 4581 | 
 | 
|---|
| 4582 |   /* Look for the first frag of sufficient size for the initial stab
 | 
|---|
| 4583 |      symbol, and collect a pointer to it.  */
 | 
|---|
| 4584 |   while (frag && frag->fr_fix < 12)
 | 
|---|
| 4585 |     frag = frag->fr_next;
 | 
|---|
| 4586 |   assert (frag != 0);
 | 
|---|
| 4587 |   p = frag->fr_literal;
 | 
|---|
| 4588 |   assert (p != 0);
 | 
|---|
| 4589 | 
 | 
|---|
| 4590 |   /* Write in the number of stab symbols and the size of the string
 | 
|---|
| 4591 |      table.  */
 | 
|---|
| 4592 |   bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
 | 
|---|
| 4593 |   bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
 | 
|---|
| 4594 | }
 | 
|---|
| 4595 | 
 | 
|---|
| 4596 | #endif /* not BFD_ASSEMBLER */
 | 
|---|
| 4597 | 
 | 
|---|
| 4598 | const pseudo_typeS coff_pseudo_table[] =
 | 
|---|
| 4599 | {
 | 
|---|
| 4600 |   {"def", obj_coff_def, 0},
 | 
|---|
| 4601 |   {"dim", obj_coff_dim, 0},
 | 
|---|
| 4602 |   {"endef", obj_coff_endef, 0},
 | 
|---|
| 4603 |   {"line", obj_coff_line, 0},
 | 
|---|
| 4604 |   {"ln", obj_coff_ln, 0},
 | 
|---|
| 4605 | #ifdef BFD_ASSEMBLER
 | 
|---|
| 4606 |   {"loc", obj_coff_loc, 0},
 | 
|---|
| 4607 | #endif
 | 
|---|
| 4608 |   {"appline", obj_coff_ln, 1},
 | 
|---|
| 4609 |   {"scl", obj_coff_scl, 0},
 | 
|---|
| 4610 |   {"size", obj_coff_size, 0},
 | 
|---|
| 4611 |   {"tag", obj_coff_tag, 0},
 | 
|---|
| 4612 |   {"type", obj_coff_type, 0},
 | 
|---|
| 4613 |   {"val", obj_coff_val, 0},
 | 
|---|
| 4614 |   {"section", obj_coff_section, 0},
 | 
|---|
| 4615 |   {"sect", obj_coff_section, 0},
 | 
|---|
| 4616 |   /* FIXME: We ignore the MRI short attribute.  */
 | 
|---|
| 4617 |   {"section.s", obj_coff_section, 0},
 | 
|---|
| 4618 |   {"sect.s", obj_coff_section, 0},
 | 
|---|
| 4619 |   /* We accept the .bss directive for backward compatibility with
 | 
|---|
| 4620 |      earlier versions of gas.  */
 | 
|---|
| 4621 |   {"bss", obj_coff_bss, 0},
 | 
|---|
| 4622 |   {"weak", obj_coff_weak, 0},
 | 
|---|
| 4623 |   {"ident", obj_coff_ident, 0},
 | 
|---|
| 4624 | #ifndef BFD_ASSEMBLER
 | 
|---|
| 4625 |   {"use", obj_coff_section, 0},
 | 
|---|
| 4626 |   {"text", obj_coff_text, 0},
 | 
|---|
| 4627 |   {"data", obj_coff_data, 0},
 | 
|---|
| 4628 |   {"lcomm", obj_coff_lcomm, 0},
 | 
|---|
| 4629 | #else
 | 
|---|
| 4630 |   {"optim", s_ignore, 0},       /* For sun386i cc (?) */
 | 
|---|
| 4631 | #endif
 | 
|---|
| 4632 |   {"version", s_ignore, 0},
 | 
|---|
| 4633 |   {"ABORT", s_abort, 0},
 | 
|---|
| 4634 | #if defined( TC_M88K ) || defined ( TC_TIC4X )
 | 
|---|
| 4635 |   /* The m88k and tic4x uses sdef instead of def.  */
 | 
|---|
| 4636 |   {"sdef", obj_coff_def, 0},
 | 
|---|
| 4637 | #endif
 | 
|---|
| 4638 |   {NULL, NULL, 0}               /* end sentinel */
 | 
|---|
| 4639 | };                              /* coff_pseudo_table */
 | 
|---|
| 4640 |  | 
|---|
| 4641 | 
 | 
|---|
| 4642 | #ifdef BFD_ASSEMBLER
 | 
|---|
| 4643 | 
 | 
|---|
| 4644 | /* Support for a COFF emulation.  */
 | 
|---|
| 4645 | 
 | 
|---|
| 4646 | static void coff_pop_insert PARAMS ((void));
 | 
|---|
| 4647 | static int coff_separate_stab_sections PARAMS ((void));
 | 
|---|
| 4648 | 
 | 
|---|
| 4649 | static void
 | 
|---|
| 4650 | coff_pop_insert ()
 | 
|---|
| 4651 | {
 | 
|---|
| 4652 |   pop_insert (coff_pseudo_table);
 | 
|---|
| 4653 | }
 | 
|---|
| 4654 | 
 | 
|---|
| 4655 | static int
 | 
|---|
| 4656 | coff_separate_stab_sections ()
 | 
|---|
| 4657 | {
 | 
|---|
| 4658 |   return 1;
 | 
|---|
| 4659 | }
 | 
|---|
| 4660 | 
 | 
|---|
| 4661 | const struct format_ops coff_format_ops =
 | 
|---|
| 4662 | {
 | 
|---|
| 4663 |   bfd_target_coff_flavour,
 | 
|---|
| 4664 |   0,    /* dfl_leading_underscore */
 | 
|---|
| 4665 |   1,    /* emit_section_symbols */
 | 
|---|
| 4666 |   0,    /* begin */
 | 
|---|
| 4667 |   c_dot_file_symbol,
 | 
|---|
| 4668 |   coff_frob_symbol,
 | 
|---|
| 4669 |   0,    /* frob_file */
 | 
|---|
| 4670 |   0,    /* frob_file_before_adjust */
 | 
|---|
| 4671 |   0,    /* frob_file_before_fix */
 | 
|---|
| 4672 |   coff_frob_file_after_relocs,
 | 
|---|
| 4673 |   0,    /* s_get_size */
 | 
|---|
| 4674 |   0,    /* s_set_size */
 | 
|---|
| 4675 |   0,    /* s_get_align */
 | 
|---|
| 4676 |   0,    /* s_set_align */
 | 
|---|
| 4677 |   0,    /* s_get_other */
 | 
|---|
| 4678 |   0,    /* s_set_other */
 | 
|---|
| 4679 |   0,    /* s_get_desc */
 | 
|---|
| 4680 |   0,    /* s_set_desc */
 | 
|---|
| 4681 |   0,    /* s_get_type */
 | 
|---|
| 4682 |   0,    /* s_set_type */
 | 
|---|
| 4683 |   0,    /* copy_symbol_attributes */
 | 
|---|
| 4684 |   0,    /* generate_asm_lineno */
 | 
|---|
| 4685 |   0,    /* process_stab */
 | 
|---|
| 4686 |   coff_separate_stab_sections,
 | 
|---|
| 4687 |   obj_coff_init_stab_section,
 | 
|---|
| 4688 |   0,    /* sec_sym_ok_for_reloc */
 | 
|---|
| 4689 |   coff_pop_insert,
 | 
|---|
| 4690 |   0,    /* ecoff_set_ext */
 | 
|---|
| 4691 |   coff_obj_read_begin_hook,
 | 
|---|
| 4692 |   coff_obj_symbol_new_hook
 | 
|---|
| 4693 | };
 | 
|---|
| 4694 | 
 | 
|---|
| 4695 | #endif
 | 
|---|