1

I get linking problem when create library for iOS 7 on iPhone (ARM64).

The error message is:

ld: in /long_path/libHEVCCodec.a(inv_xforms_arm64.o), in section TEXT,text reloc 0:
ARM64_RELOC_SUBTRACTOR must have r_length of 2 or 3 for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

This error appears as a result to this code (it's some sort of switch):

    adr     addr,   .L.dct_add_switch
    ldrh    offset, [addr, ta, lsl #1]
    add     addr,   addr, offset, uxth
    br      addr

.L.dct_add_switch:
    .hword  .L.dct_add_4   - .L.dct_add_switch
    .hword  .L.dst_add_4   - .L.dct_add_switch
...

ta, addr, offset are general registers x3, x4, w5 respectively.

Does anybody know how to handle this situation?

PS: there are not any problems with GNU GCC & Android.

EDIT1: It seems that problem is not in linker itself but in compiler. I checked object file (objdump) and instead of difference constants there are just zeros.

.L.dct_add_switch:
0000000000000010    .long   0x00000000
0000000000000014    .long   0x00000000
0000000000000018    .long   0x00000000
000000000000001c    nop

When I put manually calculated constants instead of ".L.dct_add_4 - .L.dct_add_switch", etc expressions, everything is going all right.

Maybe there is some compiler keys which will make compiler to do it job rightfully?

Thanks.

user3124812
  • 1,861
  • 3
  • 18
  • 39

2 Answers2

0

Well there is a compiler & linker problem and it depends on the size of data which are used for offsets. Clang is not very friendly to anything what is different from 4 Bytes.

The discussion and possible solutions in other topic: creating constant jump table; xcode; clang; asm

Community
  • 1
  • 1
user3124812
  • 1,861
  • 3
  • 18
  • 39
0

The problem is the Mach-O object file format for ARM 64-bit targets doesn't support a relocation for the 16-bit difference between two symbols. It appears that the difference must be 32-bit or 64-bit. It doesn't seem to be a problem with the compiler or the linker. The assembly code you've quoted in your question looks like handcrafted assembly, not compiler output.

The solution would be to rewrite the assembly to use 32-bit difference values. Something like this:

    adr     addr,   .L.dct_add_switch
    ldr     offset, [addr, ta, lsl #2]
    add     addr,   addr, offset, uxtw
    br      addr

.L.dct_add_switch:
    .word  .L.dct_add_4   - .L.dct_add_switch
    .word  .L.dst_add_4   - .L.dct_add_switch
Ross Ridge
  • 38,414
  • 7
  • 81
  • 112