From 23de7ff6f56bea5d28d7263a62343641a0aa1cbc Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Tue, 26 Nov 1991 02:16:53 +0000 Subject: [PATCH] Initial revision --- gas/config/obj-coff-bfd.c | 2184 +++++++++++++++++++++++++++++++++++++ gas/config/obj-coff-bfd.h | 558 ++++++++++ 2 files changed, 2742 insertions(+) create mode 100755 gas/config/obj-coff-bfd.c create mode 100755 gas/config/obj-coff-bfd.h diff --git a/gas/config/obj-coff-bfd.c b/gas/config/obj-coff-bfd.c new file mode 100755 index 00000000000..ed256830908 --- /dev/null +++ b/gas/config/obj-coff-bfd.c @@ -0,0 +1,2184 @@ + +/* coff object file format + Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. + +This file is part of GAS. + +GAS is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GAS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + + How does this releate to the rest of GAS ? + + Well, all the other files in gas are more or less a black box. It + takes care of openning files, parsing command lines, stripping blanks + etc etc. This module gets a chance to register what it wants to do by + saying that it is interested in various pseduo ops. The other big + change is write_object_file. This runs through all the data + structures that gas builds, and outputs the file in the format of our + choice. + + + Hacked for BFDness by steve chamberlain + sac@cygnus.com +*/ + +#include "as.h" +#include "obstack.h" +#include "subsegs.h" +#include "frags.h" + + + + + +/* This vector is used to turn an internal segment into a section # + suitable for insertion into a coff symbol table +*/ + +const short seg_N_TYPE[] = { /* in: segT out: N_TYPE bits */ + C_ABS_SECTION, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + C_UNDEF_SECTION, /* SEG_UNKNOWN */ + C_UNDEF_SECTION, /* SEG_ABSENT */ + C_UNDEF_SECTION, /* SEG_PASS1 */ + C_UNDEF_SECTION, /* SEG_GOOF */ + C_UNDEF_SECTION, /* SEG_BIG */ + C_UNDEF_SECTION, /* SEG_DIFFERENCE */ + C_DEBUG_SECTION, /* SEG_DEBUG */ + C_NTV_SECTION, /* SEG_NTV */ + C_PTV_SECTION, /* SEG_PTV */ + C_REGISTER_SECTION, /* SEG_REGISTER */ +}; + +int function_lineoff = -1; /* Offset in line#s where the last function + started (the odd entry for line #0) */ + +int our_lineno_number = 0; /* we use this to build pointers from .bf's + into the linetable. It should match + exactly the values that are later + assigned in text_lineno_number by + write.c. */ + +int text_lineno_number = 0; + +/* Add 4 to the real value to get the index and compensate the + negatives. This vector is used by S_GET_SEGMENT to turn a coff + section number into a segment number +*/ +static symbolS *previous_file_symbol = NULL; +void c_symbol_merge(); + +symbolS *c_section_symbol(); +bfd *abfd; +void EXFUN(bfd_as_write_hook,(struct internal_filehdr *, + bfd *abfd)); + +static void EXFUN(fill_section,(bfd *abfd , + struct internal_filehdr *f, unsigned + long *)); + + +char *EXFUN(s_get_name,(symbolS *s)); +static symbolS *EXFUN(tag_find_or_make,(char *name)); +static symbolS* EXFUN(tag_find,(char *name)); + + +static void EXFUN(w_symbols,( +bfd *abfd , +char **where , + symbolS *symbol_rootP)); + + + +static void EXFUN( obj_coff_def,(int what)); +static void EXFUN( obj_coff_lcomm,(void)); +static void EXFUN( obj_coff_dim,(void)); +static void EXFUN( obj_coff_text,(void)); +static void EXFUN( obj_coff_data,(void)); +static void EXFUN( obj_coff_endef,(void)); +static void EXFUN( obj_coff_line,(void)); +static void EXFUN( obj_coff_ln,(void)); +static void EXFUN( obj_coff_scl,(void)); +static void EXFUN( obj_coff_size,(void)); +static void EXFUN( obj_coff_stab,(int what)); +static void EXFUN( obj_coff_tag,(void)); +static void EXFUN( obj_coff_type,(void)); +static void EXFUN( obj_coff_val,(void)); +static void EXFUN( obj_coff_section,(void)); +static void EXFUN( tag_init,(void)); +static void EXFUN( tag_insert,(char *name, symbolS *symbolP)); + + +static struct hash_control *tag_hash; +static symbolS *def_symbol_in_progress = NULL; + +const pseudo_typeS obj_pseudo_table[] = { + { "def", obj_coff_def, 0 }, + { "dim", obj_coff_dim, 0 }, + { "endef", obj_coff_endef, 0 }, + { "line", obj_coff_line, 0 }, + { "ln", obj_coff_ln, 0 }, + { "scl", obj_coff_scl, 0 }, + { "size", obj_coff_size, 0 }, + { "tag", obj_coff_tag, 0 }, + { "type", obj_coff_type, 0 }, + { "val", obj_coff_val, 0 }, + { "section", obj_coff_section, 0 }, + { "text", obj_coff_text, 0 }, + { "data", obj_coff_data, 0 }, + + { "ident", s_ignore, 0 }, /* we don't yet handle this. */ + { "ABORT", s_abort, 0 }, + { "lcomm", obj_coff_lcomm, 0}, + { NULL} /* end sentinel */ +}; /* obj_pseudo_table */ + + + +/* Section stuff + + We allow more than just the standard 3 sections, infact, we allow + 10 sections, (though the usual three have to be there). + + This structure performs the mappings for us: + +*/ + +/* OBS stuff +static struct internal_scnhdr bss_section_header; +struct internal_scnhdr data_section_header; +struct internal_scnhdr text_section_header; + +const segT N_TYPE_seg [32] = +{ + +}; + +*/ + +#define N_SEG 32 +typedef struct +{ + segT seg_t; +int i; +} seg_info_type; + +seg_info_type seg_info_off_by_4[N_SEG] = +{ +{SEG_PTV, }, +{SEG_NTV, }, +{SEG_DEBUG, }, +{SEG_ABSOLUTE, }, +{SEG_UNKNOWN, }, +{SEG_E0}, +{SEG_E1}, +{SEG_E2}, +{SEG_E3}, +{SEG_E4}, +{SEG_E5}, +{SEG_E6}, +{SEG_E7}, +{SEG_E8}, +{SEG_E9}, +{SEG_REGISTER}, + +}; + +#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4]) +#define SEG_INFO_FROM_SEG_NUMBER(x) (seg_info_off_by_4[(x)]) + + +static relax_addressT +DEFUN(relax_align,(address, alignment), +register relax_addressT address AND +register long alignment ) +{ + relax_addressT mask; + relax_addressT new_address; + + mask = ~ ( (~0) << alignment ); + new_address = (address + mask) & (~ mask); + return (new_address - address); +} /* relax_align() */ + + +segT +DEFUN(s_get_segment,(x) , +symbolS* x) +{ + return SEG_INFO_FROM_SECTION_NUMBER(x->sy_symbol.ost_entry.n_scnum).seg_t; +} + + + +/* calculate the size of the frag chain and fill in the section header + to contain all of it, also fill in the addr of the sections */ +static unsigned int DEFUN(size_section,(abfd, idx), + bfd *abfd AND + unsigned int idx) +{ + asection *sec; + unsigned int size = 0; + fragS *frag = segment_info[idx].frag_root; + while (frag) { + if (frag->fr_address != size) { + printf("Out of step\n"); + size = frag->fr_address; + } + size += frag->fr_fix; + switch (frag->fr_type) { + case rs_fill: + case rs_org: + size += frag->fr_offset * frag->fr_var; + break; + case rs_align: + size += relax_align(size, frag->fr_offset); + } + frag = frag->fr_next; + } + segment_info[idx].scnhdr.s_size = size; + return size; +} + +/* Count the relocations in a chain */ + +static unsigned int DEFUN(count_entries_in_chain,(idx), + unsigned int idx) +{ + unsigned int nrelocs; + fixS *fixup_ptr; + + /* Count the relocations */ + fixup_ptr = segment_info[idx].fix_root; + nrelocs = 0; + while (fixup_ptr != (fixS *)NULL) + { + nrelocs ++ ; + fixup_ptr = fixup_ptr->fx_next; + + } + return nrelocs; +} + +/* output all the relocations for a section */ +void DEFUN(do_relocs_for,(abfd, file_cursor), + bfd *abfd AND + unsigned long *file_cursor) +{ + unsigned int nrelocs; + arelent **reloc_ptr_vector; + arelent *reloc_vector; + asymbol **ptrs; + unsigned int idx; + + asection *section = (asection *)(segment_info[idx].user_stuff); + unsigned int i; + fixS *from; + for (idx = SEG_E0; idx < SEG_E9; idx++) + { + if (segment_info[idx].scnhdr.s_name[0]) + { + + struct external_reloc *ext_ptr; + struct external_reloc *external_reloc_vec; + unsigned int external_reloc_size; + fixS * fix_ptr = segment_info[idx].fix_root; + nrelocs = count_entries_in_chain(idx); + external_reloc_size = nrelocs * RELSZ; + external_reloc_vec = (struct external_reloc*)alloca(external_reloc_size); + + ext_ptr = external_reloc_vec; + + /* Fill in the internal coff style reloc struct from the + internal fix list */ + while (fix_ptr) + { + symbolS *symbol_ptr; + struct internal_reloc intr; + + symbol_ptr = fix_ptr->fx_addsy; + + /* If this relocation is attached to a symbol then it's ok + to output it */ + intr.r_type = TC_COFF_FIX2RTYPE(fix_ptr); + intr.r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where ; + + intr.r_offset = fix_ptr->fx_offset; + + if (symbol_ptr) + intr.r_symndx = symbol_ptr->sy_number; + else + intr.r_symndx = -1; + + (void)bfd_coff_swap_reloc_out(abfd, &intr, ext_ptr); + ext_ptr++; + + fix_ptr = fix_ptr->fx_next; + } + + /* Write out the reloc table */ + segment_info[idx].scnhdr.s_relptr = *file_cursor; + segment_info[idx].scnhdr.s_nreloc = nrelocs; + bfd_write(external_reloc_vec, 1, external_reloc_size, abfd); + *file_cursor += external_reloc_size; + } + } +} + + +/* run through a frag chain and write out the data to go with it, fill + in the scnhdrs with the info on the file postions +*/ +static void DEFUN(fill_section,(abfd, filehdr, file_cursor), + bfd *abfd AND + struct internal_filehdr *filehdr AND + unsigned long *file_cursor) +{ + + unsigned int i; + unsigned int paddr = 0; + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) { + unsigned int offset = 0; + + struct internal_scnhdr *s = &( segment_info[i].scnhdr); + + if (s->s_name[0]) { + fragS *frag = segment_info[i].frag_root; + char *buffer = alloca(s->s_size); + s->s_scnptr = *file_cursor; + s->s_paddr = paddr; + s->s_vaddr = paddr; + + s->s_flags = STYP_REG; + if (strcmp(s->s_name,".text")==0) + s->s_flags |= STYP_TEXT; + else if (strcmp(s->s_name,".data")==0) + s->s_flags |= STYP_DATA; + else if (strcmp(s->s_name,".text")==0) + s->s_flags |= STYP_BSS | STYP_NOLOAD; + + + while (frag) { + unsigned int fill_size; + unsigned int count; + switch (frag->fr_type) { + case rs_fill: + case rs_align: + case rs_org: + if(frag->fr_fix) + { + memcpy(buffer + frag->fr_address, + frag->fr_literal, + frag->fr_fix); + offset += frag->fr_fix; + } + + fill_size = frag->fr_var; + if (fill_size) + { + unsigned int off = frag->fr_fix; + for (count = frag->fr_offset; count; count--) + { + memcpy(buffer + frag->fr_address + off, + frag->fr_literal + frag->fr_fix, + fill_size); + off += fill_size; + offset += fill_size; + + } + + } + break; + default: + abort(); + } + frag = frag->fr_next; + } + + /*paddr += offset; + This causes problems with relocation. For the moment, all + sections start at 0 + */ + bfd_write(buffer, s->s_size,1,abfd); + *file_cursor += s->s_size; + } + } +} + + + +/* Coff file generation & utilities */ + + +static void +DEFUN(obj_header_append,(abfd, filehdr, aouthdr), + bfd *abfd AND + struct internal_filehdr *filehdr AND + struct internal_aouthdr *aouthdr) +{ + unsigned int i; + char buffer[1000]; + char buffero[1000]; + + bfd_seek(abfd, 0, 0); +#if 0 + filehdr.f_opthdr = bfd_coff_swap_aouthdr_out(abfd, aouthdr, + buffero); +#else + filehdr->f_opthdr = 0; +#endif + i = bfd_coff_swap_filehdr_out(abfd, filehdr, buffer); + + bfd_write(buffer, i ,1, abfd); + bfd_write(buffero, filehdr->f_opthdr, 1, abfd); + + for (i = SEG_E0; i < SEG_E9; i++) + { + if (segment_info[i].scnhdr.s_name[0]) + { + unsigned int size = + bfd_coff_swap_scnhdr_out(abfd, + &(segment_info[i].scnhdr), + buffer); + bfd_write(buffer, size, 1, abfd); + } + } +} + + +void +DEFUN(symbol_to_chars,(abfd, where, symbolP), + bfd*abfd AND + char **where AND + symbolS *symbolP) +{ + unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux; + unsigned int i; + + /* Turn any symbols with register attributes into abs symbols */ + if (S_GET_SEGMENT(symbolP) == SEG_REGISTER) + { + S_SET_SEGMENT(symbolP, SEG_ABSOLUTE); + } + *where += bfd_coff_swap_sym_out(abfd, &symbolP->sy_symbol.ost_entry, + *where); + + for (i = 0; i < numaux; i++) + { + *where += bfd_coff_swap_aux_out(abfd, + &symbolP->sy_symbol.ost_auxent[i], + S_GET_DATA_TYPE(symbolP), + S_GET_STORAGE_CLASS(symbolP), + *where); + } +} + + + + +void obj_symbol_new_hook(symbolP) +symbolS *symbolP; +{ + char underscore = 0; /* Symbol has leading _ */ + + /* Effective symbol */ + /* Store the pointer in the offset. */ + S_SET_ZEROES(symbolP, 0L); + S_SET_DATA_TYPE(symbolP, T_NULL); + S_SET_STORAGE_CLASS(symbolP, 0); + S_SET_NUMBER_AUXILIARY(symbolP, 0); + /* Additional information */ + symbolP->sy_symbol.ost_flags = 0; + /* Auxiliary entries */ + bzero((char*)&symbolP->sy_symbol.ost_auxent[0], AUXESZ); + +#ifdef STRIP_UNDERSCORE + /* Remove leading underscore at the beginning of the symbol. + * This is to be compatible with the standard librairies. + */ + if (*S_GET_NAME(symbolP) == '_') { + underscore = 1; + S_SET_NAME(symbolP, S_GET_NAME(symbolP) + 1); + } /* strip underscore */ +#endif /* STRIP_UNDERSCORE */ + + if (S_IS_STRING(symbolP)) + SF_SET_STRING(symbolP); + if (!underscore && S_IS_LOCAL(symbolP)) + SF_SET_LOCAL(symbolP); + + return; +} /* obj_symbol_new_hook() */ + + /* stack stuff */ +stack* stack_init(chunk_size, element_size) +unsigned long chunk_size; +unsigned long element_size; +{ + stack* st; + + if ((st = (stack*)malloc(sizeof(stack))) == (stack*)0) + return (stack*)0; + if ((st->data = malloc(chunk_size)) == (char*)0) { + free(st); + return (stack*)0; + } + st->pointer = 0; + st->size = chunk_size; + st->chunk_size = chunk_size; + st->element_size = element_size; + return st; +} /* stack_init() */ + +void stack_delete(st) +stack* st; +{ + free(st->data); + free(st); +} + +char *stack_push(st, element) +stack *st; +char *element; +{ + if (st->pointer + st->element_size >= st->size) { + st->size += st->chunk_size; + if ((st->data = xrealloc(st->data, st->size)) == (char*)0) + return (char*)0; + } + memcpy(st->data + st->pointer, element, st->element_size); + st->pointer += st->element_size; + return st->data + st->pointer; +} /* stack_push() */ + +char* stack_pop(st) +stack* st; +{ + if ((st->pointer -= st->element_size) < 0) { + st->pointer = 0; + return (char*)0; + } + return st->data + st->pointer; +} + +char* stack_top(st) +stack* st; +{ + return st->data + st->pointer - st->element_size; +} + + +/* + * Handle .ln directives. + */ + +static void obj_coff_ln() { + if (def_symbol_in_progress != NULL) { + as_warn(".ln pseudo-op inside .def/.endef: ignored."); + demand_empty_rest_of_line(); + return; + } /* wrong context */ + + c_line_new(0, + obstack_next_free(&frags) - frag_now->fr_literal, + get_absolute_expression(), + frag_now); + + demand_empty_rest_of_line(); + return; +} /* obj_coff_line() */ + +/* + * def() + * + * Handle .def directives. + * + * One might ask : why can't we symbol_new if the symbol does not + * already exist and fill it with debug information. Because of + * the C_EFCN special symbol. It would clobber the value of the + * function symbol before we have a chance to notice that it is + * a C_EFCN. And a second reason is that the code is more clear this + * way. (at least I think it is :-). + * + */ + +#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') +#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ + *input_line_pointer == '\t') \ + input_line_pointer++; + +static void obj_coff_def(what) +int what; +{ + char name_end; /* Char after the end of name */ + char *symbol_name; /* Name of the debug symbol */ + char *symbol_name_copy; /* Temporary copy of the name */ + unsigned int symbol_name_length; + /*$char* directiveP;$ */ /* Name of the pseudo opcode */ + /*$char directive[MAX_DIRECTIVE];$ */ /* Backup of the directive */ + /*$char end = 0;$ */ /* If 1, stop parsing */ + + if (def_symbol_in_progress != NULL) { + as_warn(".def pseudo-op used inside of .def/.endef: ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + SKIP_WHITESPACES(); + + def_symbol_in_progress = (symbolS *) obstack_alloc(¬es, sizeof(*def_symbol_in_progress)); + bzero(def_symbol_in_progress, sizeof(*def_symbol_in_progress)); + + symbol_name = input_line_pointer; + name_end = get_symbol_end(); + symbol_name_length = strlen(symbol_name); + symbol_name_copy = xmalloc(symbol_name_length + 1); + strcpy(symbol_name_copy, symbol_name); + + /* Initialize the new symbol */ +#ifdef STRIP_UNDERSCORE + S_SET_NAME(def_symbol_in_progress, (*symbol_name_copy == '_' + ? symbol_name_copy + 1 + : symbol_name_copy)); +#else /* STRIP_UNDERSCORE */ + S_SET_NAME(def_symbol_in_progress, symbol_name_copy); +#endif /* STRIP_UNDERSCORE */ + /* free(symbol_name_copy); */ + def_symbol_in_progress->sy_name_offset = ~0; + def_symbol_in_progress->sy_number = ~0; + def_symbol_in_progress->sy_frag = &zero_address_frag; + + if (S_IS_STRING(def_symbol_in_progress)) { + SF_SET_STRING(def_symbol_in_progress); + } /* "long" name */ + + *input_line_pointer = name_end; + + demand_empty_rest_of_line(); + return; +} /* obj_coff_def() */ + +unsigned int dim_index; +static void obj_coff_endef() { + symbolS *symbolP; +/* DIM BUG FIX sac@cygnus.com */ + dim_index =0; + if (def_symbol_in_progress == NULL) { + as_warn(".endef pseudo-op used outside of .def/.endef: ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + /* Set the section number according to storage class. */ + switch (S_GET_STORAGE_CLASS(def_symbol_in_progress)) { + case C_STRTAG: + case C_ENTAG: + case C_UNTAG: + SF_SET_TAG(def_symbol_in_progress); + /* intentional fallthrough */ + case C_FILE: + case C_TPDEF: + SF_SET_DEBUG(def_symbol_in_progress); + S_SET_SEGMENT(def_symbol_in_progress, SEG_DEBUG); + break; + + case C_EFCN: + SF_SET_LOCAL(def_symbol_in_progress); /* Do not emit this symbol. */ + /* intentional fallthrough */ + case C_BLOCK: + SF_SET_PROCESS(def_symbol_in_progress); /* Will need processing before writing */ + /* intentional fallthrough */ + case C_FCN: + S_SET_SEGMENT(def_symbol_in_progress, SEG_E0); + + if (def_symbol_in_progress->sy_symbol.ost_entry.n_name[1] == 'b') { /* .bf */ + if (function_lineoff < 0) { + fprintf(stderr, "`.bf' symbol without preceding function\n"); + } /* missing function symbol */ + SA_GET_SYM_LNNOPTR(def_symbol_in_progress) = function_lineoff; + SF_SET_PROCESS(def_symbol_in_progress); /* Will need relocating */ + function_lineoff = -1; + } + break; + +#ifdef C_AUTOARG + case C_AUTOARG: +#endif /* C_AUTOARG */ + case C_AUTO: + case C_REG: + case C_MOS: + case C_MOE: + case C_MOU: + case C_ARG: + case C_REGPARM: + case C_FIELD: + case C_EOS: + SF_SET_DEBUG(def_symbol_in_progress); + S_SET_SEGMENT(def_symbol_in_progress, SEG_ABSOLUTE); + break; + + case C_EXT: + case C_STAT: + case C_LABEL: + /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ + break; + + case C_USTATIC: + case C_EXTDEF: + case C_ULABEL: + as_warn("unexpected storage class %d", S_GET_STORAGE_CLASS(def_symbol_in_progress)); + break; + } /* switch on storage class */ + + /* Now that we have built a debug symbol, try to + find if we should merge with an existing symbol + or not. If a symbol is C_EFCN or SEG_ABSOLUTE or + untagged SEG_DEBUG it never merges. */ + + /* Two cases for functions. Either debug followed + by definition or definition followed by debug. + For definition first, we will merge the debug + symbol into the definition. For debug first, the + lineno entry MUST point to the definition + function or else it will point off into space + when crawl_symbols() merges the debug + symbol into the real symbol. Therefor, let's + presume the debug symbol is a real function + reference. */ + + /* FIXME-SOON If for some reason the definition + label/symbol is never seen, this will probably + leave an undefined symbol at link time. */ + + if (S_GET_STORAGE_CLASS(def_symbol_in_progress) == C_EFCN + || (S_GET_SEGMENT(def_symbol_in_progress) == SEG_DEBUG + && !SF_GET_TAG(def_symbol_in_progress)) + || S_GET_SEGMENT(def_symbol_in_progress) == SEG_ABSOLUTE + || (symbolP = symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP)) == NULL) { + + symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); + + } else { + /* This symbol already exists, merge the + newly created symbol into the old one. + This is not mandatory. The linker can + handle duplicate symbols correctly. But I + guess that it save a *lot* of space if + the assembly file defines a lot of + symbols. [loic] */ + + /* The debug entry (def_symbol_in_progress) + is merged into the previous definition. */ + + c_symbol_merge(def_symbol_in_progress, symbolP); + /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */ + def_symbol_in_progress = symbolP; + + if (SF_GET_FUNCTION(def_symbol_in_progress) + || SF_GET_TAG(def_symbol_in_progress)) { + /* For functions, and tags, the symbol *must* be where the debug symbol + appears. Move the existing symbol to the current place. */ + /* If it already is at the end of the symbol list, do nothing */ + if (def_symbol_in_progress != symbol_lastP) { + symbol_remove(def_symbol_in_progress, &symbol_rootP, &symbol_lastP); + symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); + } /* if not already in place */ + } /* if function */ + } /* normal or mergable */ + + if (SF_GET_TAG(def_symbol_in_progress) + && symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP) == NULL) { + tag_insert(S_GET_NAME(def_symbol_in_progress), def_symbol_in_progress); + } /* If symbol is a {structure,union} tag, associate symbol to its name. */ + + if (SF_GET_FUNCTION(def_symbol_in_progress)) { + know(sizeof(def_symbol_in_progress) <= sizeof(long)); + function_lineoff = c_line_new((long) def_symbol_in_progress,0, 0, &zero_address_frag); + SF_SET_PROCESS(def_symbol_in_progress); + + if (symbolP == NULL) { + /* That is, if this is the first + time we've seen the function... */ + symbol_table_insert(def_symbol_in_progress); + } /* definition follows debug */ + } /* Create the line number entry pointing to the function being defined */ + + def_symbol_in_progress = NULL; + demand_empty_rest_of_line(); + return; +} /* obj_coff_endef() */ + +static void obj_coff_dim() +{ + register int dim_index; + + if (def_symbol_in_progress == NULL) { + as_warn(".dim pseudo-op used outside of .def/.endef: ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1); + + for (dim_index = 0; dim_index < DIMNUM; dim_index++) { + SKIP_WHITESPACES(); + SA_SET_SYM_DIMEN(def_symbol_in_progress, dim_index, get_absolute_expression()); + + switch (*input_line_pointer) { + + case ',': + input_line_pointer++; + break; + + default: + as_warn("badly formed .dim directive ignored"); + /* intentional fallthrough */ + case '\n': + case ';': + dim_index = DIMNUM; + break; + } /* switch on following character */ + } /* for each dimension */ + + demand_empty_rest_of_line(); + return; +} /* obj_coff_dim() */ + +static void obj_coff_line() { + if (def_symbol_in_progress == NULL) { + obj_coff_ln(); + return; + } /* if it looks like a stabs style line */ + + S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1); + SA_SET_SYM_LNNO(def_symbol_in_progress, get_absolute_expression()); + + demand_empty_rest_of_line(); + return; +} /* obj_coff_line() */ + +static void obj_coff_size() { + if (def_symbol_in_progress == NULL) { + as_warn(".size pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1); + SA_SET_SYM_SIZE(def_symbol_in_progress, get_absolute_expression()); + demand_empty_rest_of_line(); + return; +} /* obj_coff_size() */ + +static void obj_coff_scl() { + if (def_symbol_in_progress == NULL) { + as_warn(".scl pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + S_SET_STORAGE_CLASS(def_symbol_in_progress, get_absolute_expression()); + demand_empty_rest_of_line(); + return; +} /* obj_coff_scl() */ + +static void obj_coff_tag() { + char *symbol_name; + char name_end; + + if (def_symbol_in_progress == NULL) { + as_warn(".tag pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1); + symbol_name = input_line_pointer; + name_end = get_symbol_end(); + + /* Assume that the symbol referred to by .tag is always defined. */ + /* This was a bad assumption. I've added find_or_make. xoxorich. */ + SA_SET_SYM_TAGNDX(def_symbol_in_progress, (long) tag_find_or_make(symbol_name)); + if (SA_GET_SYM_TAGNDX(def_symbol_in_progress) == 0L) { + as_warn("tag not found for .tag %s", symbol_name); + } /* not defined */ + + SF_SET_TAGGED(def_symbol_in_progress); + *input_line_pointer = name_end; + + demand_empty_rest_of_line(); + return; +} /* obj_coff_tag() */ + +static void obj_coff_type() { + if (def_symbol_in_progress == NULL) { + as_warn(".type pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + S_SET_DATA_TYPE(def_symbol_in_progress, get_absolute_expression()); + + if (ISFCN(S_GET_DATA_TYPE(def_symbol_in_progress)) && + S_GET_STORAGE_CLASS(def_symbol_in_progress) != C_TPDEF) { + SF_SET_FUNCTION(def_symbol_in_progress); + } /* is a function */ + + demand_empty_rest_of_line(); + return; +} /* obj_coff_type() */ + +static void obj_coff_val() { + if (def_symbol_in_progress == NULL) { + as_warn(".val pseudo-op used outside of .def/.endef ignored."); + demand_empty_rest_of_line(); + return; + } /* if not inside .def/.endef */ + + if (is_name_beginner(*input_line_pointer)) { + char *symbol_name = input_line_pointer; + char name_end = get_symbol_end(); + + if (!strcmp(symbol_name, ".")) { + def_symbol_in_progress->sy_frag = frag_now; + S_SET_VALUE(def_symbol_in_progress, obstack_next_free(&frags) - frag_now->fr_literal); + /* If the .val is != from the .def (e.g. statics) */ + } else if (strcmp(S_GET_NAME(def_symbol_in_progress), symbol_name)) { + def_symbol_in_progress->sy_forward = symbol_find_or_make(symbol_name); + + /* If the segment is undefined when the forward + reference is solved, then copy the segment id + from the forward symbol. */ + SF_SET_GET_SEGMENT(def_symbol_in_progress); + } + /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ + *input_line_pointer = name_end; + } else { + S_SET_VALUE(def_symbol_in_progress, get_absolute_expression()); + } /* if symbol based */ + + demand_empty_rest_of_line(); + return; +} /* obj_coff_val() */ + +/* + * Maintain a list of the tagnames of the structres. + */ + +static void tag_init() { + tag_hash = hash_new(); + return ; +} /* tag_init() */ + +static void tag_insert(name, symbolP) +char *name; +symbolS *symbolP; +{ + register char * error_string; + + if (*(error_string = hash_jam(tag_hash, name, (char *)symbolP))) { + as_fatal("Inserting \"%s\" into structure table failed: %s", + name, error_string); + } + return ; +} /* tag_insert() */ + +static symbolS *tag_find_or_make(name) +char *name; +{ + symbolS *symbolP; + + if ((symbolP = tag_find(name)) == NULL) { + symbolP = symbol_new(name, + SEG_UNKNOWN, + 0, + &zero_address_frag); + + tag_insert(S_GET_NAME(symbolP), symbolP); + symbol_table_insert(symbolP); + } /* not found */ + + return(symbolP); +} /* tag_find_or_make() */ + +static symbolS *tag_find(name) +char *name; +{ +#ifdef STRIP_UNDERSCORE + if (*name == '_') name++; +#endif /* STRIP_UNDERSCORE */ + return((symbolS*)hash_find(tag_hash, name)); +} /* tag_find() */ + +void obj_read_begin_hook() { + /* These had better be the same. Usually 18 bytes. */ +#ifndef BFD_HEADERS + know(sizeof(SYMENT) == sizeof(AUXENT)); + know(SYMESZ == AUXESZ); +#endif + tag_init(); + + return; +} /* obj_read_begin_hook() */ + +/* This function runs through the symbol table and puts all the + externals onto another chain */ + +/* The chain of externals */ +symbolS *symbol_externP = NULL; +symbolS *symbol_extern_lastP = NULL; + +stack*block_stack; + symbolS *last_functionP = NULL; + symbolS *last_tagP; + + +static unsigned int DEFUN_VOID(yank_symbols) +{ + symbolS *symbolP; + unsigned int symbol_number =0; + + for (symbolP = symbol_rootP; + symbolP; + symbolP = symbolP ? symbol_next(symbolP) : symbol_rootP) { + if (!SF_GET_DEBUG(symbolP)) { + /* Debug symbols do not need all this rubbish */ + symbolS* real_symbolP; + + /* L* and C_EFCN symbols never merge. */ + if (!SF_GET_LOCAL(symbolP) + && (real_symbolP = symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) + && real_symbolP != symbolP) { + /* FIXME-SOON: where do dups come from? + Maybe tag references before definitions? xoxorich. */ + /* Move the debug data from the debug symbol to the + real symbol. Do NOT do the oposite (i.e. move from + real symbol to debug symbol and remove real symbol from the + list.) Because some pointers refer to the real symbol + whereas no pointers refer to the debug symbol. */ + c_symbol_merge(symbolP, real_symbolP); + /* Replace the current symbol by the real one */ + /* The symbols will never be the last or the first + because : 1st symbol is .file and 3 last symbols are + .text, .data, .bss */ + symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP); + symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP); + symbol_remove(symbolP, &symbol_rootP, &symbol_lastP); + symbolP = real_symbolP; + } /* if not local but dup'd */ + + if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_E1)) { + S_SET_SEGMENT(symbolP, SEG_E0); + } /* push data into text */ + + S_SET_VALUE(symbolP, + S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address); + + if (!S_IS_DEFINED(symbolP) && !SF_GET_LOCAL(symbolP)) + { + S_SET_EXTERNAL(symbolP); + } + else if (S_GET_STORAGE_CLASS(symbolP) == C_NULL) + { + if (S_GET_SEGMENT(symbolP) == SEG_E0) + { + S_SET_STORAGE_CLASS(symbolP, C_LABEL); + } + else + { + S_SET_STORAGE_CLASS(symbolP, C_STAT); + } + } + + /* Mainly to speed up if not -g */ + if (SF_GET_PROCESS(symbolP)) + { + /* Handle the nested blocks auxiliary info. */ + if (S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) { + if (!strcmp(S_GET_NAME(symbolP), ".bb")) + stack_push(block_stack, (char *) &symbolP); + else { /* .eb */ + register symbolS* begin_symbolP; + begin_symbolP = *(symbolS**)stack_pop(block_stack); + if (begin_symbolP == (symbolS*)0) + as_warn("mismatched .eb"); + else + SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number+2); + } + } + /* If we are able to identify the type of a function, and we + are out of a function (last_functionP == 0) then, the + function symbol will be associated with an auxiliary + entry. */ + if (last_functionP == (symbolS*)0 && + SF_GET_FUNCTION(symbolP)) { + last_functionP = symbolP; + + if (S_GET_NUMBER_AUXILIARY(symbolP) < 1) { + S_SET_NUMBER_AUXILIARY(symbolP, 1); + } /* make it at least 1 */ + + /* Clobber possible stale .dim information. */ + bzero(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen, + sizeof(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen)); + } + /* The C_FCN doesn't need any additional information. + I don't even know if this is needed for sdb. But the + standard assembler generates it, so... + */ + if (S_GET_STORAGE_CLASS(symbolP) == C_EFCN) { + if (last_functionP == (symbolS*)0) + as_fatal("C_EFCN symbol out of scope"); + SA_SET_SYM_FSIZE(last_functionP, + (long)(S_GET_VALUE(symbolP) - + S_GET_VALUE(last_functionP))); + SA_SET_SYM_ENDNDX(last_functionP, symbol_number); + last_functionP = (symbolS*)0; + } + } + } else if (SF_GET_TAG(symbolP)) { + /* First descriptor of a structure must point to + the first slot after the structure description. */ + last_tagP = symbolP; + + } else if (S_GET_STORAGE_CLASS(symbolP) == C_EOS) { + /* +2 take in account the current symbol */ + SA_SET_SYM_ENDNDX(last_tagP, symbol_number + 2); + } else if (S_GET_STORAGE_CLASS(symbolP) == C_FILE) { + if (S_GET_VALUE(symbolP)) { + S_SET_VALUE((symbolS *) S_GET_VALUE(symbolP), symbol_number); + S_SET_VALUE(symbolP, 0); + } /* no one points at the first .file symbol */ + } /* if debug or tag or eos or file */ + + /* We must put the external symbols apart. The loader + does not bomb if we do not. But the references in + the endndx field for a .bb symbol are not corrected + if an external symbol is removed between .bb and .be. + I.e in the following case : + [20] .bb endndx = 22 + [21] foo external + [22] .be + ld will move the symbol 21 to the end of the list but + endndx will still be 22 instead of 21. */ + + + if (SF_GET_LOCAL(symbolP)) { + /* remove C_EFCN and LOCAL (L...) symbols */ + /* next pointer remains valid */ + symbol_remove(symbolP, &symbol_rootP, &symbol_lastP); + + } else if (!S_IS_DEFINED(symbolP) + && !S_IS_DEBUG(symbolP) + && !SF_GET_STATICS(symbolP)) { + /* S_GET_STORAGE_CLASS(symbolP) == C_EXT && !SF_GET_FUNCTION(symbolP)) { */ + /* if external, Remove from the list */ + symbolS *hold = symbol_previous(symbolP); + + symbol_remove(symbolP, &symbol_rootP, &symbol_lastP); + symbol_clear_list_pointers(symbolP); + symbol_append(symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP); + symbolP = hold; + } else { + if (SF_GET_STRING(symbolP)) { + symbolP->sy_name_offset = string_byte_count; + string_byte_count += strlen(S_GET_NAME(symbolP)) + 1; + } else { + symbolP->sy_name_offset = 0; + } /* fix "long" names */ + + symbolP->sy_number = symbol_number; + symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP); + } /* if local symbol */ + } /* traverse the symbol list */ + return symbol_number; + +} + + +static unsigned int DEFUN_VOID(glue_symbols) +{ + unsigned int symbol_number = 0; + symbolS *symbolP; + for (symbolP = symbol_externP; symbol_externP;) { + symbolS *tmp = symbol_externP; + + /* append */ + symbol_remove(tmp, &symbol_externP, &symbol_extern_lastP); + symbol_append(tmp, symbol_lastP, &symbol_rootP, &symbol_lastP); + + /* and process */ + if (SF_GET_STRING(tmp)) { + tmp->sy_name_offset = string_byte_count; + string_byte_count += strlen(S_GET_NAME(tmp)) + 1; + } else { + tmp->sy_name_offset = 0; + } /* fix "long" names */ + + tmp->sy_number = symbol_number; + symbol_number += 1 + S_GET_NUMBER_AUXILIARY(tmp); + } /* append the entire extern chain */ + return symbol_number; + +} + +static unsigned int DEFUN_VOID(tie_tags) +{ + unsigned int symbol_number = 0; + + symbolS*symbolP; + for (symbolP = symbol_rootP; symbolP; symbolP = + symbol_next(symbolP)) + { + symbolP->sy_number = symbol_number; + if (SF_GET_TAGGED(symbolP)) + { + SA_SET_SYM_TAGNDX + (symbolP, + ((symbolS*) SA_GET_SYM_TAGNDX(symbolP))->sy_number); + } + + symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP); + } + return symbol_number; + +} + +static void DEFUN(crawl_symbols,(headers, abfd), + struct internal_filehdr *headers AND + bfd *abfd) +{ + + unsigned int i; + unsigned int ptr = 0; + + + symbolS *symbolP; + + /* Initialize the stack used to keep track of the matching .bb .be */ + + block_stack = stack_init(512, sizeof(symbolS*)); + /* JF deal with forward references first... */ + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) { + + if (symbolP->sy_forward) { + S_SET_VALUE(symbolP, (S_GET_VALUE(symbolP) + + S_GET_VALUE(symbolP->sy_forward) + + symbolP->sy_forward->sy_frag->fr_address)); + + if (SF_GET_GET_SEGMENT(symbolP)) { + S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward)); + } /* forward segment also */ + + symbolP->sy_forward=0; + } /* if it has a forward reference */ + } /* walk the symbol chain */ + + + /* The symbol list should be ordered according to the following sequence + * order : + * . .file symbol + * . debug entries for functions + * . fake symbols for the sections, including.text .data and .bss + * . defined symbols + * . undefined symbols + * But this is not mandatory. The only important point is to put the + * undefined symbols at the end of the list. + */ + + if (symbol_rootP == NULL + || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) { + c_dot_file_symbol("fake"); + } + /* Is there a .file symbol ? If not insert one at the beginning. */ + + /* + * Build up static symbols for the sections + */ + + + for (i = SEG_E0; i < SEG_E9; i++) + { + if (segment_info[i].scnhdr.s_name[0]) + { + segment_info[i].dot = + c_section_symbol(segment_info[i].scnhdr.s_name, + i, + ptr, + i-SEG_E0+1, + segment_info[i].scnhdr.s_size, + segment_info[i].scnhdr.s_paddr, + 0,0); + } + } + + +#if defined(DEBUG) + verify_symbol_chain(symbol_rootP, symbol_lastP); +#endif /* DEBUG */ + + /* Take all the externals out and put them into another chain */ +headers->f_nsyms = yank_symbols(); + /* Take the externals and glue them onto the end.*/ + headers->f_nsyms += glue_symbols(); + +headers->f_nsyms = tie_tags(); + know(symbol_externP == NULL); + know(symbol_extern_lastP == NULL); + +#if 0 + /* FIXME-SOMEDAY + I'm counting line no's here so we know what to put in the section + headers, and I'm resolving the addresses since I'm not sure how to + do it later. I am NOT resolving the linno's representing functions. + Their symbols need a fileptr pointing to this linno when emitted. + Thus, I resolve them on emit. xoxorich. */ + + for (lineP = lineno_rootP; lineP; lineP = lineP->next) + { + if (lineP->line.l_lnno > 0) { + lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address; + } else { + ; + } + text_lineno_number++; + } /* for each line number */ +#endif + return; +} + +/* + * Find strings by crawling along symbol table chain. + */ + +w_strings(where) +char *where; +{ + symbolS *symbolP; + + /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ + md_number_to_chars(where, string_byte_count, sizeof(string_byte_count)); + where += sizeof(string_byte_count); + for (symbolP = symbol_rootP; + symbolP; + symbolP = symbol_next(symbolP)) + { + unsigned int size; + + if (SF_GET_STRING(symbolP)) { + size = strlen(S_GET_NAME(symbolP)) + 1; + + memcpy(where, S_GET_NAME(symbolP),size); + where += size; + + } + } + +} + + +#if 0 +void obj_pre_write_hook(headers) +object_headers *headers; +{ + register fixS *fixP; + + /* FIXME-SOMEDAY this should be done at + fixup_segment time but I'm going to wait until I + do multiple segments. xoxorich. */ + unsigned int i; + unsigned int reloc_size = 0; + + for (i =0; i < N_SEG; i++) + { + seg_info_type *s = &(SEG_INFO_FROM_SEG_NUMBER(i)); + + if (s->real_section) + { + + for (fixP = s->fix_root; fixP; fixP = fixP->fx_next) { + if (fixP->fx_addsy) { + s->relocation_number++; + } + } + + } + headers->relocation_size += s->relocation_number * RELSZ; + } + + /* filehdr */ + H_SET_FILE_MAGIC_NUMBER(headers, FILE_HEADER_MAGIC); + H_SET_NUMBER_OF_SECTIONS(headers, 3); /* text+data+bss */ +#ifndef OBJ_COFF_OMIT_TIMESTAMP + H_SET_TIME_STAMP(headers, (long)time((long*)0)); +#else /* OBJ_COFF_OMIT_TIMESTAMP */ + H_SET_TIME_STAMP(headers, 0); +#endif /* OBJ_COFF_OMIT_TIMESTAMP */ + H_SET_SYMBOL_TABLE_POINTER(headers, H_GET_SYMBOL_TABLE_FILE_OFFSET(headers)); +#if 0 + printf("FILHSZ %x\n", FILHSZ); + printf("OBJ_COFF_AOUTHDRSZ %x\n", OBJ_COFF_AOUTHDRSZ); + printf("section headers %x\n", H_GET_NUMBER_OF_SECTIONS(headers) * SCNHSZ); + printf("get text size %x\n", H_GET_TEXT_SIZE(headers)); + printf("get data size %x\n", H_GET_DATA_SIZE(headers)); + printf("get relocation size %x\n", H_GET_RELOCATION_SIZE(headers)); + printf("get lineno size %x\n", H_GET_LINENO_SIZE(headers)); +#endif + /* symbol table size allready set */ + H_SET_SIZEOF_OPTIONAL_HEADER(headers, OBJ_COFF_AOUTHDRSZ); + H_SET_FLAGS(headers, (text_lineno_number == 0 ? F_LNNO : 0) + | headers->relocation_size ? F_RELFLG : 0 + | BYTE_ORDERING); + + /* aouthdr */ + /* magic number allready set */ + H_SET_VERSION_STAMP(headers, 0); + +} /* obj_pre_write_hook() */ +#endif +/* This is a copy from aout. All I do is neglect to actually build the symbol. */ + +static void obj_coff_stab(what) +int what; +{ + char *string; + expressionS e; + int goof = 0; /* TRUE if we have aborted. */ + int length; + int saved_type = 0; + long longint; + symbolS *symbolP = 0; + + if (what == 's') { + string = demand_copy_C_string(&length); + SKIP_WHITESPACE(); + + if (*input_line_pointer == ',') { + input_line_pointer++; + } else { + as_bad("I need a comma after symbol's name"); + goof = 1; + } /* better be a comma */ + } /* skip the string */ + + /* + * Input_line_pointer->after ','. String->symbol name. + */ + if (!goof) { + if (get_absolute_expression_and_terminator(&longint) != ',') { + as_bad("I want a comma after the n_type expression"); + goof = 1; + input_line_pointer--; /* Backup over a non-',' char. */ + } /* on error */ + } /* no error */ + + if (!goof) { + if (get_absolute_expression_and_terminator(&longint) != ',') { + as_bad("I want a comma after the n_other expression"); + goof = 1; + input_line_pointer--; /* Backup over a non-',' char. */ + } /* on error */ + } /* no error */ + + if (!goof) { + get_absolute_expression(); + + if (what == 's' || what == 'n') { + if (*input_line_pointer != ',') { + as_bad("I want a comma after the n_desc expression"); + goof = 1; + } else { + input_line_pointer++; + } /* on goof */ + } /* not stabd */ + } /* no error */ + + expression(&e); + + if (goof) { + ignore_rest_of_line(); + } else { + demand_empty_rest_of_line(); + } /* on error */ +} /* obj_coff_stab() */ + +#ifdef DEBUG + /* for debugging */ +char *s_get_name(s) +symbolS *s; +{ + return((s == NULL) ? "(NULL)" : S_GET_NAME(s)); +} /* s_get_name() */ + +void symbol_dump() { + symbolS *symbolP; + + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) { + printf("%3ld: 0x%lx \"%s\" type = %ld, class = %d, segment = %d\n", + symbolP->sy_number, + (unsigned long) symbolP, + S_GET_NAME(symbolP), + (long) S_GET_DATA_TYPE(symbolP), + S_GET_STORAGE_CLASS(symbolP), + (int) S_GET_SEGMENT(symbolP)); + } /* traverse symbols */ + + return; +} /* symbol_dump() */ +#endif /* DEBUG */ + + + +static void +DEFUN(do_linenos_for,(abfd, file_cursor), + bfd *abfd AND + unsigned long *file_cursor) +{ + unsigned int idx; + + for (idx = SEG_E0; idx < SEG_E9; idx++) + { + segment_info_type *s = segment_info + idx; + + if (s->scnhdr.s_nlnno != 0) + { + struct lineno_list *line_ptr ; + + struct external_lineno *buffer = + (struct external_lineno *)alloca(s->scnhdr.s_nlnno * LINESZ); + + struct external_lineno *dst= buffer; + + /* Run through the table we've built and turn it into its external + form */ + + for (line_ptr = s->lineno_list_head; + line_ptr != (struct lineno_list *)NULL; + line_ptr = line_ptr->next) + { + if (line_ptr->line.l_lnno == 0) + { + /* Turn a pointer to a symbol into the symbols' index */ + line_ptr->line.l_addr.l_symndx = + ( (symbolS *)line_ptr->line.l_addr.l_symndx)->sy_number; + } + (void) bfd_coff_swap_lineno_out(abfd, &(line_ptr->line), dst); + dst++; + } + + s->scnhdr.s_lnnoptr = *file_cursor; + + bfd_write(buffer, 1, s->scnhdr.s_nlnno* LINESZ, abfd); + *file_cursor += s->scnhdr.s_nlnno * LINESZ; + } + } +} + +/* + * Local Variables: + * comment-column: 0 + * fill-column: 131 + * End: + */ + +/* end of obj-coff.c */ + + + +extern void DEFUN_VOID(write_object_file) +{ + int i; + struct frchain *frchain_ptr; + struct frag *frag_ptr; + struct internal_filehdr filehdr; + struct internal_aouthdr aouthdr; +unsigned long file_cursor; + bfd *abfd; + + abfd = bfd_openw(out_file_name, TARGET_FORMAT); + + if (abfd == 0) { + as_perror ("FATAL: Can't create %s", out_file_name); + exit(42); + } + bfd_set_format(abfd, bfd_object); + bfd_set_arch_mach(abfd, bfd_arch_h8300, 0); + + + string_byte_count = 4; + + for (frchain_ptr = frchain_root; + frchain_ptr != (struct frchain *)NULL; + frchain_ptr = frchain_ptr->frch_next) { + /* Run through all the sub-segments and align them up. Also close any + open frags. We tack a .fill onto the end of the frag chain so + that any .align's size can be worked by looking at the next + frag */ + + subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg); +#define SUB_SEGMENT_ALIGN 2 + frag_align(SUB_SEGMENT_ALIGN,0); + frag_wane(frag_now); + frag_now->fr_fix = 0; + know( frag_now->fr_next == NULL ); + } + + /* Now build one big frag chain for each segment, linked through + fr_next. */ + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + + fragS ** prev_frag_ptr_ptr ; + struct frchain *next_frchain_ptr; + + /* struct frag **head_ptr = segment_info[i].frag_root;*/ + + segment_info[i].frag_root = segment_info[i].frchainP->frch_root; +#if 0 + /* Im not sure what this is for */ + for (frchain_ptr = segment_info[i].frchainP->frch_root; + frchain_ptr != (struct frchain *)NULL; + frchain_ptr = frchain_ptr->frch_next) + { + *head_ptr = frchain_ptr; + head_ptr = &frchain_ptr->next; + } + + +#endif + } +#if 1 + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + relax_segment(segment_info[i].frag_root, i); + } + + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { +/* fixup_segment(segment_info[i].fix_root, i);*/ + } + +#endif + +{ + unsigned int addr = 0; + filehdr.f_nscns = 0; + + /* Find out how big the sections are */ + for (i = SEG_E0; i < SEG_UNKNOWN; i++) + { + + if (segment_info[i].scnhdr.s_name[0]) + { + filehdr.f_nscns++; + } + segment_info[i].scnhdr.s_paddr = addr; + if (i == SEG_E2) { + /* THis is a special case, we leave the size alone, which will have */ + /* been made up from all and any lcomms seen */ + + } + else { + addr += size_section(abfd, i); + } + } +} + + /* Turn the gas native symbol table shape into a coff symbol table */ + crawl_symbols(&filehdr, abfd); + + file_cursor = FILHSZ + SCNHSZ * filehdr.f_nscns ; + + bfd_seek(abfd, file_cursor, 0); + + do_relocs_for(abfd, &file_cursor); + do_linenos_for(abfd, &file_cursor); + + + /* Plant the data */ + + fill_section(abfd,&filehdr, &file_cursor); + + filehdr.f_magic = 0x8300; + filehdr.f_timdat = 0; + filehdr.f_flags = 0; + + + +{ + + unsigned int symtable_size = filehdr.f_nsyms * SYMESZ; + char *buffer1 = malloc(symtable_size); + char *buffer2 = malloc(string_byte_count+4); + char *ptr = buffer1; + filehdr.f_symptr = bfd_tell(abfd); + w_symbols(abfd,&buffer1, symbol_rootP); + bfd_write(ptr, 1, symtable_size, abfd); + + w_strings(buffer2); + bfd_write(buffer2, 1, string_byte_count, abfd); + +} + obj_header_append(abfd, &filehdr, &aouthdr); + + bfd_close_all_done(abfd); +} + + +static void DEFUN(change_to_section,(name, len), + char *name AND + unsigned int len) +{ + unsigned int i; + /* Find out if we've already got a section of this name etc */ + for(i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0] ; i++) + { + if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0) + { + subseg_new(i, 0); + return; + + } + } + /* No section, add one */ + strncpy(segment_info[i].scnhdr.s_name, name, 8); + subseg_new(i, 0); +} + +static void +DEFUN_VOID(obj_coff_section) +{ + /* Strip out the section name */ + char *section_name ; + char *section_name_end; + + unsigned int len; + + section_name = input_line_pointer; + get_symbol_end(); + section_name_end = input_line_pointer; + input_line_pointer++; + + len = section_name_end - section_name ; + + + change_to_section(section_name, len); + +} + + +static void obj_coff_text() +{ + change_to_section(".text",5); +} + + +static void obj_coff_data() +{ + change_to_section(".data",5); +} + +void c_symbol_merge(debug, normal) +symbolS *debug; +symbolS *normal; +{ + S_SET_DATA_TYPE(normal, S_GET_DATA_TYPE(debug)); + S_SET_STORAGE_CLASS(normal, S_GET_STORAGE_CLASS(debug)); + + if (S_GET_NUMBER_AUXILIARY(debug) > S_GET_NUMBER_AUXILIARY(normal)) { + S_SET_NUMBER_AUXILIARY(normal, S_GET_NUMBER_AUXILIARY(debug)); + } /* take the most we have */ + + if (S_GET_NUMBER_AUXILIARY(debug) > 0) { + memcpy((char*)&normal->sy_symbol.ost_auxent[0], (char*)&debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY(debug) * AUXESZ); + } /* Move all the auxiliary information */ + + /* Move the debug flags. */ + SF_SET_DEBUG_FIELD(normal, SF_GET_DEBUG_FIELD(debug)); +} /* c_symbol_merge() */ + +int +c_line_new(symbol, paddr, line_number, frag) +symbolS *symbol; +long paddr; +unsigned short line_number; +fragS* frag; +{ + struct lineno_list* new_line = + (struct lineno_list *)xmalloc(sizeof(struct lineno_list)); + + segment_info_type *s = segment_info + now_seg; + new_line->line.l_lnno = line_number; + if (line_number == 0) + { + new_line->line.l_addr.l_symndx = (long)symbol; + } + else + { + new_line->line.l_addr.l_paddr = paddr; + } + + new_line->frag = (char*)frag; + new_line->next = (struct lineno_list*)NULL; + + + if (s->lineno_list_head == (struct lineno_list *)NULL) + { + s->lineno_list_head = new_line; + } + else + { + s->lineno_list_tail->next = new_line; + } + s->lineno_list_tail = new_line; + return LINESZ * s->scnhdr.s_nlnno ++; +} + +void c_dot_file_symbol(filename) +char *filename; +{ + symbolS* symbolP; + + symbolP = symbol_new(".file", + SEG_DEBUG, + 0, + &zero_address_frag); + + S_SET_STORAGE_CLASS(symbolP, C_FILE); + S_SET_NUMBER_AUXILIARY(symbolP, 1); + SA_SET_FILE_FNAME(symbolP, filename); + SF_SET_DEBUG(symbolP); + S_SET_VALUE(symbolP, (long) previous_file_symbol); + + previous_file_symbol = symbolP; + + /* Make sure that the symbol is first on the symbol chain */ + if (symbol_rootP != symbolP) { + if (symbolP == symbol_lastP) { + symbol_lastP = symbol_lastP->sy_previous; + } /* if it was the last thing on the list */ + + symbol_remove(symbolP, &symbol_rootP, &symbol_lastP); + symbol_insert(symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); + symbol_rootP = symbolP; + } /* if not first on the list */ + +} /* c_dot_file_symbol() */ + +/* + * Build a 'section static' symbol. + */ + +symbolS *c_section_symbol(name,idx, value, length, nreloc, nlnno) +char *name; +long value; +long length; +unsigned short nreloc; +unsigned short nlnno; +{ + symbolS *symbolP; + + symbolP = symbol_new(name,idx, + value, + &zero_address_frag); + + S_SET_STORAGE_CLASS(symbolP, C_STAT); + S_SET_NUMBER_AUXILIARY(symbolP, 1); + + SA_SET_SCN_SCNLEN(symbolP, length); + SA_SET_SCN_NRELOC(symbolP, nreloc); + SA_SET_SCN_NLINNO(symbolP, nlnno); + + SF_SET_STATICS(symbolP); + + return symbolP; +} /* c_section_symbol() */ +static void +DEFUN(w_symbols,(abfd, where, symbol_rootP), +bfd *abfd AND +char **where AND +symbolS *symbol_rootP) +{ + symbolS *symbolP; + /* + * Emit all symbols left in the symbol chain. + */ + for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) { + /* Used to save the offset of the name. It is used to point + to the string in memory but must be a file offset. */ + register char * temp; + + tc_coff_symbol_emit_hook(symbolP); + + temp = S_GET_NAME(symbolP); + if (SF_GET_STRING(symbolP)) { + S_SET_OFFSET(symbolP, symbolP->sy_name_offset); + S_SET_ZEROES(symbolP, 0); + } else { + bzero(symbolP->sy_symbol.ost_entry.n_name, SYMNMLEN); + strncpy(symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN); + } + symbol_to_chars(abfd, where, symbolP); + S_SET_NAME(symbolP,temp); + } +} /* w_symbols() */ + +#if 0 +static long fixup_segment(fixP, this_segment_type) +register fixS * fixP; +segT this_segment_type; /* N_TYPE bits for segment. */ +{ + register long seg_reloc_count; + register symbolS *add_symbolP; + register symbolS *sub_symbolP; + register long add_number; + register int size; + register char *place; + register long where; + register char pcrel; + register fragS *fragP; + register segT add_symbol_segment = SEG_ABSOLUTE; + + /* FIXME: remove this line */ /* fixS *orig = fixP; */ + seg_reloc_count = 0; + + for ( ; fixP; fixP = fixP->fx_next) { + fragP = fixP->fx_frag; + know(fragP); + where = fixP->fx_where; + place = fragP->fr_literal + where; + size = fixP->fx_size; + add_symbolP = fixP->fx_addsy; +#ifdef TC_I960 + if (fixP->fx_callj && TC_S_IS_CALLNAME(add_symbolP)) { + /* Relocation should be done via the + associated 'bal' entry point + symbol. */ + + if (!TC_S_IS_BALNAME(tc_get_bal_of_call(add_symbolP))) { + as_bad("No 'bal' entry point for leafproc %s", + S_GET_NAME(add_symbolP)); + continue; + } + fixP->fx_addsy = add_symbolP = tc_get_bal_of_call(add_symbolP); + } /* callj relocation */ +#endif + sub_symbolP = fixP->fx_subsy; + add_number = fixP->fx_offset; + pcrel = fixP->fx_pcrel; + + if (add_symbolP) { + add_symbol_segment = S_GET_SEGMENT(add_symbolP); + } /* if there is an addend */ + + if (sub_symbolP) { + if (!add_symbolP) { + /* Its just -sym */ + if (S_GET_SEGMENT(sub_symbolP) != SEG_ABSOLUTE) { + as_bad("Negative of non-absolute symbol %s", S_GET_NAME(sub_symbolP)); + } /* not absolute */ + + add_number -= S_GET_VALUE(sub_symbolP); + + /* if sub_symbol is in the same segment that add_symbol + and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */ + } else if ((S_GET_SEGMENT(sub_symbolP) == add_symbol_segment) + && (SEG_NORMAL(add_symbol_segment) + || (add_symbol_segment == SEG_ABSOLUTE))) { + /* Difference of 2 symbols from same segment. */ + /* Can't make difference of 2 undefineds: 'value' means */ + /* something different for N_UNDF. */ +#ifdef TC_I960 + /* Makes no sense to use the difference of 2 arbitrary symbols + * as the target of a call instruction. + */ + if (fixP->fx_callj) { + as_bad("callj to difference of 2 symbols"); + } +#endif /* TC_I960 */ + add_number += S_GET_VALUE(add_symbolP) - + S_GET_VALUE(sub_symbolP); + + add_symbolP = NULL; + fixP->fx_addsy = NULL; + } else { + /* Different segments in subtraction. */ + know(!(S_IS_EXTERNAL(sub_symbolP) && (S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE))); + + if ((S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)) { + add_number -= S_GET_VALUE(sub_symbolP); + } else { + as_bad("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.", + segment_name(S_GET_SEGMENT(sub_symbolP)), + S_GET_NAME(sub_symbolP), fragP->fr_address + where); + } /* if absolute */ + } + } /* if sub_symbolP */ + + if (add_symbolP) { + if (add_symbol_segment == this_segment_type && pcrel) { + /* + * This fixup was made when the symbol's segment was + * SEG_UNKNOWN, but it is now in the local segment. + * So we know how to do the address without relocation. + */ +#ifdef TC_I960 + /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal', + * in which cases it modifies *fixP as appropriate. In the case + * of a 'calls', no further work is required, and *fixP has been + * set up to make the rest of the code below a no-op. + */ + reloc_callj(fixP); +#endif /* TC_I960 */ + + add_number += S_GET_VALUE(add_symbolP); + add_number -= md_pcrel_from (fixP); + pcrel = 0; /* Lie. Don't want further pcrel processing. */ + fixP->fx_addsy = NULL; /* No relocations please. */ + } else { + switch (add_symbol_segment) { + case SEG_ABSOLUTE: +#ifdef TC_I960 + reloc_callj(fixP); /* See comment about reloc_callj() above*/ +#endif /* TC_I960 */ + add_number += S_GET_VALUE(add_symbolP); + fixP->fx_addsy = NULL; + add_symbolP = NULL; + break; + default: + seg_reloc_count ++; + add_number += S_GET_VALUE(add_symbolP); + break; + + case SEG_UNKNOWN: +#ifdef TC_I960 + if ((int)fixP->fx_bit_fixP == 13) { + /* This is a COBR instruction. They have only a + * 13-bit displacement and are only to be used + * for local branches: flag as error, don't generate + * relocation. + */ + as_bad("can't use COBR format with external label"); + fixP->fx_addsy = NULL; /* No relocations please. */ + continue; + } /* COBR */ +#endif /* TC_I960 */ + /* FIXME-SOON: I think this is trash, but I'm not sure. xoxorich. */ +#ifdef comment +#ifdef OBJ_COFF + if (S_IS_COMMON(add_symbolP)) + add_number += S_GET_VALUE(add_symbolP); +#endif /* OBJ_COFF */ +#endif /* comment */ + + ++seg_reloc_count; + + break; + + + } /* switch on symbol seg */ + } /* if not in local seg */ + } /* if there was a + symbol */ + + if (pcrel) { + add_number -= md_pcrel_from(fixP); + if (add_symbolP == 0) { + fixP->fx_addsy = & abs_symbol; + ++seg_reloc_count; + } /* if there's an add_symbol */ + } /* if pcrel */ + + if (!fixP->fx_bit_fixP) { + if ((size==1 && + (add_number& ~0xFF) && (add_number&~0xFF!=(-1&~0xFF))) || + (size==2 && + (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF)))) { + as_bad("Value of %d too large for field of %d bytes at 0x%x", + add_number, size, fragP->fr_address + where); + } /* generic error checking */ + } /* not a bit fix */ + + md_apply_fix(fixP, add_number); + } /* For each fixS in this segment. */ + +#ifdef OBJ_COFF +#ifdef TC_I960 +{ + fixS *topP = fixP; + + /* two relocs per callj under coff. */ + for (fixP = topP; fixP; fixP = fixP->fx_next) { + if (fixP->fx_callj && fixP->fx_addsy != 0) { + ++seg_reloc_count; + } /* if callj and not already fixed. */ + } /* for each fix */ +} +#endif /* TC_I960 */ + +#endif /* OBJ_COFF */ + return(seg_reloc_count); +} /* fixup_segment() */ +#endif + + +void obj_coff_lcomm(void) +{ + char *name; + char c; + int temp; + char *p; +symbolS *symbolP; + name = input_line_pointer; + + + + c = get_symbol_end(); + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE(); + if (*input_line_pointer != ',') { + as_bad("Expected comma after name"); + ignore_rest_of_line(); + return; + } + if (*input_line_pointer == '\n') { + as_bad("Missing size expression"); + return; + } +input_line_pointer++; + if ((temp = get_absolute_expression ()) < 0) { + as_warn("lcomm length (%d.) <0! Ignored.", temp); + ignore_rest_of_line(); + return; + } + *p = 0; + symbolP = symbol_find_or_make(name); + S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size); + S_SET_SEGMENT(symbolP, SEG_E2); + segment_info[SEG_E2].scnhdr.s_size += temp; + S_SET_STORAGE_CLASS(symbolP, C_STAT); + demand_empty_rest_of_line(); +} diff --git a/gas/config/obj-coff-bfd.h b/gas/config/obj-coff-bfd.h new file mode 100755 index 00000000000..97a7e0aba93 --- /dev/null +++ b/gas/config/obj-coff-bfd.h @@ -0,0 +1,558 @@ +/* coff object file format + Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. + +This file is part of GAS. + +GAS is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GAS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* $Id$ */ + +#define OBJ_COFF 1 + +#include "targ-cpu.h" + + +#ifdef BFD_HEADERS +#include "bfd.h" + +extern bfd *stdoutput; +/* This internal_lineno crap is to stop namespace pollution from the + bfd internal coff headerfile. */ + +#define internal_lineno bfd_internal_lineno +#include "internalcoff.h" +#undef internal_lineno + +#if defined(TC_H8300) +#include "coff-h8300.h" +#define TARGET_FORMAT "coff-h8300" +#elif defined(TC_A29K) +#include "coff-a29k.h" +#define TARGET_FORMAT "coff-a29k-big" +#else +help me +#endif +#else +#include "coff.gnu.h" +#endif + +#ifdef USE_NATIVE_HEADERS +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* USE_NATIVE_HEADERS */ + +/* Define some processor dependent values according to the processor we are + on. */ +#if defined(TC_H8300) +#define BYTE_ORDERING 0 +#define FILE_HEADER_MAGIC H8300MAGIC +#elif defined(TC_M68K) + +#define BYTE_ORDERING F_AR32W /* See filehdr.h for more info. */ +#ifndef FILE_HEADER_MAGIC +#define FILE_HEADER_MAGIC MC68MAGIC /* ... */ +#endif /* FILE_HEADER_MAGIC */ + +#elif defined(TC_I386) + +#define BYTE_ORDERING F_AR32WR /* See filehdr.h for more info. */ +#ifndef FILE_HEADER_MAGIC +#define FILE_HEADER_MAGIC I386MAGIC /* ... */ +#endif /* FILE_HEADER_MAGIC */ + +#elif defined(TC_I960) + +#define BYTE_ORDERING F_AR32WR /* See filehdr.h for more info. */ +#ifndef FILE_HEADER_MAGIC +#define FILE_HEADER_MAGIC I960ROMAGIC /* ... */ +#endif /* FILE_HEADER_MAGIC */ + +#elif defined(TC_A29K) + +#define BYTE_ORDERING F_AR32W /* big endian. */ +#ifndef FILE_HEADER_MAGIC +#define FILE_HEADER_MAGIC SIPFBOMAGIC +#endif /* FILE_HEADER_MAGIC */ + +#else +you lose +#endif + + +#ifndef OBJ_COFF_MAX_AUXENTRIES +#define OBJ_COFF_MAX_AUXENTRIES 1 +#endif /* OBJ_COFF_MAX_AUXENTRIES */ + +extern const short seg_N_TYPE[]; +extern const segT N_TYPE_seg[]; + +/* Magic number of paged executable. */ +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 0x8300 + +#ifndef BFD_HEADERS + +/* Add these definitions to have a consistent convention for all the + types used in COFF format. */ +#define AOUTHDR struct aouthdr +#define AOUTHDRSZ sizeof(AOUTHDR) +#endif + +/* SYMBOL TABLE */ + + /* targets may also set this */ +#ifndef SYMBOLS_NEED_BACKPOINTERS +#define SYMBOLS_NEED_BACKPOINTERS 1 +#endif /* SYMBOLS_NEED_BACKPOINTERS */ + +/* Symbol table entry data type */ + +typedef struct +{ + struct internal_syment ost_entry; /* Basic symbol */ + union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; /* Auxiliary entry. */ + + unsigned int ost_flags; /* obj_coff internal use only flags */ +} obj_symbol_type; + +#define DO_NOT_STRIP 0 +#define DO_STRIP 1 + +/* Symbol table macros and constants */ + +/* Possible and usefull section number in symbol table + * The values of TEXT, DATA and BSS may not be portable. + */ + +#define C_ABS_SECTION N_ABS +#define C_UNDEF_SECTION N_UNDEF +#define C_DEBUG_SECTION N_DEBUG +#define C_NTV_SECTION N_TV +#define C_PTV_SECTION P_TV +#define C_REGISTER_SECTION 4 + +/* + * Macros to extract information from a symbol table entry. + * This syntaxic indirection allows independence regarding a.out or coff. + * The argument (s) of all these macros is a pointer to a symbol table entry. + */ + +/* Predicates */ +/* True if the symbol is external */ +#define S_IS_EXTERNAL(s) ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION) +/* True if symbol has been defined, ie : + section > 0 (DATA, TEXT or BSS) + section == 0 and value > 0 (external bss symbol) */ +#define S_IS_DEFINED(s) ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION || \ + ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION && \ + (s)->sy_symbol.ost_entry.n_value > 0)) +/* True if a debug special symbol entry */ +#define S_IS_DEBUG(s) ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION) +/* True if a symbol is local symbol name */ +/* A symbol name whose name begin with ^A is a gas internal pseudo symbol */ +#define S_IS_LOCAL(s) (S_GET_NAME(s)[0] == '\001' || \ + (s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION || \ + (S_LOCAL_NAME(s) && !flagseen['L'])) +/* True if a symbol is not defined in this file */ +#define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value == 0) +/* + * True if a symbol can be multiply defined (bss symbols have this def + * though it is bad practice) + */ +#define S_IS_COMMON(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value != 0) +/* True if a symbol name is in the string table, i.e. its length is > 8. */ +#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0) + +/* Accessors */ +/* The name of the symbol */ +#define S_GET_NAME(s) ((char*)(s)->sy_symbol.ost_entry.n_offset) +/* The pointer to the string table */ +#define S_GET_OFFSET(s) ((s)->sy_symbol.ost_entry.n_offset) +/* The zeroes if symbol name is longer than 8 chars */ +#define S_GET_ZEROES(s) ((s)->sy_symbol.ost_entry.n_zeroes) +/* The value of the symbol */ +#define S_GET_VALUE(s) ((unsigned) ((s)->sy_symbol.ost_entry.n_value)) +/* The numeric value of the segment */ +#define S_GET_SEGMENT(s) s_get_segment(s) +/* The data type */ +#define S_GET_DATA_TYPE(s) ((s)->sy_symbol.ost_entry.n_type) +/* The storage class */ +#define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass) +/* The number of auxiliary entries */ +#define S_GET_NUMBER_AUXILIARY(s) ((s)->sy_symbol.ost_entry.n_numaux) + +/* Modifiers */ +/* Set the name of the symbol */ +#define S_SET_NAME(s,v) ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v)) +/* Set the offset of the symbol */ +#define S_SET_OFFSET(s,v) ((s)->sy_symbol.ost_entry.n_offset = (v)) +/* The zeroes if symbol name is longer than 8 chars */ +#define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v)) +/* Set the value of the symbol */ +#define S_SET_VALUE(s,v) ((s)->sy_symbol.ost_entry.n_value = (v)) +/* The numeric value of the segment */ +#define S_SET_SEGMENT(s,v) ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v)) +/* The data type */ +#define S_SET_DATA_TYPE(s,v) ((s)->sy_symbol.ost_entry.n_type = (v)) +/* The storage class */ +#define S_SET_STORAGE_CLASS(s,v) ((s)->sy_symbol.ost_entry.n_sclass = (v)) +/* The number of auxiliary entries */ +#define S_SET_NUMBER_AUXILIARY(s,v) ((s)->sy_symbol.ost_entry.n_numaux = (v)) + +/* Additional modifiers */ +/* The symbol is external (does not mean undefined) */ +#define S_SET_EXTERNAL(s) { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); } + +/* Auxiliary entry macros. SA_ stands for symbol auxiliary */ +/* Omit the tv related fields */ +/* Accessors */ +#ifdef BFD_HEADERS +#define SA_GET_SYM_TAGNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l) +#else +#define SA_GET_SYM_TAGNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx) +#endif +#define SA_GET_SYM_LNNO(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno) +#define SA_GET_SYM_SIZE(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size) +#define SA_GET_SYM_FSIZE(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize) +#define SA_GET_SYM_LNNOPTR(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr) +#ifdef BFD_HEADERS +#define SA_GET_SYM_ENDNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l) +#else +#define SA_GET_SYM_ENDNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx) +#endif +#define SA_GET_SYM_DIMEN(s,i) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)]) +#define SA_GET_FILE_FNAME(s) ((s)->sy_symbol.ost_auxent[0].x_file.x_fname) +#define SA_GET_SCN_SCNLEN(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen) +#define SA_GET_SCN_NRELOC(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc) +#define SA_GET_SCN_NLINNO(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno) + +/* Modifiers */ +#ifdef BFD_HEADERS +#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l=(v)) +#else +#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx=(v)) +#endif +#define SA_SET_SYM_LNNO(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno=(v)) +#define SA_SET_SYM_SIZE(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size=(v)) +#define SA_SET_SYM_FSIZE(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize=(v)) +#define SA_SET_SYM_LNNOPTR(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr=(v)) +#ifdef BFD_HEADERS +#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l=(v)) +#else +#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx=(v)) +#endif +#define SA_SET_SYM_DIMEN(s,i,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v)) +#define SA_SET_FILE_FNAME(s,v) strncpy((s)->sy_symbol.ost_auxent[0].x_file.x_fname,(v),FILNMLEN) +#define SA_SET_SCN_SCNLEN(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen=(v)) +#define SA_SET_SCN_NRELOC(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc=(v)) +#define SA_SET_SCN_NLINNO(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno=(v)) + +/* + * Internal use only definitions. SF_ stands for symbol flags. + * + * These values can be assigned to sy_symbol.ost_flags field of a symbolS. + * + * You'll break i960 if you shift the SYSPROC bits anywhere else. for + * more on the balname/callname hack, see tc-i960.h. b.out is done + * differently. + */ + +#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */ +#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ +#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */ +#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */ +#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */ + +#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */ + +#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */ +#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */ +#define SF_STRING (0x00004000) /* Symbol name length > 8 */ +#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */ + +#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */ + +#define SF_FUNCTION (0x00010000) /* The symbol is a function */ +#define SF_PROCESS (0x00020000) /* Process symbol before write */ +#define SF_TAGGED (0x00040000) /* Is associated with a tag */ +#define SF_TAG (0x00080000) /* Is a tag */ +#define SF_DEBUG (0x00100000) /* Is in debug or abs section */ +#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */ + /* All other bits are unused. */ + +/* Accessors */ +#define SF_GET(s) ((s)->sy_symbol.ost_flags) +#define SF_GET_NORMAL_FIELD(s) ((s)->sy_symbol.ost_flags & SF_NORMAL_MASK) +#define SF_GET_DEBUG_FIELD(s) ((s)->sy_symbol.ost_flags & SF_DEBUG_MASK) +#define SF_GET_FILE(s) ((s)->sy_symbol.ost_flags & SF_FILE) +#define SF_GET_STATICS(s) ((s)->sy_symbol.ost_flags & SF_STATICS) +#define SF_GET_DEFINED(s) ((s)->sy_symbol.ost_flags & SF_DEFINED) +#define SF_GET_STRING(s) ((s)->sy_symbol.ost_flags & SF_STRING) +#define SF_GET_LOCAL(s) ((s)->sy_symbol.ost_flags & SF_LOCAL) +#define SF_GET_FUNCTION(s) ((s)->sy_symbol.ost_flags & SF_FUNCTION) +#define SF_GET_PROCESS(s) ((s)->sy_symbol.ost_flags & SF_PROCESS) +#define SF_GET_DEBUG(s) ((s)->sy_symbol.ost_flags & SF_DEBUG) +#define SF_GET_TAGGED(s) ((s)->sy_symbol.ost_flags & SF_TAGGED) +#define SF_GET_TAG(s) ((s)->sy_symbol.ost_flags & SF_TAG) +#define SF_GET_GET_SEGMENT(s) ((s)->sy_symbol.ost_flags & SF_GET_SEGMENT) +#define SF_GET_I960(s) ((s)->sy_symbol.ost_flags & SF_I960_MASK) /* used by i960 */ +#define SF_GET_BALNAME(s) ((s)->sy_symbol.ost_flags & SF_BALNAME) /* used by i960 */ +#define SF_GET_CALLNAME(s) ((s)->sy_symbol.ost_flags & SF_CALLNAME) /* used by i960 */ +#define SF_GET_IS_SYSPROC(s) ((s)->sy_symbol.ost_flags & SF_IS_SYSPROC) /* used by i960 */ +#define SF_GET_SYSPROC(s) ((s)->sy_symbol.ost_flags & SF_SYSPROC) /* used by i960 */ + +/* Modifiers */ +#define SF_SET(s,v) ((s)->sy_symbol.ost_flags = (v)) +#define SF_SET_NORMAL_FIELD(s,v)((s)->sy_symbol.ost_flags |= ((v) & SF_NORMAL_MASK)) +#define SF_SET_DEBUG_FIELD(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_DEBUG_MASK)) +#define SF_SET_FILE(s) ((s)->sy_symbol.ost_flags |= SF_FILE) +#define SF_SET_STATICS(s) ((s)->sy_symbol.ost_flags |= SF_STATICS) +#define SF_SET_DEFINED(s) ((s)->sy_symbol.ost_flags |= SF_DEFINED) +#define SF_SET_STRING(s) ((s)->sy_symbol.ost_flags |= SF_STRING) +#define SF_SET_LOCAL(s) ((s)->sy_symbol.ost_flags |= SF_LOCAL) +#define SF_CLEAR_LOCAL(s) ((s)->sy_symbol.ost_flags &= ~SF_LOCAL) +#define SF_SET_FUNCTION(s) ((s)->sy_symbol.ost_flags |= SF_FUNCTION) +#define SF_SET_PROCESS(s) ((s)->sy_symbol.ost_flags |= SF_PROCESS) +#define SF_SET_DEBUG(s) ((s)->sy_symbol.ost_flags |= SF_DEBUG) +#define SF_SET_TAGGED(s) ((s)->sy_symbol.ost_flags |= SF_TAGGED) +#define SF_SET_TAG(s) ((s)->sy_symbol.ost_flags |= SF_TAG) +#define SF_SET_GET_SEGMENT(s) ((s)->sy_symbol.ost_flags |= SF_GET_SEGMENT) +#define SF_SET_I960(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_I960_MASK)) /* used by i960 */ +#define SF_SET_BALNAME(s) ((s)->sy_symbol.ost_flags |= SF_BALNAME) /* used by i960 */ +#define SF_SET_CALLNAME(s) ((s)->sy_symbol.ost_flags |= SF_CALLNAME) /* used by i960 */ +#define SF_SET_IS_SYSPROC(s) ((s)->sy_symbol.ost_flags |= SF_IS_SYSPROC) /* used by i960 */ +#define SF_SET_SYSPROC(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_SYSPROC)) /* used by i960 */ + +/* File header macro and type definition */ + +/* + * File position calculators. Beware to use them when all the + * appropriate fields are set in the header. + */ + +#ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER +#define OBJ_COFF_AOUTHDRSZ (0) +#else +#define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ) +#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ + +#define H_GET_FILE_SIZE(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \ + H_GET_SYMBOL_TABLE_SIZE(h) + \ + (h)->string_table_size) +#define H_GET_TEXT_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ) +#define H_GET_DATA_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h)) +#define H_GET_BSS_FILE_OFFSET(h) 0 +#define H_GET_RELOCATION_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h)) +#define H_GET_LINENO_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_RELOCATION_SIZE(h)) +#define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \ + (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ + H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ + H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h)) + +/* Accessors */ +/* aouthdr */ +#define H_GET_MAGIC_NUMBER(h) ((h)->aouthdr.magic) +#define H_GET_VERSION_STAMP(h) ((h)->aouthdr.vstamp) +#define H_GET_TEXT_SIZE(h) ((h)->aouthdr.tsize) +#define H_GET_DATA_SIZE(h) ((h)->aouthdr.dsize) +#define H_GET_BSS_SIZE(h) ((h)->aouthdr.bsize) +#define H_GET_ENTRY_POINT(h) ((h)->aouthdr.entry) +#define H_GET_TEXT_START(h) ((h)->aouthdr.text_start) +#define H_GET_DATA_START(h) ((h)->aouthdr.data_start) +/* filehdr */ +#define H_GET_FILE_MAGIC_NUMBER(h) ((h)->filehdr.f_magic) +#define H_GET_NUMBER_OF_SECTIONS(h) ((h)->filehdr.f_nscns) +#define H_GET_TIME_STAMP(h) ((h)->filehdr.f_timdat) +#define H_GET_SYMBOL_TABLE_POINTER(h) ((h)->filehdr.f_symptr) +#define H_GET_SYMBOL_COUNT(h) ((h)->filehdr.f_nsyms) +#define H_GET_SYMBOL_TABLE_SIZE(h) (H_GET_SYMBOL_COUNT(h) * SYMESZ) +#define H_GET_SIZEOF_OPTIONAL_HEADER(h) ((h)->filehdr.f_opthdr) +#define H_GET_FLAGS(h) ((h)->filehdr.f_flags) +/* Extra fields to achieve bsd a.out compatibility and for convenience */ +#define H_GET_RELOCATION_SIZE(h) ((h)->relocation_size) +#define H_GET_STRING_SIZE(h) ((h)->string_table_size) +#define H_GET_LINENO_SIZE(h) ((h)->lineno_size) + +#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER +#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ + + sizeof(AOUTHDR)\ + + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) +#else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ +#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ + + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) +#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ + +#define H_GET_TEXT_RELOCATION_SIZE(h) (text_section_header.s_nreloc * RELSZ) +#define H_GET_DATA_RELOCATION_SIZE(h) (data_section_header.s_nreloc * RELSZ) + +/* Modifiers */ +/* aouthdr */ +#define H_SET_MAGIC_NUMBER(h,v) ((h)->aouthdr.magic = (v)) +#define H_SET_VERSION_STAMP(h,v) ((h)->aouthdr.vstamp = (v)) +#define H_SET_TEXT_SIZE(h,v) ((h)->aouthdr.tsize = (v)) +#define H_SET_DATA_SIZE(h,v) ((h)->aouthdr.dsize = (v)) +#define H_SET_BSS_SIZE(h,v) ((h)->aouthdr.bsize = (v)) +#define H_SET_ENTRY_POINT(h,v) ((h)->aouthdr.entry = (v)) +#define H_SET_TEXT_START(h,v) ((h)->aouthdr.text_start = (v)) +#define H_SET_DATA_START(h,v) ((h)->aouthdr.data_start = (v)) +/* filehdr */ +#define H_SET_FILE_MAGIC_NUMBER(h,v) ((h)->filehdr.f_magic = (v)) +#define H_SET_NUMBER_OF_SECTIONS(h,v) ((h)->filehdr.f_nscns = (v)) +#define H_SET_TIME_STAMP(h,v) ((h)->filehdr.f_timdat = (v)) +#define H_SET_SYMBOL_TABLE_POINTER(h,v) ((h)->filehdr.f_symptr = (v)) +#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->filehdr.f_nsyms = (v)) +#define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v)) +#define H_SET_FLAGS(h,v) ((h)->filehdr.f_flags = (v)) +/* Extra fields to achieve bsd a.out compatibility and for convinience */ +#define H_SET_RELOCATION_SIZE(h,t,d) ((h)->relocation_size = (t)+(d)) +#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) +#define H_SET_LINENO_SIZE(h,v) ((h)->lineno_size = (v)) + + /* Segment flipping */ +#define segment_name(v) (seg_name[(int) (v)]) + +typedef struct { +#ifdef BFD_HEADERS + struct internal_aouthdr aouthdr; /* a.out header */ + struct internal_filehdr filehdr; /* File header, not machine dep. */ +#else + AOUTHDR aouthdr; /* a.out header */ + FILHDR filehdr; /* File header, not machine dep. */ +#endif + long string_table_size; /* names + '\0' + sizeof(int) */ + long relocation_size; /* Cumulated size of relocation + information for all sections in + bytes. */ + long lineno_size; /* Size of the line number information + table in bytes */ +} object_headers; + + + +struct lineno_list +{ + + struct bfd_internal_lineno line; + char* frag; /* Frag to which the line number is related */ + struct lineno_list* next; /* Forward chain pointer */ +} ; + + + + + /* stack stuff */ +typedef struct { + unsigned long chunk_size; + unsigned long element_size; + unsigned long size; + char* data; + unsigned long pointer; +} stack; + +#ifdef __STDC__ + +char *stack_pop(stack *st); +char *stack_push(stack *st, char *element); +char *stack_top(stack *st); +stack *stack_init(unsigned long chunk_size, unsigned long element_size); +void c_dot_file_symbol(char *filename); +void obj_extra_stuff(object_headers *headers); +void stack_delete(stack *st); + +#ifndef tc_headers_hook +void tc_headers_hook(object_headers *headers); +#endif /* tc_headers_hook */ + +#ifndef tc_coff_symbol_emit_hook +void tc_coff_symbol_emit_hook(); /* really tc_coff_symbol_emit_hook(symbolS *symbolP) */ +#endif /* tc_coff_symbol_emit_hook */ + +void c_section_header( +#ifdef BFD_HEADERS + struct internal_scnhdr *header, +#else + SCNHDR *header, +#endif + + char *name, + long core_address, + long size, + long data_ptr, + long reloc_ptr, + long lineno_ptr, + long reloc_number, + long lineno_number, + long alignment); + +#else /* __STDC__ */ + +char *stack_pop(); +char *stack_push(); +char *stack_top(); +stack *stack_init(); +void c_dot_file_symbol(); +void c_section_header(); +void obj_extra_stuff(); +void stack_delete(); +void tc_headers_hook(); +void tc_coff_symbol_emit_hook(); + +#endif /* __STDC__ */ + + + /* sanity check */ + +#ifdef TC_I960 +#ifndef C_LEAFSTAT +hey! Where is the C_LEAFSTAT definition? i960-coff support is depending on it. +#endif /* no C_LEAFSTAT */ +#endif /* TC_I960 */ +#ifdef BFD_HEADERS +extern struct internal_scnhdr data_section_header; +extern struct internal_scnhdr text_section_header; +#else +extern SCNHDR data_section_header; +extern SCNHDR text_section_header; +#endif +/* + * Local Variables: + * comment-column: 0 + * fill-column: 131 + * End: + */ + +/* end of obj-coff.h */ -- 2.30.2