кто определяет значение "#: abs_g3: main" - PullRequest
0 голосов
/ 04 ноября 2018

У меня странная ошибка, и я пытаюсь понять. В частности, по крайней мере, я хотел бы быть уверен в том, какое программное обеспечение мне следует изучить: компоновщик, 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 и друзей?

1 Ответ

0 голосов
/ 04 ноября 2018

Какой компонент выходит из строя? Основная программа или общий объект?

sysdep/aarch64/start.S не следует связывать в динамический общий объект, поскольку он является частью кода запуска для основного исполняемого файла. Большинство программ не имеют динамического символа для main, поэтому привязка не удалась бы, даже если бы использовались правильные перемещения. (Перемещения #:abs_gX несовместимы с независимым от позиции кодом, необходимым для общих объектов.)

В случае сбоя основной программы может возникнуть ряд проблем. В вашем вопросе действительно недостаточно информации, чтобы дать твердый совет. Я предполагаю, что это некое несоответствие PIE / non-PIE, которое приводит к неправильной версии кода запуска. Обратите внимание, что start.S собирается несколько раз в процессе сборки glibc с разными флагами препроцессора и связывается с crt1.o (исполняемый файл без PIE / ET_EXEC), Scrt1.o (исполняемый файл PIE / ET_DYN) и gcrt1.o (профилирование).

...