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