/* * relax_section() here we set the fr_address values in the frags. * After this, all frags in this segment have addresses that are correct * relative to the section (that is the section starts at address zero). * After all of the sections have been processed by this call and their sizes * are know then they can be slid to their final address. */ static int relax_section( struct frag *frag_root, int nsect) { struct frag *fragP; relax_addressT address; int32_t 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. */ int32_t 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 need another pass */ #ifndef ARM const relax_typeS *this_type; const relax_typeS *start_type; relax_substateT next_state; relax_substateT this_state; int32_t aim; #endif /* !defined(ARM) */ int32_t growth; uint32_t was_address; int32_t offset; symbolS *symbolP; int32_t target; int32_t after; uint32_t oldoff, newoff; int ret; ret = 0; growth = 0; /* * For each frag in segment count and store (a 1st guess of) fr_address. */ address = 0; for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){ #ifdef ARM fragP->relax_marker = 0; #endif /* ARM */ 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: offset = relax_align (address, (int) fragP->fr_offset); /* * If a maximum number of bytes to fill was specified for this * align (stored in fr_subtype) then check to see if this align * can be done. If not ignore it. If so and this alignment is * larger than any previous alignment then this becomes the * section's alignment. */ if(fragP->fr_subtype != 0){ if(offset > (int32_t)fragP->fr_subtype){ offset = 0; } else{ if(frchain_now->frch_section.align < (uint32_t)fragP->fr_offset) frchain_now->frch_section.align = fragP->fr_offset; } } address += 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, nsect); break; case rs_dwarf2dbg: address += dwarf2dbg_estimate_size_before_relax(fragP); break; case rs_leb128: /* Initial guess is always 1; doing otherwise can result in stable solutions that are larger than the minimum. */ address += fragP->fr_offset = 1; break; default: BAD_CASE(fragP->fr_type); break; } } /* * Do relax(). * Make repeated passes over the chain of frags allowing each frag to * grow if needed. On each pass each frag's address is incremented by * the accumulated growth, kept in stretched. Passes are continued * until there is no stretch on the previous pass. */ do{ stretch = 0; stretched = 0; for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){ #ifdef ARM fragP->relax_marker ^= 1; #endif /* ARM */ was_address = fragP->fr_address; fragP->fr_address += stretch; address = fragP->fr_address; symbolP = fragP->fr_symbol; offset = fragP->fr_offset; switch(fragP->fr_type){ case rs_fill: /* .fill never relaxes. */ growth = 0; break; case rs_align: oldoff = relax_align(was_address + fragP->fr_fix, offset); newoff = relax_align(address + fragP->fr_fix, offset); /* * Check if a maximum number of bytes to fill was specified * for this align (stored in fr_subtype). */ if(fragP->fr_subtype != 0){ if(oldoff > fragP->fr_subtype) oldoff = 0; if(newoff > fragP->fr_subtype) newoff = 0; } growth = newoff - oldoff; break; case rs_org: target = offset; if(symbolP != NULL){ know(((symbolP->sy_type & N_TYPE) == N_ABS) || ((symbolP->sy_type & N_TYPE) == N_SECT)); know(symbolP->sy_frag); know((symbolP->sy_type & N_TYPE) != N_ABS || symbolP->sy_frag == &zero_address_frag ); target += symbolP->sy_value + symbolP->sy_frag->fr_address; } know(fragP->fr_next); after = fragP->fr_next->fr_address; /* * Growth may be negative, but variable part of frag cannot * have < 0 chars. That is, we can't .org backwards. */ growth = ((target - after ) > 0) ? (target - after) : 0; growth -= stretch; /* This is an absolute growth factor */ break; case rs_machine_dependent: #ifdef ARM growth = arm_relax_frag(nsect, fragP, stretch); #else /* !defined(ARM) */ this_state = fragP->fr_subtype; this_type = md_relax_table + this_state; start_type = this_type; target = offset; if(symbolP){ know(((symbolP->sy_type & N_TYPE) == N_ABS) || ((symbolP->sy_type & N_TYPE) == N_SECT)); know(symbolP->sy_frag); know((symbolP->sy_type & N_TYPE) != N_ABS || symbolP->sy_frag == &zero_address_frag); target += symbolP->sy_value + symbolP->sy_frag->fr_address; /* * If frag has yet to be reached on this pass, * assume it will move by STRETCH just as we did. * If this is not so, it will be because some frag * between grows, and that will force another pass. */ if(symbolP->sy_frag->fr_address >= was_address && is_down_range(fragP, symbolP->sy_frag)) target += stretch; } aim = target - address - fragP->fr_fix; if(aim < 0){ /* Look backwards. */ for(next_state = this_type->rlx_more; next_state; ){ if(aim >= this_type->rlx_backward) next_state = 0; else{ /* Grow to next state. */ this_state = next_state; this_type = md_relax_table + this_state; next_state = this_type->rlx_more; } } } else{ /* Look forwards. */ for(next_state = this_type->rlx_more; next_state; ){ if(aim <= this_type->rlx_forward) next_state = 0; else{ /* Grow to next state. */ this_state = next_state; this_type = md_relax_table + this_state; next_state = this_type->rlx_more; } } } if((growth = this_type->rlx_length -start_type->rlx_length)) fragP->fr_subtype = this_state; #endif /* !defined(ARM) */ break; case rs_dwarf2dbg: growth = dwarf2dbg_relax_frag(fragP); break; case rs_leb128: { valueT value; offsetT size; #ifdef OLD value = resolve_symbol_value (fragP->fr_symbol); #else 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 + expression->X_add_symbol->sy_frag->fr_address); if(expression->X_subtract_symbol != NULL) value -= (expression->X_subtract_symbol->sy_nlist.n_value + expression->X_subtract_symbol-> sy_frag->fr_address); value += expression->X_add_number; } else{ value = fragP->fr_symbol->sy_nlist.n_value + fragP->fr_address; } #endif size = sizeof_leb128 (value, fragP->fr_subtype); growth = size - fragP->fr_offset; fragP->fr_offset = size; } break; default: BAD_CASE(fragP->fr_type); break; } if(growth) { stretch += growth; stretched++; } } /* For each frag in the segment. */ }while(stretched); /* Until nothing further to relax. */ /* * We now have valid fr_address'es for each frag. All fr_address's * are correct, relative to their own section. We have made all the * fixS for this section that will be made. */ for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){ if(fragP->last_fr_address != fragP->fr_address){ fragP->last_fr_address = fragP->fr_address; ret = 1; } } return(ret); }
/* * relax_section() here we set the fr_address values in the frags. * After this, all frags in this segment have addresses that are correct * relative to the section (that is the section starts at address zero). * After all of the sections have been processed by this call and their sizes * are know then they can be slid to their final address. */ static void relax_section( struct frag *frag_root, int nsect) { struct frag *fragP; relax_addressT address; long 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. */ long 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 need another pass */ const relax_typeS *this_type; const relax_typeS *start_type; relax_substateT next_state; relax_substateT this_state; long growth; unsigned long was_address; long offset; symbolS *symbolP; long target; long after; long aim; unsigned long oldoff, newoff; growth = 0; /* * For each frag in segment count and store (a 1st guess of) fr_address. */ address = 0; for(fragP = frag_root; fragP != NULL; 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: offset = relax_align (address, (int) fragP->fr_offset); /* * If a maximum number of bytes to fill was specified for this * align (stored in fr_subtype) then check to see if this align * can be done. If not ignore it. If so and this alignment is * larger than any previous alignment then this becomes the * section's alignment. */ if(fragP->fr_subtype != 0){ if(offset > (long)fragP->fr_subtype){ offset = 0; } else{ if(frchain_now->frch_section.align < (unsigned long)fragP->fr_offset) frchain_now->frch_section.align = fragP->fr_offset; } } address += 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, nsect); break; default: BAD_CASE(fragP->fr_type); break; } } /* * Do relax(). * Make repeated passes over the chain of frags allowing each frag to * grow if needed. On each pass each frag's address is incremented by * the accumulated growth, kept in stretched. Passes are continued * until there is no stretch on the previous pass. */ do{ stretch = 0; stretched = 0; for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){ was_address = fragP->fr_address; fragP->fr_address += stretch; address = fragP->fr_address; symbolP = fragP->fr_symbol; offset = fragP->fr_offset; switch(fragP->fr_type){ case rs_fill: /* .fill never relaxes. */ growth = 0; break; case rs_align: oldoff = relax_align(was_address + fragP->fr_fix, offset); newoff = relax_align(address + fragP->fr_fix, offset); /* * Check if a maximum number of bytes to fill was specified * for this align (stored in fr_subtype). */ if(fragP->fr_subtype != 0){ if(oldoff > fragP->fr_subtype) oldoff = 0; if(newoff > fragP->fr_subtype) newoff = 0; } growth = newoff - oldoff; break; case rs_org: target = offset; if(symbolP != NULL){ know(((symbolP->sy_type & N_TYPE) == N_ABS) || ((symbolP->sy_type & N_TYPE) == N_SECT)); know(symbolP->sy_frag); know((symbolP->sy_type & N_TYPE) != N_ABS || symbolP->sy_frag == &zero_address_frag ); target += symbolP->sy_value + symbolP->sy_frag->fr_address; } know(fragP->fr_next); after = fragP->fr_next->fr_address; /* * Growth may be negative, but variable part of frag cannot * have < 0 chars. That is, we can't .org backwards. */ growth = ((target - after ) > 0) ? (target - after) : 0; growth -= stretch; /* This is an absolute growth factor */ break; case rs_machine_dependent: this_state = fragP->fr_subtype; this_type = md_relax_table + this_state; start_type = this_type; target = offset; if(symbolP){ know(((symbolP->sy_type & N_TYPE) == N_ABS) || ((symbolP->sy_type & N_TYPE) == N_SECT)); know(symbolP->sy_frag); know((symbolP->sy_type & N_TYPE) != N_ABS || symbolP->sy_frag == &zero_address_frag); target += symbolP->sy_value + symbolP->sy_frag->fr_address; /* * If frag has yet to be reached on this pass, * assume it will move by STRETCH just as we did. * If this is not so, it will be because some frag * between grows, and that will force another pass. */ if(symbolP->sy_frag->fr_address >= was_address && is_down_range(fragP, symbolP->sy_frag)) target += stretch; } aim = target - address - fragP->fr_fix; if(aim < 0){ /* Look backwards. */ for(next_state = this_type->rlx_more; next_state; ){ if(aim >= this_type->rlx_backward) next_state = 0; else{ /* Grow to next state. */ this_state = next_state; this_type = md_relax_table + this_state; next_state = this_type->rlx_more; } } } else{ /* Look forwards. */ for(next_state = this_type->rlx_more; next_state; ){ if(aim <= this_type->rlx_forward) next_state = 0; else{ /* Grow to next state. */ this_state = next_state; this_type = md_relax_table + this_state; next_state = this_type->rlx_more; } } } if((growth = this_type->rlx_length -start_type->rlx_length)) fragP->fr_subtype = this_state; break; default: BAD_CASE(fragP->fr_type); break; } if(growth) { stretch += growth; stretched++; } } /* For each frag in the segment. */ }while(stretched); /* Until nothing further to relax. */ /* * We now have valid fr_address'es for each frag. All fr_address's * are correct, relative to their own section. We have made all the * fixS for this section that will be made. */ }