Выравнивание стека и вызов АПИ x64

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Выравнивание стека и вызов АПИ x64

Сообщение myles » 03.04.2012 20:21:40

Встретился к своему сожалению в багом, описываю:

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

procedure f1;
var ...
begin
p :=MapViewOfFile(hMap ,FILE_MAP_ALL_ACCESS,0,0,SIZE_1);
end;

И эта штука рабоатет в зависимости от того, выравнен ли стек на границу 0x20 !!

То есть пишу прогу, она работает. Далее если описываю в переменных процедуры перемунную и юзаю ее, то на момент вызова сбивается стек (а он выравнен по 0х10). Итого получается что мне нужно внимательно следить за тем, чтобы на момент вызова АПИ был выравнен стек, и если у меня в процедуре или функции размер моих переменных на кратен 0x20, то мне прийдется добавлять "пустые" переменные.. чтобы самостоятельно выравнять стек?

Есть ли может какой способ или директива по автовыравниванию стека в функциях?

(актуально для х64)
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15

Re: Выравнивание стека и вызов АПИ x64

Сообщение Sergei I. Gorelkin » 03.04.2012 21:05:10

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

Выравнивание стека на 16 байт, требуемое x86_64, осуществляется само по себе без всяких директив. Других требований к выравниванию со сторны ABI нет.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Выравнивание стека и вызов АПИ x64

Сообщение myles » 03.04.2012 23:04:35

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




У меня дело так:
Код: Выделить всё
type
TMapViewOfFile= function(hFileMappingObject: THandle; dwDesiredAccess: DWORD;
  dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap: DWORD): Pointer; stdcall;

var MapViewOfFile:TMapViewOfFile;
..
Pointer(MapViewOfFile):=GetProcAddress...
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15

Re: Выравнивание стека и вызов АПИ x64

Сообщение Sergei I. Gorelkin » 04.04.2012 00:37:29

myles писал(а):Тут можно поподробнее?

Например, вместо ReadFile(hFile, p^, ...) написано ReadFile(hFile, p, ...), причем где-нибудь совсем в другом месте программы. Данные читаются не туда, куда указывает p, а прямо в стек. Подробнее по приведенным отрывкам сказать ничего нельзя.

myles писал(а):type TMapViewOfFile= function(hFileMappingObject: THandle; dwDesiredAccess: DWORD;  dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap: DWORD): Pointer; stdcall;


Тут последний параметр (dwNumberOfBytesToMap) должен быть типа size_t.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Выравнивание стека и вызов АПИ x64

Сообщение myles » 04.04.2012 08:19:28

Например, вместо ReadFile(hFile, p^, ...) написано ReadFile(hFile, p, ...), причем где-нибудь совсем в другом месте программы. Данные читаются не туда, куда указывает p, а прямо в стек.


Что значит: "данные читаются не туда. куда указывает р, а прямо в стек"?
Вообще если изучить описание функции ReadFile, то вторым параметром будет указатель на буфер с данными, как и везде.
И получается, что в случае 32 бит в стек положится указатель на данные, а не сами данные!
В 64 бит картина другая. т.к. первеы 4 параметра передаются через регистры rcx, rdx, r8, r9, а остальные через стек, но и в этом случае будет передан указатель на буфер, но никак не сам буфер.
Далее, (беру Делфи, но и в Лазарусе така же штука)

Описание функций будут идентичные:
Код: Выделить всё
function f1(pDW:PDWORD)....

function f1(var dw:dword)...


Единственная разница - в самом теле функции синтаксис будет pDW^:= или просто dw:=
Но если посмотреть в отадочнике - будет точно такой же код - передача указателей.

Аналогичныеми будут конструкции:

Код: Выделить всё
function f21(p :Pointer)....

function f22(b:buffer)...

Вызываем их:
Код: Выделить всё
var buff:array [0..127] of char;
pn:pointer;
..
f21(@buff);

pn:=@buff;
f22(buff);
f22(pn^);


Двоичный код получиться одинаковый. а штука ReadFile(hFile, p, ...) либо не откампилируется, либо будет падать программа, т.к. буфер будет записан в стек и перетрет адреса возврата и другие переменные..

Тут последний параметр (dwNumberOfBytesToMap) должен быть типа size_t.

А вот эта штука уже более вероятна, т.к. неизвестно что будет в старшем двойном слове.
myles
незнакомец
 
Сообщения: 8
Зарегистрирован: 09.03.2012 20:12:15


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 232

Рейтинг@Mail.ru