Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.09.19;
Скачать: CL | DM;

Вниз

Импрот функций из exe.   Найти похожие ветки 

 
Тимохов ©   (2004-06-29 11:44) [0]

Прочел тут как-то, что импортировать функции можно не только из dll, но и из других exe. Попробовал сделать динамической загрузкой, получилось :)) Я сделал один dpr, даже без begin и end, т.е. одна функция и секция exports.

Вопросы:

1. Что происходит при загрузке exe череp LoadLibrary? Для dll, если не ошибаюсь вызывается стартовая функция библиотеки с соответствующим флагом, что-то типа dllproc process_attach (на память не помню). Что вызывается для exe? У него вроде нет такой функции.

2. Почему у меня не сработал такой код в библиотеке

procedure f();
begin
  MessageBox(0, "text", "caption", MB_OK);
end;


При вызове f из другого приложения впесто текстов получается ерунда (т.е. случайная область памяти).

И совершенно нормально сработал такой

procedure f();
var
  kText: packed array[0..4] of char;
  kCaption: packed array[0..7] of char;
begin
  kText[0] := "t";
  kText[1] := "t";
  kText[2] := "t";
  kText[3] := "t";
  kText[4] := #0;

  kCaption[0] := "c";
  kCaption[1] := "a";
  kCaption[2] := "p";
  kCaption[3] := "t";
  kCaption[4] := "i";
  kCaption[5] := "o";
  kCaption[6] := "t";
  kCaption[7] := #0;

  MessageBox(0, @kText, @kCaption, MB_OK);
end;


В последнем случае все вывелось корректно.


 
Игорь Шевченко ©   (2004-06-29 13:34) [1]


> 2. Почему у меня не сработал такой код в библиотеке
>
> procedure f();
> begin
>   MessageBox(0, "text", "caption", MB_OK);
> end;


Как ты загружал приложение ?


 
Тимохов ©   (2004-06-29 13:53) [2]


> Как ты загружал приложение ?

Приложение, из которого, я ипортировал процедуру f я загрузал через loadlibrary.


 
Игорь Шевченко ©   (2004-06-29 14:14) [3]

Тимохов ©   (29.06.04 13:53)

По какому базовому адресу загрузилось приложение ? :))


 
Тимохов ©   (2004-06-29 14:17) [4]


> По какому базовому адресу загрузилось приложение ? :))


конечно не по желаемому, т.к. оба exe имели $00400000 в качестве оного :)

Но вроде это не мое дело - система должна сделать релокацию? Имхо так в рихтере написано :)


 
Digitman ©   (2004-06-29 15:32) [5]

а посмотреть в ходе трассировки 1-го случая CPU-окно - не судьба ?


 
Тимохов ©   (2004-06-29 15:56) [6]


> Digitman ©   (29.06.04 15:32) [5]

смотрел :)))

адрес откуда загружается текст указывает на область, в которой хранится явно не то, что нужно


 
Игорь Шевченко ©   (2004-06-29 16:04) [7]


> адрес откуда загружается текст указывает на область, в которой
> хранится явно не то, что нужно


Вот и ответ на "
> 2. Почему у меня не сработал такой код в библиотеке
"


 
Тимохов ©   (2004-06-29 16:10) [8]


> Игорь Шевченко ©   (29.06.04 16:04) [7]

Ну Игорь, ну что вы издеваетесь :))
Какой же это ответ.

Это вполне корректный код

procedure f();
begin
 MessageBox(0, "text", "caption", MB_OK);
end;


Он же без проблем выполняется. Почему же не выполняется в случае загрузки exe как библиотеки.

Данный вопрос, конечно не является для меня в текущую секунду жизненно важным. Для меня важно понять, что я понимаю не так: про релокацию я вроде читал, опять же не вижу причин почему это не работает.

Есть у меня предположение, что в случае задания строковых констант загрузчик не может им сделать корректную релокацию. Вот и интересуюсь мнением бывалых почему.


 
Игорь Шевченко ©   (2004-06-29 16:20) [9]

Тимохов ©   (29.06.04 16:10)

