📄 write.c
字号:
for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next) { arelent *reloc; bfd_reloc_status_type s; symbolS *sym; if (fixp->fx_done) { n--; continue; } /* If this is an undefined symbol which was equated to another symbol, then use generate the reloc against the latter symbol rather than the former. */ sym = fixp->fx_addsy; while (symbol_equated_p (sym) && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym))) { symbolS *n; /* We must avoid looping, as that can occur with a badly written program. */ n = symbol_get_value_expression (sym)->X_add_symbol; if (n == sym) break; fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number; sym = n; } fixp->fx_addsy = sym; reloc = tc_gen_reloc (sec, fixp); if (!reloc) { n--; continue; }#if 0 /* This test is triggered inappropriately for the SH. */ if (fixp->fx_where + fixp->fx_size > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset) abort ();#endif 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; case bfd_reloc_outofrange: as_bad_where (fixp->fx_file, fixp->fx_line, _("relocation out of range")); break; default: as_fatal (_("%s:%u: bad return from bfd_install_relocation: %x"), fixp->fx_file, fixp->fx_line, s); } relocs[i++] = reloc; }#else n = n * MAX_RELOC_EXPANSION; /* Set up reloc information as well. */ relocs = (arelent **) xmalloc (n * sizeof (arelent *)); i = 0; for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next) { arelent **reloc; char *data; bfd_reloc_status_type s; symbolS *sym; int j; if (fixp->fx_done) { n--; continue; } /* If this is an undefined symbol which was equated to another symbol, then generate the reloc against the latter symbol rather than the former. */ sym = fixp->fx_addsy; while (symbol_equated_p (sym) && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym))) sym = symbol_get_value_expression (sym)->X_add_symbol; fixp->fx_addsy = sym; reloc = tc_gen_reloc (sec, fixp); for (j = 0; reloc[j]; j++) { relocs[i++] = reloc[j]; assert (i <= n); } 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) as_bad_where (fixp->fx_file, fixp->fx_line, _("internal error: fixup not contained within frag")); for (j = 0; reloc[j]; j++) { 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 (_("%s:%u: bad return from bfd_install_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 bfd_set_section_flags (abfd, sec, (bfd_get_section_flags (abfd, sec) & (flagword) ~SEC_RELOC));#ifdef SET_SECTION_RELOCS SET_SECTION_RELOCS (sec, relocs, n);#endif#ifdef DEBUG3 { int i; arelent *r; asymbol *s; fprintf (stderr, "relocs for sec %s\n", sec->name); for (i = 0; i < n; i++) { r = relocs[i]; s = *r->sym_ptr_ptr; fprintf (stderr, " reloc %2d @%08x off %4x : sym %-10s addend %x\n", i, r, r->address, s->name, r->addend); } }#endif}static voidwrite_contents (abfd, sec, xxx) bfd *abfd ATTRIBUTE_UNUSED; asection *sec; PTR xxx ATTRIBUTE_UNUSED;{ segment_info_type *seginfo = seg_info (sec); unsigned long offset = 0; fragS *f; /* Write out the frags. */ if (seginfo == NULL || !(bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)) return; for (f = seginfo->frchainP->frch_root; f; f = f->fr_next) { int x; unsigned long fill_size; char *fill_literal; long count; assert (f->fr_type == rs_fill); if (f->fr_fix) { x = bfd_set_section_contents (stdoutput, sec, f->fr_literal, (file_ptr) offset, (bfd_size_type) f->fr_fix); 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; fill_size = f->fr_var; count = f->fr_offset; assert (count >= 0); if (fill_size && count) { 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#if defined(BFD_ASSEMBLER) || (!defined (BFD) && !defined(OBJ_AOUT))static voidmerge_data_into_text (){#if defined(BFD_ASSEMBLER) || defined(MANY_SEGMENTS) seg_info (text_section)->frchainP->frch_last->fr_next = seg_info (data_section)->frchainP->frch_root; seg_info (text_section)->frchainP->frch_last = seg_info (data_section)->frchainP->frch_last; seg_info (data_section)->frchainP = 0;#else fixS *tmp; text_last_frag->fr_next = data_frag_root; text_last_frag = data_last_frag; data_last_frag = NULL; data_frag_root = NULL; if (text_fix_root) { for (tmp = text_fix_root; tmp->fx_next; tmp = tmp->fx_next);; tmp->fx_next = data_fix_root; text_fix_tail = data_fix_tail; } else text_fix_root = data_fix_root; data_fix_root = NULL;#endif}#endif /* BFD_ASSEMBLER || (! BFD && ! OBJ_AOUT) */#if !defined (BFD_ASSEMBLER) && !defined (BFD)static voidrelax_and_size_all_segments (){ fragS *fragP; relax_segment (text_frag_root, SEG_TEXT); relax_segment (data_frag_root, SEG_DATA); relax_segment (bss_frag_root, SEG_BSS); /* Now the addresses of frags are correct within the segment. */ know (text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0); H_SET_TEXT_SIZE (&headers, text_last_frag->fr_address); text_last_frag->fr_address = H_GET_TEXT_SIZE (&headers); /* Join the 2 segments into 1 huge segment. To do this, re-compute every rn_address in the SEG_DATA frags. Then join the data frags after the text frags. Determine a_data [length of data segment]. */ if (data_frag_root) { register relax_addressT slide; know ((text_last_frag->fr_type == rs_fill) && (text_last_frag->fr_offset == 0)); H_SET_DATA_SIZE (&headers, data_last_frag->fr_address); data_last_frag->fr_address = H_GET_DATA_SIZE (&headers); slide = H_GET_TEXT_SIZE (&headers); /* & in file of the data segment. */#ifdef OBJ_BOUT#define RoundUp(N,S) (((N)+(S)-1)&-(S)) /* For b.out: If the data section has a strict alignment requirement, its load address in the .o file will be rounded up from the size of the text section. These two values are *not* the same! Similarly for the bss section.... */ slide = RoundUp (slide, 1 << section_alignment[SEG_DATA]);#endif for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) fragP->fr_address += slide; know (text_last_frag != 0); text_last_frag->fr_next = data_frag_root; } else { H_SET_DATA_SIZE (&headers, 0); }#ifdef OBJ_BOUT /* See above comments on b.out data section address. */ { long bss_vma; if (data_last_frag == 0) bss_vma = H_GET_TEXT_SIZE (&headers); else bss_vma = data_last_frag->fr_address; bss_vma = RoundUp (bss_vma, 1 << section_alignment[SEG_BSS]); bss_address_frag.fr_address = bss_vma; }#else /* ! OBJ_BOUT */ bss_address_frag.fr_address = (H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers));#endif /* ! OBJ_BOUT */ /* Slide all the frags. */ if (bss_frag_root) { relax_addressT slide = bss_address_frag.fr_address; for (fragP = bss_frag_root; fragP; fragP = fragP->fr_next) fragP->fr_address += slide; } if (bss_last_frag) H_SET_BSS_SIZE (&headers, bss_last_frag->fr_address - bss_frag_root->fr_address); else H_SET_BSS_SIZE (&headers, 0);}#endif /* ! BFD_ASSEMBLER && ! BFD */#if defined (BFD_ASSEMBLER) || !defined (BFD)#ifdef BFD_ASSEMBLERstatic voidset_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] = symbol_get_bfdsym (symp); symbol_mark_written (symp); } } else asympp = 0; result = bfd_set_symtab (stdoutput, asympp, nsyms); assert (result == true); symbol_table_frozen = 1;}#endif#if defined (BFD_ASSEMBLER) && defined (OBJ_COFF) && defined (TE_GO32)static voidset_segment_vma (abfd, sec, xxx) bfd *abfd; asection *sec; PTR xxx ATTRIBUTE_UNUSED;{ static bfd_vma addr = 0; bfd_set_section_vma (abfd, sec, addr); addr += bfd_section_size (abfd, sec);}#endif /* BFD_ASSEMBLER && OBJ_COFF && !TE_PE *//* Finish the subsegments. 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 frag that requires least thought. ".align" frags like to have a following frag since that makes calculating their intended length trivial. */#ifndef SUB_SEGMENT_ALIGN#ifdef BFD_ASSEMBLER#define SUB_SEGMENT_ALIGN(SEG) (0)#else#define SUB_SEGMENT_ALIGN(SEG) (2)#endif#endifvoidsubsegs_finish (){ struct frchain *frchainP; for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next) { int alignment; subseg_set (frchainP->frch_seg, frchainP->frch_subseg); /* This now gets called even if we had errors. In that case, any alignment is meaningless, and, moreover, will look weird if we are generating a listing. */ alignment = had_errors () ? 0 : SUB_SEGMENT_ALIGN (now_seg); /* The last subsegment gets an aligment corresponding to the alignment of the section. This allows proper nop-filling at the end of code-bearing sections. */ if (!frchainP->frch_next || frchainP->frch_next->frch_seg != now_seg) alignment = get_recorded_alignment (now_seg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -