void frag_grow (unsigned int nchars) { if (obstack_room (&frchain_now->frch_obstack) < nchars) { unsigned int n; long oldc; frag_wane (frag_now); frag_new (0); oldc = frchain_now->frch_obstack.chunk_size; /* Try to allocate a bit more than needed right now. But don't do this if we would waste too much memory. Especially necessary for extremely big (like 2GB initialized) frags. */ if (nchars < 0x10000) frchain_now->frch_obstack.chunk_size = 2 * nchars; else frchain_now->frch_obstack.chunk_size = nchars + 0x10000; frchain_now->frch_obstack.chunk_size += SIZEOF_STRUCT_FRAG; if (frchain_now->frch_obstack.chunk_size > 0) while ((n = obstack_room (&frchain_now->frch_obstack)) < nchars && (unsigned long) frchain_now->frch_obstack.chunk_size > nchars) { frag_wane (frag_now); frag_new (0); } frchain_now->frch_obstack.chunk_size = oldc; } if (obstack_room (&frchain_now->frch_obstack) < nchars) as_fatal (_("can't extend frag %u chars"), nchars); }
/* * frag_grow() * * Try to augment current frag by nchars chars. * If there is no room, close of the current frag with a ".fill 0" * and begin a new frag. Unless the new frag has nchars chars available * do not return. Do not set up any fields of *now_frag. */ void frag_grow( unsigned int nchars) { if(frags.chunk_size == 0) { know(flagseen['n']); as_fatal("with -n a section directive must be seen before assembly " "can begin"); } if ((int)(obstack_room(&frags)) < nchars) { unsigned int n,oldn; long oldc; frag_wane (frag_now); frag_new (0); oldn=(unsigned)-1; oldc=frags.chunk_size; frags.chunk_size=2*nchars; while((int)(n=obstack_room(&frags)) < nchars && n < oldn) { frag_wane(frag_now); frag_new(0); oldn=n; } frags.chunk_size=oldc; } if ((int)(obstack_room(&frags)) < nchars) as_fatal ("Can't extend frag %d. chars", nchars); }
/* * add_last_frags_to_sections() does what layout_addresses() does below about * adding a last ".fill 0" frag to each section. This is called by * dwarf2_finish() allow get_frag_fix() in dwarf2dbg.c to work for the last * fragment in a section. */ void add_last_frags_to_sections( void) { struct frchain *frchainP; if(frchain_root == NULL) return; /* * If there is any current frag close it off. */ if(frag_now != NULL && frag_now->fr_fix == 0){ frag_now->fr_fix = obstack_next_free(&frags) - frag_now->fr_literal; frag_wane(frag_now); } /* * For every section, add a last ".fill 0" frag that will later be used * as the ending address of that section. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ /* * We must do the obstack_finish(), so the next object we put on * obstack frags will not appear to start at the fr_literal of the * current frag. Also, it ensures that the next object will begin * on a address that is aligned correctly for the engine that runs * the assembler. */ (void)obstack_finish(&frags); /* * Make a fresh frag for the last frag. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; (void)obstack_finish(&frags); /* * Append the new frag to current frchain. */ frchainP->frch_last->fr_next = frag_now; frchainP->frch_last = frag_now; frag_wane(frag_now); } }
void frag_append_1_char (int datum) { frag_alloc_check (&frchain_now->frch_obstack); if (obstack_room (&frchain_now->frch_obstack) <= 1) { frag_wane (frag_now); frag_new (0); } obstack_1grow (&frchain_now->frch_obstack, datum); }
void frag_grow (unsigned int nchars) { if (obstack_room (&frchain_now->frch_obstack) < nchars) { long oldc; long newc; /* Try to allocate a bit more than needed right now. But don't do this if we would waste too much memory. Especially necessary for extremely big (like 2GB initialized) frags. */ if (nchars < 0x10000) newc = 2 * nchars; else newc = nchars + 0x10000; newc += SIZEOF_STRUCT_FRAG; /* Check for possible overflow. */ if (newc < 0) as_fatal (_("can't extend frag %u chars"), nchars); /* Force to allocate at least NEWC bytes, but not less than the default. */ oldc = obstack_chunk_size (&frchain_now->frch_obstack); if (newc > oldc) obstack_chunk_size (&frchain_now->frch_obstack) = newc; while (obstack_room (&frchain_now->frch_obstack) < nchars) { /* Not enough room in this frag. Close it and start a new one. This must be done in a loop because the created frag may not be big enough if the current obstack chunk is used. */ frag_wane (frag_now); frag_new (0); } /* Restore the old chunk size. */ obstack_chunk_size (&frchain_now->frch_obstack) = oldc; } }
/* * layout_addresses() is called after all the assembly code has been read and * fragments, symbols and fixups have been created. This routine sets the * address of the fragments and symbols. Then it does the fixups of the frags * and prepares the fixes so relocation entries can be created from them. */ void layout_addresses( void) { struct frchain *frchainP; fragS *fragP; relax_addressT slide, tmp; symbolS *symbolP; uint32_t nbytes, fill_size, repeat_expression, partial_bytes, layout_pass; relax_stateT old_fr_type; int changed; if(frchain_root == NULL) return; /* * If there is any current frag close it off. */ if(frag_now != NULL && frag_now->fr_fix == 0){ frag_now->fr_fix = obstack_next_free(&frags) - frag_now->fr_literal; frag_wane(frag_now); } /* * For every section, add a last ".fill 0" frag that will later be used * as the ending address of that section. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ /* * We must do the obstack_finish(), so the next object we put on * obstack frags will not appear to start at the fr_literal of the * current frag. Also, it ensures that the next object will begin * on a address that is aligned correctly for the engine that runs * the assembler. */ (void)obstack_finish(&frags); /* * Make a fresh frag for the last frag. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; (void)obstack_finish(&frags); /* * Append the new frag to current frchain. */ frchainP->frch_last->fr_next = frag_now; frchainP->frch_last = frag_now; frag_wane(frag_now); } /* * Now set the relative addresses of frags within the section by * relaxing each section. That is all sections will start at address * zero and addresses of the frags in that section will increase from * there. * * The debug sections are done last as other section are needed to be * done first becase debug sections may have line numbers with .loc * directives in them and their sizes need to be set before processing * the line number sections. We also do sections that have rs_leb128s * in them before debug sections but after other sections since they * are used for things like exception tables and they may be refering to * sections such that their sizes too must be known first. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ if((frchainP->frch_section.flags & S_ATTR_DEBUG) == S_ATTR_DEBUG) frchainP->layout_pass = 2; else if(frchainP->has_rs_leb128s == TRUE) frchainP->layout_pass = 1; else frchainP->layout_pass = 0; } for(layout_pass = 0; layout_pass < 3; layout_pass++){ do{ changed = 0; for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ if(frchainP->layout_pass != layout_pass) continue; if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL) continue; /* * This is done so in case md_estimate_size_before_relax() * (called by relax_section) wants to make fixSs they are * for this section. */ frchain_now = frchainP; changed += relax_section(frchainP->frch_root, frchainP->frch_nsect); } } while(changed != 0); } /* * Now set the absolute addresses of all frags by sliding the frags in * each non-zerofill section by the address ranges taken up by the * sections before it. */ slide = 0; for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL) continue; slide = round(slide, 1 << frchainP->frch_section.align); tmp = frchainP->frch_last->fr_address; if(slide != 0){ for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){ fragP->fr_address += slide; } } slide += tmp; } /* * Now with the non-zerofill section addresses set set all of the * addresses of the zerofill sections. Comming in the fr_address is * the size of the section and going out it is the start address. This * will make layout_symbols() work out naturally. The only funky thing * is that section numbers do not end up in address order. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ if((frchainP->frch_section.flags & SECTION_TYPE) != S_ZEROFILL) continue; slide = round(slide, 1 << frchainP->frch_section.align); tmp = frchainP->frch_root->fr_address; frchainP->frch_root->fr_address = slide; frchainP->frch_last->fr_address = tmp + slide; slide += tmp; } /* * Set the symbol addresses based on their frag's address. * First forward references are handled. */ for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){ if(symbolP->sy_forward != NULL){ if(symbolP->sy_nlist.n_type & N_STAB) symbolP->sy_other = symbolP->sy_forward->sy_other; symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address; symbolP->sy_forward = 0; } } for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){ symbolP->sy_value += symbolP->sy_frag->fr_address; } /* * At this point the addresses of frags now reflect addresses we use in * the object file and the symbol values are correct. * Scan the frags, converting any ".org"s and ".align"s to ".fill"s. * Also converting any machine-dependent frags using md_convert_frag(); */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ /* * This is done so any fixes created by md_convert_frag() are for * this section. */ frchain_now = frchainP; for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){ switch(fragP->fr_type){ case rs_align: case rs_org: old_fr_type = fragP->fr_type; /* convert this frag to an rs_fill type */ fragP->fr_type = rs_fill; /* * Calculate the number of bytes the variable part of the * the rs_fill frag will need to fill. Then calculate this * as the fill_size * repeat_expression + partial_bytes. */ know(fragP->fr_next != NULL); nbytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix; if(nbytes < 0){ as_warn("rs_org invalid, dot past value by %d bytes", nbytes); nbytes = 0; } fill_size = fragP->fr_var; repeat_expression = nbytes / fill_size; #ifdef I386 /* * For x86 architecures in sections containing only * instuctions being padded with nops that are aligned to 16 * bytes or less and are assembled with -dynamic we will * actually end up padding with the optimal nop sequence. * Previously there has been the maximum number of bytes * allocated in the frag to use for this. */ if(old_fr_type == rs_align && (frchain_now->frch_section.flags & S_ATTR_PURE_INSTRUCTIONS) != 0 && fill_size == 1 && fragP->fr_literal[fragP->fr_fix] == (char)0x90 && nbytes > 0 && nbytes < 16 && flagseen['k'] == TRUE){ i386_align_code(fragP, nbytes); /* * The call to i386_align_code() has set the fill_size * in fragP->fr_var to nbytes. So we set the fr_offset * to the fill repeat_expression to 1 to match for this * now an rs_fill type frag. */ fragP->fr_offset = 1; break; } #endif /* I386 */ partial_bytes = nbytes - (repeat_expression * fill_size); /* * Now set the fr_offset to the fill repeat_expression * since this is now an rs_fill type. The fr_var is still * the fill_size. */ fragP->fr_offset = repeat_expression; /* * For rs_align frags there may be partial_bytes to fill * with zeros before we can fill with the fill_expression * of fill_size. When the rs_align frag was created it was * created with fill_size-1 extra bytes in the fixed part. */ if(partial_bytes != 0){ /* moved the fill_expression bytes foward */ memmove(fragP->fr_literal +fragP->fr_fix +partial_bytes, fragP->fr_literal +fragP->fr_fix, fragP->fr_var); /* zero out the partial_bytes */ memset(fragP->fr_literal + fragP->fr_fix, '\0', partial_bytes); /* adjust the fixed part of the frag */ fragP->fr_fix += partial_bytes; } break; case rs_fill: break; case rs_machine_dependent: md_convert_frag(fragP); /* * After md_convert_frag, we make the frag into a ".fill 0" * md_convert_frag() should set up any fixSs and constants * required. */ frag_wane(fragP); break; case rs_dwarf2dbg: dwarf2dbg_convert_frag(fragP); break; case rs_leb128: { int size; #ifdef OLD valueT value = S_GET_VALUE (fragP->fr_symbol); #else valueT value; expressionS *expression; if(fragP->fr_symbol->expression != NULL){ expression = (expressionS *)fragP->fr_symbol->expression; value = 0; if(expression->X_add_symbol != NULL) value += expression->X_add_symbol->sy_nlist.n_value; if(expression->X_subtract_symbol != NULL) value -= expression->X_subtract_symbol->sy_nlist.n_value; value += expression->X_add_number; } else{ value = fragP->fr_symbol->sy_nlist.n_value + fragP->fr_address; } #endif size = output_leb128 (fragP->fr_literal + fragP->fr_fix, value, fragP->fr_subtype); fragP->fr_fix += size; fragP->fr_type = rs_fill; fragP->fr_var = 0; fragP->fr_offset = 0; fragP->fr_symbol = NULL; } break; default: BAD_CASE(fragP->fr_type); break; } } } /* * For each section do the fixups for the frags. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ now_seg = frchainP->frch_nsect; fixup_section(frchainP->frch_fix_root, frchainP->frch_nsect); } }
/* * section_new() (for non-zerofill sections) switches to a new section, creating * it if needed, and creates a fresh fragment. If it is the current section * nothing happens except checks to make sure the type, attributes and * sizeof_stub are the same. The segment and section names will be trimed to * fit in the section structure and is the responsiblity of the caller to * report errors if they don't. For zerofill sections only the struct frchain * for the section is returned after possibly being created (these section are * never made the current section and no frags are ever touched). * * Globals on input: * frchain_now points to the (possibly none) struct frchain for the current * section. * frag_now points at an incomplete frag for current section. * If frag_now == NULL, then there is no old, incomplete frag, so the old * frag is not closed off. * * Globals on output: * frchain_now points to the (possibly new) struct frchain for this section. * frchain_root updated if needed (for the first section created). * frag_now is set to the last (possibly new) frag in the section. * now_seg is set to the Mach-O section number (frch_nsect field) except * it is not set for section types of S_ZEROFILL. */ frchainS * section_new( char *segname, char *sectname, uint32_t type, uint32_t attributes, uint32_t sizeof_stub) { frchainS *frcP; frchainS **lastPP; uint32_t last_nsect; if(frags.chunk_size == 0) /* * This line is use instead of: * obstack_begin(&frags, 5000); * which the only difference is that frags are allocated on 4 byte * boundaries instead of the default. The problem with the default * is that on some RISC machines the obstack uses 8 (the alignment * of a double after a char in a struct) and then the common use of: * frag_now->fr_fix = obstack_next_free(&frags) - * frag_now->fr_literal; * can get an extra 4 bytes that are not in the frag because of the * 8 byte alignment where only 4 byte alignment for frags are * needed. */ _obstack_begin(&frags, 5000, 4, obstack_chunk_alloc, obstack_chunk_free); /* * Determine if this section has been seen. */ last_nsect = 0; for(frcP = *(lastPP = &frchain_root); frcP != NULL; frcP = *(lastPP = &frcP->frch_next)){ if(strncmp(frcP->frch_section.segname, segname, sizeof(frcP->frch_section.segname)) == 0 && strncmp(frcP->frch_section.sectname, sectname, sizeof(frcP->frch_section.sectname)) == 0) break; last_nsect = frcP->frch_nsect; } /* * If this section has been seen make sure it's type and attributes * for this call are the same as when the section was created. */ if(frcP != NULL){ if((frcP->frch_section.flags & SECTION_TYPE) != type){ as_warn("section type does not match previous section type"); } if(type == S_SYMBOL_STUBS && frcP->frch_section.reserved2 != sizeof_stub){ as_warn("section stub size does not match previous section " "stub size"); } frcP->frch_section.flags |= attributes; } /* * If the current section is the same as for this call there is nothing * more to do. */ if(frcP != NULL && (frchain_now == frcP || type == S_ZEROFILL)){ if(type != S_ZEROFILL) now_seg = frcP->frch_nsect; return(frcP); } /* * For non-zerofill sections it will be made the current section so deal * with the current frag. */ if(type != S_ZEROFILL){ /* * If there is any current frag in the old section close it off. */ if(frag_now != NULL){ frag_now->fr_fix = obstack_next_free(&frags) - frag_now->fr_literal; frag_wane(frag_now); } /* * We must do the obstack_finish(), so the next object we put on * obstack frags will not appear to start at the fr_literal of the * current frag. Also, it ensures that the next object will begin * on a address that is aligned correctly for the engine that runs * the assembler. */ obstack_finish(&frags); } /* * If this section exists since it is not the current section switch to * it by making it the current chain and create a new frag in it. */ if(frcP != NULL){ if(type != S_ZEROFILL) now_seg = frcP->frch_nsect; /* * For a zerofill section no frags are created here and since it * exist just return a pointer to the section. */ if((frcP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL){ return(frcP); } else{ /* * Make this section the current section. */ frchain_now = frcP; if(type != S_ZEROFILL) now_seg = frchain_now->frch_nsect; /* * Make a fresh frag for the section. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; /* * Append the new frag to the existing frchain. */ frchain_now->frch_last->fr_next = frag_now; frchain_now->frch_last = frag_now; } } else{ /* * This section does not exist so create a new frchainS struct fill * it in, link it to the chain */ frcP = (frchainS *)xmalloc(sizeof(frchainS)); memset(frcP, '\0', sizeof(frchainS)); strncpy(frcP->frch_section.segname, segname, sizeof(frcP->frch_section.segname)); strncpy(frcP->frch_section.sectname, sectname, sizeof(frcP->frch_section.sectname)); frcP->frch_section.flags = attributes | type; frcP->frch_section.reserved2 = sizeof_stub; frcP->frch_nsect = last_nsect + 1; if(type != S_ZEROFILL) now_seg = frcP->frch_nsect; *lastPP = frcP; /* * For zerofill sections no frag is created here so just return. * For non-zerofill section create the sections new frag and * make the section the current chain. */ if(type == S_ZEROFILL){ return(frcP); } else{ /* * Make a fresh frag for the new section. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; /* * Append the new frag to new frchain. */ frcP->frch_root = frag_now; frcP->frch_last = frag_now; /* * Make this section the current section. */ frchain_now = frcP; } } return(frchain_now); }
void md_assemble (char *str) { frv_insn insn; char *errmsg; int packing_constraint; finished_insnS finished_insn; fragS *double_nop_frag = NULL; fragS *single_nop_frag = NULL; struct vliw_insn_list *vliw_insn_list_entry = NULL; /* Initialize GAS's cgen interface for a new instruction. */ gas_cgen_init_parse (); memset (&insn, 0, sizeof (insn)); insn.insn = frv_cgen_assemble_insn (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg); if (!insn.insn) { as_bad ("%s", errmsg); return; } /* If the cpu is tomcat, then we need to insert nops to workaround hardware limitations. We need to keep track of each vliw unit and examine the length of the unit and the individual insns within the unit to determine the number and location of the required nops. */ if (frv_mach == bfd_mach_frvtomcat) { /* If we've just finished a VLIW insn OR this is a branch, then start up a new frag. Fill it with nops. We will get rid of those that are not required after we've seen all of the instructions but before we start resolving fixups. */ if ( !FRV_IS_NOP (insn) && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack)) { char *buffer; frag_wane (frag_now); frag_new (0); double_nop_frag = frag_now; buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0); md_number_to_chars (buffer, FRV_NOP_PACK, 4); md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4); frag_wane (frag_now); frag_new (0); single_nop_frag = frag_now; buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0); md_number_to_chars (buffer, FRV_NOP_NOPACK, 4); } vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT); vliw_insn_list_entry->insn = insn.insn; if (frv_is_branch_insn (insn.insn)) vliw_insn_list_entry->type = VLIW_BRANCH_TYPE; if ( !FRV_IS_NOP (insn) && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack)) { vliw_insn_list_entry->snop_frag = single_nop_frag; vliw_insn_list_entry->dnop_frag = double_nop_frag; } } /* Make sure that this insn does not violate the VLIW packing constraints. */ /* -mno-pack disallows any packing whatsoever. */ if (frv_flags & EF_FRV_NOPACK) { if (! insn.fields.f_pack) { as_bad (_("VLIW packing used for -mno-pack")); return; } } /* -mcpu=FRV is an idealized FR-V implementation that supports all of the instructions, don't do vliw checking. */ else if (frv_mach != bfd_mach_frv) { if (!target_implements_insn_p (insn.insn)) { as_bad (_("Instruction not supported by this architecture")); return; } packing_constraint = frv_vliw_add_insn (& vliw, insn.insn); if (frv_mach == bfd_mach_fr550 && ! packing_constraint) packing_constraint = fr550_check_acc_range (& vliw, & insn); if (insn.fields.f_pack) frv_vliw_reset (& vliw, frv_mach, frv_flags); if (packing_constraint) { as_bad (_("VLIW packing constraint violation")); return; } } /* Doesn't really matter what we pass for RELAX_P here. */ gas_cgen_finish_insn (insn.insn, insn.buffer, CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn); /* If the cpu is tomcat, then we need to insert nops to workaround hardware limitations. We need to keep track of each vliw unit and examine the length of the unit and the individual insns within the unit to determine the number and location of the required nops. */ if (frv_mach == bfd_mach_frvtomcat) { if (vliw_insn_list_entry) vliw_insn_list_entry->address = finished_insn.addr; else abort(); if (insn.fields.f_pack) { /* We've completed a VLIW insn. */ previous_vliw_chain = current_vliw_chain; current_vliw_chain = NULL; current_vliw_insn = NULL; } } }
static void new_frag (void) { frag_wane (frag_now); frag_new (0); }
/* * layout_addresses() is called after all the assembly code has been read and * fragments, symbols and fixups have been created. This routine sets the * address of the fragments and symbols. Then it does the fixups of the frags * and prepares the fixes so relocation entries can be created from them. */ void layout_addresses( void) { struct frchain *frchainP; fragS *fragP; relax_addressT slide, tmp; symbolS *symbolP; unsigned long nbytes, fill_size, repeat_expression, partial_bytes; if(frchain_root == NULL) return; /* * If there is any current frag close it off. */ if(frag_now != NULL && frag_now->fr_fix == 0){ frag_now->fr_fix = obstack_next_free(&frags) - frag_now->fr_literal; frag_wane(frag_now); } /* * For every section, add a last ".fill 0" frag that will later be used * as the ending address of that section. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ /* * We must do the obstack_finish(), so the next object we put on * obstack frags will not appear to start at the fr_literal of the * current frag. Also, it ensures that the next object will begin * on a address that is aligned correctly for the engine that runs * the assembler. */ obstack_finish(&frags); /* * Make a fresh frag for the last frag. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; obstack_finish(&frags); /* * Append the new frag to current frchain. */ frchainP->frch_last->fr_next = frag_now; frchainP->frch_last = frag_now; frag_wane(frag_now); } /* * Now set the relitive addresses of frags within the section by * relaxing each section. That is all sections will start at address * zero and addresses of the frags in that section will increase from * there. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL) continue; /* * This is done so in case md_estimate_size_before_relax() (called * by relax_section) wants to make fixSs they are for this * section. */ frchain_now = frchainP; relax_section(frchainP->frch_root, frchainP->frch_nsect); } /* * Now set the absolute addresses of all frags by sliding the frags in * each non-zerofill section by the address ranges taken up by the * sections before it. */ slide = 0; for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL) continue; slide = round(slide, 1 << frchainP->frch_section.align); tmp = frchainP->frch_last->fr_address; if(slide != 0){ for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){ fragP->fr_address += slide; } } slide += tmp; } /* * Now with the non-zerofill section addresses set set all of the * addresses of the zerofill sections. Comming in the fr_address is * the size of the section and going out it is the start address. This * will make layout_symbols() work out naturally. The only funky thing * is that section numbers do not end up in address order. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ if((frchainP->frch_section.flags & SECTION_TYPE) != S_ZEROFILL) continue; slide = round(slide, 1 << frchainP->frch_section.align); tmp = frchainP->frch_root->fr_address; frchainP->frch_root->fr_address = slide; frchainP->frch_last->fr_address = tmp + slide; slide += tmp; } /* * Set the symbol addresses based on there frag's address. * First forward references are handled. */ for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){ if(symbolP->sy_forward != NULL){ if(symbolP->sy_nlist.n_type & N_STAB) symbolP->sy_other = symbolP->sy_forward->sy_other; symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address; symbolP->sy_forward = 0; } } for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){ symbolP->sy_value += symbolP->sy_frag->fr_address; } /* * At this point the addresses of frags now reflect addresses we use in * the object file and the symbol values are correct. * Scan the frags, converting any ".org"s and ".align"s to ".fill"s. * Also converting any machine-dependent frags using md_convert_frag(); */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ /* * This is done so any fixes created by md_convert_frag() are for * this section. */ frchain_now = frchainP; for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){ switch(fragP->fr_type){ case rs_align: case rs_org: /* convert this frag to an rs_fill type */ fragP->fr_type = rs_fill; /* * Calculate the number of bytes the variable part of the * the rs_fill frag will need to fill. Then calculate this * as the fill_size * repeat_expression + partial_bytes. */ know(fragP->fr_next != NULL); nbytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix; if(nbytes < 0){ as_warn("rs_org invalid, dot past value by %ld bytes", nbytes); nbytes = 0; } fill_size = fragP->fr_var; repeat_expression = nbytes / fill_size; partial_bytes = nbytes - (repeat_expression * fill_size); /* * Now set the fr_offset to the fill repeat_expression * since this is now an rs_fill type. The fr_var is still * the fill_size. */ fragP->fr_offset = repeat_expression; /* * For rs_align frags there may be partial_bytes to fill * with zeros before we can fill with the fill_expression * of fill_size. When the rs_align frag was created it was * created with fill_size-1 extra bytes in the fixed part. */ if(partial_bytes != 0){ /* moved the fill_expression bytes foward */ memmove(fragP->fr_literal +fragP->fr_fix +partial_bytes, fragP->fr_literal +fragP->fr_fix, fragP->fr_var); /* zero out the partial_bytes */ memset(fragP->fr_literal + fragP->fr_fix, '\0', partial_bytes); /* adjust the fixed part of the frag */ fragP->fr_fix += partial_bytes; } break; case rs_fill: break; case rs_machine_dependent: md_convert_frag(fragP); /* * After md_convert_frag, we make the frag into a ".fill 0" * md_convert_frag() should set up any fixSs and constants * required. */ frag_wane(fragP); break; default: BAD_CASE(fragP->fr_type); break; } } } /* * For each section do the fixups for the frags. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ fixup_section(frchainP->frch_fix_root, frchainP->frch_nsect); } }