Я не издеваюсь. Но с другой стороны, я не собираюсь делать тестовый пример, и смотреть, что и как там проиходит. Я полагаю, что лучше бы было, если бы ты привел здесь содержимое окна CPU с кодом функции, заодно и показал бы, на что указывают адреса и т.д.

Я эта...тонко намекаю, что чужое время можно бы и уважать...


 
Тимохов ©   (2004-06-29 16:24) [10]


> Игорь Шевченко ©   (29.06.04 16:20) [9]

да ладно, раньше бы сказали, что времени нет :)))

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

Оказалось нет...


 
Digitman ©   (2004-06-29 16:28) [11]


> адрес откуда загружается текст указывает на область, в которой
> хранится явно не то, что нужно


значит, секция иниц.данных в случае LoadLibrary() была загружена по иному вирт.адресу


 
Тимохов ©   (2004-06-29 16:33) [12]


> значит, секция иниц.данных в случае LoadLibrary() была загружена
> по иному вирт.адресу

это утверждение следует из того, что оба exe имели одинаковый предпочитительный адрес (стандартный для exe)?


 
Игорь Шевченко ©   (2004-06-29 16:40) [13]

Тимохов ©   (29.06.04 16:33)

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


 
Тимохов ©   (2004-06-29 16:47) [14]


> Игорь Шевченко ©   (29.06.04 16:40) [13]

виноват, да я так - по ходу спросил.
больше не буду.

)


 
Тимохов ©   (2004-06-29 17:43) [15]

Итак развернутый вопрос :)

Написано два exe: ExeLibrary (сама библиотека, эскспортирующая функции) и ExeLibraryClient (пример использования).

Код главной формы ExeLibrary

unit FExeLibrary;
... // здесь стандартный заголовок модуля с формой, ничего больше
implementation

{$R *.dfm}

// Пример с массивом char
procedure ExportFunctionWithCharArray();
var
  kText: packed array[0..2] of char;
begin
  kText[0] := "h";
  kText[1] := "i";
  kText[2] := #0;
  MessageBox(0, @kText, @kText, MB_OK);
end;

// Пример со строковой константой
procedure ExportFunctionWithStringConst();
begin
  MessageBox(0, "hi", "hi", MB_OK);
end;

exports
  ExportFunctionWithCharArray,
  ExportFunctionWithStringConst;

// Это две кнопки, призванные показать, что
// если ExeLibrary запускать как таковой, то обе
// экспортируемые функции работают корректно.
procedure TForm1.Button1Click(Sender: TObject);
begin
  ExportFunctionWithCharArray();
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ExportFunctionWithStringConst();
end;

end.


Код главной формц ExeLibraryClient

...// вырезано лишнее.
implementation

{$R *.dfm}

// здесь будет все ок,т.е. "hi"
procedure TForm1.Button1Click(Sender: TObject);
var
  kLib: HMODULE;
  kP: Pointer;
begin
  kLib := LoadLibrary("ExeLibrary.exe");
  kP := GetProcAddress(kLib, "ExportFunctionWithCharArray");
  TProcedure(kP);
  FreeLibrary(kLib);
end;

// здесь будет случайная ерунда
procedure TForm1.Button2Click(Sender: TObject);
var
  kLib: HMODULE;
  kP: Pointer;
begin
  kLib := LoadLibrary("ExeLibrary.exe");
  kP := GetProcAddress(kLib, "ExportFunctionWithStringConst");
  TProcedure(kP);
  FreeLibrary(kLib);
end;

end.


Будучи просмотренными из ExeLibraryClient функции выглядят так:

ExportFunctionWithCharArray

00DFDBD0 51               push ecx
00DFDBD1 C6042468         mov byte ptr [esp],$68
00DFDBD5 C644240169       mov byte ptr [esp+$01],$69
00DFDBDA C644240200       mov byte ptr [esp+$02],$00
00DFDBDF 6A00             push $00
00DFDBE1 8D442404         lea eax,[esp+$04]
00DFDBE5 50               push eax
00DFDBE6 8D442408         lea eax,[esp+$08]
00DFDBEA 50               push eax
00DFDBEB 6A00             push $00
00DFDBED E83691FBFF       call -$00046eca
00DFDBF2 5A               pop edx
00DFDBF3 C3               ret

