This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Relaxations, and "attempt to move .org backwards"


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]