Stack layout question(+)

Все, что вы хотели знать о программизме, но боялись спросить.
Ответить
Аватара пользователя
aldep
Маньяк
Сообщения: 1593
Зарегистрирован: 18 фев 2003, 08:06
Откуда: Toronto
Контактная информация:

Stack layout question(+)

Сообщение aldep »

Вопрос - где можно подробно прочесть про формат и устройство стека в WinNT.
Задача сделать Thread Dump (про StackWalk - читал, интересно как оно внутри устроено).
Boo
Пользователь
Сообщения: 92
Зарегистрирован: 20 фев 2003, 00:41

Сообщение Boo »

На стек вызовов функций программы стандарта нету. Зависит от имплементации языка на котором работаешь. Формат стека будет разным например для следующих систем:
- дельфи
- VC
- Watcom C
- GCC

Ессно, все языки обязаны соблюдать calling conventions когда доходит до системных вызовов. Т.е. сначала пушатся аргументы в обратном порядке, затем идет CALL, который пушит адрес возврата (это на I386).

Кроме того, когда мы говорим про NT, то для разных процессоров это будет выглядеть по-разному.
Аватара пользователя
aldep
Маньяк
Сообщения: 1593
Зарегистрирован: 18 фев 2003, 08:06
Откуда: Toronto
Контактная информация:

Сообщение aldep »

Ну допустим надо для платформы intel32 (возможно intel64).
Интересует в первую очередь _stdcall convertion. Но что-то у меня сомнение, что нельзя сделать универсальную функцию - StackWalk работает и для _cdecl и для _stdcall.
в общем я понимаю, что в рамках форума это не расскажешь. Поэтому меня интересуют ссылки - на любую полезную информацию.
Boo
Пользователь
Сообщения: 92
Зарегистрирован: 20 фев 2003, 00:41

Сообщение Boo »

Статьи, которая отвечала на вопрос прямо я не видел. Просмотр файлов Dbghelp.h, winnt.h и stdarg.h частично может удовлетворить любопыство. Еще можно пойти на интел и взять там книжку про программированию на 386 проце. Еще больше информации получаешь когда компиляешь программу

Код: Выделить всё

int __stdcall  test(int x)
{
    return 0;
}
с ключами /Fa /Od /c. Для окончательного понимания как работает StackWalk надо смотреть не только то что происходит до вызова, но и сразу после него (push ebp; mov ebp, esp). Т.е. начало стека при входе в процедуру сохраняется. Это позволяет бэктрейсить.

Это если любопытство праздное. Практически, не советую писать StackWalk самому, он уже есть в системе :). Если это вопрос совсем конкретной практики, то могу написать что я делал когда программа зависала на продакшн серверах, т.е. дебажить нельзя надо а понять где стоит....
Аватара пользователя
aldep
Маньяк
Сообщения: 1593
Зарегистрирован: 18 фев 2003, 08:06
Откуда: Toronto
Контактная информация:

Сообщение aldep »

Boo писал(а): Для окончательного понимания как работает StackWalk надо смотреть не только то что происходит до вызова, но и сразу после него (push ebp; mov ebp, esp). Т.е. начало стека при входе в процедуру сохраняется. Это позволяет бэктрейсить.
Вот это я и имел ввиду, что должно сохраняться.
Boo писал(а):
Это если любопытство праздное. Практически, не советую писать StackWalk самому, он уже есть в системе :). Если это вопрос совсем конкретной практики, то могу написать что я делал когда программа зависала на продакшн серверах, т.е. дебажить нельзя надо а понять где стоит....
Нет не праздное, писать самому вроде не предполагается, но для отладки хотелось бы понимать, как все это работает. Поэтому все что сможешь написать, будет принято с большой благодарностью.
Boo
Пользователь
Сообщения: 92
Зарегистрирован: 20 фев 2003, 00:41

Сообщение Boo »

с точки зрения StackWalk разницы между __stdcall и __cdecl особой нет. это важно для очистки пушнутых в стек аргументов, это сугубо взаимоотношения вызывающего и вызываемого кода (если я понятно выражаюсь). для StackWalk важно отыскать стек фреймы. чтобы понять как это делается, грузим книжку с Интела http://developer.intel.com/design/penti ... 319001.pdf и читаем главу 4.2.4. там есть картинки и подробное описание стека. весь стек побит на фреймы которые являются в сущности однонаправленным списком. вот по нему StackWalk просто идет и в результате мы имеем список адресов вызывающих процедур.

хорошо, но в дебугере мы видим не список адресов, и имена функций и иногда даже их параметры, откуда это-то берется? ответ: из дебуггерной информации которая создается компилятором в при компиляции, это те самые *.pdb файлы. кроме разной другой информации в них есть имена функций с их адресами. в принципе тассировщик стека со всеми прибамбасами можно написать самому, для этого даже есть библиотечка, которую можно выкачать отсюда. кстати, автор - экперт по дебужинью программ, он больше ничем по жизни не занимается :shock: . есть чему поучиться :).

в заключение, как понять где висит твоя прога если тебе нельзя ее дебужить? например где-нибудь у кастомера в мексике, но у тебя есть доступ только по терминалу. выкачиваем Microsoft Debugging Tools. смотрим описание к файлику "adplus.vbs". копируем его + cdb.exe + еще несколько ДЛЛ-ей к кастомеру на машину. натравливаем это на "плохой" процесс. в результате имеем один текстовый файл со стеками, регистрами и прочим барахлом. из него уже очень многое можно понять. если информации все еще недостаточно, то будет еще другой бинарный файл, который является копией всего адресного пространства процесса. это файл можно грузить прямо в отладчик и глядеть все что обычно глядишь в отладчике.

фуу, вот.... :)
Аватара пользователя
aldep
Маньяк
Сообщения: 1593
Зарегистрирован: 18 фев 2003, 08:06
Откуда: Toronto
Контактная информация:

Сообщение aldep »

Спасибо, то что нужно. :D
Ответить