ExportFunctionWithStringConst

00DFDBF4 6A00             push $00
00DFDBF6 6808DC4400       push $0044dc08
00DFDBFB 6808DC4400       push $0044dc08
00DFDC00 6A00             push $00
00DFDC02 E82191FBFF       call -$00046edf
00DFDC07 C3               ret


Меня вначале удивило, что MessageBox имеет разный адрес, но потом я понял, что скорее всего это из-за того, что я загружаею библиотеку каждый раз повтороно. Или нет?

Заметьте

00DFDBF6 6808DC4400       push $0044dc08

По идее это пихается в стек адрес слова "hi".Но по этому адресу лежит полная ерунда :(((

ЗЫ
Если кто-нибудь проявит инетерес к моему вопросу, готов дать любую дополнительную инфу


 
Тимохов ©   (2004-06-29 17:46) [16]

Хочу добавить, что cpu функции ExportFunctionWithStringConst будучи просмотренным из ExeLibrary имеет точно такие же ссылки на адреса, т.е. на адрес $0044dc08.

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

Почему не было релокации?


 
Игорь Шевченко ©   (2004-06-29 17:58) [17]


> Почему не было релокации?


А что находится в Relocation Info в PE-модуле ? :)


 
SammIk ©   (2004-06-29 17:59) [18]

Мое мнение такое:
Когда делаешь через строки, то адрес получается статическим
00DFDBF6 6808DC4400       push $0044dc08
00DFDBFB 6808DC4400       push $0044dc08
Определенно чувствуется разница))) Как думаешь
А сдесь(массив)
00DFDBE1 8D442404         lea eax,[esp+$04]
00DFDBE5 50               push eax
00DFDBE6 8D442408         lea eax,[esp+$08]
00DFDBEA 50               push eax

Динамически, но еслибы ты сказал значение esp,
можно было точнее сказать.
---------
И по моему, никто тебе не будет релокать если у тебя нет соответствующеи секции(вот не знаю, встовляет ли компилер
в exe релоки, посмотри. Интересно)):)


 
Тимохов ©   (2004-06-29 18:01) [19]


> Игорь Шевченко ©   (29.06.04 17:58) [17]

Игорь, мне стыдно, но я не знаю как посмотреть (а-а-а-ааа)


 
SammIk ©   (2004-06-29 18:02) [20]

Тоесть должно быть где-то здесь $00DFDBF4-$(4-10),а не $0044dc08


 
Тимохов ©   (2004-06-29 18:05) [21]


> SammIk ©   (29.06.04 18:02) [20]

ну код, какой есть.
логичней было бы относительный адрес сделатать...


 
SammIk ©   (2004-06-29 18:07) [22]

Ну как раз из-за этого и баг.
А ты попробуи так
var
str:string;
begin
str:="ffff";
....
messagebox(0,@str[1],pchar(str),MB_OK);
....
end;


 
Тимохов ©   (2004-06-29 18:10) [23]


> Игорь Шевченко ©   (29.06.04 17:58) [17]

Я понял Ваш тонкий намек - никакой релокации нет, т.к. этого нет в соответствующей секции модуля.
Тогда уже два вопроса:
1. Как посмотреть секцию pe модуля? Тем же dumpbin?
2. Как вы думаете, почему константные строки не склчюаются в секцию релокации? Или это не нужно exe, а в dll делается (последнее надо проверить :)))?


 
Тимохов ©   (2004-06-29 18:12) [24]


> SammIk ©   (29.06.04 18:07) [22]

пойду смотреть ...


 
SammIk ©   (2004-06-29 18:13) [25]

Да и скажи что в есп при случае с mb(0,"ggg","ggg".
Будет полезно


 
Тимохов ©   (2004-06-29 18:16) [26]


> SammIk ©   (29.06.04 18:13) [25]

Прошу прощения, я почити совсем не знаю асм (только учить начал :)). В какой момент нужно знать значение esp?


 
Тимохов ©   (2004-06-29 18:20) [27]


