@@ -191,17 +191,21 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
191191 }
192192 r .Xsym = rs
193193
194- // the first instruction is always at the lower address, this is endian neutral;
195- // but note that o0 and o1 should still use the target endian.
196- o0 := ld .Thelinkarch .ByteOrder .Uint32 (s .P [r .Off : r .Off + 4 ])
197- o1 := ld .Thelinkarch .ByteOrder .Uint32 (s .P [r .Off + 4 : r .Off + 8 ])
198-
199194 // Note: ld64 currently has a bug that any non-zero addend for BR26 relocation
200195 // will make the linking fail because it thinks the code is not PIC even though
201196 // the BR26 relocation should be fully resolved at link time.
202197 // That is the reason why the next if block is disabled. When the bug in ld64
203198 // is fixed, we can enable this block and also enable duff's device in cmd/7g.
204199 if false && ld .HEADTYPE == obj .Hdarwin {
200+ var o0 , o1 uint32
201+
202+ if ld .Ctxt .Arch .ByteOrder == binary .BigEndian {
203+ o0 = uint32 (* val >> 32 )
204+ o1 = uint32 (* val )
205+ } else {
206+ o0 = uint32 (* val )
207+ o1 = uint32 (* val >> 32 )
208+ }
205209 // Mach-O wants the addend to be encoded in the instruction
206210 // Note that although Mach-O supports ARM64_RELOC_ADDEND, it
207211 // can only encode 24-bit of signed addend, but the instructions
@@ -210,23 +214,21 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
210214 o0 |= (uint32 ((r .Xadd >> 12 )& 3 ) << 29 ) | (uint32 ((r .Xadd >> 12 >> 2 )& 0x7ffff ) << 5 )
211215 o1 |= uint32 (r .Xadd & 0xfff ) << 10
212216 r .Xadd = 0
213- }
214217
215- // when laid out, the instruction order must always be o1, o2.
216- if ld .Ctxt .Arch .ByteOrder == binary .BigEndian {
217- * val = int64 (o0 )<< 32 | int64 (o1 )
218- } else {
219- * val = int64 (o1 )<< 32 | int64 (o0 )
218+ // when laid out, the instruction order must always be o1, o2.
219+ if ld .Ctxt .Arch .ByteOrder == binary .BigEndian {
220+ * val = int64 (o0 )<< 32 | int64 (o1 )
221+ } else {
222+ * val = int64 (o1 )<< 32 | int64 (o0 )
223+ }
220224 }
221225
222226 return 0
223227
224228 case obj .R_CALLARM64 :
225229 r .Done = 0
226230 r .Xsym = r .Sym
227- * val = int64 (0xfc000000 & uint32 (r .Add ))
228- r .Xadd = int64 ((uint32 (r .Add ) &^ 0xfc000000 ) * 4 )
229- r .Add = 0
231+ r .Xadd = r .Add
230232 return 0
231233 }
232234 }
@@ -246,10 +248,15 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
246248 ld .Diag ("program too large, address relocation distance = %d" , t )
247249 }
248250
249- // the first instruction is always at the lower address, this is endian neutral;
250- // but note that o0 and o1 should still use the target endian.
251- o0 := ld .Thelinkarch .ByteOrder .Uint32 (s .P [r .Off : r .Off + 4 ])
252- o1 := ld .Thelinkarch .ByteOrder .Uint32 (s .P [r .Off + 4 : r .Off + 8 ])
251+ var o0 , o1 uint32
252+
253+ if ld .Ctxt .Arch .ByteOrder == binary .BigEndian {
254+ o0 = uint32 (* val >> 32 )
255+ o1 = uint32 (* val )
256+ } else {
257+ o0 = uint32 (* val )
258+ o1 = uint32 (* val >> 32 )
259+ }
253260
254261 o0 |= (uint32 ((t >> 12 )& 3 ) << 29 ) | (uint32 ((t >> 12 >> 2 )& 0x7ffff ) << 5 )
255262 o1 |= uint32 (t & 0xfff ) << 10
@@ -263,7 +270,11 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
263270 return 0
264271
265272 case obj .R_CALLARM64 :
266- * val = int64 ((0xfc000000 & uint32 (r .Add )) | uint32 ((ld .Symaddr (r .Sym )+ r .Add * 4 - (s .Value + int64 (r .Off )))/ 4 ))
273+ t := (ld .Symaddr (r .Sym ) + r .Add ) - (s .Value + int64 (r .Off ))
274+ if t >= 1 << 27 || t < - 1 << 27 {
275+ ld .Diag ("program too large, call relocation distance = %d" , t )
276+ }
277+ * val |= (t >> 2 ) & 0x03ffffff
267278 return 0
268279 }
269280
0 commit comments