This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
RE: attempt to move .org backwards
Hi All,
In further analysis, I understood that
- I was wrong. 'growth' should be calculated based on next instruction
only
- 'stretch' shall not be added to the address of instructions that
follows '.org' directive.
An '.org' directive advances the location counter of the current section
to offset specified. So, shrinking or expanding instructions before
'.org' directive shall not cause any change for instructions that follos
'.org' directive.
Binutils-2.22
gas/write.c : relax_segment
> 2637 know (fragP->fr_next);
> 2638 after = fragP->fr_next->fr_address + stretch;
> 2639 growth = target - after;
> 2640 if (growth < 0)
The above code shall be modified as follows:
2637 know (fragP->fr_next);
2638 after = fragP->fr_next->fr_address; // stretch shall not be added
2639 stretch = 0; // stretch should be reset as '.org' defines new
offset
2640 growth = target - after;
2641 if (growth < 0)
Is my understanding about 'relax_segment' function correct?
Regards,
Pitchumani.S
> -----Original Message-----
> From: binutils-owner@sourceware.org
[mailto:binutils-owner@sourceware.org]
> On Behalf Of S, Pitchumani
> Sent: Monday, March 05, 2012 3:53 PM
> To: binutils@sourceware.org
> Subject: attempt to move .org backwards
>
> Hi,
>
> I have a doubt regarding '.org' processing in relax_segment function.
>
> Binutils-2.22
> gas/write.c : relax_segment
>
> --- code ---
> 2622 case rs_org:
> 2623 {
> 2624 addressT target = offset;
> 2625 addressT after;
> 2626
> 2627 if (symbolP)
> 2628 {
> 2629 /* Convert from an actual address to an octet offset
> 2630 into the section. Here it is assumed that the
> 2631 section's VMA is zero, and can omit subtracting it
> 2632 from the symbol's value to get the address offset. */
> 2633 know (S_GET_SEGMENT (symbolP)->vma == 0);
> 2634 target += S_GET_VALUE (symbolP) * OCTETS_PER_BYTE;
> 2635 }
> 2636
> 2637 know (fragP->fr_next);
> 2638 after = fragP->fr_next->fr_address + stretch;
> 2639 growth = target - after;
> 2640 if (growth < 0)
> 2641 {
> 2642 growth = 0;
> 2643
> 2644 /* Don't error on first few frag relax passes.
> 2655 ... */
> 2656 if (pass < 2)
> 2657 {
> 2658 /* Force another pass. */
> 2659 ret = 1;
> 2660 break;
> 2661 }
> 2662
> 2663 /* Growth may be negative, but variable part of frag
> 2664 cannot have fewer than 0 chars. That is, we can't
> 2665 .org backwards. */
> 2666 as_bad_where (fragP->fr_file, fragP->fr_line,
> 2667 _("attempt to move .org backwards"));
> 2668
> 2669 /* We've issued an error message. Change the
> 2670 frag to avoid cascading errors. */
> 2671 fragP->fr_type = rs_align;
> 2672 fragP->fr_subtype = 0;
> 2673 fragP->fr_offset = 0;
> 2674 fragP->fr_fix = after - address;
> 2675 }
> 2676 }
> 2677 break;
> --- code ---
>
> The above code checks for "attempt to move .org backwards" error.
>
> To find the growth, next instruction's address (+ stretch) is
subtracted
> from offset of .org directive.
>
> Next instruction's address will be same as .org offset after
calculating
> address in the first iteration. So, growth will become negative if any
> instruction present before .org is stretched.
>
> Example:
> 0x0000 func1
> 0x0000 call func2 <== 2/4 byte instruction
> 0x0002 .org 0x0404
> 0x0404 func2
> 0x0404 nop
>
> If call instruction size is stretched to 4 bytes (from 2 bytes),
> growth will become -2 ((0x404 + 2) - 0x0404)
>
> But, .org is not moved backwards.
>
> So, I think, growth should be calculated based on previous instruction
> address.
> Example:
> growth = (prev. insn address (including stretch) + prev. insn size) -
> offset
>
> Please correct me if I'm wrong.
>
> Regards,
> Pitchumani.S