> SammIk ©   (29.06.04 18:07) [22]


> messagebox(0,@str[1],pchar(str),MB_OK);


в этом случае при присвоении значения str есть абс адрес

kS := "ggg";

0044DC07 8D45FC           lea eax,[ebp-$04]
0044DC0A BA58DC4400       mov edx,$0044dc58
0044DC0F E87C66FBFF       call @LStrLAsg


 
SammIk ©   (2004-06-29 18:31) [28]

00DFDBE1 8D442404         lea eax,[esp+$04]<---Сдесь
00DFDBE5 50               push eax
00DFDBE6 8D442408         lea eax,[esp+$08]
00DFDBEA 50               push eax


 
Тимохов ©   (2004-06-29 18:40) [29]

Находясь на указанной вами строке в esp имею 0012F5AC


 
SammIk ©   (2004-06-29 18:43) [30]

Это нормально))
А теперь скажи, что у тебя в стеке по этому адресу?


 
SammIk ©   (2004-06-29 18:44) [31]

По идее, окно со стеком должно быть справа снизу, в окне
дизасмера.


 
Тимохов ©   (2004-06-29 18:45) [32]


> Игорь Шевченко ©   (29.06.04 17:58) [17]

Выполнил команду
TDUMP.EXE ExeLibrary.exe > result

Что в полученном файле является relocation секцией?
По строке "Relocation" найдено всего два места

Relocation Table entry count                          0000h  (     0. )
Relocation Table address                              0040h  (    64. )


 
SammIk ©   (2004-06-29 18:47) [33]

Хотя в принципе это не важно))
И так ясно, куда надо указывает)))
Извени, загонял тебя)


 
Тимохов ©   (2004-06-29 18:48) [34]


> SammIk ©   (29.06.04 18:43) [30]

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


> SammIk ©   (29.06.04 18:44) [31]

Находится 00000000


 
Тимохов ©   (2004-06-29 18:50) [35]


> SammIk ©   (29.06.04 18:47) [33]

да ничего.

ведь интересно же - в чем фишка.

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


 
SammIk ©   (2004-06-29 18:57) [36]

Вообщем мои ответ тако:
В случае №1(когда не получается) у тебя адрес(те push $xxxxxx)
статическии(на этапи компиляции биндится), а когда ты грузишь свои exe как либу, то база у тебя далеко не $40000(или какая там). А поскольку базы у фаилов одни и теже, то фортень
загружает твою "длл" в другое место и все адреса меняются, НО
этот статическии адрес НЕ меняется. Получается, что строка
берется из адресного пространства вызывающеи проги.
Короче видешь ерундень вместо текста.
Что делать?
Поищи в делфовом справочнике директивы на эту тему.
У меня справочника нет, подсказать не могу.


 
Тимохов ©   (2004-06-29 19:00) [37]


> Поищи в делфовом справочнике директивы на эту тему.

Пойду искать...

Дома еще попробую ту же фишку с dll.
Не может быть там такого, чтобы был тот же баг.


 
SammIk ©   (2004-06-29 19:02) [38]

И не будет)))


 
Тимохов ©   (2004-06-29 19:02) [39]

я тоже в этом уверен.
интересно было бы знать, где это написано...


 
SammIk ©   (2004-06-29 19:03) [40]

В хелпе



Страницы: 1 2 3 вся ветка

Текущий архив: 2004.09.19;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.04 c
3-1093324233
Janbolat
2004-08-24 09:10
2004.09.19
Как поймать момент дублирования индекса?


3-1093279783
mouse_web
2004-08-23 20:49
2004.09.19
Запустить дополнительную форму параллельно процессу


9-1085000153
feanor
2004-05-20 00:55
2004.09.19
НАРОД подскажите как создать клон БК(очень нужо)


1-1093935514
hgd
2004-08-31 10:58
2004.09.19
Подсмотреть команду с exe


14-1093814793
SergP
2004-08-30 01:26
2004.09.19
Производительность камней.