Связывание проблем при создании библиотеки для iOS 7

При создании библиотеки для iOS 7 на iPhone возникает проблема со связыванием (ARM64).

Сообщение об ошибке:

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)

Эта ошибка появляется в результате этого кода (это своего рода переключатель):

    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 общие регистры x3, x4, w5 соответственно.

Кто-нибудь знает, как справиться с этой ситуацией?

PS: с GNU GCC & Android проблем нет.

EDIT1: кажется, что проблема не в самом компоновщике, а в компиляторе. Я проверил объектный файл (objdump) и вместо констант разницы просто нули.

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

Когда я помещаю вычисленные вручную константы вместо выражений ".L.dct_add_4 - .L.dct_add_switch" и т. Д., Все идет хорошо.

Может быть, есть какие-то ключи компилятора, которые заставят компилятор делать это правильно?

Благодарю.

2 ответа

Решение

Ну, есть проблема компилятора и компоновщика, и это зависит от размера данных, которые используются для смещений. Clang не очень дружелюбен ко всему, что отличается от 4 байтов.

Обсуждение и возможные решения в другой теме: создание таблицы постоянных переходов; Xcode; лязг; как м

Проблема в том, что формат объектного файла Mach-O для 64-разрядных целей ARM не поддерживает перемещение 16-разрядной разницы между двумя символами. Похоже, что разница должна быть 32-битной или 64-битной. Похоже, это не проблема с компилятором или компоновщиком. Код сборки, который вы цитировали в своем вопросе, выглядит как сборка, созданная вручную, а не как вывод компилятора.

Решением было бы переписать сборку, чтобы использовать 32-разрядные значения разности. Что-то вроде этого:

    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
Другие вопросы по тегам