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