Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Запретить компиллятору использовать регистр


Автор: svlary 13.7.2015, 11:25
Пишу драйвер. При  работе драйвера, иногда (очень редко!) выскаивает "Oops!!!". По распечатке стека знаю, в какой функции это происходит.
Но дальнешая локализация ошибки затруднена, так как:
1) Функция работает внутри обработки прерывания, поэтому вставить туда отладочную печать не могу.
2) Функция очень большая, но разбивать её на куски не хчется (есть на то причины). Так что найти ошибку просто читая код не получается.

Возникла идея - писать в один из общих регистров значения типа 1...N, отмечающие ключевые точки кода. Тогда, по распечатке при "Oops!!!" можно будет опознать участок по значению в этом регистре.  Как записать значение в регистр с помощью встроенного ассемблера, я знаю. 

Но как сделать так, что бы компиллятор этот регистр не тргал ?

Автор: xvr 13.7.2015, 16:40
https://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html#Global-Reg-Vars - оно?
И еще опция -ffixed-reg (см https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options )

Автор: svlary 13.7.2015, 20:23
Цитата

https://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html#Global-Reg-Vars - оно?

    Оно... В самую точку ! Вот только автор этого текста мучается той же самой проблемой:
Цитата

Choose a register ..., so that library routines will not clobber it.
 
   А кака его выбрать ?!


Цитата

