RIP gzip, we found a nicer playmate.
[dragonfly.git] / gnu / usr.bin / as / config / obj-coffbfd.c
1 /* coff object file format with bfd
2    Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3
4    This file is part of GAS.
5
6    GAS is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GAS is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GAS; see the file COPYING.  If not, write to
18    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21
22   How does this releate to the rest of GAS ?
23
24   Well, all the other files in gas are more or less a black box. It
25   takes care of opening files, parsing command lines, stripping blanks
26   etc etc. This module gets a chance to register what it wants to do by
27   saying that it is interested in various pseduo ops. The other big
28   change is write_object_file. This runs through all the data
29   structures that gas builds, and outputs the file in the format of our
30   choice.
31
32   Hacked for BFDness by steve chamberlain
33
34   This object module now supports the Hitachi H8/300 and the AMD 29k
35
36   sac@cygnus.com
37   */
38
39 #include "as.h"
40 #include "obstack.h"
41 #include "subsegs.h"
42 #include "frags.h"
43 #include "../bfd/libbfd.h"
44
45
46 /* This vector is used to turn an internal segment into a section #
47    suitable for insertion into a coff symbol table
48    */
49
50 const short seg_N_TYPE[] = { /* in: segT   out: N_TYPE bits */
51         C_ABS_SECTION,
52         1,
53         2,
54         3,
55         4,
56         5,
57         6,
58         7,
59         8,
60         9,
61         10,
62         C_UNDEF_SECTION,                /* SEG_UNKNOWN */
63         C_UNDEF_SECTION,                /* SEG_ABSENT */
64         C_UNDEF_SECTION,                /* SEG_PASS1 */
65         C_UNDEF_SECTION,                /* SEG_GOOF */
66         C_UNDEF_SECTION,                /* SEG_BIG */
67         C_UNDEF_SECTION,                /* SEG_DIFFERENCE */
68         C_DEBUG_SECTION,                /* SEG_DEBUG */
69         C_NTV_SECTION,          /* SEG_NTV */
70         C_PTV_SECTION,          /* SEG_PTV */
71         C_REGISTER_SECTION,     /* SEG_REGISTER */
72 };
73
74
75 int function_lineoff = -1;      /* Offset in line#s where the last function
76                                    started (the odd entry for line #0) */
77
78 int our_lineno_number = 0;      /* we use this to build pointers from .bf's
79                                    into the linetable.  It should match
80                                    exactly the values that are later
81                                    assigned in text_lineno_number by
82                                    write.c. */
83
84 int text_lineno_number = 0;
85
86 /* Add 4 to the real value to get the index and compensate the
87    negatives. This vector is used by S_GET_SEGMENT to turn a coff
88    section number into a segment number
89    */
90 static symbolS *previous_file_symbol = NULL;
91 void c_symbol_merge();
92 static int line_base;
93
94 symbolS *c_section_symbol();
95 bfd *abfd;
96 void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
97                               bfd *abfd));
98
99 static void EXFUN(fixup_segment,(fixS * fixP,
100                                  segT   this_segment_type));
101
102 static void EXFUN(fill_section,(bfd *abfd ,
103                                 struct internal_filehdr *f, unsigned
104                                 long *));
105
106
107 char *EXFUN(s_get_name,(symbolS *s));
108 static symbolS *EXFUN(tag_find_or_make,(char *name));
109 static symbolS* EXFUN(tag_find,(char *name));
110
111
112 static int
113     EXFUN(c_line_new,(
114                       symbolS *symbol,
115                       long paddr,
116                       unsigned short line_number,
117                       fragS* frag));
118
119
120 static void EXFUN(w_symbols,
121                   (bfd *abfd ,
122                    char *where ,
123                    symbolS *symbol_rootP));
124
125
126
127 static void EXFUN( obj_coff_def,(int what));
128 static void EXFUN( obj_coff_lcomm,(void));
129 static void EXFUN( obj_coff_dim,(void));
130 static void EXFUN( obj_coff_text,(void));
131 static void EXFUN( obj_coff_data,(void));
132 static void EXFUN( obj_coff_endef,(void));
133 static void EXFUN( obj_coff_line,(void));
134 static void EXFUN( obj_coff_ln,(void));
135 static void EXFUN( obj_coff_scl,(void));
136 static void EXFUN( obj_coff_size,(void));
137 static void EXFUN( obj_coff_tag,(void));
138 static void EXFUN( obj_coff_type,(void));
139 static void EXFUN( obj_coff_val,(void));
140 static void EXFUN( obj_coff_section,(void));
141 static void EXFUN( tag_init,(void));
142 static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
143
144
145 static struct hash_control *tag_hash;
146 static symbolS *def_symbol_in_progress = NULL;
147
148 const pseudo_typeS obj_pseudo_table[] = {
149         { "def",        obj_coff_def,           0       },
150         { "dim",        obj_coff_dim,           0       },
151         { "endef",      obj_coff_endef,         0       },
152         { "line",       obj_coff_line,          0       },
153         { "ln",         obj_coff_ln,            0       },
154         { "scl",        obj_coff_scl,           0       },
155         { "size",       obj_coff_size,          0       },
156         { "tag",        obj_coff_tag,           0       },
157         { "type",       obj_coff_type,          0       },
158         { "val",        obj_coff_val,           0       },
159         { "section",    obj_coff_section,       0       },
160         { "text",       obj_coff_text,          0       },
161         { "data",       obj_coff_data,          0       },
162         /* we don't yet handle this. */
163         { "ident",      s_ignore,               0       },
164         { "ABORT",      s_abort,                0 },
165         { "lcomm",      obj_coff_lcomm, 0},
166         { NULL} /* end sentinel */
167 }; /* obj_pseudo_table */
168
169
170
171 /* Section stuff
172
173    We allow more than just the standard 3 sections, infact, we allow
174    10 sections, (though the usual three have to be there).
175
176    This structure performs the mappings for us:
177
178    */
179
180 /* OBS stuff
181    static struct internal_scnhdr bss_section_header;
182    struct internal_scnhdr data_section_header;
183    struct internal_scnhdr text_section_header;
184
185    const segT N_TYPE_seg[32] =
186    {
187
188    };
189
190    */
191
192 #define N_SEG 32
193 typedef struct
194 {
195         segT seg_t;
196         int i;
197 } seg_info_type;
198
199 seg_info_type seg_info_off_by_4[N_SEG] =
200 {
201         {SEG_PTV,  },
202         {SEG_NTV,  },
203         {SEG_DEBUG, },
204         {SEG_ABSOLUTE,  },
205         {SEG_UNKNOWN,    },
206         {SEG_E0},
207         {SEG_E1},
208         {SEG_E2},
209         {SEG_E3},
210         {SEG_E4},
211         {SEG_E5},
212         {SEG_E6},
213         {SEG_E7},
214         {SEG_E8},
215         {SEG_E9},
216         {15},
217         {16},
218         {17},
219         {18},
220         {19},
221         {20},
222         {0},
223         {0},
224         {0},
225         {SEG_REGISTER},0,0,0,0};
226
227 #define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
228 #define SEG_INFO_FROM_SEG_NUMBER(x) (seg_info_off_by_4[(x)])
229
230
231 relax_addressT
232     DEFUN(relax_align,(address, alignment),
233           register relax_addressT address AND
234           register long alignment )
235 {
236         relax_addressT  mask;
237         relax_addressT  new_address;
238
239         mask = ~ ( (~0) << alignment );
240         new_address = (address + mask) & (~ mask);
241         return (new_address - address);
242 } /* relax_align() */
243
244
245 segT
246     DEFUN(s_get_segment,(x) ,
247           symbolS* x)
248 {
249         return SEG_INFO_FROM_SECTION_NUMBER(x->sy_symbol.ost_entry.n_scnum).seg_t;
250 }
251
252
253
254 /* calculate the size of the frag chain and fill in the section header
255    to contain all of it, also fill in the addr of the sections */
256 static unsigned int  DEFUN(size_section,(abfd, idx),
257                            bfd *abfd AND
258                            unsigned int idx)
259 {
260
261         unsigned int size = 0;
262         fragS *frag = segment_info[idx].frchainP->frch_root;
263         while (frag) {
264                 if (frag->fr_address != size) {
265                         printf("Out of step\n");
266                         size = frag->fr_address;
267                 }
268                 size += frag->fr_fix;
269                 switch (frag->fr_type) {
270                 case rs_fill:
271                 case rs_org:
272                         size  +=    frag->fr_offset * frag->fr_var;
273                         break;
274                 case rs_align:
275                         size  +=   relax_align(size, frag->fr_offset);
276                 }
277                 frag = frag->fr_next;
278         }
279         segment_info[idx].scnhdr.s_size = size;
280         return size;
281 }
282
283
284 static unsigned int DEFUN(count_entries_in_chain,(idx),
285                           unsigned int idx)
286 {
287         unsigned int nrelocs;
288         fixS *fixup_ptr;
289
290         /* Count the relocations */
291         fixup_ptr = segment_info[idx].fix_root;
292         nrelocs = 0;
293         while (fixup_ptr != (fixS *)NULL)
294             {
295                     if (TC_COUNT_RELOC(fixup_ptr))
296                         {
297
298 #ifdef TC_A29K
299
300                                 if (fixup_ptr->fx_r_type == RELOC_CONSTH)
301                                     nrelocs+=2;
302                                 else
303                                     nrelocs++;
304 #else
305                                 nrelocs++;
306 #endif
307                         }
308
309                     fixup_ptr = fixup_ptr->fx_next;
310             }
311         return nrelocs;
312 }
313
314 /* output all the relocations for a section */
315 void DEFUN(do_relocs_for,(abfd, file_cursor),
316            bfd *abfd AND
317            unsigned long *file_cursor)
318 {
319         unsigned int nrelocs;
320         unsigned int idx;
321
322         for (idx = SEG_E0; idx < SEG_E9; idx++)
323             {
324                     if (segment_info[idx].scnhdr.s_name[0])
325                         {
326
327                                 struct external_reloc *ext_ptr;
328                                 struct external_reloc *external_reloc_vec;
329                                 unsigned int external_reloc_size;
330                                 unsigned int count = 0;
331                                 unsigned int base  = segment_info[idx].scnhdr.s_paddr;
332                                 fixS *   fix_ptr = segment_info[idx].fix_root;
333                                 nrelocs = count_entries_in_chain(idx);
334                                 external_reloc_size = nrelocs * RELSZ;
335                                 external_reloc_vec =
336                                     (struct external_reloc*)malloc(external_reloc_size);
337
338
339
340                                 ext_ptr = external_reloc_vec;
341
342                                 /* Fill in the internal coff style reloc struct from the
343                                    internal fix list */
344                                 while (fix_ptr)
345                                     {
346                                             symbolS *symbol_ptr;
347                                             struct internal_reloc intr;
348
349                                             /* Only output some of the relocations */
350                                             if (TC_COUNT_RELOC(fix_ptr))
351                                                 {
352 #ifdef TC_RELOC_MANGLE
353                                                         TC_RELOC_MANGLE(fix_ptr, &intr, base);
354
355 #else
356                                                         symbolS *dot;
357                                                         symbol_ptr = fix_ptr->fx_addsy;
358
359                                                         intr.r_type = TC_COFF_FIX2RTYPE(fix_ptr);
360                                                         intr.r_vaddr =
361                                                             base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where ;
362
363                                                         intr.r_offset = fix_ptr->fx_offset;
364
365                                                         intr.r_offset = 0;
366
367                                                         /* Turn the segment of the symbol into an offset
368                                                          */
369                                                         if (symbol_ptr)
370                                                             {
371                                                                     dot = segment_info[S_GET_SEGMENT(symbol_ptr)].dot;
372                                                                     if (dot)
373                                                                         {
374                                                                                 intr.r_symndx = dot->sy_number;
375                                                                         }
376                                                                     else
377                                                                         {
378                                                                                 intr.r_symndx = symbol_ptr->sy_number;
379                                                                         }
380
381                                                             }
382                                                         else
383                                                             {
384                                                                     intr.r_symndx = -1;
385
386
387                                                             }
388 #endif
389
390                                                         (void)bfd_coff_swap_reloc_out(abfd, &intr, ext_ptr);
391                                                         ext_ptr++;
392
393 #if defined(TC_A29K)
394                                                         /* The 29k has a special kludge for the high 16 bit reloc.
395                                                            Two relocations are emmited, R_IHIHALF, and
396                                                            R_IHCONST. The second one doesn't contain a symbol,
397                                                            but uses the value for offset */
398
399                                                         if (intr.r_type == R_IHIHALF)
400                                                             {
401                                                                     /* now emit the second bit */
402                                                                     intr.r_type = R_IHCONST;
403                                                                     intr.r_symndx = fix_ptr->fx_addnumber;
404                                                                     (void)bfd_coff_swap_reloc_out(abfd,&intr,ext_ptr);
405                                                                     ext_ptr++;
406                                                             }
407 #endif
408                                                 }
409
410                                             fix_ptr = fix_ptr->fx_next;
411                                     }
412
413                                 /* Write out the reloc table */
414                                 segment_info[idx].scnhdr.s_relptr = *file_cursor;
415                                 segment_info[idx].scnhdr.s_nreloc = nrelocs;
416                                 bfd_write((PTR)external_reloc_vec, 1, external_reloc_size, abfd);
417                                 *file_cursor += external_reloc_size;
418                                 free( external_reloc_vec);
419                         }
420             }
421 }
422
423
424 /* run through a frag chain and write out the data to go with it, fill
425    in the scnhdrs with the info on the file postions
426    */
427 static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
428                   bfd *abfd AND
429                   struct internal_filehdr *filehdr AND
430                   unsigned long *file_cursor)
431 {
432
433         unsigned int i;
434         unsigned int paddr = 0;
435
436         for (i = SEG_E0; i < SEG_UNKNOWN; i++)
437             {
438                     unsigned int offset = 0;
439
440                     struct internal_scnhdr *s = &( segment_info[i].scnhdr);
441
442                     if (s->s_name[0])
443                         {
444                                 fragS *frag = segment_info[i].frchainP->frch_root;
445                                 char *buffer =  malloc(s->s_size);
446                                 s->s_scnptr = *file_cursor;
447                                 s->s_paddr =  paddr;
448                                 s->s_vaddr =  paddr;
449
450                                 s->s_flags = STYP_REG;
451                                 if (strcmp(s->s_name,".text") == 0)
452                                     s->s_flags |= STYP_TEXT;
453                                 else if (strcmp(s->s_name,".data") == 0)
454                                     s->s_flags |= STYP_DATA;
455                                 else if (strcmp(s->s_name,".bss") == 0)
456                                     s->s_flags |= STYP_BSS | STYP_NOLOAD;
457
458                                 while (frag) {
459                                         unsigned int fill_size;
460                                         switch (frag->fr_type) {
461
462                                         case rs_fill:
463                                         case rs_align:
464                                         case rs_org:
465                                                 if (frag->fr_fix)
466                                                     {
467                                                             memcpy(buffer + frag->fr_address,
468                                                                    frag->fr_literal,
469                                                                    frag->fr_fix);
470                                                             offset += frag->fr_fix;
471                                                     }
472
473                                                 fill_size = frag->fr_var;
474                                                 if (fill_size)
475                                                     {
476                                                             unsigned int count ;
477                                                             unsigned int off = frag->fr_fix;
478                                                             for (count = frag->fr_offset; count;  count--)
479                                                                 {
480                                                                         memcpy(buffer +  frag->fr_address  + off,
481                                                                                frag->fr_literal + frag->fr_fix,
482                                                                                fill_size);
483                                                                         off += fill_size;
484                                                                         offset += fill_size;
485
486                                                                 }
487
488                                                     }
489                                                 break;
490                                         default:
491                                                 abort();
492                                         }
493                                         frag = frag->fr_next;
494                                 }
495
496
497                                 bfd_write(buffer, s->s_size,1,abfd);
498                                 free(buffer);
499
500                                 *file_cursor += s->s_size;
501                                 paddr += s->s_size;
502                         }
503             }
504
505 }
506
507
508
509 /* Coff file generation & utilities */
510
511
512 static void
513     DEFUN(coff_header_append,(abfd, filehdr, aouthdr),
514           bfd *abfd AND
515           struct internal_filehdr *filehdr AND
516           struct internal_aouthdr *aouthdr)
517 {
518         unsigned int i;
519         char buffer[1000];
520         char buffero[1000];
521
522         bfd_seek(abfd, 0, 0);
523 #if 0
524         filehdr.f_opthdr = bfd_coff_swap_aouthdr_out(abfd, aouthdr,
525                                                      buffero);
526 #else
527         filehdr->f_opthdr = 0;
528 #endif
529         i = bfd_coff_swap_filehdr_out(abfd, filehdr, buffer);
530
531         bfd_write(buffer, i ,1, abfd);
532         bfd_write(buffero, filehdr->f_opthdr, 1, abfd);
533
534         for (i = SEG_E0; i < SEG_E9; i++)
535             {
536                     if (segment_info[i].scnhdr.s_name[0])
537                         {
538                                 unsigned int size =
539                                     bfd_coff_swap_scnhdr_out(abfd,
540                                                              &(segment_info[i].scnhdr),
541                                                              buffer);
542                                 bfd_write(buffer, size, 1, abfd);
543                         }
544             }
545 }
546
547
548 char *
549     DEFUN(symbol_to_chars,(abfd, where, symbolP),
550           bfd*abfd AND
551           char *where AND
552           symbolS *symbolP)
553 {
554         unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
555         unsigned int i;
556
557         /* Turn any symbols with register attributes into abs symbols */
558         if (S_GET_SEGMENT(symbolP) == SEG_REGISTER)
559             {
560                     S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
561             }
562         /* At the same time, relocate all symbols to their output value */
563
564         S_SET_VALUE(symbolP,
565                     segment_info[S_GET_SEGMENT(symbolP)].scnhdr.s_paddr
566                     + S_GET_VALUE(symbolP));
567
568         where += bfd_coff_swap_sym_out(abfd, &symbolP->sy_symbol.ost_entry,
569                                        where);
570
571         for (i = 0; i < numaux; i++)
572             {
573                     where += bfd_coff_swap_aux_out(abfd,
574                                                    &symbolP->sy_symbol.ost_auxent[i],
575                                                    S_GET_DATA_TYPE(symbolP),
576                                                    S_GET_STORAGE_CLASS(symbolP),
577                                                    where);
578             }
579         return where;
580
581 }
582
583
584
585
586 void obj_symbol_new_hook(symbolP)
587 symbolS *symbolP;
588 {
589         char underscore = 0;      /* Symbol has leading _ */
590
591         /* Effective symbol */
592         /* Store the pointer in the offset. */
593         S_SET_ZEROES(symbolP, 0L);
594         S_SET_DATA_TYPE(symbolP, T_NULL);
595         S_SET_STORAGE_CLASS(symbolP, 0);
596         S_SET_NUMBER_AUXILIARY(symbolP, 0);
597         /* Additional information */
598         symbolP->sy_symbol.ost_flags = 0;
599         /* Auxiliary entries */
600         memset((char*) &symbolP->sy_symbol.ost_auxent[0], '\0', AUXESZ);
601
602 #ifdef STRIP_UNDERSCORE
603         /* Remove leading underscore at the beginning of the symbol.
604          * This is to be compatible with the standard librairies.
605          */
606         if (*S_GET_NAME(symbolP) == '_') {
607                 underscore = 1;
608                 S_SET_NAME(symbolP, S_GET_NAME(symbolP) + 1);
609         } /* strip underscore */
610 #endif /* STRIP_UNDERSCORE */
611
612         if (S_IS_STRING(symbolP))
613             SF_SET_STRING(symbolP);
614         if (!underscore && S_IS_LOCAL(symbolP))
615             SF_SET_LOCAL(symbolP);
616
617         return;
618 } /* obj_symbol_new_hook() */
619
620 /* stack stuff */
621 stack* stack_init(chunk_size, element_size)
622 unsigned long chunk_size;
623 unsigned long element_size;
624 {
625         stack* st;
626
627         if ((st = (stack*)malloc(sizeof(stack))) == (stack*)0)
628             return (stack*)0;
629         if ((st->data = malloc(chunk_size)) == (char*)0) {
630                 free(st);
631                 return (stack*)0;
632         }
633         st->pointer = 0;
634         st->size = chunk_size;
635         st->chunk_size = chunk_size;
636         st->element_size = element_size;
637         return st;
638 } /* stack_init() */
639
640 void stack_delete(st)
641 stack* st;
642 {
643         free(st->data);
644         free(st);
645 }
646
647 char *stack_push(st, element)
648 stack *st;
649 char *element;
650 {
651         if (st->pointer + st->element_size >= st->size) {
652                 st->size += st->chunk_size;
653                 if ((st->data = xrealloc(st->data, st->size)) == (char*)0)
654                     return (char*)0;
655         }
656         memcpy(st->data + st->pointer, element, st->element_size);
657         st->pointer += st->element_size;
658         return st->data + st->pointer;
659 } /* stack_push() */
660
661 char* stack_pop(st)
662 stack* st;
663 {
664         if ((st->pointer -= st->element_size) < 0) {
665                 st->pointer = 0;
666                 return (char*)0;
667         }
668
669         return st->data + st->pointer;
670 }
671
672 char* stack_top(st)
673 stack* st;
674 {
675         return st->data + st->pointer - st->element_size;
676 }
677
678
679 /*
680  * Handle .ln directives.
681  */
682
683 static void obj_coff_ln()
684 {
685         int l;
686
687         if (def_symbol_in_progress != NULL) {
688                 as_warn(".ln pseudo-op inside .def/.endef: ignored.");
689                 demand_empty_rest_of_line();
690                 return;
691         }                               /* wrong context */
692
693         c_line_new(0,
694                    obstack_next_free(&frags) - frag_now->fr_literal,
695                    l = get_absolute_expression(),
696                    frag_now);
697 #ifndef NO_LISTING
698         {
699                 extern int listing;
700
701                 if (listing)
702                     {
703                             listing_source_line(l + line_base - 1);
704                     }
705
706         }
707 #endif
708         demand_empty_rest_of_line();
709         return;
710 }                               /* obj_coff_line() */
711
712 /*
713  *                      def()
714  *
715  * Handle .def directives.
716  *
717  * One might ask : why can't we symbol_new if the symbol does not
718  * already exist and fill it with debug information.  Because of
719  * the C_EFCN special symbol. It would clobber the value of the
720  * function symbol before we have a chance to notice that it is
721  * a C_EFCN. And a second reason is that the code is more clear this
722  * way. (at least I think it is :-).
723  *
724  */
725
726 #define SKIP_SEMI_COLON()       while (*input_line_pointer++ != ';')
727 #define SKIP_WHITESPACES()      while (*input_line_pointer == ' ' || \
728                                        *input_line_pointer == '\t') \
729     input_line_pointer++;
730
731 static void
732     DEFUN(obj_coff_def,(what),
733           int what)
734 {
735         char name_end;          /* Char after the end of name */
736         char *symbol_name;              /* Name of the debug symbol */
737         char *symbol_name_copy; /* Temporary copy of the name */
738         unsigned int symbol_name_length;
739         /*$char*        directiveP;$ */         /* Name of the pseudo opcode */
740         /*$char directive[MAX_DIRECTIVE];$ */ /* Backup of the directive */
741         /*$char end = 0;$ */ /* If 1, stop parsing */
742
743         if (def_symbol_in_progress != NULL) {
744                 as_warn(".def pseudo-op used inside of .def/.endef: ignored.");
745                 demand_empty_rest_of_line();
746                 return;
747         }                       /* if not inside .def/.endef */
748
749         SKIP_WHITESPACES();
750
751         def_symbol_in_progress = (symbolS *) obstack_alloc(&notes, sizeof(*def_symbol_in_progress));
752         memset(def_symbol_in_progress, '\0', sizeof(*def_symbol_in_progress));
753
754         symbol_name = input_line_pointer;
755         name_end = get_symbol_end();
756         symbol_name_length = strlen(symbol_name);
757         symbol_name_copy = xmalloc(symbol_name_length + 1);
758         strcpy(symbol_name_copy, symbol_name);
759
760         /* Initialize the new symbol */
761 #ifdef STRIP_UNDERSCORE
762         S_SET_NAME(def_symbol_in_progress, (*symbol_name_copy == '_'
763                                             ? symbol_name_copy + 1
764                                             : symbol_name_copy));
765 #else                           /* STRIP_UNDERSCORE */
766         S_SET_NAME(def_symbol_in_progress, symbol_name_copy);
767 #endif                          /* STRIP_UNDERSCORE */
768         /* free(symbol_name_copy); */
769         def_symbol_in_progress->sy_name_offset = ~0;
770         def_symbol_in_progress->sy_number = ~0;
771         def_symbol_in_progress->sy_frag = &zero_address_frag;
772
773         if (S_IS_STRING(def_symbol_in_progress)) {
774                 SF_SET_STRING(def_symbol_in_progress);
775         }                       /* "long" name */
776
777         *input_line_pointer = name_end;
778
779         demand_empty_rest_of_line();
780         return;
781 }                               /* obj_coff_def() */
782
783 unsigned int dim_index;
784 static void
785     DEFUN_VOID(obj_coff_endef)
786 {
787         symbolS *symbolP = 0;
788         /* DIM BUG FIX sac@cygnus.com */
789         dim_index =0;
790         if (def_symbol_in_progress == NULL) {
791                 as_warn(".endef pseudo-op used outside of .def/.endef: ignored.");
792                 demand_empty_rest_of_line();
793                 return;
794         }                       /* if not inside .def/.endef */
795
796         /* Set the section number according to storage class. */
797         switch (S_GET_STORAGE_CLASS(def_symbol_in_progress)) {
798         case C_STRTAG:
799         case C_ENTAG:
800         case C_UNTAG:
801                 SF_SET_TAG(def_symbol_in_progress);
802                 /* intentional fallthrough */
803         case C_FILE:
804         case C_TPDEF:
805                 SF_SET_DEBUG(def_symbol_in_progress);
806                 S_SET_SEGMENT(def_symbol_in_progress, SEG_DEBUG);
807                 break;
808
809         case C_EFCN:
810                 SF_SET_LOCAL(def_symbol_in_progress); /* Do not emit this symbol. */
811                 /* intentional fallthrough */
812         case C_BLOCK:
813                 SF_SET_PROCESS(def_symbol_in_progress); /* Will need processing before writing */
814                 /* intentional fallthrough */
815         case C_FCN:
816                 S_SET_SEGMENT(def_symbol_in_progress, SEG_E0);
817
818                 if (def_symbol_in_progress->sy_symbol.ost_entry.n_name[1] == 'b') { /* .bf */
819                         if (function_lineoff < 0) {
820                                 fprintf(stderr, "`.bf' symbol without preceding function\n");
821                         }       /* missing function symbol */
822                         SA_GET_SYM_LNNOPTR(def_symbol_in_progress) = function_lineoff;
823                         SF_SET_PROCESS(def_symbol_in_progress); /* Will need relocating */
824                         function_lineoff = -1;
825                 }
826                 break;
827
828 #ifdef C_AUTOARG
829         case C_AUTOARG:
830 #endif                          /* C_AUTOARG */
831         case C_AUTO:
832         case C_REG:
833         case C_MOS:
834         case C_MOE:
835         case C_MOU:
836         case C_ARG:
837         case C_REGPARM:
838         case C_FIELD:
839         case C_EOS:
840                 SF_SET_DEBUG(def_symbol_in_progress);
841                 S_SET_SEGMENT(def_symbol_in_progress, SEG_ABSOLUTE);
842                 break;
843
844         case C_EXT:
845         case C_STAT:
846         case C_LABEL:
847                 /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
848                 break;
849
850         case C_USTATIC:
851         case C_EXTDEF:
852         case C_ULABEL:
853                 as_warn("unexpected storage class %d", S_GET_STORAGE_CLASS(def_symbol_in_progress));
854                 break;
855         }                       /* switch on storage class */
856
857         /* Now that we have built a debug symbol, try to
858            find if we should merge with an existing symbol
859            or not.  If a symbol is C_EFCN or SEG_ABSOLUTE or
860            untagged SEG_DEBUG it never merges. */
861
862         /* Two cases for functions.  Either debug followed
863            by definition or definition followed by debug.
864            For definition first, we will merge the debug
865            symbol into the definition.  For debug first, the
866            lineno entry MUST point to the definition
867            function or else it will point off into space
868            when crawl_symbols() merges the debug
869            symbol into the real symbol.  Therefor, let's
870            presume the debug symbol is a real function
871            reference. */
872
873         /* FIXME-SOON If for some reason the definition
874            label/symbol is never seen, this will probably
875            leave an undefined symbol at link time. */
876
877         if (S_GET_STORAGE_CLASS(def_symbol_in_progress) == C_EFCN
878             || (S_GET_SEGMENT(def_symbol_in_progress) == SEG_DEBUG
879                 && !SF_GET_TAG(def_symbol_in_progress))
880             || S_GET_SEGMENT(def_symbol_in_progress) == SEG_ABSOLUTE
881             || (symbolP = symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP)) == NULL) {
882
883                 symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
884
885         } else {
886                 /* This symbol already exists, merge the
887                    newly created symbol into the old one.
888                    This is not mandatory. The linker can
889                    handle duplicate symbols correctly. But I
890                    guess that it save a *lot* of space if
891                    the assembly file defines a lot of
892                    symbols. [loic] */
893
894                 /* The debug entry (def_symbol_in_progress)
895                    is merged into the previous definition. */
896
897                 c_symbol_merge(def_symbol_in_progress, symbolP);
898                 /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
899                 def_symbol_in_progress = symbolP;
900
901                 if (SF_GET_FUNCTION(def_symbol_in_progress)
902                     || SF_GET_TAG(def_symbol_in_progress)) {
903                         /* For functions, and tags, the symbol *must* be where the debug symbol
904                            appears.  Move the existing symbol to the current place. */
905                         /* If it already is at the end of the symbol list, do nothing */
906                         if (def_symbol_in_progress != symbol_lastP) {
907                                 symbol_remove(def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
908                                 symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
909                         }       /* if not already in place */
910                 }               /* if function */
911         }                       /* normal or mergable */
912
913         if (SF_GET_TAG(def_symbol_in_progress)
914             && symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP) == NULL) {
915                 tag_insert(S_GET_NAME(def_symbol_in_progress), def_symbol_in_progress);
916         }                       /* If symbol is a {structure,union} tag, associate symbol to its name. */
917
918         if (SF_GET_FUNCTION(def_symbol_in_progress)) {
919                 know(sizeof(def_symbol_in_progress) <= sizeof(long));
920                 function_lineoff
921                     = c_line_new(def_symbol_in_progress,0, 0, &zero_address_frag);
922
923
924
925                 SF_SET_PROCESS(def_symbol_in_progress);
926
927                 if (symbolP == NULL) {
928                         /* That is, if this is the first
929                            time we've seen the function... */
930                         symbol_table_insert(def_symbol_in_progress);
931                 }               /* definition follows debug */
932         }                       /* Create the line number entry pointing to the function being defined */
933
934         def_symbol_in_progress = NULL;
935         demand_empty_rest_of_line();
936         return;
937 }                               /* obj_coff_endef() */
938
939 static void
940     DEFUN_VOID(obj_coff_dim)
941 {
942         register int dim_index;
943
944         if (def_symbol_in_progress == NULL)
945             {
946                     as_warn(".dim pseudo-op used outside of .def/.endef: ignored.");
947                     demand_empty_rest_of_line();
948                     return;
949             }                           /* if not inside .def/.endef */
950
951         S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
952
953         for (dim_index = 0; dim_index < DIMNUM; dim_index++)
954             {
955                     SKIP_WHITESPACES();
956                     SA_SET_SYM_DIMEN(def_symbol_in_progress, dim_index, get_absolute_expression());
957
958                     switch (*input_line_pointer)
959                         {
960
961                         case ',':
962                                 input_line_pointer++;
963                                 break;
964
965                         default:
966                                 as_warn("badly formed .dim directive ignored");
967                                 /* intentional fallthrough */
968                         case '\n':
969                         case ';':
970                                 dim_index = DIMNUM;
971                                 break;
972                         }                       /* switch on following character */
973             }                           /* for each dimension */
974
975         demand_empty_rest_of_line();
976         return;
977 }                               /* obj_coff_dim() */
978
979 static void obj_coff_line()
980 {
981         int this_base;
982
983         if (def_symbol_in_progress == NULL) {
984                 obj_coff_ln();
985                 return;
986         }                               /* if it looks like a stabs style line */
987
988         this_base = get_absolute_expression();
989         if (this_base > line_base)
990             {
991                     line_base = this_base;
992             }
993
994
995 #ifndef NO_LISTING
996         {
997                 extern int listing;
998                 if (listing && 0) {
999                         listing_source_line(line_base);
1000                 }
1001         }
1002 #endif
1003         S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1004         SA_SET_SYM_LNNO(def_symbol_in_progress, line_base);
1005
1006         demand_empty_rest_of_line();
1007         return;
1008 }                               /* obj_coff_line() */
1009
1010 static void obj_coff_size() {
1011         if (def_symbol_in_progress == NULL) {
1012                 as_warn(".size pseudo-op used outside of .def/.endef ignored.");
1013                 demand_empty_rest_of_line();
1014                 return;
1015         } /* if not inside .def/.endef */
1016
1017         S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1018         SA_SET_SYM_SIZE(def_symbol_in_progress, get_absolute_expression());
1019         demand_empty_rest_of_line();
1020         return;
1021 } /* obj_coff_size() */
1022
1023 static void obj_coff_scl() {
1024         if (def_symbol_in_progress == NULL) {
1025                 as_warn(".scl pseudo-op used outside of .def/.endef ignored.");
1026                 demand_empty_rest_of_line();
1027                 return;
1028         } /* if not inside .def/.endef */
1029
1030         S_SET_STORAGE_CLASS(def_symbol_in_progress, get_absolute_expression());
1031         demand_empty_rest_of_line();
1032         return;
1033 } /* obj_coff_scl() */
1034
1035 static void obj_coff_tag() {
1036         char *symbol_name;
1037         char name_end;
1038
1039         if (def_symbol_in_progress == NULL) {
1040                 as_warn(".tag pseudo-op used outside of .def/.endef ignored.");
1041                 demand_empty_rest_of_line();
1042                 return;
1043         } /* if not inside .def/.endef */
1044
1045         S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1046         symbol_name = input_line_pointer;
1047         name_end = get_symbol_end();
1048
1049         /* Assume that the symbol referred to by .tag is always defined. */
1050         /* This was a bad assumption.  I've added find_or_make. xoxorich. */
1051         SA_SET_SYM_TAGNDX(def_symbol_in_progress, (long) tag_find_or_make(symbol_name));
1052         if (SA_GET_SYM_TAGNDX(def_symbol_in_progress) == 0L) {
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         return;
1061 } /* obj_coff_tag() */
1062
1063 static void obj_coff_type() {
1064         if (def_symbol_in_progress == NULL) {
1065                 as_warn(".type pseudo-op used outside of .def/.endef ignored.");
1066                 demand_empty_rest_of_line();
1067                 return;
1068         } /* if not inside .def/.endef */
1069
1070         S_SET_DATA_TYPE(def_symbol_in_progress, get_absolute_expression());
1071
1072         if (ISFCN(S_GET_DATA_TYPE(def_symbol_in_progress)) &&
1073             S_GET_STORAGE_CLASS(def_symbol_in_progress) != C_TPDEF) {
1074                 SF_SET_FUNCTION(def_symbol_in_progress);
1075         } /* is a function */
1076
1077         demand_empty_rest_of_line();
1078         return;
1079 } /* obj_coff_type() */
1080
1081 static void obj_coff_val() {
1082         if (def_symbol_in_progress == NULL) {
1083                 as_warn(".val pseudo-op used outside of .def/.endef ignored.");
1084                 demand_empty_rest_of_line();
1085                 return;
1086         } /* if not inside .def/.endef */
1087
1088         if (is_name_beginner(*input_line_pointer)) {
1089                 char *symbol_name = input_line_pointer;
1090                 char name_end = get_symbol_end();
1091
1092                 if (!strcmp(symbol_name, ".")) {
1093                         def_symbol_in_progress->sy_frag = frag_now;
1094                         S_SET_VALUE(def_symbol_in_progress, obstack_next_free(&frags) - frag_now->fr_literal);
1095                         /* If the .val is != from the .def (e.g. statics) */
1096                 } else if (strcmp(S_GET_NAME(def_symbol_in_progress), symbol_name)) {
1097                         def_symbol_in_progress->sy_forward = symbol_find_or_make(symbol_name);
1098
1099                         /* If the segment is undefined when the forward
1100                            reference is solved, then copy the segment id
1101                            from the forward symbol. */
1102                         SF_SET_GET_SEGMENT(def_symbol_in_progress);
1103                 }
1104                 /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
1105                 *input_line_pointer = name_end;
1106         } else {
1107                 S_SET_VALUE(def_symbol_in_progress, get_absolute_expression());
1108         } /* if symbol based */
1109
1110         demand_empty_rest_of_line();
1111         return;
1112 } /* obj_coff_val() */
1113
1114 /*
1115  * Maintain a list of the tagnames of the structres.
1116  */
1117
1118 static void tag_init() {
1119         tag_hash = hash_new();
1120         return ;
1121 } /* tag_init() */
1122
1123 static void tag_insert(name, symbolP)
1124 char *name;
1125 symbolS *symbolP;
1126 {
1127         register char * error_string;
1128
1129         if (*(error_string = hash_jam(tag_hash, name, (char *)symbolP))) {
1130                 as_fatal("Inserting \"%s\" into structure table failed: %s",
1131                          name, error_string);
1132         }
1133         return ;
1134 } /* tag_insert() */
1135
1136 static symbolS *tag_find_or_make(name)
1137 char *name;
1138 {
1139         symbolS *symbolP;
1140
1141         if ((symbolP = tag_find(name)) == NULL) {
1142                 symbolP = symbol_new(name,
1143                                      SEG_UNKNOWN,
1144                                      0,
1145                                      &zero_address_frag);
1146
1147                 tag_insert(S_GET_NAME(symbolP), symbolP);
1148                 symbol_table_insert(symbolP);
1149         } /* not found */
1150
1151         return(symbolP);
1152 } /* tag_find_or_make() */
1153
1154 static symbolS *tag_find(name)
1155 char *name;
1156 {
1157 #ifdef STRIP_UNDERSCORE
1158         if (*name == '_') name++;
1159 #endif /* STRIP_UNDERSCORE */
1160         return((symbolS*)hash_find(tag_hash, name));
1161 } /* tag_find() */
1162
1163 void obj_read_begin_hook() {
1164         /* These had better be the same.  Usually 18 bytes. */
1165 #ifndef BFD_HEADERS
1166         know(sizeof(SYMENT) == sizeof(AUXENT));
1167         know(SYMESZ == AUXESZ);
1168 #endif
1169         tag_init();
1170
1171         return;
1172 } /* obj_read_begin_hook() */
1173
1174 /* This function runs through the symbol table and puts all the
1175    externals onto another chain */
1176
1177 /* The chain of externals */
1178 symbolS *symbol_externP = NULL;
1179 symbolS *symbol_extern_lastP = NULL;
1180
1181 stack*block_stack;
1182 symbolS *last_functionP = NULL;
1183 symbolS *last_tagP;
1184
1185
1186 static unsigned int DEFUN_VOID(yank_symbols)
1187 {
1188         symbolS *symbolP;
1189         unsigned int symbol_number =0;
1190
1191         for (symbolP = symbol_rootP;
1192              symbolP;
1193              symbolP = symbolP ? symbol_next(symbolP) : symbol_rootP) {
1194                 if (!SF_GET_DEBUG(symbolP)) {
1195                         /* Debug symbols do not need all this rubbish */
1196                         symbolS* real_symbolP;
1197
1198                         /* L* and C_EFCN symbols never merge. */
1199                         if (!SF_GET_LOCAL(symbolP)
1200                             && (real_symbolP = symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP))
1201                             && real_symbolP != symbolP) {
1202                                 /* FIXME-SOON: where do dups come from?
1203                                    Maybe tag references before definitions? xoxorich. */
1204                                 /* Move the debug data from the debug symbol to the
1205                                    real symbol. Do NOT do the oposite (i.e. move from
1206                                    real symbol to debug symbol and remove real symbol from the
1207                                    list.) Because some pointers refer to the real symbol
1208                                    whereas no pointers refer to the debug symbol. */
1209                                 c_symbol_merge(symbolP, real_symbolP);
1210                                 /* Replace the current symbol by the real one */
1211                                 /* The symbols will never be the last or the first
1212                                    because : 1st symbol is .file and 3 last symbols are
1213                                    .text, .data, .bss */
1214                                 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
1215                                 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
1216                                 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1217                                 symbolP = real_symbolP;
1218                         }                       /* if not local but dup'd */
1219
1220                         if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_E1)) {
1221                                 S_SET_SEGMENT(symbolP, SEG_E0);
1222                         }                       /* push data into text */
1223
1224                         S_SET_VALUE(symbolP,
1225                                     S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
1226
1227                         if (!S_IS_DEFINED(symbolP) && !SF_GET_LOCAL(symbolP))
1228                             {
1229                                     S_SET_EXTERNAL(symbolP);
1230                             }
1231                         else if (S_GET_STORAGE_CLASS(symbolP) == C_NULL)
1232                             {
1233                                     if (S_GET_SEGMENT(symbolP) == SEG_E0)
1234                                         {
1235                                                 S_SET_STORAGE_CLASS(symbolP, C_LABEL);
1236                                         }
1237                                     else
1238                                         {
1239                                                 S_SET_STORAGE_CLASS(symbolP, C_STAT);
1240                                         }
1241                             }
1242
1243                         /* Mainly to speed up if not -g */
1244                         if (SF_GET_PROCESS(symbolP))
1245                             {
1246                                     /* Handle the nested blocks auxiliary info. */
1247                                     if (S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
1248                                             if (!strcmp(S_GET_NAME(symbolP), ".bb"))
1249                                                 stack_push(block_stack, (char *) &symbolP);
1250                                             else {              /* .eb */
1251                                                     register symbolS* begin_symbolP;
1252                                                     begin_symbolP = *(symbolS**)stack_pop(block_stack);
1253                                                     if (begin_symbolP == (symbolS*)0)
1254                                                         as_warn("mismatched .eb");
1255                                                     else
1256                                                         SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number+2);
1257                                             }
1258                                     }
1259                                     /* If we are able to identify the type of a function, and we
1260                                        are out of a function (last_functionP == 0) then, the
1261                                        function symbol will be associated with an auxiliary
1262                                        entry. */
1263                                     if (last_functionP == (symbolS*)0 &&
1264                                         SF_GET_FUNCTION(symbolP)) {
1265                                             last_functionP = symbolP;
1266
1267                                             if (S_GET_NUMBER_AUXILIARY(symbolP) < 1) {
1268                                                     S_SET_NUMBER_AUXILIARY(symbolP, 1);
1269                                             }           /* make it at least 1 */
1270
1271                                             /* Clobber possible stale .dim information. */
1272                                             memset(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
1273                                                   '\0', sizeof(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
1274                                     }
1275                                     /* The C_FCN doesn't need any additional information.
1276                                        I don't even know if this is needed for sdb. But the
1277                                        standard assembler generates it, so...
1278                                        */
1279                                     if (S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
1280                                             if (last_functionP == (symbolS*)0)
1281                                                 as_fatal("C_EFCN symbol out of scope");
1282                                             SA_SET_SYM_FSIZE(last_functionP,
1283                                                              (long)(S_GET_VALUE(symbolP) -
1284                                                                     S_GET_VALUE(last_functionP)));
1285                                             SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
1286                                             last_functionP = (symbolS*)0;
1287                                     }
1288                             }
1289                 } else if (SF_GET_TAG(symbolP)) {
1290                         /* First descriptor of a structure must point to
1291                            the first slot after the structure description. */
1292                         last_tagP = symbolP;
1293
1294                 } else if (S_GET_STORAGE_CLASS(symbolP) == C_EOS) {
1295                         /* +2 take in account the current symbol */
1296                         SA_SET_SYM_ENDNDX(last_tagP, symbol_number + 2);
1297                 } else if (S_GET_STORAGE_CLASS(symbolP) == C_FILE) {
1298                         if (S_GET_VALUE(symbolP)) {
1299                                 S_SET_VALUE((symbolS *) S_GET_VALUE(symbolP), symbol_number);
1300                                 S_SET_VALUE(symbolP, 0);
1301                         }               /* no one points at the first .file symbol */
1302                 }                       /* if debug or tag or eos or file */
1303
1304                 /* We must put the external symbols apart. The loader
1305                    does not bomb if we do not. But the references in
1306                    the endndx field for a .bb symbol are not corrected
1307                    if an external symbol is removed between .bb and .be.
1308                    I.e in the following case :
1309                    [20] .bb endndx = 22
1310                    [21] foo external
1311                    [22] .be
1312                    ld will move the symbol 21 to the end of the list but
1313                    endndx will still be 22 instead of 21. */
1314
1315
1316                 if (SF_GET_LOCAL(symbolP)) {
1317                         /* remove C_EFCN and LOCAL (L...) symbols */
1318                         /* next pointer remains valid */
1319                         symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1320
1321                 }
1322                 else if (!S_IS_DEFINED(symbolP)
1323                          && !S_IS_DEBUG(symbolP)
1324                          && !SF_GET_STATICS(symbolP) &&
1325                          S_GET_STORAGE_CLASS(symbolP) == C_EXT)
1326                     { /* C_EXT && !SF_GET_FUNCTION(symbolP))  */
1327                             /* if external, Remove from the list */
1328                             symbolS *hold = symbol_previous(symbolP);
1329
1330                             symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1331                             symbol_clear_list_pointers(symbolP);
1332                             symbol_append(symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
1333                             symbolP = hold;
1334                     } else {
1335                             if (SF_GET_STRING(symbolP)) {
1336                                     symbolP->sy_name_offset = string_byte_count;
1337                                     string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
1338                             } else {
1339                                     symbolP->sy_name_offset = 0;
1340                             }           /* fix "long" names */
1341
1342                             symbolP->sy_number = symbol_number;
1343                             symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
1344                     }                   /* if local symbol */
1345         }                               /* traverse the symbol list */
1346         return symbol_number;
1347
1348 }
1349
1350
1351 static unsigned int DEFUN_VOID(glue_symbols)
1352 {
1353         unsigned int symbol_number = 0;
1354         symbolS *symbolP;
1355         for (symbolP = symbol_externP; symbol_externP;) {
1356                 symbolS *tmp = symbol_externP;
1357
1358                 /* append */
1359                 symbol_remove(tmp, &symbol_externP, &symbol_extern_lastP);
1360                 symbol_append(tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
1361
1362                 /* and process */
1363                 if (SF_GET_STRING(tmp)) {
1364                         tmp->sy_name_offset = string_byte_count;
1365                         string_byte_count += strlen(S_GET_NAME(tmp)) + 1;
1366                 } else {
1367                         tmp->sy_name_offset = 0;
1368                 }                       /* fix "long" names */
1369
1370                 tmp->sy_number = symbol_number;
1371                 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(tmp);
1372         }                               /* append the entire extern chain */
1373         return symbol_number;
1374
1375 }
1376
1377 static unsigned int DEFUN_VOID(tie_tags)
1378 {
1379         unsigned int symbol_number = 0;
1380
1381         symbolS*symbolP;
1382         for (symbolP = symbol_rootP; symbolP; symbolP =
1383              symbol_next(symbolP))
1384             {
1385                     symbolP->sy_number = symbol_number;
1386
1387
1388
1389                     if (SF_GET_TAGGED(symbolP))
1390                         {
1391                                 SA_SET_SYM_TAGNDX
1392                                     (symbolP,
1393                                      ((symbolS*) SA_GET_SYM_TAGNDX(symbolP))->sy_number);
1394                         }
1395
1396                     symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
1397             }
1398         return symbol_number;
1399
1400 }
1401
1402 static void
1403     DEFUN(crawl_symbols,(headers, abfd),
1404           struct    internal_filehdr *headers AND
1405           bfd *abfd)
1406 {
1407
1408         unsigned int i;
1409         unsigned int ptr = 0;
1410
1411
1412         symbolS *symbolP;
1413
1414         /* Initialize the stack used to keep track of the matching .bb .be */
1415
1416         block_stack = stack_init(512, sizeof(symbolS*));
1417         /* JF deal with forward references first... */
1418         for (symbolP = symbol_rootP;
1419              symbolP;
1420              symbolP = symbol_next(symbolP))
1421             {
1422
1423                     if (symbolP->sy_forward) {
1424                             S_SET_VALUE(symbolP, (S_GET_VALUE(symbolP)
1425                                                   + S_GET_VALUE(symbolP->sy_forward)
1426                                                   + symbolP->sy_forward->sy_frag->fr_address));
1427
1428                             if (SF_GET_GET_SEGMENT(symbolP)) {
1429                                     S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
1430                             }                   /* forward segment also */
1431
1432                             symbolP->sy_forward=0;
1433                     }                           /* if it has a forward reference */
1434             }                           /* walk the symbol chain */
1435
1436
1437         /* The symbol list should be ordered according to the following sequence
1438          * order :
1439          * . .file symbol
1440          * . debug entries for functions
1441          * . fake symbols for the sections, including.text .data and .bss
1442          * . defined symbols
1443          * . undefined symbols
1444          * But this is not mandatory. The only important point is to put the
1445          * undefined symbols at the end of the list.
1446          */
1447
1448         if (symbol_rootP == NULL
1449             || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
1450                 c_dot_file_symbol("fake");
1451         }
1452         /* Is there a .file symbol ? If not insert one at the beginning. */
1453
1454         /*
1455          * Build up static symbols for the sections, they are filled in later
1456          */
1457
1458
1459         for (i = SEG_E0; i < SEG_E9; i++)
1460             {
1461                     if (segment_info[i].scnhdr.s_name[0])
1462                         {
1463                                 segment_info[i].dot =
1464                                     c_section_symbol(segment_info[i].scnhdr.s_name,
1465                                                      i-SEG_E0+1);
1466
1467                         }
1468             }
1469
1470
1471         /* Take all the externals out and put them into another chain */
1472         headers->f_nsyms =   yank_symbols();
1473         /* Take the externals and glue them onto the end.*/
1474         headers->f_nsyms +=  glue_symbols();
1475
1476         headers->f_nsyms =   tie_tags();
1477         know(symbol_externP == NULL);
1478         know(symbol_extern_lastP == NULL);
1479
1480         return;
1481 }
1482
1483 /*
1484  * Find strings by crawling along symbol table chain.
1485  */
1486
1487 void DEFUN(w_strings,(where),
1488            char *where)
1489 {
1490         symbolS *symbolP;
1491
1492         /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
1493         md_number_to_chars(where, string_byte_count, sizeof(string_byte_count));
1494         where += sizeof(string_byte_count);
1495         for (symbolP = symbol_rootP;
1496              symbolP;
1497              symbolP = symbol_next(symbolP))
1498             {
1499                     unsigned int size;
1500
1501                     if (SF_GET_STRING(symbolP)) {
1502                             size = strlen(S_GET_NAME(symbolP)) + 1;
1503
1504                             memcpy(where,  S_GET_NAME(symbolP),size);
1505                             where += size;
1506
1507                     }
1508             }
1509
1510 }
1511
1512
1513
1514
1515
1516 static void
1517     DEFUN(do_linenos_for,(abfd, file_cursor),
1518           bfd *abfd AND
1519           unsigned long *file_cursor)
1520 {
1521         unsigned int idx;
1522
1523         for (idx = SEG_E0;  idx < SEG_E9; idx++)
1524             {
1525                     segment_info_type *s = segment_info + idx;
1526
1527
1528                     if (s->scnhdr.s_nlnno != 0)
1529                         {
1530                                 struct lineno_list *line_ptr ;
1531
1532                                 struct external_lineno *buffer =
1533                                     (struct external_lineno *)xmalloc(s->scnhdr.s_nlnno * LINESZ);
1534
1535                                 struct external_lineno *dst= buffer;
1536
1537                                 /* Run through the table we've built and turn it into its external
1538                                    form, take this chance to remove duplicates */
1539
1540                                 for (line_ptr = s->lineno_list_head;
1541                                      line_ptr != (struct lineno_list *)NULL;
1542                                      line_ptr = line_ptr->next)
1543                                     {
1544
1545                                             if (line_ptr->line.l_lnno == 0)
1546                                                 {
1547                                                         /* Turn a pointer to a symbol into the symbols' index */
1548                                                         line_ptr->line.l_addr.l_symndx =
1549                                                             ( (symbolS *)line_ptr->line.l_addr.l_symndx)->sy_number;
1550                                                 }
1551                                             else
1552                                                 {
1553                                                         line_ptr->line.l_addr.l_paddr += ((struct frag * )(line_ptr->frag))->fr_address;
1554                                                 }
1555
1556
1557                                             (void)  bfd_coff_swap_lineno_out(abfd, &(line_ptr->line), dst);
1558                                             dst++;
1559
1560                                     }
1561
1562                                 s->scnhdr.s_lnnoptr = *file_cursor;
1563
1564                                 bfd_write(buffer, 1, s->scnhdr.s_nlnno* LINESZ, abfd);
1565                                 free(buffer);
1566
1567                                 *file_cursor += s->scnhdr.s_nlnno * LINESZ;
1568                         }
1569             }
1570 }
1571
1572
1573 /* Now we run through the list of frag chains in a segment and
1574    make all the subsegment frags appear at the end of the
1575    list, as if the seg 0 was extra long */
1576
1577 static void DEFUN_VOID(remove_subsegs)
1578 {
1579         unsigned int i;
1580
1581         for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1582             {
1583                     frchainS *head =  segment_info[i].frchainP;
1584                     fragS dummy;
1585                     fragS * prev_frag = &dummy;
1586
1587                     while (head && head->frch_seg == i)
1588                         {
1589                                 prev_frag->fr_next = head->frch_root;
1590                                 prev_frag = head->frch_last;
1591                                 head = head->frch_next;
1592                         }
1593                     prev_frag->fr_next = 0;
1594             }
1595 }
1596
1597
1598 extern void DEFUN_VOID(write_object_file)
1599 {
1600         int i;
1601         struct frchain *frchain_ptr;
1602
1603         struct internal_filehdr filehdr;
1604         struct internal_aouthdr aouthdr;
1605         unsigned long file_cursor;
1606         bfd *abfd;
1607         unsigned int addr = 0;
1608         abfd = bfd_openw(out_file_name, TARGET_FORMAT);
1609
1610
1611         if (abfd == 0) {
1612                 as_perror ("FATAL: Can't create %s", out_file_name);
1613                 exit(42);
1614         }
1615         bfd_set_format(abfd, bfd_object);
1616         bfd_set_arch_mach(abfd, BFD_ARCH, 0);
1617
1618
1619
1620         string_byte_count = 4;
1621
1622         for (frchain_ptr = frchain_root;
1623              frchain_ptr != (struct frchain *)NULL;
1624              frchain_ptr = frchain_ptr->frch_next) {
1625                 /* Run through all the sub-segments and align them up. Also close any
1626                    open frags. We tack a .fill onto the end of the frag chain so
1627                    that any .align's size can be worked by looking at the next
1628                    frag */
1629
1630                 subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
1631 #define SUB_SEGMENT_ALIGN 1
1632                 frag_align(SUB_SEGMENT_ALIGN,0);
1633                 frag_wane(frag_now);
1634                 frag_now->fr_fix = 0;
1635                 know( frag_now->fr_next == NULL );
1636         }
1637
1638
1639         remove_subsegs();
1640
1641
1642         for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1643             {
1644                     relax_segment(segment_info[i].frchainP->frch_root, i);
1645             }
1646
1647
1648
1649
1650
1651         filehdr.f_nscns = 0;
1652
1653         /* Find out how big the sections are */
1654         for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1655             {
1656
1657                     if (segment_info[i].scnhdr.s_name[0])
1658                         {
1659                                 filehdr.f_nscns++;
1660                         }
1661                     segment_info[i].scnhdr.s_paddr = addr;
1662                     if (i == SEG_E2) {
1663                             /* THis is a special case, we leave the size alone, which will have */
1664                             /* been made up from all and any lcomms seen */
1665                     }
1666                     else {
1667                             addr += size_section(abfd, i);
1668                     }
1669             }
1670
1671
1672
1673         /* Turn the gas native symbol table shape into a coff symbol table */
1674         crawl_symbols(&filehdr, abfd);
1675 #ifndef TC_H8300
1676         for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1677             {
1678                     fixup_segment(segment_info[i].fix_root, i);
1679             }
1680 #endif
1681
1682         file_cursor =   FILHSZ + SCNHSZ * filehdr.f_nscns ;
1683
1684         bfd_seek(abfd, file_cursor, 0);
1685
1686
1687         do_relocs_for(abfd, &file_cursor);
1688
1689         do_linenos_for(abfd, &file_cursor);
1690
1691
1692         /* Plant the data */
1693
1694         fill_section(abfd,&filehdr, &file_cursor);
1695
1696         filehdr.f_magic = COFF_MAGIC;
1697         filehdr.f_timdat = 0;
1698         filehdr.f_flags = 0;
1699
1700
1701
1702         {
1703
1704                 unsigned int   symtable_size = filehdr.f_nsyms * SYMESZ;
1705                 char *buffer1 = malloc(symtable_size + string_byte_count + 4);
1706                 char *ptr = buffer1;
1707                 filehdr.f_symptr = bfd_tell(abfd);
1708                 w_symbols(abfd, buffer1, symbol_rootP);
1709                 w_strings(buffer1 + symtable_size);
1710                 bfd_write(buffer1, 1,symtable_size +  string_byte_count + 4, abfd);
1711                 free(buffer1);
1712
1713         }
1714         coff_header_append(abfd, &filehdr, &aouthdr);
1715
1716         bfd_close_all_done(abfd);
1717 }
1718
1719
1720 static void DEFUN(change_to_section,(name, len, exp),
1721                   char *name AND
1722                   unsigned int len AND
1723                   unsigned int exp)
1724 {
1725         unsigned int i;
1726         /* Find out if we've already got a section of this name etc */
1727         for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0] ; i++)
1728             {
1729                     if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0)
1730                         {
1731                                 subseg_new(i, exp);
1732                                 return;
1733
1734                         }
1735             }
1736         /* No section, add one */
1737         strncpy(segment_info[i].scnhdr.s_name, name, 8);
1738         subseg_new(i, exp);
1739 }
1740
1741 static void
1742     DEFUN_VOID(obj_coff_section)
1743 {
1744         /* Strip out the section name */
1745         char *section_name ;
1746         char *section_name_end;
1747         char c;
1748
1749         unsigned int len;
1750         unsigned int exp;
1751
1752         section_name =  input_line_pointer;
1753         c =   get_symbol_end();
1754         section_name_end =  input_line_pointer;
1755
1756         len = section_name_end - section_name ;
1757         input_line_pointer++;
1758         SKIP_WHITESPACE();
1759         if (c == ',')
1760             {
1761                     exp = get_absolute_expression();
1762             }
1763         else if ( *input_line_pointer == ',')
1764             {
1765
1766                     input_line_pointer++;
1767                     exp = get_absolute_expression();
1768             }
1769         else
1770             {
1771                     exp = 0;
1772             }
1773
1774         change_to_section(section_name, len,exp);
1775         *section_name_end = c;
1776
1777 }
1778
1779
1780 static void obj_coff_text()
1781 {
1782         change_to_section(".text",5, get_absolute_expression());
1783 }
1784
1785
1786 static void obj_coff_data()
1787 {
1788         change_to_section(".data",5, get_absolute_expression());
1789 }
1790
1791 void c_symbol_merge(debug, normal)
1792 symbolS *debug;
1793 symbolS *normal;
1794 {
1795         S_SET_DATA_TYPE(normal, S_GET_DATA_TYPE(debug));
1796         S_SET_STORAGE_CLASS(normal, S_GET_STORAGE_CLASS(debug));
1797
1798         if (S_GET_NUMBER_AUXILIARY(debug) > S_GET_NUMBER_AUXILIARY(normal)) {
1799                 S_SET_NUMBER_AUXILIARY(normal, S_GET_NUMBER_AUXILIARY(debug));
1800         } /* take the most we have */
1801
1802         if (S_GET_NUMBER_AUXILIARY(debug) > 0) {
1803                 memcpy((char*)&normal->sy_symbol.ost_auxent[0], (char*)&debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
1804         } /* Move all the auxiliary information */
1805
1806         /* Move the debug flags. */
1807         SF_SET_DEBUG_FIELD(normal, SF_GET_DEBUG_FIELD(debug));
1808 } /* c_symbol_merge() */
1809
1810 static int
1811     DEFUN(c_line_new,(symbol, paddr, line_number, frag),
1812           symbolS *symbol AND
1813           long paddr AND
1814           unsigned short line_number AND
1815           fragS* frag)
1816 {
1817         struct lineno_list* new_line =
1818             (struct lineno_list *)xmalloc(sizeof(struct lineno_list));
1819
1820         segment_info_type *s =   segment_info + now_seg;
1821         new_line->line.l_lnno = line_number;
1822
1823         if (line_number == 0)
1824             {
1825                     new_line->line.l_addr.l_symndx = (long)symbol;
1826             }
1827         else
1828             {
1829                     new_line->line.l_addr.l_paddr = paddr;
1830             }
1831
1832         new_line->frag = (char*)frag;
1833         new_line->next = (struct lineno_list*)NULL;
1834
1835
1836         if (s->lineno_list_head == (struct lineno_list *)NULL)
1837             {
1838                     s->lineno_list_head = new_line;
1839             }
1840         else
1841             {
1842                     s->lineno_list_tail->next = new_line;
1843             }
1844         s->lineno_list_tail = new_line;
1845         return LINESZ * s->scnhdr.s_nlnno ++;
1846 }
1847
1848 void c_dot_file_symbol(filename)
1849 char *filename;
1850 {
1851         symbolS* symbolP;
1852
1853         symbolP = symbol_new(".file",
1854                              SEG_DEBUG,
1855                              0,
1856                              &zero_address_frag);
1857
1858         S_SET_STORAGE_CLASS(symbolP, C_FILE);
1859         S_SET_NUMBER_AUXILIARY(symbolP, 1);
1860         SA_SET_FILE_FNAME(symbolP, filename);
1861 #ifndef NO_LISTING
1862         {
1863                 extern int listing;
1864                 if (listing)
1865                     {
1866                             listing_source_file(filename);
1867                     }
1868
1869         }
1870
1871 #endif
1872         SF_SET_DEBUG(symbolP);
1873         S_SET_VALUE(symbolP, (long) previous_file_symbol);
1874
1875         previous_file_symbol = symbolP;
1876
1877         /* Make sure that the symbol is first on the symbol chain */
1878         if (symbol_rootP != symbolP) {
1879                 if (symbolP == symbol_lastP) {
1880                         symbol_lastP = symbol_lastP->sy_previous;
1881                 } /* if it was the last thing on the list */
1882
1883                 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1884                 symbol_insert(symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
1885                 symbol_rootP = symbolP;
1886         } /* if not first on the list */
1887
1888 } /* c_dot_file_symbol() */
1889
1890 /*
1891  * Build a 'section static' symbol.
1892  */
1893
1894 symbolS *c_section_symbol(name,idx)
1895 char *name;
1896 int idx;
1897 {
1898         symbolS *symbolP;
1899
1900         symbolP = symbol_new(name,idx,
1901                              0,
1902                              &zero_address_frag);
1903
1904         S_SET_STORAGE_CLASS(symbolP, C_STAT);
1905         S_SET_NUMBER_AUXILIARY(symbolP, 1);
1906
1907         SF_SET_STATICS(symbolP);
1908
1909         return symbolP;
1910 } /* c_section_symbol() */
1911
1912 static void
1913     DEFUN(w_symbols,(abfd, where, symbol_rootP),
1914           bfd *abfd AND
1915           char *where AND
1916           symbolS *symbol_rootP)
1917 {
1918         symbolS *symbolP;
1919         unsigned int i;
1920
1921         /* First fill in those values we have only just worked out */
1922         for (i = SEG_E0; i < SEG_E9; i++)
1923             {
1924                     symbolP = segment_info[i].dot;
1925                     if (symbolP)
1926                         {
1927
1928                                 SA_SET_SCN_SCNLEN(symbolP, segment_info[i].scnhdr.s_size);
1929                                 SA_SET_SCN_NRELOC(symbolP, segment_info[i].scnhdr.s_nreloc);
1930                                 SA_SET_SCN_NLINNO(symbolP, segment_info[i].scnhdr.s_nlnno);
1931
1932                         }
1933             }
1934
1935         /*
1936          * Emit all symbols left in the symbol chain.
1937          */
1938         for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
1939                 /* Used to save the offset of the name. It is used to point
1940                    to the string in memory but must be a file offset. */
1941                 register char * temp;
1942
1943                 tc_coff_symbol_emit_hook(symbolP);
1944
1945                 temp = S_GET_NAME(symbolP);
1946                 if (SF_GET_STRING(symbolP)) {
1947                         S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
1948                         S_SET_ZEROES(symbolP, 0);
1949                 } else {
1950                         memset(symbolP->sy_symbol.ost_entry.n_name, '\0', SYMNMLEN);
1951                         strncpy(symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
1952                 }
1953                 where =  symbol_to_chars(abfd, where, symbolP);
1954                 S_SET_NAME(symbolP,temp);
1955         }
1956
1957 }                               /* w_symbols() */
1958
1959 static void DEFUN_VOID(obj_coff_lcomm)
1960 {
1961         char *name;
1962         char c;
1963         int temp;
1964         char *p;
1965         symbolS *symbolP;
1966         name = input_line_pointer;
1967
1968
1969
1970         c = get_symbol_end();
1971         p = input_line_pointer;
1972         *p = c;
1973         SKIP_WHITESPACE();
1974         if (*input_line_pointer != ',') {
1975                 as_bad("Expected comma after name");
1976                 ignore_rest_of_line();
1977                 return;
1978         }
1979         if (*input_line_pointer == '\n') {
1980                 as_bad("Missing size expression");
1981                 return;
1982         }
1983         input_line_pointer++;
1984         if ((temp = get_absolute_expression ()) < 0) {
1985                 as_warn("lcomm length (%d.) <0! Ignored.", temp);
1986                 ignore_rest_of_line();
1987                 return;
1988         }
1989         *p = 0;
1990         symbolP = symbol_find_or_make(name);
1991         S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
1992         S_SET_SEGMENT(symbolP, SEG_E2);
1993         segment_info[SEG_E2].scnhdr.s_size += temp;
1994         S_SET_STORAGE_CLASS(symbolP, C_STAT);
1995         demand_empty_rest_of_line();
1996 }
1997
1998
1999 #if 1
2000 static void DEFUN(fixup_segment,(fixP, this_segment_type),
2001                   register fixS *       fixP AND
2002                   segT          this_segment_type)
2003 {
2004         register symbolS *add_symbolP;
2005         register symbolS *sub_symbolP;
2006         register long add_number;
2007         register int size;
2008         register char *place;
2009         register long where;
2010         register char pcrel;
2011         register fragS *fragP;
2012         register segT add_symbol_segment = SEG_ABSOLUTE;
2013
2014
2015         for ( ;  fixP;  fixP = fixP->fx_next)
2016             {
2017                     fragP       = fixP->fx_frag;
2018                     know(fragP);
2019                     where         = fixP->fx_where;
2020                     place       = fragP->fr_literal + where;
2021                     size          = fixP->fx_size;
2022                     add_symbolP = fixP->fx_addsy;
2023 #ifdef TC_I960
2024                     if (fixP->fx_callj && TC_S_IS_CALLNAME(add_symbolP)) {
2025                             /* Relocation should be done via the
2026                                associated 'bal' entry point
2027                                symbol. */
2028
2029                             if (!TC_S_IS_BALNAME(tc_get_bal_of_call(add_symbolP))) {
2030                                     as_bad("No 'bal' entry point for leafproc %s",
2031                                            S_GET_NAME(add_symbolP));
2032                                     continue;
2033                             }
2034                             fixP->fx_addsy = add_symbolP = tc_get_bal_of_call(add_symbolP);
2035                     }                   /* callj relocation */
2036 #endif
2037                     sub_symbolP = fixP->fx_subsy;
2038                     add_number  = fixP->fx_offset;
2039                     pcrel         = fixP->fx_pcrel;
2040
2041                     if (add_symbolP) {
2042                             add_symbol_segment = S_GET_SEGMENT(add_symbolP);
2043                     }                   /* if there is an addend */
2044
2045                     if (sub_symbolP) {
2046                             if (!add_symbolP) {
2047                                     /* Its just -sym */
2048                                     if (S_GET_SEGMENT(sub_symbolP) != SEG_ABSOLUTE) {
2049                                             as_bad("Negative of non-absolute symbol %s", S_GET_NAME(sub_symbolP));
2050                                     }   /* not absolute */
2051
2052                                     add_number -= S_GET_VALUE(sub_symbolP);
2053
2054                                     /* if sub_symbol is in the same segment that add_symbol
2055                                        and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
2056                             } else if ((S_GET_SEGMENT(sub_symbolP) == add_symbol_segment)
2057                                        && (SEG_NORMAL(add_symbol_segment)
2058                                            || (add_symbol_segment == SEG_ABSOLUTE))) {
2059                                     /* Difference of 2 symbols from same segment. */
2060                                     /* Can't make difference of 2 undefineds: 'value' means */
2061                                     /* something different for N_UNDF. */
2062 #ifdef TC_I960
2063                                     /* Makes no sense to use the difference of 2 arbitrary symbols
2064                                      * as the target of a call instruction.
2065                                      */
2066                                     if (fixP->fx_callj) {
2067                                             as_bad("callj to difference of 2 symbols");
2068                                     }
2069 #endif                          /* TC_I960 */
2070                                     add_number += S_GET_VALUE(add_symbolP) -
2071                                         S_GET_VALUE(sub_symbolP);
2072
2073                                     add_symbolP = NULL;
2074                                     fixP->fx_addsy = NULL;
2075                             } else {
2076                                     /* Different segments in subtraction. */
2077                                     know(!(S_IS_EXTERNAL(sub_symbolP) && (S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)));
2078
2079                                     if ((S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)) {
2080                                             add_number -= S_GET_VALUE(sub_symbolP);
2081                                     } else {
2082                                             as_bad("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
2083                                                    segment_name(S_GET_SEGMENT(sub_symbolP)),
2084                                                    S_GET_NAME(sub_symbolP), fragP->fr_address + where);
2085                                     } /* if absolute */
2086                             }
2087                     }                   /* if sub_symbolP */
2088
2089                     if (add_symbolP) {
2090                             if (add_symbol_segment == this_segment_type && pcrel) {
2091                                     /*
2092                                      * This fixup was made when the symbol's segment was
2093                                      * SEG_UNKNOWN, but it is now in the local segment.
2094                                      * So we know how to do the address without relocation.
2095                                      */
2096 #ifdef TC_I960
2097                                     /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
2098                                      * in which cases it modifies *fixP as appropriate.  In the case
2099                                      * of a 'calls', no further work is required, and *fixP has been
2100                                      * set up to make the rest of the code below a no-op.
2101                                      */
2102                                     reloc_callj(fixP);
2103 #endif                          /* TC_I960 */
2104
2105                                     add_number += S_GET_VALUE(add_symbolP);
2106                                     add_number -= md_pcrel_from (fixP);
2107                                     pcrel = 0; /* Lie. Don't want further pcrel processing. */
2108                                     fixP->fx_addsy = NULL; /* No relocations please. */
2109                             } else
2110                                 {
2111                                         switch (add_symbol_segment)
2112                                             {
2113                                             case SEG_ABSOLUTE:
2114 #ifdef TC_I960
2115                                                     reloc_callj(fixP); /* See comment about reloc_callj() above*/
2116 #endif                          /* TC_I960 */
2117                                                     add_number += S_GET_VALUE(add_symbolP);
2118                                                     fixP->fx_addsy = NULL;
2119                                                     add_symbolP = NULL;
2120                                                     break;
2121                                             default:
2122
2123                                                     add_number += S_GET_VALUE(add_symbolP) +
2124                                                         segment_info[S_GET_SEGMENT(add_symbolP)].scnhdr.s_paddr ;
2125                                                     break;
2126
2127                                             case SEG_UNKNOWN:
2128 #ifdef TC_I960
2129                                                     if ((int)fixP->fx_bit_fixP == 13) {
2130                                                             /* This is a COBR instruction.  They have only a
2131                                                              * 13-bit displacement and are only to be used
2132                                                              * for local branches: flag as error, don't generate
2133                                                              * relocation.
2134                                                              */
2135                                                             as_bad("can't use COBR format with external label");
2136                                                             fixP->fx_addsy = NULL; /* No relocations please. */
2137                                                             continue;
2138                                                     } /* COBR */
2139 #endif                          /* TC_I960 */
2140
2141
2142
2143                                                     break;
2144
2145
2146                                             }   /* switch on symbol seg */
2147                                 }               /* if not in local seg */
2148                     }                   /* if there was a + symbol */
2149
2150                     if (pcrel) {
2151                             add_number -= md_pcrel_from(fixP);
2152                             if (add_symbolP == 0) {
2153                                     fixP->fx_addsy = & abs_symbol;
2154                             }           /* if there's an add_symbol */
2155                     }                   /* if pcrel */
2156
2157                     if (!fixP->fx_bit_fixP) {
2158                             if ((size == 1
2159                                  && (add_number & ~0xFF) && (add_number & ~0xFF != (-1 & ~0xFF))) ||
2160                                 (size == 2
2161                                  && (add_number & ~0xFFFF) && (add_number & ~0xFFFF != (-1 & ~0xFFFF)))) {
2162                                     as_bad("Value of %d too large for field of %d bytes at 0x%x",
2163                                            add_number, size, fragP->fr_address + where);
2164                             }           /* generic error checking */
2165                     }                   /* not a bit fix */
2166                     /* once this fix has been applied, we don't have to output anything
2167                        nothing more need be done -*/
2168                     md_apply_fix(fixP, add_number);
2169
2170             }                           /* For each fixS in this segment. */
2171
2172
2173 } /* fixup_segment() */
2174 #endif
2175
2176 /*
2177  * Local Variables:
2178  * fill-column: 131
2179  * End:
2180  */
2181
2182 /* end of obj-coffbfd.c */