/* * 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); } }
/* * 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); } }