![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: нет Всего: 12 |
Всем привет
Задача: пройти по файлам dll, найти функцию по имени, успешно вызвать Решение:
Результат: всё по идее хорошо, но если прототип совпадает, а если нет? я так понимаю (и получаю) падение программы. у функции нет контроля над тем, что ты пытаешься загрузить, есть имя в def и адрес, к прототипу любого вида можно привезти Вопрос: можно ли как - нибудь избежать падения, при динамическом импорте функций из библиотек, при несовпадании прототипов? какие - нибудь дополнительные проверки или другие функции для этих целей. Надеюсь вопрос понятен, заранее благодарен за помощь |
|||
|
||||
| 12usver12 |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 247 Регистрация: 5.1.2007 Репутация: 1 Всего: 1 |
в отдельном потоке вызывать и ставить хук на завершении функции и смотреть адрес возврата
|
|||
|
||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 6 Всего: 135 |
Если библиотеки твои (или сделаны по твоим правилам), то можно в них заменить __cdecl на __stdcall, а также убрать extern "C". В этом случае прототип будет выглядеть как-то так
func_name@4i4i -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
проверять esp
|
|||
|
||||
| null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: нет Всего: 12 |
borisbn, да, библы мои, но никогда не слышал об этом способе
Abyx, а можно по подробнее и что я должен там обнаружить? |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 40 Всего: 223 |
Полной информации о прототипе функции в dll нет. Есть масса способов извлечь некоторую информацию о вызываемой функции. Большую часть их уже озвучили, могу добавить еще:
|
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 7 Всего: 118 |
все игры с стеком справдливы только для win32 (!) это важно....
-------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 16 Всего: 39 |
Очень сложно, если нужен контроль параметров вызываемой функции. -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
borisbn, xvr, при чем тут манглинг?
Если известно имя функции, то очевидно известен ее прототип, в том числе число параметров. Если функция неправильная, то никакой манглинг тут не поможет. Импортируется функция вместе с манглингом, GetProcAddress(hlib, "foo@8"), расшифровка никакой новой информации не даст. Проверка esp позволит узнать правильное ли было количество параметров у функции, после ее вызова, не более того. |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
при декорировании например C++ прототип и кодируется именем функции, stdcall - тоже, но в меньшей степени: тут можно определить только размер фрейма так что манглинг тут многое может прояснить, конечно, все можно получить из отладочной секции, но доступ к имени гораздо проще, рекомендую декорирование C++ взять на контроль, если надо обязательно знать прототип, в vs есть утилитка undname.exe и есть соответствующая API недостаток у них только есть небольшой: слишком длинные имена не распознают, это особенно актуально при экспорте шаблонных имплементаций -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| Abyx |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
Как я понимаю, у ТСа проблема в том, что он не уверен, что функция в длл будет иметь ожидаемый прототип.
Например - длл это плагин, написанный сторонним разработчиком на другом языке. В этом случае, ТС может специфицировать что функция имеет прототип extern "C" void __stdcall foo(int a, int b); соответственно в таблице экспорта длл должно быть имя "foo@8" но человек пишущий длл, может писать ее на другом языке, и напишет
Добавлено @ 10:43 какбэ от того что ТС напишет
ничего не поменяется кроме того что это усложнит жизнь тому кто пишет длл Это сообщение отредактировал(а) Abyx - 3.6.2010, 10:45 |
||||
|
|||||
| null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: нет Всего: 12 |
Abyx, да про это и речь, что там вообще может быть всё что угодно, те же 8 байт параметров и та же функция... а в функции происходит работа вообще с другими типами... Мне нужна длл с моими четкими параметрами (TCHAR *, std :: vector<std::basic_string<TCHAR> > &) = те же 8 байтов (для 32 бит)
Но GremlinProg, xvr, про декорирование имен говорят, сейчас читаю и пытаюсь понять, зашит ли там при сборке длл прототип, если да, то это как раз то что нужно.... http://en.wikipedia.org/wiki/Name_mangling |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
||||
|
||||
| GremlinProg |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
ну да, есть такой вариант, но я бы не стал беспокоиться по поводу неправильного имени, т.к. эта ошибка будет очевидна: повреждение стека отладочная версия обнаружит сразу, если параметры передаются в нем, если нет - тем более, значит функция обработает параметры, которые не были переданы гораздо проще приложение может упасть в самой библиотеке :) try-except не защитит только от ошибки со стеком, т.к. она фатальна в любой ситуации, все остальное поймает -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
||||
|
|||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
восстановление ebp решает все ошибки со стеком %)
т.е. try сохраняет ebp, и при отлове эксепшена ebp восстанавливается, а в эпилоге функции восстанавливается и esp собственно если в функции есть ebp-фрейм, на ошибки с esp можно не обращать внимания, лишь бы esp не поднимался выше нижней границы фрейма Это сообщение отредактировал(а) Abyx - 3.6.2010, 11:09 |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
а ebp ты где сохранишь перед восстановлением :)) -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 7 Всего: 118 |
Abyx, да ну?)) а если я запишу в адрес возрата своё что-нибудь)?
Даешь каждому плагину по отдельному процессу и пайпы (например) для обмена информацией !)) В любом случае вы не сможете защититься от хитрых (тупых) программистов которые косячат в плагинах и используют хаки - процесс-то один... плагин может тупо вызвать ExitProcess(0) идите - ловите.. Считаю что проверка стека и т.д. - избыточна, это микроскопом гвозди зибивать -- если плагин кривой, то он кривой, и тут уже ничего не сделать. -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
хотя действительно, если вызываемая функция решит что у нее больше параметров чем должно быть, и если она начнет менять значения "параметров", то она может убить SEH фрейм. Тогда надо создавать новый стек. Добавлено через 33 секунды jonie, при чем тут адрес возврата? |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 7 Всего: 118 |
Abyx, функция может убить стек вообще (например если у функции 2-а параметра (указателя) куда она активно пишет, а вызывающий думает что 1)...
-------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
Во-первых прога не должна падать из за кривых плагинов. Это надо предусмотреть, иначе юзеры будут недовольны, когда прога будет молча падать на старте. Во вторых если разработчик плагина написал не тот прототип, неплохо чтобы прога ему это сообщила. Хороший пример - это COM. Передал неверное число параметров - получил соответствующее исключение, знаешь где ошибка. Добавлено через 31 секунду jonie, читайте пост выше |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
это и решает новый поток, хотя его нарушение по-моему ситуацию не меняет, т.к. этот стек в той же памяти процесса скорее всего поддержу jonie:
-------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
впринципе да, можно ставить VEH и создавать новый поток, ловить исключение и убивать поток.
что случится со стеком потока - не важно. |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
ну и тут то же самое: COM-объект имеет свой динамический прототип, который можно переврать точно так же как и название функции при экспорте -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
GremlinProg, однако COM безопасен, и выдает информативные сообщения об ошибках
Это сообщение отредактировал(а) Abyx - 3.6.2010, 11:28 |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
он безопасен на том же уровне, что и правильно написанный плагин
неправильно написанный COM небезопасен точно так же как и неправильно написанный плагин и ни какие методы самоконтроля COM тут не помогут: упадет точно так же единственная разница в том, что прототип COM-объекта модифицировать сложнее чем поменять имя экспортируемой функции, отсюда и видимая безопасность -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| xvr |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 40 Всего: 223 |
|
||||
|
|||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
TCHAR - это вообще #define
|
|||
|
||||
| null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: нет Всего: 12 |
xvr, хорошо, что сказали... сделаем так: std :: vector<std::basic_string<TCHAR> > => (unsigned int, TCHAR **), иными словами без стл сделаем
Добавлено через 1 минуту и 54 секунды
пускай будет wchar_t |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 40 Всего: 223 |
Кстати, plugin вполне может упасть не только при вызове неправильно оформленной функции, но и в процессе ее работы. Ошибки, они везде бывают
|
|||
|
||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 6 Всего: 135 |
очень не советую передавать между exe и dll stl-классы, т.к. это будет нормально работать только если и то и то собрано одним и тем же компилятором, причём одной и той же версии SDK. -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 7 Всего: 118 |
borisbn, и с одними и теми же параметрами компилятора..
xvr, смотря что делает плагин, может ему надо всего-то послать сообщение "начни работать" -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 6 Всего: 135 |
Да, конечно. Просто в своих классах/структурах/интерфейсах, передающихся между dll и exe всегда ставлю явное выравнивание ( pragma pack... ), явный тип вызова ( __stdcall или __cdecl ) и явный размер в enum'ах ( enumName_FORCE_DWORD = 0x7FFFFFFF ), поэтому и забыл о параметрах компилятора -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 7 Всего: 118 |
borisbn, указанные опции не спасут тебя, если в коде stl стоит нечто вроде "#ifdef FAST_FLOAT ..." (т.е. внутренни шаблонные классы могут скопилиться по-разному даже если задать то что ты описал )
-------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 6 Всего: 135 |
jonie, полностью согласен, что stl нельзя передавать в/из dll. Я говорил о своих классах и структурах
Это сообщение отредактировал(а) borisbn - 3.6.2010, 20:09 -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: нет Всего: 12 |
Мне посоветовали наиболее быстрое решение предотвращения ошибки
Надежный ли это вариант ловли вызова с неверными параметрами? у меня на тестовом примере исключение отрабатывает |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
от неверного числа параметров это не поможет
|
|||
|
||||
| Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 16 Всего: 39 |
Ага, ошибка может и не выскочит, но не известно когда приложение свалится -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
| null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: нет Всего: 12 |
просто я передавал и даже не передавал вообще параметры, вроде ловила она этот момент... но видимо это частный случай....
|
|||
|
||||
| rogi08 |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 25 Регистрация: 18.2.2009 Репутация: нет Всего: нет |
А прокатит ли вариант с блоком
Это сообщение отредактировал(а) rogi08 - 4.6.2010, 12:33 |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
проблема будет не обязательно в невалидных параметрах, проблема будет при возврате из функции, когда эта функция как-либо потрет(изменит) стек, где по ее мнению расположен фрейм, а на самом деле там будут переменные или фреймы основной программы, состояние которых после вызова и будут определять, где конкретно свалится программа чем больше будет потерто лишнего, тем больше переменных и фреймов основной программы будет влиять на то, где оно свалится, так что в общем случае не спасет даже забор вложенных try-except -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| rogi08 |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 25 Регистрация: 18.2.2009 Репутация: нет Всего: нет |
подойдёт ли вариант с функцией SetUnhandledExceptionFilter?
|
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
rogi08, вы ее когданить использовать пробовали?
вернее так: пример кода покажите который решает задачу ТСа Это сообщение отредактировал(а) Abyx - 4.6.2010, 13:13 |
|||
|
||||
| rogi08 |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 25 Регистрация: 18.2.2009 Репутация: нет Всего: нет |
Abyx,
идею использования SetUnhandledExceptionFilter предложил punxer: http://wasm.ru/forum/viewtopic.php?pid=382029#p382029 Судя на коду и комментариям, идея не подходит. |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 2 Всего: 10 |
rogi08, я тоже читаю васм, не надо сюда кидать ссылки %)
алсо какой смысл повторять чужие неверные идеи %) |
|||
|
||||
| rogi08 |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 25 Регистрация: 18.2.2009 Репутация: нет Всего: нет |
||||
|
||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |