У меня странная ошибка, и я пытаюсь понять. В частности, по крайней мере, я хотел бы быть уверен в том, какое программное обеспечение мне следует изучить: компоновщик, glibc, ассемблер, компилятор или другое.
Я знаю, что предоставление сокращенного контрольного примера крайне важно. Тем не менее, извините за невозможность сделать это. Он не воспроизводит в x86. Он воспроизводится на arm64 и конкретном дистрибутиве Linux, который я не уверен, если он открыт для публики. Я еще недостаточно хорошо понимаю сам тестовый пример, чтобы сделать сокращенный тестовый пример.
Исполняемый файл получает ошибку сегментации в __libc_start_main. Причиной, по которой это происходит, является попытка элемента управления перейти к адресу, эффективно сохраняемому в регистре, x0, который странным образом равен 0. x0 устанавливается в функции _start.
// in sysdep/aarch64/start.S of glibc
MOVL (0, main)
Макрос MOVL выглядит следующим образом в sysdep.h в том же каталоге:
# define MOVL(R, NAME) \
movz PTR_REG (R), #:abs_g3:NAME; \
movk PTR_REG (R), #:abs_g2_nc:NAME; \
movk PTR_REG (R), #:abs_g1_nc:NAME; \
movk PTR_REG (R), #:abs_g0_nc:NAME;
Таким образом, я предполагаю, что #: abs_g0_nc: main и друзья должны быть ненулевыми, но определены как 0.
Итак, мой вопрос в том, какой компонент я должен винить. Исполняемый файл взят из исходного кода Go. Инструмент Go создает общую библиотеку без помощи внешнего компоновщика. Затем инструмент Go компилирует исходный код Go и связывает его с общей библиотекой Go, а также с несколькими другими библиотеками с внешним компоновщиком, gcc с компоновщиком gold.
Я видел _start в start.S похоже на конечный исполняемый файл. Только то, что #: abs_g * вещи пропали. Кто заменяет макрос (?) Числовыми значениями (в данном случае 0)?
gcc или компилятор уже компилирует _start заранее и помещает скомпилированный / собранный бинарный файл куда-то вроде / usr / lib {64}? Или, когда компоновщик ссылается вообще, компоновщик заменяет макрос каким-либо числовым значением? Если компоновщик делает это, когда проблемный исполняемый файл создается путем компоновки, от чего зависит компоновщик для вычисления значения #: abs_g0_nc и друзей?