Почему компилятор добавляет дополнительную инструкцию 'sxtw' (что приводит к панике ядра)? - PullRequest
1 голос
/ 26 марта 2019

Проблема / Симптом:

В конце возврата функции компилятор добавляет инструкцию sxtw, как показано в разборке, в результате чего адрес возврата составляет только 32 бита вместо 64 бит, что приводит кПаника ядра:

Unable to handle kernel paging request at virtual address xxxx

Среда сборки:

Платформа: ARMV7LE
gcc, linux-4.4.60
Архитектура: arm64
gdb: aarch64-5.3-glibc-2.22 / usr / bin / aarch64-linux-gdb

Подробности:

Вот упрощенная структура проекта.Об этом позаботились правильно в соответствующем make-файле.Также обратите внимание, что file1.c и file2.c являются частью одного и того же модуля.

../src/file1.c / * В нем определена функция func1 (), а также /
../src/file2.c
../inc/files.h /
В заголовке не объявлено func1 () * /

Причина проблемы:

Вызов функции func1 () был добавлен из объявления file2.cw/o func1 в файлах file.h или file2.c.(В основном, включение func1 было случайно пропущено в файлах .h.)

Код, скомпилированный без ошибок, но с ожидаемым предупреждением - Implicit declaration of function func1.

Во время выполнения, однако,сразу после возврата из func1 в file2, система потерпела крах, когда она попыталась разыменовать возвращенный адрес из func1.

Дальнейший анализ показал, что в конце возврата функции компилятор добавил инструкцию sxtw, как показано вдизассемблирование, в результате чего адрес возврата всего 32 бита вместо 64 бит, что приводит к панике ядра.

Unable to handle kernel paging request at virtual address xxxx
  • Обратите внимание, что x19 имеет 64 бит, а w0 32 бит.
  • Обратите внимание, что слово x0 LS совпадает со словом x19.
  • Сбой системы во время разыменования x19.

sxtw x19, w0 / * Это было добавлено компилятором в качестве дополнительной инструкции / ldp x1, x0, [x19, # 304] / Здесь произошел сбой системы * /

Регистры:

[   91.388130] pc : [<ffffff80016c9074>] lr : [<ffffff80016c906c>] pstate: 80000145
[   91.462090] sp : ffffff80094333b0
[   91.552708] x29: ffffff80094333d0 x28: ffffffc06995408a
[   91.652701] x27: ffffffc06c400a00 x26: 0000000000000000
[   91.716243] x25: 0000000000000000 x24: ffffffc069958000
[   91.779784] x23: ffffffc076e00000 x22: ffffffc06c400a00
[   91.843326] x21: 0000000000000031 x20: ffffffc073060000
[   91.906867] x19: 0000000066bfc780 x18: ffffff8009436888
[   91.970409] x17: 0000000000000000 x16: ffffff8008193074
[   92.033952] x15: 00000000000a8c06 x14: 2c30323030387830
[   92.097492] x13: 3d7367616c66202c x12: 3038653030303030
[   92.161034] x11: 3038666666666666 x10: 78303d646e65202c
[   92.224576] x9 : 3063303030303030 x8 : 3030303030303030
[   92.288117] x7 : 0000000000000880 x6 : 0000000000000000
[   92.351659] x5 : ffffffc07fd10ad8 x4 : 0000000000000001
[   92.415202] x3 : 0000000000000007 x2 : cb88537fdc8ba63c
[   92.478743] x1 : 0000000000000000 x0 : ffffffc066bfc780

После добавления объявления func1 в files.h, дополнительная инструкция и, следовательно, сбой не видел.

Можеткто-нибудь, пожалуйста, объясните, почему компилятор добавил sxtw в этом случае?

1 Ответ

2 голосов
/ 26 марта 2019

Вы должны были получить как минимум два предупреждения, одно о пропущенном объявлении функции и другое о неявном преобразовании из int в тип указателя.

Причина в том, что неявно объявленные функции имеют тип возврата int. Преобразование этого значения int в 64-битный указатель отбрасывает 32-битный результат. Это ожидаемое поведение GNU C, основанное на том, что сделали компиляторы C для ранних 64-битных целей. Инструкция sxtw необходима для реализации этого поведения. (Текущие стандарты C больше не имеют неявных объявлений функций, но GCC по-прежнему должен поддерживать их для обратной совместимости с существующими тестами autoconf.)

Обратите внимание, что ваша платформа, очевидно, Aarch64 (с 64-битными регистрами), а не 32-битная ARMv7.

...