X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fwrite.c;h=91871da548ee4ee06766e22e1b8afc4b3eea4e05;hb=96fe71e1d5874b8796145e7e73bd7efedb578666;hp=dc4c4e45a764c8a3c0e9dce26e08e38c57d84792;hpb=3a0e38ee59290c597fb61f8c681f40f44e931a2e;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/write.c b/gas/write.c index dc4c4e45a7..91871da548 100644 --- a/gas/write.c +++ b/gas/write.c @@ -1,5 +1,6 @@ /* write.c - emit .o file - Copyright (C) 1986, 87, 90, 91, 92, 93, 1994 Free Software Foundation, Inc. + Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 1995 + Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -15,7 +16,7 @@ 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. */ + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This thing should be set up to do byteordering correctly. But... */ @@ -24,6 +25,10 @@ #include "obstack.h" #include "output-file.h" +/* This looks like a good idea. Let's try turning it on always, for now. */ +#undef BFD_FAST_SECTION_FILL +#define BFD_FAST_SECTION_FILL + /* The NOP_OPCODE is for the alignment fill value. Fill it with a nop instruction so that the disassembler does not choke on it. */ #ifndef NOP_OPCODE @@ -38,11 +43,32 @@ #define TC_FORCE_RELOCATION(FIXP) 0 #endif +#ifndef TC_FORCE_RELOCATION_SECTION +#define TC_FORCE_RELOCATION_SECTION(FIXP,SEG) TC_FORCE_RELOCATION(FIXP) +#endif + +#ifndef MD_PCREL_FROM_SECTION +#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from(FIXP) +#endif + #ifndef WORKING_DOT_WORD extern CONST int md_short_jump_size; extern CONST int md_long_jump_size; #endif +int symbol_table_frozen; +void print_fixup PARAMS ((fixS *)); + +#ifdef BFD_ASSEMBLER +static void renumber_sections PARAMS ((bfd *, asection *, PTR)); + +/* We generally attach relocs to frag chains. However, after we have + chained these all together into a segment, any relocs we add after + that must be attached to a segment. This will include relocs added + in md_estimate_size_for_relax, for example. */ +static int frags_chained = 0; +#endif + #ifndef BFD_ASSEMBLER #ifndef MANY_SEGMENTS @@ -55,9 +81,8 @@ struct frag *data_last_frag; /* Last frag in segment. */ static struct frag *bss_last_frag; /* Last frag in segment. */ #endif -#if ! defined (BFD_ASSEMBLER) && ! defined (BFD) +#ifndef BFD static object_headers headers; -static char *the_object_file; #endif long string_byte_count; @@ -80,7 +105,7 @@ static fixS *fix_new_internal PARAMS ((fragS *, int where, int size, offsetT offset, int pcrel, int r_type)); #endif -#if defined (BFD_ASSEMBLER) || !defined (BFD) +#if defined (BFD_ASSEMBLER) || (!defined (BFD) && !defined (OBJ_VMS)) static long fixup_segment PARAMS ((fixS * fixP, segT this_segment_type)); #endif static relax_addressT relax_align PARAMS ((relax_addressT addr, int align)); @@ -113,10 +138,17 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel, fixP->fx_frag = frag; fixP->fx_where = where; fixP->fx_size = size; + /* We've made fx_size a narrow field; check that it's wide enough. */ + if (fixP->fx_size != size) + { + as_bad ("field fx_size too small to hold %d", size); + abort (); + } fixP->fx_addsy = add_symbol; fixP->fx_subsy = sub_symbol; fixP->fx_offset = offset; fixP->fx_pcrel = pcrel; + fixP->fx_plt = 0; #if defined(NEED_FX_R_TYPE) || defined (BFD_ASSEMBLER) fixP->fx_r_type = r_type; #endif @@ -124,12 +156,11 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel, fixP->fx_pcrel_adjust = 0; fixP->fx_bit_fixP = 0; fixP->fx_addnumber = 0; - fixP->tc_fix_data = NULL; fixP->fx_tcbit = 0; fixP->fx_done = 0; -#ifdef TC_something - fixP->fx_bsr = 0; +#ifdef TC_FIX_TYPE + TC_INIT_FIX_DATA(fixP); #endif as_where (&fixP->fx_file, &fixP->fx_line); @@ -142,8 +173,12 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel, { #ifdef BFD_ASSEMBLER - fixS **seg_fix_rootP = &frchain_now->fix_root; - fixS **seg_fix_tailP = &frchain_now->fix_tail; + fixS **seg_fix_rootP = (frags_chained + ? &seg_info (now_seg)->fix_root + : &frchain_now->fix_root); + fixS **seg_fix_tailP = (frags_chained + ? &seg_info (now_seg)->fix_tail + : &frchain_now->fix_tail); #endif #ifdef REVERSE_SORT_RELOCS @@ -174,7 +209,7 @@ fixS * fix_new (frag, where, size, add_symbol, offset, pcrel, r_type) fragS *frag; /* Which frag? */ int where; /* Where in that frag? */ - short int size; /* 1, 2, or 4 usually. */ + int size; /* 1, 2, or 4 usually. */ symbolS *add_symbol; /* X_add_symbol. */ offsetT offset; /* X_add_number. */ int pcrel; /* TRUE if PC-relative relocation. */ @@ -196,7 +231,7 @@ fixS * fix_new_exp (frag, where, size, exp, pcrel, r_type) fragS *frag; /* Which frag? */ int where; /* Where in that frag? */ - short int size; /* 1, 2, or 4 usually. */ + int size; /* 1, 2, or 4 usually. */ expressionS *exp; /* Expression. */ int pcrel; /* TRUE if PC-relative relocation. */ #ifdef BFD_ASSEMBLER @@ -208,12 +243,38 @@ fix_new_exp (frag, where, size, exp, pcrel, r_type) symbolS *add = NULL; symbolS *sub = NULL; offsetT off = 0; - + switch (exp->X_op) { case O_absent: break; + case O_add: + /* This comes up when _GLOBAL_OFFSET_TABLE_+(.-L0) is read, if + the difference expression cannot immediately be reduced. */ + { + extern symbolS *make_expr_symbol (); + symbolS *stmp = make_expr_symbol (exp); + exp->X_op = O_symbol; + exp->X_op_symbol = 0; + exp->X_add_symbol = stmp; + exp->X_add_number = 0; + return fix_new_exp (frag, where, size, exp, pcrel, r_type); + } + + case O_symbol_rva: + add = exp->X_add_symbol; + off = exp->X_add_number; + +#if defined(BFD_ASSEMBLER) + r_type = BFD_RELOC_RVA; +#elif defined(TC_RVA_RELOC) + r_type = TC_RVA_RELOC; +#else + as_fatal("rva not supported"); +#endif + break; + case O_uminus: sub = exp->X_add_symbol; off = exp->X_add_number; @@ -270,6 +331,8 @@ record_alignment (seg, align) boundary, etc.) */ int align; { + if (seg == absolute_section) + return; #ifdef BFD_ASSEMBLER if (align > bfd_get_section_alignment (stdoutput, seg)) bfd_set_section_alignment (stdoutput, seg, align); @@ -279,6 +342,24 @@ record_alignment (seg, align) #endif } +#ifdef BFD_ASSEMBLER + +/* Reset the section indices after removing the gas created sections. */ + +static void +renumber_sections (abfd, sec, countparg) + bfd *abfd; + asection *sec; + PTR countparg; +{ + int *countp = (int *) countparg; + + sec->index = *countp; + ++*countp; +} + +#endif /* defined (BFD_ASSEMBLER) */ + #if defined (BFD_ASSEMBLER) || ! defined (BFD) static fragS * @@ -287,22 +368,27 @@ chain_frchains_together_1 (section, frchp) struct frchain *frchp; { fragS dummy, *prev_frag = &dummy; +#ifdef BFD_ASSEMBLER fixS fix_dummy, *prev_fix = &fix_dummy; +#endif for (; frchp && frchp->frch_seg == section; frchp = frchp->frch_next) { prev_frag->fr_next = frchp->frch_root; prev_frag = frchp->frch_last; + assert (prev_frag->fr_type != 0); #ifdef BFD_ASSEMBLER if (frchp->fix_root != (fixS *) NULL) { if (seg_info (section)->fix_root == (fixS *) NULL) seg_info (section)->fix_root = frchp->fix_root; prev_fix->fx_next = frchp->fix_root; + seg_info (section)->fix_tail = frchp->fix_tail; prev_fix = frchp->fix_tail; } #endif } + assert (prev_frag->fr_type != 0); prev_frag->fr_next = 0; return prev_frag; } @@ -325,6 +411,10 @@ chain_frchains_together (abfd, section, xxx) if (info != (segment_info_type *) NULL) info->frchainP->frch_last = chain_frchains_together_1 (section, info->frchainP); + + /* Now that we've chained the frags together, we must add new fixups + to the segment, not to the frag chain. */ + frags_chained = 1; } #endif @@ -353,23 +443,31 @@ cvt_frag_to_fill (sec, fragP) fragS *fragP; #else static void -cvt_frag_to_fill (headers, fragP) - object_headers *headers; +cvt_frag_to_fill (headersP, sec, fragP) + object_headers *headersP; + segT sec; fragS *fragP; #endif { switch (fragP->fr_type) { case rs_align: + case rs_align_code: case rs_org: + case rs_space: #ifdef HANDLE_ALIGN HANDLE_ALIGN (fragP); #endif - fragP->fr_type = rs_fill; know (fragP->fr_next != NULL); fragP->fr_offset = (fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix) / fragP->fr_var; + if (fragP->fr_offset < 0) + { + as_bad ("attempt to .org/.space backwards? (%ld)", + (long) fragP->fr_offset); + } + fragP->fr_type = rs_fill; break; case rs_fill: @@ -379,7 +477,7 @@ cvt_frag_to_fill (headers, fragP) #ifdef BFD_ASSEMBLER md_convert_frag (stdoutput, sec, fragP); #else - md_convert_frag (headers, fragP); + md_convert_frag (headersP, sec, fragP); #endif assert (fragP->fr_next == NULL || (fragP->fr_next->fr_address - fragP->fr_address == fragP->fr_fix)); @@ -432,9 +530,11 @@ relax_and_size_seg (abfd, sec, xxx) int x; valueT size, newsize; + subseg_change (sec, 0); + flags = bfd_get_section_flags (abfd, sec); - seginfo = (segment_info_type *) bfd_get_section_userdata (abfd, sec); + seginfo = seg_info (sec); if (seginfo && seginfo->frchainP) { relax_segment (seginfo->frchainP->frch_root, sec); @@ -504,9 +604,19 @@ dump_section_relocs (abfd, sec, stream_) { symbolS *s = fixp->fx_addsy; if (s) - fprintf (stream, " %08x: %s(%s+%x)+%x\n", fixp, - S_GET_NAME (s), s->bsym->section->name, - S_GET_VALUE (s), fixp->fx_offset); + { + fprintf (stream, " %08x: %s(%s", fixp, S_GET_NAME (s), + s->bsym->section->name); + if (s->bsym->flags & BSF_SECTION_SYM) + { + fprintf (stream, " section sym"); + if (S_GET_VALUE (s)) + fprintf (stream, "+%x", S_GET_VALUE (s)); + } + else + fprintf (stream, "+%x", S_GET_VALUE (s)); + fprintf (stream, ")+%x\n", fixp->fx_offset); + } else fprintf (stream, " %08x: type %d no sym\n", fixp, fixp->fx_r_type); fixp = fixp->fx_next; @@ -539,20 +649,43 @@ adjust_reloc_syms (abfd, sec, xxx) /* ignore it */; else if (fixp->fx_addsy) { - symbolS *sym = fixp->fx_addsy; - asection *symsec = sym->bsym->section; + symbolS *sym; + asection *symsec; + + reduce_fixup: + +#ifdef DEBUG5 + fprintf (stderr, "\n\nadjusting fixup:\n"); + print_fixup (fixp); +#endif + + sym = fixp->fx_addsy; + symsec = sym->bsym->section; + + if (sym != NULL && sym->sy_mri_common) + { + /* These symbols are handled specially in fixup_segment. */ + goto done; + } /* If it's one of these sections, assume the symbol is definitely going to be output. The code in md_estimate_size_before_relax in tc-mips.c uses this test as well, so if you change this code you should look at that code. */ - if (symsec == &bfd_und_section - || symsec == &bfd_abs_section + if (bfd_is_und_section (symsec) + || bfd_is_abs_section (symsec) || bfd_is_com_section (symsec)) { fixp->fx_addsy->sy_used_in_reloc = 1; - continue; +#ifdef UNDEFINED_DIFFERENCE_OK + /* We have the difference of an undefined symbol and some + other symbol. Make sure to mark the other symbol as used + in a relocation so that it will always be output. */ + if (fixp->fx_subsy) + fixp->fx_subsy->sy_used_in_reloc = 1; +#endif + goto done; } /* Since we're reducing to section symbols, don't attempt to reduce @@ -560,7 +693,7 @@ adjust_reloc_syms (abfd, sec, xxx) if (sym->bsym->flags & BSF_SECTION_SYM) { fixp->fx_addsy->sy_used_in_reloc = 1; - continue; + goto done; } /* Is there some other reason we can't adjust this one? (E.g., @@ -569,7 +702,7 @@ adjust_reloc_syms (abfd, sec, xxx) if (! obj_fix_adjustable (fixp)) { fixp->fx_addsy->sy_used_in_reloc = 1; - continue; + goto done; } #endif @@ -580,33 +713,51 @@ adjust_reloc_syms (abfd, sec, xxx) if (! tc_fix_adjustable (fixp)) { fixp->fx_addsy->sy_used_in_reloc = 1; - continue; + goto done; } #endif + /* For PIC support: We may get expressions like + "_GLOBAL_OFFSET_TABLE_+(.-L5)" where "." and "L5" may not + necessarily have had a fixed difference initially. But now + it should be a known constant, so we can reduce it. Since + we can't easily handle a symbol value that looks like + someUndefinedSymbol+const, though, we convert the fixup to + access the undefined symbol directly, and discard the + intermediate symbol. */ + if (S_GET_SEGMENT (sym) == expr_section + && sym->sy_value.X_op == O_add + && (resolve_symbol_value (sym->sy_value.X_add_symbol), + S_GET_SEGMENT (sym->sy_value.X_add_symbol) == undefined_section) + && (resolve_symbol_value (sym->sy_value.X_op_symbol), + S_GET_SEGMENT (sym->sy_value.X_op_symbol) == absolute_section)) + { + fixp->fx_offset += S_GET_VALUE (sym->sy_value.X_op_symbol); + fixp->fx_offset += sym->sy_value.X_add_number; + fixp->fx_addsy = sym->sy_value.X_add_symbol; + goto reduce_fixup; + } + /* If the section symbol isn't going to be output, the relocs at least should still work. If not, figure out what to do when we run into that case. */ fixp->fx_offset += S_GET_VALUE (sym); - if (sym->sy_frag) - fixp->fx_offset += sym->sy_frag->fr_address; fixp->fx_addsy = section_symbol (symsec); fixp->fx_addsy->sy_used_in_reloc = 1; + + done: + ; } -#ifdef RELOC_REQUIRES_SYMBOL +#if 1/*def RELOC_REQUIRES_SYMBOL*/ else { /* There was no symbol required by this relocation. However, BFD doesn't really handle relocations without symbols well. (At least, the COFF support doesn't.) So for now we fake up a local symbol in the absolute section. */ - static symbolS *abs_sym; - if (!abs_sym) - { - abs_sym = section_symbol (absolute_section); - abs_sym->sy_used_in_reloc = 1; - } - fixp->fx_addsy = abs_sym; + + fixp->fx_addsy = section_symbol (absolute_section); +/* fixp->fx_addsy->sy_used_in_reloc = 1; */ } #endif @@ -647,7 +798,6 @@ write_relocs (abfd, sec, xxx) for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next) { arelent *reloc; - char *data; bfd_reloc_status_type s; if (fixp->fx_done) @@ -661,30 +811,24 @@ write_relocs (abfd, sec, xxx) n--; continue; } - data = fixp->fx_frag->fr_literal + fixp->fx_where; if (fixp->fx_where + fixp->fx_size > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset) abort (); - if (reloc->howto->partial_inplace == false - && reloc->howto->pcrel_offset == true - && reloc->howto->pc_relative == true) - { - /* bfd_perform_relocation screws this up */ - reloc->addend += reloc->address; - } - /* Pass bogus address so that when bfd_perform_relocation adds - `reloc->address' back in, it'll come up with `data', which is where - we want it to operate. We can't just do it by fudging reloc->address, - since that might be used in the calculations(?). */ - s = bfd_perform_relocation (stdoutput, reloc, data - reloc->address, - sec, stdoutput, &err); + s = bfd_install_relocation (stdoutput, reloc, + fixp->fx_frag->fr_literal, + fixp->fx_frag->fr_address, + sec, &err); switch (s) { case bfd_reloc_ok: break; + case bfd_reloc_overflow: + as_bad_where (fixp->fx_file, fixp->fx_line, "relocation overflow"); + break; default: - as_fatal ("bad return from bfd_perform_relocation"); + as_fatal ("%s:%u: bad return from bfd_perform_relocation", + fixp->fx_file, fixp->fx_line); } relocs[i++] = reloc; } @@ -720,21 +864,45 @@ write_relocs (abfd, sec, xxx) abort (); for (j = 0; reloc[j]; j++) { - s = bfd_perform_relocation (stdoutput, reloc[j], - data - reloc[0]->address, - sec, stdoutput, &err); + s = bfd_install_relocation (stdoutput, reloc[j], + fixp->fx_frag->fr_literal, + fixp->fx_frag->fr_address, + sec, &err); switch (s) { case bfd_reloc_ok: break; + case bfd_reloc_overflow: + as_bad_where (fixp->fx_file, fixp->fx_line, + "relocation overflow"); + break; default: - as_fatal ("bad return from bfd_perform_relocation"); + as_fatal ("%s:%u: bad return from bfd_perform_relocation", + fixp->fx_file, fixp->fx_line); } } } n = i; #endif +#ifdef DEBUG4 + { + int i, j, nsyms; + asymbol **sympp; + sympp = bfd_get_outsymbols (stdoutput); + nsyms = bfd_get_symcount (stdoutput); + for (i = 0; i < n; i++) + if (((*relocs[i]->sym_ptr_ptr)->flags & BSF_SECTION_SYM) == 0) + { + for (j = 0; j < nsyms; j++) + if (sympp[j] == *relocs[i]->sym_ptr_ptr) + break; + if (j == nsyms) + abort (); + } + } +#endif + if (n) bfd_set_reloc (stdoutput, sec, relocs, n); else @@ -789,7 +957,12 @@ write_contents (abfd, sec, xxx) x = bfd_set_section_contents (stdoutput, sec, f->fr_literal, (file_ptr) offset, (bfd_size_type) f->fr_fix); - assert (x == true); + if (x == false) + { + bfd_perror (stdoutput->filename); + as_perror ("FATAL: Can't write %s", stdoutput->filename); + exit (EXIT_FAILURE); + } offset += f->fr_fix; } fill_literal = f->fr_literal + f->fr_fix; @@ -797,14 +970,56 @@ write_contents (abfd, sec, xxx) count = f->fr_offset; assert (count >= 0); if (fill_size && count) - while (count--) - { - x = bfd_set_section_contents (stdoutput, sec, - fill_literal, (file_ptr) offset, - (bfd_size_type) fill_size); - assert (x == true); - offset += fill_size; - } + { + char buf[256]; + if (fill_size > sizeof(buf)) + { + /* Do it the old way. Can this ever happen? */ + while (count--) + { + x = bfd_set_section_contents (stdoutput, sec, + fill_literal, + (file_ptr) offset, + (bfd_size_type) fill_size); + if (x == false) + { + bfd_perror (stdoutput->filename); + as_perror ("FATAL: Can't write %s", stdoutput->filename); + exit (EXIT_FAILURE); + } + offset += fill_size; + } + } + else + { + /* Build a buffer full of fill objects and output it as + often as necessary. This saves on the overhead of + potentially lots of bfd_set_section_contents calls. */ + int n_per_buf, i; + if (fill_size == 1) + { + n_per_buf = sizeof (buf); + memset (buf, *fill_literal, n_per_buf); + } + else + { + char *bufp; + n_per_buf = sizeof(buf)/fill_size; + for (i = n_per_buf, bufp = buf; i; i--, bufp += fill_size) + memcpy(bufp, fill_literal, fill_size); + } + for (; count > 0; count -= n_per_buf) + { + n_per_buf = n_per_buf > count ? count : n_per_buf; + x = bfd_set_section_contents (stdoutput, sec, + buf, (file_ptr) offset, + (bfd_size_type) n_per_buf * fill_size); + if (x != true) + as_fatal ("Cannot write to output file."); + offset += n_per_buf * fill_size; + } + } + } } } #endif @@ -933,15 +1148,50 @@ relax_and_size_all_segments () #if defined (BFD_ASSEMBLER) || !defined (BFD) +#ifdef BFD_ASSEMBLER +static void +set_symtab () +{ + int nsyms; + asymbol **asympp; + symbolS *symp; + boolean result; + extern PTR bfd_alloc PARAMS ((bfd *, size_t)); + + /* Count symbols. We can't rely on a count made by the loop in + write_object_file, because *_frob_file may add a new symbol or + two. */ + nsyms = 0; + for (symp = symbol_rootP; symp; symp = symbol_next (symp)) + nsyms++; + + if (nsyms) + { + int i; + + asympp = (asymbol **) bfd_alloc (stdoutput, + nsyms * sizeof (asymbol *)); + symp = symbol_rootP; + for (i = 0; i < nsyms; i++, symp = symbol_next (symp)) + { + asympp[i] = symp->bsym; + symp->written = 1; + } + } + else + asympp = 0; + result = bfd_set_symtab (stdoutput, asympp, nsyms); + assert (result == true); + symbol_table_frozen = 1; +} +#endif + void write_object_file () { - register struct frchain *frchainP; /* Track along all frchains. */ + struct frchain *frchainP; /* Track along all frchains. */ #if ! defined (BFD_ASSEMBLER) || ! defined (WORKING_DOT_WORD) - register fragS *fragP; /* Track along all frags. */ -#endif -#if !defined (BFD_ASSEMBLER) && !defined (OBJ_VMS) - long object_file_size; + fragS *fragP; /* Track along all frags. */ #endif /* Do we really want to write it? */ @@ -951,7 +1201,7 @@ write_object_file () n_errs = had_errors (); /* The -Z flag indicates that an object file should be generated, regardless of warnings and errors. */ - if (flagseen['Z']) + if (flag_always_generate_output) { if (n_warns || n_errs) as_warn ("%d error%s, %d warning%s, generating bad object file.\n", @@ -968,14 +1218,11 @@ write_object_file () } #ifdef OBJ_VMS - /* - * Under VMS we try to be compatible with VAX-11 "C". Thus, we - * call a routine to check for the definition of the procedure - * "_main", and if so -- fix it up so that it can be program - * entry point. - */ - VMS_Check_For_Main (); -#endif /* VMS */ + /* Under VMS we try to be compatible with VAX-11 "C". Thus, we call + a routine to check for the definition of the procedure "_main", + and if so -- fix it up so that it can be program entry point. */ + vms_check_for_main (); +#endif /* OBJ_VMS */ /* After every sub-segment, we fake an ".align ...". This conforms to BSD4.2 brane-damage. We then fake ".fill 0" because that is the kind of @@ -1012,6 +1259,8 @@ write_object_file () /* Remove the sections created by gas for its own purposes. */ { asection **seclist, *sec; + int i; + seclist = &stdoutput->sections; while (seclist && *seclist) { @@ -1027,6 +1276,8 @@ write_object_file () if (*seclist) seclist = &(*seclist)->next; } + i = 0; + bfd_map_over_sections (stdoutput, renumber_sections, &i); } bfd_map_over_sections (stdoutput, chain_frchains_together, (char *) 0); @@ -1040,7 +1291,7 @@ write_object_file () data frags into the text segment. Do this before relaxing so we know to take advantage of -R and make shorter addresses. */ #if !defined (OBJ_AOUT) || defined (BFD_ASSEMBLER) - if (flagseen['R']) + if (flag_readonly_data_in_text) { merge_data_into_text (); } @@ -1094,7 +1345,7 @@ write_object_file () for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) { - cvt_frag_to_fill (&headers, fragP); + cvt_frag_to_fill (&headers, SEG_TEXT, fragP); /* Some assert macros don't work with # directives mixed in. */ #ifndef NDEBUG @@ -1125,9 +1376,15 @@ write_object_file () exp.X_op_symbol = lie->sub; exp.X_add_number = lie->addnum; #ifdef BFD_ASSEMBLER +#ifdef TC_CONS_FIX_NEW + TC_CONS_FIX_NEW (lie->frag, + lie->word_goes_here - lie->frag->fr_literal, + 2, &exp); +#else fix_new_exp (lie->frag, lie->word_goes_here - lie->frag->fr_literal, 2, &exp, 0, BFD_RELOC_NONE); +#endif #else #if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE) fix_new_exp (lie->frag, @@ -1183,6 +1440,9 @@ write_object_file () /* Patch the jump table */ /* This is the offset from ??? to table_ptr+0 */ to_addr = table_addr - S_GET_VALUE (lie->sub); +#ifdef BFD_ASSEMBLER + to_addr -= lie->sub->sy_frag->fr_address; +#endif md_number_to_chars (lie->word_goes_here, to_addr, 2); for (untruth = lie->next_broken_word; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word) { @@ -1194,6 +1454,9 @@ write_object_file () /* this is a long jump from table_ptr+0 to the final target */ from_addr = table_addr; to_addr = S_GET_VALUE (lie->add) + lie->addnum; +#ifdef BFD_ASSEMBLER + to_addr += lie->add->sy_frag->fr_address; +#endif md_create_long_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add); table_ptr += md_long_jump_size; table_addr += md_long_jump_size; @@ -1205,6 +1468,8 @@ write_object_file () #ifndef BFD_ASSEMBLER #ifndef OBJ_VMS { /* not vms */ + char *the_object_file; + long object_file_size; /* * Scan every FixS performing fixups. We had to wait until now to do * this because md_convert_frag() may have made some fixSs. @@ -1241,6 +1506,7 @@ write_object_file () register char *fill_literal; register long fill_size; + PROGRESS (1); know (fragP->fr_type == rs_fill); append (&next_object_file_charP, fragP->fr_literal, (unsigned long) fragP->fr_fix); fill_literal = fragP->fr_literal + fragP->fr_fix; @@ -1301,32 +1567,67 @@ write_object_file () /* Write the data to the file */ output_file_append (the_object_file, object_file_size, out_file_name); + free (the_object_file); #endif } /* non vms output */ -#else /* VMS */ +#else /* OBJ_VMS */ /* * Now do the VMS-dependent part of writing the object file */ - VMS_write_object_file (H_GET_TEXT_SIZE (&headers), + vms_write_object_file (H_GET_TEXT_SIZE (&headers), H_GET_DATA_SIZE (&headers), H_GET_BSS_SIZE (&headers), text_frag_root, data_frag_root); -#endif /* VMS */ +#endif /* OBJ_VMS */ #else /* BFD_ASSEMBLER */ + /* Resolve symbol values. This needs to be done before processing + the relocations. */ + if (symbol_rootP) + { + symbolS *symp; + + for (symp = symbol_rootP; symp; symp = symbol_next (symp)) + if (!symp->sy_resolved) + resolve_symbol_value (symp); + } + + PROGRESS (1); + bfd_map_over_sections (stdoutput, adjust_reloc_syms, (char *)0); /* Set up symbol table, and write it out. */ if (symbol_rootP) { - unsigned int i = 0; - unsigned int n; symbolS *symp; for (symp = symbol_rootP; symp; symp = symbol_next (symp)) { int punt = 0; + const char *name; + + if (symp->sy_mri_common) + { + if (S_IS_EXTERNAL (symp)) + as_bad ("%s: global symbols not supported in common sections", + S_GET_NAME (symp)); + symbol_remove (symp, &symbol_rootP, &symbol_lastP); + continue; + } + name = S_GET_NAME (symp); + if (name) + { + const char *name2 = decode_local_label_name ((char *)S_GET_NAME (symp)); + /* They only differ if `name' is a fb or dollar local + label name. */ + if (name2 != name && ! S_IS_DEFINED (symp)) + as_bad ("local label %s is not defined", name2); + } + + /* Do it again, because adjust_reloc_syms might introduce + more symbols. They'll probably only be section symbols, + but they'll still need to have the values computed. */ if (! symp->sy_resolved) { if (symp->sy_value.X_op == O_constant) @@ -1345,7 +1646,7 @@ write_object_file () Put them in the common section now. */ if (S_IS_DEFINED (symp) == 0 && S_GET_VALUE (symp) != 0) - S_SET_SEGMENT (symp, &bfd_com_section); + S_SET_SEGMENT (symp, bfd_com_section_ptr); #if 0 printf ("symbol `%s'\n\t@%x: value=%d flags=%x seg=%s\n", S_GET_NAME (symp), symp, @@ -1369,35 +1670,18 @@ write_object_file () but we keep such symbols if they are used in relocs. */ if ((! EMIT_SECTION_SYMBOLS && (symp->bsym->flags & BSF_SECTION_SYM) != 0) - || ((S_IS_LOCAL (symp) || punt) + /* Note that S_IS_EXTERN and S_IS_LOCAL are not always + opposites. Sometimes the former checks flags and the + latter examines the name... */ + || (!S_IS_EXTERN (symp) + && (S_IS_LOCAL (symp) || punt) && ! symp->sy_used_in_reloc)) { - symbolS *prev, *next; + symbol_remove (symp, &symbol_rootP, &symbol_lastP); + /* After symbol_remove, symbol_next(symp) still returns + the one that came after it in the chain. So we don't + need to do any extra cleanup work here. */ - prev = symbol_previous (symp); - next = symbol_next (symp); -#ifdef DEBUG_SYMS - verify_symbol_chain_2 (symp); -#endif - if (prev) - { - symbol_next (prev) = next; - symp = prev; - } - else if (symp == symbol_rootP) - symbol_rootP = next; - else - abort (); - if (next) - symbol_previous (next) = prev; - else - symbol_lastP = prev; -#ifdef DEBUG_SYMS - if (prev) - verify_symbol_chain_2 (prev); - else if (next) - verify_symbol_chain_2 (next); -#endif continue; } @@ -1412,43 +1696,32 @@ write_object_file () /* Set the value into the BFD symbol. Up til now the value has only been kept in the gas symbolS struct. */ symp->bsym->value = S_GET_VALUE (symp); - - i++; - } - n = i; - if (n) - { - asymbol **asympp; - boolean result; - extern PTR bfd_alloc PARAMS ((bfd *, size_t)); - - asympp = (asymbol **) bfd_alloc (stdoutput, - n * sizeof (asymbol *)); - symp = symbol_rootP; - for (i = 0; i < n; i++, symp = symbol_next (symp)) - { - asympp[i] = symp->bsym; - symp->written = 1; - } - result = bfd_set_symtab (stdoutput, asympp, n); - assert (result == true); } } -#ifdef tc_frob_file - tc_frob_file (); + PROGRESS (1); + + /* Now do any format-specific adjustments to the symbol table, such + as adding file symbols. */ +#ifdef obj_adjust_symtab + obj_adjust_symtab (); #endif -#ifdef obj_frob_file - /* If obj_frob_file changes the symbol value at this point, it is + /* Now that all the sizes are known, and contents correct, we can + start writing to the file. */ + set_symtab (); + + /* If *_frob_file changes the symbol value at this point, it is responsible for moving the changed value into symp->bsym->value as well. Hopefully all symbol value changing can be done in - {obj,tc}_frob_symbol. */ + *_frob_symbol. */ +#ifdef tc_frob_file + tc_frob_file (); +#endif +#ifdef obj_frob_file obj_frob_file (); #endif - /* Now that all the sizes are known, and contents correct, we can - start writing the file. */ bfd_map_over_sections (stdoutput, write_relocs, (char *) 0); bfd_map_over_sections (stdoutput, write_contents, (char *) 0); @@ -1497,10 +1770,12 @@ relax_align (address, alignment) mask = ~((~0) << alignment); new_address = (address + mask) & (~mask); +#ifdef LINKER_RELAXING_SHRINKS_ONLY if (linkrelax) /* We must provide lots of padding, so the linker can discard it when needed. The linker will not add extra space, ever. */ new_address += (1 << alignment); +#endif return (new_address - address); } @@ -1532,6 +1807,7 @@ relax_segment (segment_frag_root, segment) break; case rs_align: + case rs_align_code: { int offset = relax_align (address, (int) fragP->fr_offset); if (offset % fragP->fr_var != 0) @@ -1545,6 +1821,7 @@ relax_segment (segment_frag_root, segment) break; case rs_org: + case rs_space: /* Assume .org is nugatory. It will grow with 1st relax. */ break; @@ -1628,7 +1905,7 @@ relax_segment (segment_frag_root, segment) + S_GET_VALUE (lie->sub))); if (offset <= -32768 || offset >= 32767) { - if (flagseen['K']) + if (flag_warn_displacement) { char buf[50]; sprint_value (buf, (addressT) lie->addnum); @@ -1660,6 +1937,7 @@ relax_segment (segment_frag_root, segment) } /* case rs_broken_word */ #endif case rs_align: + case rs_align_code: growth = (relax_align ((relax_addressT) (address + fragP->fr_fix), (int) offset) @@ -1688,18 +1966,41 @@ relax_segment (segment_frag_root, segment) know (fragP->fr_next); after = fragP->fr_next->fr_address; - growth = ((target - after) > 0) ? (target - after) : 0; - /* Growth may be negative, but variable part of frag - cannot have fewer than 0 chars. That is, we can't - .org backwards. */ + growth = target - after; + if (growth < 0) + { + /* Growth may be negative, but variable part of frag + cannot have fewer than 0 chars. That is, we can't + .org backwards. */ + as_bad ("attempt to .org backwards ignored"); + growth = 0; + } growth -= stretch; /* This is an absolute growth factor */ break; + case rs_space: + if (symbolP) + { + growth = S_GET_VALUE (symbolP); + if (symbolP->sy_frag != &zero_address_frag) + as_bad (".space specifies non-absolute value"); + fragP->fr_symbol = 0; + if (growth < 0) + { + as_warn (".space or .fill with negative value, ignored"); + growth = 0; + } + } + else + growth = 0; + break; + case rs_machine_dependent: #ifdef md_relax_frag growth = md_relax_frag (fragP, stretch); #else +#ifdef TC_GENERIC_RELAX_TABLE /* The default way to relax a frag is to look through md_relax_table. */ { @@ -1708,9 +2009,10 @@ relax_segment (segment_frag_root, segment) relax_substateT next_state; relax_substateT this_state; long aim; + const relax_typeS *table = TC_GENERIC_RELAX_TABLE; this_state = fragP->fr_subtype; - start_type = this_type = md_relax_table + this_state; + start_type = this_type = table + this_state; target = offset; if (symbolP) @@ -1747,16 +2049,14 @@ relax_segment (segment_frag_root, segment) } aim = target - address - fragP->fr_fix; - /* The displacement is affected by the instruction size - for the 32k architecture. I think we ought to be able - to add fragP->fr_pcrel_adjust in all cases (it should be - zero if not used), but just in case it breaks something - else we'll put this inside #ifdef NS32K ... #endif */ -#ifndef TC_NS32K - if (fragP->fr_pcrel_adjust) - abort (); +#ifdef TC_PCREL_ADJUST + /* Currently only the ns32k family needs this */ + aim += TC_PCREL_ADJUST(fragP); +#else + /* This machine doesn't want to use pcrel_adjust. + In that case, pcrel_adjust should be zero. */ + assert (fragP->fr_pcrel_adjust == 0); #endif - aim += fragP->fr_pcrel_adjust; if (aim < 0) { @@ -1768,7 +2068,7 @@ relax_segment (segment_frag_root, segment) { /* Grow to next state. */ this_state = next_state; - this_type = md_relax_table + this_state; + this_type = table + this_state; next_state = this_type->rlx_more; } } @@ -1785,7 +2085,7 @@ relax_segment (segment_frag_root, segment) { /* Grow to next state. */ this_state = next_state; - this_type = md_relax_table + this_state; + this_type = table + this_state; next_state = this_type->rlx_more; } } @@ -1794,6 +2094,7 @@ relax_segment (segment_frag_root, segment) if (growth != 0) fragP->fr_subtype = this_state; } +#endif /* TC_GENERIC_RELAX_TABLE */ #endif break; @@ -1821,7 +2122,11 @@ relax_segment (segment_frag_root, segment) */ } /* relax_segment() */ -#if defined (BFD_ASSEMBLER) || !defined (BFD) +#if defined (BFD_ASSEMBLER) || (!defined (BFD) && !defined (OBJ_VMS)) + +#ifndef TC_RELOC_RTSYM_LOC_FIXUP +#define TC_RELOC_RTSYM_LOC_FIXUP(X) (1) +#endif /* fixup_segment() @@ -1846,7 +2151,7 @@ fixup_segment (fixP, this_segment_type) int size; char *place; long where; - char pcrel; + int pcrel, plt; fragS *fragP; segT add_symbol_segment = absolute_section; @@ -1867,6 +2172,11 @@ fixup_segment (fixP, this_segment_type) for (; fixP; fixP = fixP->fx_next) { +#ifdef DEBUG5 + fprintf (stderr, "\nprocessing fixup:\n"); + print_fixup (fixP); +#endif + fragP = fixP->fx_frag; know (fragP); where = fixP->fx_where; @@ -1879,17 +2189,38 @@ fixup_segment (fixP, this_segment_type) sub_symbolP = fixP->fx_subsy; add_number = fixP->fx_offset; pcrel = fixP->fx_pcrel; - + plt = fixP->fx_plt; + + if (add_symbolP != NULL + && add_symbolP->sy_mri_common) + { + know (add_symbolP->sy_value.X_op == O_symbol); + add_number += S_GET_VALUE (add_symbolP); + fixP->fx_offset = add_number; + add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol; + } + if (add_symbolP) add_symbol_segment = S_GET_SEGMENT (add_symbolP); if (sub_symbolP) { - if (!add_symbolP) + resolve_symbol_value (sub_symbolP); + if (add_symbolP == NULL || add_symbol_segment == absolute_section) { - /* Its just -sym */ + if (add_symbolP != NULL) + { + add_number += S_GET_VALUE (add_symbolP); + add_symbolP = NULL; + fixP->fx_addsy = NULL; + } + + /* It's just -sym */ if (S_GET_SEGMENT (sub_symbolP) == absolute_section) - add_number -= S_GET_VALUE (sub_symbolP); + { + add_number -= S_GET_VALUE (sub_symbolP); + fixP->fx_subsy = NULL; + } else if (pcrel && S_GET_SEGMENT (sub_symbolP) == this_segment_type) { @@ -1898,12 +2229,12 @@ fixup_segment (fixP, this_segment_type) } else bad_sub_reloc: - as_bad ("Negative of non-absolute symbol %s", - S_GET_NAME (sub_symbolP)); + as_bad_where (fixP->fx_file, fixP->fx_line, + "Negative of non-absolute symbol %s", + S_GET_NAME (sub_symbolP)); } - else if ((S_GET_SEGMENT (sub_symbolP) == add_symbol_segment) - && (SEG_NORMAL (add_symbol_segment) - || (add_symbol_segment == absolute_section))) + else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment + && SEG_NORMAL (add_symbol_segment)) { /* Difference of 2 symbols from same segment. Can't make difference of 2 undefineds: 'value' means @@ -1912,19 +2243,23 @@ fixup_segment (fixP, this_segment_type) /* Makes no sense to use the difference of 2 arbitrary symbols as the target of a call instruction. */ if (fixP->fx_tcbit) - as_bad ("callj to difference of 2 symbols"); + as_bad_where (fixP->fx_file, fixP->fx_line, + "callj to difference of 2 symbols"); #endif /* TC_I960 */ add_number += S_GET_VALUE (add_symbolP) - S_GET_VALUE (sub_symbolP); add_symbolP = NULL; + pcrel = 0; /* No further pcrel processing. */ /* Let the target machine make the final determination as to whether or not a relocation will be needed to handle this fixup. */ - if (!TC_FORCE_RELOCATION (fixP)) + if (!TC_FORCE_RELOCATION_SECTION (fixP, this_segment_type)) { + fixP->fx_pcrel = 0; fixP->fx_addsy = NULL; + fixP->fx_subsy = NULL; } } else @@ -1946,7 +2281,7 @@ fixup_segment (fixP, this_segment_type) ) { /* Make it pc-relative. */ - add_number += (md_pcrel_from (fixP) + add_number += (MD_PCREL_FROM_SECTION (fixP, this_segment_type) - S_GET_VALUE (sub_symbolP)); pcrel = 1; fixP->fx_pcrel = 1; @@ -1954,6 +2289,15 @@ fixup_segment (fixP, this_segment_type) fixP->fx_subsy = 0; } #endif +#ifdef UNDEFINED_DIFFERENCE_OK + /* The PA needs this for PIC code generation. We basically + don't want to do anything if we have the difference of two + symbols at this point. */ + else if (1) + { + /* Leave it alone. */ + } +#endif #ifdef BFD_ASSEMBLER else if (fixP->fx_r_type == BFD_RELOC_GPREL32 || fixP->fx_r_type == BFD_RELOC_GPREL16) @@ -1965,16 +2309,18 @@ fixup_segment (fixP, this_segment_type) { char buf[50]; sprint_value (buf, fragP->fr_address + where); - as_bad ("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %s.", - segment_name (S_GET_SEGMENT (sub_symbolP)), - S_GET_NAME (sub_symbolP), buf); + as_bad_where (fixP->fx_file, fixP->fx_line, + "Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %s.", + segment_name (S_GET_SEGMENT (sub_symbolP)), + S_GET_NAME (sub_symbolP), buf); } } } if (add_symbolP) { - if (add_symbol_segment == this_segment_type && pcrel) + if (add_symbol_segment == this_segment_type && pcrel && !plt + && TC_RELOC_RTSYM_LOC_FIXUP (fixP)) { /* * This fixup was made when the symbol's segment was @@ -1991,7 +2337,7 @@ fixup_segment (fixP, this_segment_type) #endif /* TC_I960 */ add_number += S_GET_VALUE (add_symbolP); - add_number -= md_pcrel_from (fixP); + add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type); pcrel = 0; /* Lie. Don't want further pcrel processing. */ /* Let the target machine make the final determination @@ -2016,6 +2362,7 @@ fixup_segment (fixP, this_segment_type) /* Let the target machine make the final determination as to whether or not a relocation will be needed to handle this fixup. */ + if (!TC_FORCE_RELOCATION (fixP)) { fixP->fx_addsy = NULL; @@ -2036,7 +2383,8 @@ fixup_segment (fixP, this_segment_type) * for local branches: flag as error, don't generate * relocation. */ - as_bad ("can't use COBR format with external label"); + as_bad_where (fixP->fx_file, fixP->fx_line, + "can't use COBR format with external label"); fixP->fx_addsy = NULL; fixP->fx_done = 1; continue; @@ -2054,51 +2402,61 @@ fixup_segment (fixP, this_segment_type) else { seg_reloc_count++; +#if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF)) add_number += S_GET_VALUE (add_symbolP); +#endif } } } if (pcrel) { - add_number -= md_pcrel_from (fixP); + add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type); if (add_symbolP == 0) { +#ifndef BFD_ASSEMBLER fixP->fx_addsy = &abs_symbol; +#else + fixP->fx_addsy = section_symbol (absolute_section); +#endif + fixP->fx_addsy->sy_used_in_reloc = 1; ++seg_reloc_count; } } - if (!fixP->fx_bit_fixP && size > 0) + if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && size > 0) { valueT mask = 0; - /* set all bits to one */ - mask--; - /* Technically, combining these produces an undefined result - if size is sizeof (valueT), though I think these two - half-way operations should both be defined. And the - compiler should be able to combine them if it's valid on - the host architecture. */ - mask <<= size * 4; - mask <<= size * 4; - if ((add_number & mask) != 0 - && (add_number & mask) != mask) + if (size < sizeof (mask)) { - char buf[50], buf2[50]; - sprint_value (buf, fragP->fr_address + where); - if (add_number > 1000) - sprint_value (buf2, add_number); - else - sprintf (buf2, "%ld", (long) add_number); - as_bad_where (fixP->fx_file, fixP->fx_line, - "Value of %s too large for field of %d bytes at %s", - buf2, size, buf); - } /* generic error checking */ + /* set all bits to one */ + mask--; + /* Technically, combining these produces an undefined result + if size is sizeof (valueT), though I think these two + half-way operations should both be defined. And the + compiler should be able to combine them if it's valid on + the host architecture. */ + mask <<= size * 4; + mask <<= size * 4; + if ((add_number & mask) != 0 + && (add_number & mask) != mask) + { + char buf[50], buf2[50]; + sprint_value (buf, fragP->fr_address + where); + if (add_number > 1000) + sprint_value (buf2, add_number); + else + sprintf (buf2, "%ld", (long) add_number); + as_bad_where (fixP->fx_file, fixP->fx_line, + "Value of %s too large for field of %d bytes at %s", + buf2, size, buf); + } /* generic error checking */ + } #ifdef WARN_SIGNED_OVERFLOW_WORD /* Warn if a .word value is too large when treated as a signed number. We already know it is not too negative. This is to catch over-large switches generated by gcc on the 68k. */ - if (!flagseen['J'] + if (!flag_signed_overflow_ok && size == 2 && add_number > 0x7fff) as_bad_where (fixP->fx_file, fixP->fx_line, @@ -2110,11 +2468,15 @@ fixup_segment (fixP, this_segment_type) if (!fixP->fx_done) { +#ifdef MD_APPLY_FIX3 + md_apply_fix3 (fixP, &add_number, this_segment_type); +#else #ifdef BFD_ASSEMBLER md_apply_fix (fixP, &add_number); #else md_apply_fix (fixP, add_number); #endif +#endif #ifndef TC_HANDLES_FX_DONE /* If the tc-* files haven't been converted, assume it's handling @@ -2125,16 +2487,19 @@ fixup_segment (fixP, this_segment_type) #endif } #ifdef TC_VALIDATE_FIX - skip: + skip: ; +#endif +#ifdef DEBUG5 + fprintf (stderr, "result:\n"); + print_fixup (fixP); #endif - ; } /* For each fixS in this segment. */ TC_ADJUST_RELOC_COUNT (fixP, seg_reloc_count); return seg_reloc_count; } -#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */ +#endif /* defined (BFD_ASSEMBLER) || (!defined (BFD) && !defined (OBJ_VMS)) */ void number_to_chars_bigendian (buf, val, n) @@ -2166,4 +2531,56 @@ number_to_chars_littleendian (buf, val, n) } } +/* for debugging */ +extern int indent_level; +extern void print_symbol_value_1 (); + +void +print_fixup (fixp) + fixS *fixp; +{ + indent_level = 1; + fprintf (stderr, "fix %lx %s:%d", (long) fixp, fixp->fx_file, fixp->fx_line); + if (fixp->fx_pcrel) + fprintf (stderr, " pcrel"); + if (fixp->fx_pcrel_adjust) + fprintf (stderr, " pcrel_adjust=%d", fixp->fx_pcrel_adjust); + if (fixp->fx_im_disp) + { +#ifdef TC_NS32K + fprintf (stderr, " im_disp=%d", fixp->fx_im_disp); +#else + fprintf (stderr, " im_disp"); +#endif + } + if (fixp->fx_tcbit) + fprintf (stderr, " tcbit"); + if (fixp->fx_done) + fprintf (stderr, " done"); + fprintf (stderr, "\n size=%d frag=%lx where=%ld offset=%lx addnumber=%lx", + fixp->fx_size, (long) fixp->fx_frag, (long) fixp->fx_where, + (long) fixp->fx_offset, (long) fixp->fx_addnumber); +#ifdef BFD_ASSEMBLER + fprintf (stderr, "\n %s (%d)", bfd_get_reloc_code_name (fixp->fx_r_type), + fixp->fx_r_type); +#else +#ifdef NEED_FX_R_TYPE + fprintf (stderr, " r_type=%d", fixp->fx_r_type); +#endif +#endif + if (fixp->fx_addsy) + { + fprintf (stderr, "\n +<"); + print_symbol_value_1 (stderr, fixp->fx_addsy); + fprintf (stderr, ">"); + } + if (fixp->fx_subsy) + { + fprintf (stderr, "\n -<"); + print_symbol_value_1 (stderr, fixp->fx_subsy); + fprintf (stderr, ">"); + } + fprintf (stderr, "\n"); +} + /* end of write.c */