И еще опция -ffixed-reg (см https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options )

   Вот я тоже долго читал описание этой опции и так ни фига и не понял.... :-(

Спасибо за ответ !

Автор: xvr 14.7.2015, 12:31
Цитата(svlary @  13.7.2015,  20:23 Найти цитируемый пост)
   А кака его выбрать ?!

Не использовать библиотечные функции. Если у вас это часть ядреного дравера, то проблем с ними не будет - их там просто нет  smile 

Или пересобрать библиотеки с опцией -ffixed-reg и вашим регистром.

По другому похоже никак  smile 

Автор: tzirechnoy 14.7.2015, 13:59
Цитата
Тогда, по распечатке при "Oops!!!" можно будет опознать участок по значению в этом регистре.


Простите, а чем вас для этого регистр EIP не устраивает?

Автор: svlary 14.7.2015, 14:50
Цитата(tzirechnoy @  14.7.2015,  13:59 Найти цитируемый пост)
Простите, а чем вас для этого регистр EIP не устраивает? 


Тем, что его нет....  smile Драйвер пишу для PowerPC. Попробовал использовать  r28 - вроде бы, получается.

Добавлено через 8 минут и 46 секунд
Цитата(xvr @  14.7.2015,  12:31 Найти цитируемый пост)
их там просто нет

Ну да, таких функций как sin() и printf()  нет, зато у меня полно всякого добра типа pci_enable_device() ... Вот о них я беспокоюсь.

Автор: tzirechnoy 14.7.2015, 18:30
Цитата
Тем, что его нет....


Очень смешно. А по делу есть что ответить  или это всё ужэ неактуально?

Автор: xvr 14.7.2015, 20:15
Цитата(svlary @  14.7.2015,  14:50 Найти цитируемый пост)
Вот о них я беспокоюсь.

Правильно беспокоитесь. 
Цитата(svlary @  14.7.2015,  14:50 Найти цитируемый пост)
Драйвер пишу для PowerPC

Смотрите ABI на PowerPC и выбирайте регистр из callee saved списка.

Автор: svlary 15.7.2015, 09:53
Цитата(tzirechnoy @  14.7.2015,  18:30 Найти цитируемый пост)
Очень смешно. А по делу есть что ответить  или это всё ужэ неактуально? 


Правда -нет ! Наиболее близкая мнемоника -  NIP, но это указатель счётчика команд и (разумеется) использовать его нельзя.

По делу - актуально! Вставил запись значений в регистр GPR28, жду, когда произойдёт падение - может и увижу что-то полезное.

Добавлено через 4 минуты и 23 секунды
Цитата(xvr @  14.7.2015,  20:15 Найти цитируемый пост)
Смотрите ABI на PowerPC и выбирайте регистр из callee saved списка.


Здесь я совсем не в курсе :-(
  • Где смотреть про "ABI на PowerPC" ?
  • Что такое "callee saved" ?

Автор: tzirechnoy 15.7.2015, 10:55
Цитата
Наиболее близкая мнемоника -  NIP


Да какая разница, какая у него мненомника? rip, %pc, NIA...

Цитата
и (разумеется) использовать его нельзя.


Использовать его, разумеется, обязательно. Не в смысле -- что-то туда записывать, а в смысле -- прочесть его значение в дампе и выяснить, где конкретно гикнулась программа.

Добавлено через 3 минуты и 6 секунд
Цитата
1) Функция работает внутри обработки прерывания, поэтому вставить туда отладочную печать не могу.


И кстати, если драйвер под линукс -- то вполне можэт вставлять туда отладочную печать. printk() работает.

Автор: xvr 15.7.2015, 11:25
Цитата(svlary @  15.7.2015,  09:53 Найти цитируемый пост)
Где смотреть про "ABI на PowerPC" ?

http://cache.freescale.com/files/32bit/doc/ref_manual/E500ABIUG.pdf (вас интересует страница 29)

Цитата(svlary @  15.7.2015,  09:53 Найти цитируемый пост)
Что такое "callee saved" ?

Это регистры, которые сохраняет вызываемая процедура. В вашем случае это 'Registers used for local variables' - r14-r31. 

Цитата(svlary @  14.7.2015,  14:50 Найти цитируемый пост)
Попробовал использовать  r28 - вроде бы, получается.

Подойдет

Автор: bsa 15.7.2015, 12:04
Я бы разделил большую функцию на несколько. Можно методом деления пополам. И таким бы образом локализовал бы проблему.

Автор: svlary 15.7.2015, 14:11
Цитата(tzirechnoy @  15.7.2015,  10:55 Найти цитируемый пост)
прочесть его значение в дампе и выяснить, где конкретно гикнулась программа.

тут тоже какая-то дурацкая проблема, с которой я не справился - какие бы ключи я не ставил в Makefile в строке CFLAGS +=...  мне так и не удалось получить билистинг, т.е. ассемблерную распечатку с выдачей смещения от начала модуля и исходным текстом в виде комментариев. Пробовал получить её через objdump или gdb, но им нужна для этого отладочная информация. а и этот ключ (-g) передать не удалось. У меня сложилось такоен впечатление, что когда Make начинает просматривать сорцы ядра, он забывает про мой Makefile и работает сам по себе. Этот Makefile  писал сам и не совсем уверен в его адекватности...

Добавлено через 4 минуты и 37 секунд
Цитата(tzirechnoy @  15.7.2015,  10:55 Найти цитируемый пост)
printk() работает


Разумеется - работает! Вопрос в том,  что в обработчике прерываний запрещается использование kmalloc так как выделение виртуальной памяти может занять неопределённое время или даже не завершиться успешно. А я сильно подозреваю, что для организации буфера печати этот вызов используется.

Добавлено через 6 минут и 33 секунды
Цитата(xvr @  15.7.2015,  11:25 Найти цитируемый пост)
(вас интересует страница 29)

За ссылку - большое спасибо ! smile

Автор: tzirechnoy 15.7.2015, 14:26
Цитата
мне так и не удалось получить билистинг, т.е. ассемблерную распечатку с выдачей смещения от начала модуля и исходным текстом в виде комментариев.


По факту, если есть вызовы функцый по телу, и их имена показывает objdump -- то и без билистинга быстро становится понятно, что есть какой оператор. Там всё достаточно линейно в итоге.

Но вообще да, разобраться с -g -- в любом случае важная задача. Кстати, вероятно, там потребуются не только CLAGS, но и LDFLAGS.

И да, кстати, у меня тожэ не получилось для gcc .map-файл с листингом сделать. Только -- отдельно ассэмблерный листинг с соответствием исходнику, отдельно -- .map-файл. Впрочем, мне и не нужно это особенно было, поскольку gdb более-менее всё показывал по debug info.

Автор: tzirechnoy 15.7.2015, 15:12
Цитата
А я сильно подозреваю, что для организации буфера печати этот вызов используется.


Не надо ничего подозревать. Он просто работает. Это его свойство, и Линус довольно много умственных усилий приложыл, чтобы оно таки работало.

Да, форматированный вывод -- работать не будет (ну, наверное, не пробовал). Но printk -- вполне.

Да, на размер есть какие-то ограничения. Ну, там теперь (после эскапады systemdшников) и безо всяких прерываний есть ограничения на количество.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)