📄 write.c
字号:
know( fragP -> fr_next ); fragP -> fr_offset = fragP -> fr_next -> fr_address - fragP -> fr_address - fragP -> fr_fix; break; case rs_fill: break; case rs_machine_dependent: md_convert_frag (fragP); /* * After md_convert_frag, we make the frag into a ".space 0". * Md_convert_frag() should set up any fixSs and constants * required. */ frag_wane (fragP); break;#ifndef WORKING_DOT_WORD case rs_broken_word: { struct broken_word *lie; extern md_short_jump_size; extern md_long_jump_size; if(fragP->fr_subtype) { fragP->fr_fix+=md_short_jump_size; for(lie=(struct broken_word *)(fragP->fr_symbol);lie && lie->dispfrag==fragP;lie=lie->next_broken_word) if(lie->added==1) fragP->fr_fix+=md_long_jump_size; } frag_wane(fragP); } break;#endif default: BAD_CASE( fragP -> fr_type ); break; } /* switch (fr_type) */ } /* for each frag. */#ifndef WORKING_DOT_WORD { struct broken_word *lie; struct broken_word **prevP; prevP= &broken_words; for(lie=broken_words; lie; lie=lie->next_broken_word) if(!lie->added) {#if defined(SPARC) || defined(I860) fix_new( lie->frag, lie->word_goes_here - lie->frag->fr_literal, 2, lie->add, lie->sub, lie->addnum, 0, NO_RELOC);#endif#ifdef NS32K fix_new_ns32k(lie->frag, lie->word_goes_here - lie->frag->fr_literal, 2, lie->add, lie->sub, lie->addnum, 0, 0, 2, 0, 0);#endif#if !defined(SPARC) && !defined(NS32K) && !defined(I860) fix_new( lie->frag, lie->word_goes_here - lie->frag->fr_literal, 2, lie->add, lie->sub, lie->addnum, 0);#endif /* md_number_to_chars(lie->word_goes_here, lie->add->sy_value + lie->addnum - (lie->sub->sy_value), 2); */ *prevP=lie->next_broken_word; } else prevP= &(lie->next_broken_word); for(lie=broken_words;lie;) { struct broken_word *untruth; char *table_ptr; long table_addr; long from_addr, to_addr; int n, m; extern md_short_jump_size; extern md_long_jump_size; void md_create_short_jump(); void md_create_long_jump(); fragP=lie->dispfrag; /* Find out how many broken_words go here */ n=0; for(untruth=lie;untruth && untruth->dispfrag==fragP;untruth=untruth->next_broken_word) if(untruth->added==1) n++; table_ptr=lie->dispfrag->fr_opcode; table_addr=lie->dispfrag->fr_address+(table_ptr - lie->dispfrag->fr_literal); /* Create the jump around the long jumps */ /* This is a short jump from table_ptr+0 to table_ptr+n*long_jump_size */ from_addr=table_addr; to_addr = table_addr + md_short_jump_size + n * md_long_jump_size; md_create_short_jump(table_ptr,from_addr,to_addr,lie->dispfrag,lie->add); table_ptr+=md_short_jump_size; table_addr+=md_short_jump_size; for(m=0;lie && lie->dispfrag==fragP;m++,lie=lie->next_broken_word) { if(lie->added==2) continue; /* Patch the jump table */ /* This is the offset from ??? to table_ptr+0 */ to_addr = table_addr - (lie->sub->sy_value); 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) { if(untruth->use_jump==lie) md_number_to_chars(untruth->word_goes_here,to_addr,2); } /* Install the long jump */ /* this is a long jump from table_ptr+0 to the final target */ from_addr=table_addr; to_addr=lie->add->sy_value+lie->addnum; 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; } } }#endif#ifndef VMS /* * Scan every FixS performing fixups. We had to wait until now to do * this because md_convert_frag() may have made some fixSs. */ /* the_exec . a_trsize = sizeof(struct relocation_info) * fixup_segment (text_fix_root, N_TEXT); the_exec . a_drsize = sizeof(struct relocation_info) * fixup_segment (data_fix_root, N_DATA); */ tr_siz=sizeof(struct relocation_info) * fixup_segment (text_fix_root, N_TEXT); md_number_to_chars((char *)&the_exec.a_trsize, tr_siz ,sizeof(the_exec.a_trsize)); dr_siz=sizeof(struct relocation_info) * fixup_segment (data_fix_root, N_DATA); md_number_to_chars((char *)&the_exec.a_drsize, dr_siz, sizeof(the_exec.a_drsize)); md_number_to_chars((char *)&the_exec.a_info,omagic,sizeof(the_exec.a_info)); md_number_to_chars((char *)&the_exec.a_entry,0,sizeof(the_exec.a_entry));#ifdef EXEC_MACHINE_TYPE md_number_to_chars((char *)&the_exec.a_machtype, EXEC_MACHINE_TYPE, sizeof(the_exec.a_machtype));#endif#ifdef EXEC_VERSION md_number_to_chars((char *)&the_exec.a_version,EXEC_VERSION,sizeof(the_exec.a_version));#endif /* the_exec . a_entry = 0; */ size_of_the_object_file = sizeof( the_exec ) + text_siz + data_siz + syms_siz + tr_siz + dr_siz + string_byte_count; next_object_file_charP = the_object_file = xmalloc ( size_of_the_object_file ); output_file_create (out_file_name); append (& next_object_file_charP, (char *)(&the_exec), (unsigned long)sizeof(the_exec)); /* * Emit code. */ for (fragP = text_frag_root; fragP; fragP = fragP -> fr_next) { register long int count; register char * fill_literal; register long int fill_size; 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; fill_size = fragP -> fr_var; know( fragP -> fr_offset >= 0 ); for (count = fragP -> fr_offset; count; count --) append (& next_object_file_charP, fill_literal, (unsigned long)fill_size); } /* for each code frag. */ /* * Emit relocations. */ emit_relocations (text_fix_root, (relax_addressT)0); emit_relocations (data_fix_root, text_last_frag -> fr_address); /* * Emit all symbols left in the symbol chain. * Any symbol still undefined is made N_EXT. */ for ( symbolP = symbol_rootP; symbolP; symbolP = symbolP -> sy_next ) { register char * temp; temp = symbolP -> sy_nlist . n_un . n_name; /* JF fix the numbers up. Call by value RULES! */ md_number_to_chars((char *)&(symbolP -> sy_nlist . n_un . n_strx ),symbolP -> sy_name_offset,sizeof(symbolP -> sy_nlist . n_un . n_strx )); md_number_to_chars((char *)&(symbolP->sy_nlist.n_desc),symbolP->sy_nlist.n_desc,sizeof(symbolP -> sy_nlist . n_desc)); md_number_to_chars((char *)&(symbolP->sy_nlist.n_value),symbolP->sy_nlist.n_value,sizeof(symbolP->sy_nlist.n_value)); /* symbolP -> sy_nlist . n_un . n_strx = symbolP -> sy_name_offset; JF replaced by md above */ if (symbolP -> sy_type == N_UNDF) symbolP -> sy_type |= N_EXT; /* Any undefined symbols become N_EXT. */ append (& next_object_file_charP, (char *)(& symbolP -> sy_nlist), (unsigned long)sizeof(struct nlist)); symbolP -> sy_nlist . n_un . n_name = temp; } /* for each symbol */ /* * next_object_file_charP -> slot for next object byte. * Emit strings. * Find strings by crawling along symbol table chain. *//* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ md_number_to_chars((char *)&string_byte_count, string_byte_count, sizeof(string_byte_count)); append (& next_object_file_charP, (char *)&string_byte_count, (unsigned long)sizeof(string_byte_count)); for ( symbolP = symbol_rootP; symbolP; symbolP = symbolP -> sy_next ) { if (symbolP -> sy_name) { /* Ordinary case: not .stabd. */ append (& next_object_file_charP, symbolP -> sy_name, (unsigned long)(strlen (symbolP -> sy_name) + 1)); } } /* for each symbol */ know( next_object_file_charP == the_object_file + size_of_the_object_file ); output_file_append (the_object_file, size_of_the_object_file, out_file_name);#ifdef DONTDEF if (flagseen['G']) /* GDB symbol file to be appended? */ { gdb_emit (out_file_name); gdb_end (); }#endif output_file_close (out_file_name);#else /* VMS */ /* * Now do the VMS-dependent part of writing the object file */ VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root);#endif /* VMS */} /* write_object_file() *//* * relax_segment() * * Now we have a segment, not a crowd of sub-segments, we can make fr_address * values. * * Relax the frags. * * After this, all frags in this segment have addresses that are correct * within the segment. Since segments live in different file addresses, * these frag addresses may not be the same as final object-file addresses. */#ifndef VMSstatic#endif /* not VMS */voidrelax_segment (segment_frag_root, segment_type) struct frag * segment_frag_root; segT segment_type; /* N_DATA or N_TEXT */{ register struct frag * fragP; register relax_addressT address; /* register relax_addressT old_address; JF unused */ /* register relax_addressT new_address; JF unused */ know( segment_type == SEG_DATA || segment_type == SEG_TEXT ); /* In case md_estimate_size_before_relax() wants to make fixSs. */ subseg_change (segment_type, 0); /* * For each frag in segment: count and store (a 1st guess of) fr_address. */ address = 0; for ( fragP = segment_frag_root; fragP; fragP = fragP -> fr_next ) { fragP -> fr_address = address; address += fragP -> fr_fix; switch (fragP -> fr_type) { case rs_fill: address += fragP -> fr_offset * fragP -> fr_var; break; case rs_align: address += relax_align (address, fragP -> fr_offset); break; case rs_org: /* * Assume .org is nugatory. It will grow with 1st relax. */ break; case rs_machine_dependent: address += md_estimate_size_before_relax (fragP, seg_N_TYPE [(int) segment_type]); break;#ifndef WORKING_DOT_WORD /* Broken words don't concern us yet */ case rs_broken_word: break;#endif default: BAD_CASE( fragP -> fr_type ); break; } /* switch(fr_type) */ } /* for each frag in the segment */ /* * Do relax(). */ { register long int stretch; /* May be any size, 0 or negative. */ /* Cumulative number of addresses we have */ /* relaxed this pass. */ /* We may have relaxed more than one address. */ register long int stretched; /* Have we stretched on this pass? */ /* This is 'cuz stretch may be zero, when, in fact some piece of code grew, and another shrank. If a branch instruction doesn't fit anymore, we could be scrod */ do { stretch = stretched = 0; for (fragP = segment_frag_root; fragP; fragP = fragP -> fr_next) { register long int growth; register long int was_address; /* register long int var; */ register long int offset; register symbolS * symbolP; register long int target; register long int after; register long int aim; was_address = fragP -> fr_address; address = fragP -> fr_address += stretch; symbolP = fragP -> fr_symbol; offset = fragP -> fr_offset; /* var = fragP -> fr_var; */ switch (fragP -> fr_type) { case rs_fill: /* .fill never relaxes. */ growth = 0; break;#ifndef WORKING_DOT_WORD /* JF: This is RMS's idea. I do *NOT* want to be blamed for it I do not want to write it. I do not want to have anything to do with it. This is not the proper way to implement this misfeature. */ case rs_broken_word: { struct broken_word *lie; struct broken_word *untruth; extern int md_short_jump_size; extern int md_long_jump_size; /* Yes this is ugly (storing the broken_word pointer in the symbol slot). Still, this whole chunk of code is ugly, and I don't feel like doing anything about it. Think of it as stubbornness in action */ growth=0; for(lie=(struct broken_word *)(fragP->fr_symbol); lie && lie->dispfrag==fragP; lie=lie->next_broken_word) { if(lie->added) continue; offset= lie->add->sy_frag->fr_address+lie->add->sy_value + lie->addnum - (lie->sub->sy_frag->fr_address+lie->sub->sy_value); if(offset<=-32768 || offset>=32767) { if(flagseen['k']) as_warn(".word %s-%s+%ld didn't fit",lie->add->sy_name,lie->sub->sy_name,lie->addnum); lie->added=1; if(fragP->fr_subtype==0) { fragP->fr_subtype++; growth+=md_short_jump_size; } for(untruth=lie->next_broken_word;untruth && untruth->dispfrag==lie->dispfrag;untruth=untruth->next_broken_word) if(untruth->add->sy_frag==lie->add->sy_frag && untruth->add->sy_value==lie->add->sy_value) { untruth->added=2; untruth->use_jump=lie; } growth+=md_long_jump_size; } } } break;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -