Relaxations, and "attempt to move .org backwards"

anonymous johnandsara2@cox.net
Fri Jan 8 00:39:00 GMT 2016


Johnson, Nicholas Paul wrote:
> Hello and happy new year,
> 
> I am attempting to implement relaxations on my out-of-tree target, and I'm encountering the "attempt to move .org backwards" error.  I would appreciate any help diagnosing my mistake.  My work is based on the 2.25.1 (git hash 2bd25930...)
> 
> While tracing through the relaxation process of a small testcase, it seems like the stretch term is being inappropriately added to the offset of an rs_org fragment (near the top of the loop in relax_segment, write.c, line 2496).  That violates my understanding of the .org: why would changing the size of earlier fragments affect the absolute address of a subsequent .org fragment?  And why is it bad to move a .org fragment backwards, yet acceptable to move a .org fragment forward?
> 
> 
> Below is everything I know about how my setup produces the error.
> 
> My testcase, below, features a machine-dependent relaxation on the pc-relative branch 'beq'.  That branch defaults to an 8-byte "long-form" though can be relaxed to a 4-byte "short-form" when the branch displacement is small.
> 
> # begin testcase
> label1:
>   beq r3.3, r5.1, label2, 0  # machine-dependent relaxation
> .org 0x1000
> label2:
> #end testcase
> 
> 
> I implemented md_estimate_size_before_relax, md_relax_frag, and md_convert_frag.  This is the sequence of events:
> 
> (1) md_estimate_size_before_relax returns '8' to indicate an 8-byte instruction.  
> 
> (2) md_relax_frag is called thrice on this fragment.  First call: the frag containing 'label2' had not been visited yet, and so md_relax_frag thinks label2 is at offset 8 (initially incorrect).  Since the displacement is small, md_relax_frag opts for a short-form instruction and returns -4 (==4bytes - 8bytes).
> 
> (3) Second call to md_relax_frag: the frag containing label2 has been visited, and so md_relax_frag thinks label2 is at offset 0x1000 (correct).  The branch displacement is large, so md_relax_frag opts for a long-form instruction and returns +4 (==8bytes - 4bytes).
> 
> (4) md_relax_frag is called a third time.  Md_relax_frag now estimates that label2 is at offset 0x1004. This offset is incorrect, perhaps indicating that the stretch term was inappropriatetly applied to an rs_org frag.  The branch displacement is still large, and again md_relax_frag opts for a long-form instruction and returns 0 (==8bytes - 8bytes).
> 
> (5--8) Repeats steps [1--4] exactly.  (9--12) Repeats steps [1--4], except step 11 triggers the  "attempt to move .org backwards" error.
> 
> (13) md_convert_frag is called for the first time.  It leaves the long-form instruction unchanged, sets fragP->fr_fix += 8 and fragP->fr_var = 0.
> 
> 
> Thank you,
> Nick Johnson
> D. E. Shaw Research
> 

i assume if relax is a mechanism for changing the byte width, then 
certainly it would matter "before and after"

i think in some architectures that "no-relax" is already an option



More information about the Binutils mailing list