Сообщение Re[5]: особенности структурной обработки исключений в Win64 от 03.12.2016 19:04
Изменено 03.12.2016 19:11 ononim
O>>Ну прежде чем делать какие либо выводы нужно бы заглянуть в WININET!DispatchAPICall+0x3f0. А предде чем заглядывать в вывод отладчика вообще нужно бы настроить символы..
кт>Не понял, какие символы настроить?
Дебажные символы. windbg настраивается на публичный микрософтовский символ-сервер двумя командами: .symfix и .reload
кт>Это была всего лишь иллюстрация бездумного сохранения при вызове простейшей функции.
С чего вы взяли что сохранение бездумное, а функция простейшая? Что за код по адресу WININET!DispatchAPICall+0x3f0 которая вызывается между сохранением/восстановлением MMX регистров вы смотрели? Ну и к выравниванию стека это вообще отношения не имеет.
O>>Это часть соглашений о вызове.
кт>Lunix без этого обходится. Там как раз запоминается, что нужно, а не вообще все
кт>SSE2 используются не часто, ну и запоминайте их в тех редких случаях, когда их действительно используют
Во-первых, очень часто используется. Во-вторых сохранение SSE2 не предусмотрено calling convention, предусмотрено только выравнивание стека для того чтоб компилятор мог без дополнительных проверок в любом месте воспользоваться SSE. MMX контекст сохраняется только если используется.
В вашем примере компилятор решил сохранить SSE перед вызовом непубличной функции. Это его право, так как для непубличных функций компилятор вправе положить на volatile/preserved registers. Уверен что по адресу WININET!DispatchAPICall+0x3f0 находится код который таки юзает SSE.
O>>Такое исключение не приведет к падению. 64 стек всегда аллоцируется кратным sizeof(void *) то есть 8. Добиться неровности можно только некорректным кодом, а не исключением в корректном коде, сгерененным компилятором с учетом известных ему правил. Если писать свой код на асме который делает add rsp, 3, а потом хвататься за свою голову остается только посочувтсовать. Как я уже сказал — меньше всего авторы соглашений колдогенерации в х64 позаботились о любителях теплого лампового ассемблера.
кт>Это вообще не понял. В примере речь шла вообще не о стеке, а об исчезновении порядка ("антипереполнении") переменной x типа double. В программе в этом случае ей присваивается "чистый" 0.0E0. В ряде вычислений так и надо, но иногда антипереполнение — это признак ошибки расчета. Перехватывается аппаратное прерывание от FPU и корректируется переменная. После исключения программа продолжает нормальное (предусмотренное) выполнение. Это был пример на "жизнь после исключения".
Еще раз: есть пример кода, когда конкретно этот сценарий использования исключений работает некорректно на х64? Или ваши жалобы касаются лишь того что сложно все это понять "на глазок" как оно все теперь работает и быстро на коленке обработать это дело самописным дебаггером?
кт>Не понял, какие символы настроить?
Дебажные символы. windbg настраивается на публичный микрософтовский символ-сервер двумя командами: .symfix и .reload
кт>Это была всего лишь иллюстрация бездумного сохранения при вызове простейшей функции.
С чего вы взяли что сохранение бездумное, а функция простейшая? Что за код по адресу WININET!DispatchAPICall+0x3f0 которая вызывается между сохранением/восстановлением MMX регистров вы смотрели? Ну и к выравниванию стека это вообще отношения не имеет.
O>>Это часть соглашений о вызове.
кт>Lunix без этого обходится. Там как раз запоминается, что нужно, а не вообще все
кт>SSE2 используются не часто, ну и запоминайте их в тех редких случаях, когда их действительно используют
Во-первых, очень часто используется. Во-вторых сохранение SSE2 не предусмотрено calling convention, предусмотрено только выравнивание стека для того чтоб компилятор мог без дополнительных проверок в любом месте воспользоваться SSE. MMX контекст сохраняется только если используется.
В вашем примере компилятор решил сохранить SSE перед вызовом непубличной функции. Это его право, так как для непубличных функций компилятор вправе положить на volatile/preserved registers. Уверен что по адресу WININET!DispatchAPICall+0x3f0 находится код который таки юзает SSE.
O>>Такое исключение не приведет к падению. 64 стек всегда аллоцируется кратным sizeof(void *) то есть 8. Добиться неровности можно только некорректным кодом, а не исключением в корректном коде, сгерененным компилятором с учетом известных ему правил. Если писать свой код на асме который делает add rsp, 3, а потом хвататься за свою голову остается только посочувтсовать. Как я уже сказал — меньше всего авторы соглашений колдогенерации в х64 позаботились о любителях теплого лампового ассемблера.
кт>Это вообще не понял. В примере речь шла вообще не о стеке, а об исчезновении порядка ("антипереполнении") переменной x типа double. В программе в этом случае ей присваивается "чистый" 0.0E0. В ряде вычислений так и надо, но иногда антипереполнение — это признак ошибки расчета. Перехватывается аппаратное прерывание от FPU и корректируется переменная. После исключения программа продолжает нормальное (предусмотренное) выполнение. Это был пример на "жизнь после исключения".
Еще раз: есть пример кода, когда конкретно этот сценарий использования исключений работает некорректно на х64? Или ваши жалобы касаются лишь того что сложно все это понять "на глазок" как оно все теперь работает и быстро на коленке обработать это дело самописным дебаггером?
Re[5]: особенности структурной обработки исключений в Win64
O>>Ну прежде чем делать какие либо выводы нужно бы заглянуть в WININET!DispatchAPICall+0x3f0. А предде чем заглядывать в вывод отладчика вообще нужно бы настроить символы..
кт>Не понял, какие символы настроить?
Дебажные символы. windbg настраивается на публичный микрософтовский символ-сервер двумя командами: .symfix и .reload
кт>Это была всего лишь иллюстрация бездумного сохранения при вызове простейшей функции.
С чего вы взяли что сохранение бездумное, а функция простейшая? Что за код по адресу WININET!DispatchAPICall+0x3f0 которая вызывается между сохранением/восстановлением MMX регистров вы смотрели? Ну и к выравниванию стека это вообще отношения не имеет.
O>>Это часть соглашений о вызове.
кт>Lunix без этого обходится. Там как раз запоминается, что нужно, а не вообще все
кт>SSE2 используются не часто, ну и запоминайте их в тех редких случаях, когда их действительно используют
Во-первых, очень часто используется. Во-вторых обязательнон сохранение MMX регистров прям таки всегда не предусмотрено calling convention, предусмотрено только выравнивание стека для того чтоб компилятор мог без дополнительных проверок в любом месте воспользоваться SSE. А MMX контекст сохраняется только если используется.
В вашем примере компилятор решил сохранить SSE перед вызовом непубличной функции. Это его право, так как для непубличных функций компилятор вправе положить на volatile/preserved registers. Уверен что по адресу WININET!DispatchAPICall+0x3f0 находится код который таки юзает SSE, потому компилятор и решил сохранить ММХ контекст. А поскольку функция по адресу WININET!DispatchAPICall+0x3f0 не является публичной, то компилятор вполне вправе поместить сохранение/восстановление ММХ контекста в вызывающем коде. Соглашения о volatile/preserved регистрах — это только для публичных символов. Внутренние вызовы компилятор волен оптимизировать как угодно, в том числе не подчиняясь соглашениям о сохранении регистров, и он это делает повсеместно. В х64 кстати оптимизатор стал особенно злым.
O>>Такое исключение не приведет к падению. 64 стек всегда аллоцируется кратным sizeof(void *) то есть 8. Добиться неровности можно только некорректным кодом, а не исключением в корректном коде, сгерененным компилятором с учетом известных ему правил. Если писать свой код на асме который делает add rsp, 3, а потом хвататься за свою голову остается только посочувтсовать. Как я уже сказал — меньше всего авторы соглашений колдогенерации в х64 позаботились о любителях теплого лампового ассемблера.
кт>Это вообще не понял. В примере речь шла вообще не о стеке, а об исчезновении порядка ("антипереполнении") переменной x типа double. В программе в этом случае ей присваивается "чистый" 0.0E0. В ряде вычислений так и надо, но иногда антипереполнение — это признак ошибки расчета. Перехватывается аппаратное прерывание от FPU и корректируется переменная. После исключения программа продолжает нормальное (предусмотренное) выполнение. Это был пример на "жизнь после исключения".
Еще раз: есть пример кода, когда конкретно этот сценарий использования исключений работает некорректно на х64? Или ваши жалобы касаются лишь того что сложно все это понять "на глазок" как оно все теперь работает и быстро на коленке обработать это дело самописным дебаггером?
кт>Не понял, какие символы настроить?
Дебажные символы. windbg настраивается на публичный микрософтовский символ-сервер двумя командами: .symfix и .reload
кт>Это была всего лишь иллюстрация бездумного сохранения при вызове простейшей функции.
С чего вы взяли что сохранение бездумное, а функция простейшая? Что за код по адресу WININET!DispatchAPICall+0x3f0 которая вызывается между сохранением/восстановлением MMX регистров вы смотрели? Ну и к выравниванию стека это вообще отношения не имеет.
O>>Это часть соглашений о вызове.
кт>Lunix без этого обходится. Там как раз запоминается, что нужно, а не вообще все
кт>SSE2 используются не часто, ну и запоминайте их в тех редких случаях, когда их действительно используют
Во-первых, очень часто используется. Во-вторых обязательнон сохранение MMX регистров прям таки всегда не предусмотрено calling convention, предусмотрено только выравнивание стека для того чтоб компилятор мог без дополнительных проверок в любом месте воспользоваться SSE. А MMX контекст сохраняется только если используется.
В вашем примере компилятор решил сохранить SSE перед вызовом непубличной функции. Это его право, так как для непубличных функций компилятор вправе положить на volatile/preserved registers. Уверен что по адресу WININET!DispatchAPICall+0x3f0 находится код который таки юзает SSE, потому компилятор и решил сохранить ММХ контекст. А поскольку функция по адресу WININET!DispatchAPICall+0x3f0 не является публичной, то компилятор вполне вправе поместить сохранение/восстановление ММХ контекста в вызывающем коде. Соглашения о volatile/preserved регистрах — это только для публичных символов. Внутренние вызовы компилятор волен оптимизировать как угодно, в том числе не подчиняясь соглашениям о сохранении регистров, и он это делает повсеместно. В х64 кстати оптимизатор стал особенно злым.
O>>Такое исключение не приведет к падению. 64 стек всегда аллоцируется кратным sizeof(void *) то есть 8. Добиться неровности можно только некорректным кодом, а не исключением в корректном коде, сгерененным компилятором с учетом известных ему правил. Если писать свой код на асме который делает add rsp, 3, а потом хвататься за свою голову остается только посочувтсовать. Как я уже сказал — меньше всего авторы соглашений колдогенерации в х64 позаботились о любителях теплого лампового ассемблера.
кт>Это вообще не понял. В примере речь шла вообще не о стеке, а об исчезновении порядка ("антипереполнении") переменной x типа double. В программе в этом случае ей присваивается "чистый" 0.0E0. В ряде вычислений так и надо, но иногда антипереполнение — это признак ошибки расчета. Перехватывается аппаратное прерывание от FPU и корректируется переменная. После исключения программа продолжает нормальное (предусмотренное) выполнение. Это был пример на "жизнь после исключения".
Еще раз: есть пример кода, когда конкретно этот сценарий использования исключений работает некорректно на х64? Или ваши жалобы касаются лишь того что сложно все это понять "на глазок" как оно все теперь работает и быстро на коленке обработать это дело самописным дебаггером?