если вы хотите, чтобы какая-то функция содержала одну jmp
инструкцию по какому-либо адресу - вам нужно объявить ее с __declspec(dllimport)
(это Microsoft Specific и работает только для CL компилятора, но вы считаете, что другие компиляторы имеют эквивалентсинтаксис).скажем, например,
void __declspec(dllimport) TrimLeft(char);
, если вам нужно это для всех функций-членов в классе - объявите все классы следующим образом:
class __declspec(dllimport) zSTRING
{
zSTRING();
// .. more declarations
};
это повлияет на все не виртуальные функции-члены истатический член данных для класса, подобный объявленному с __declspec(dllimport)
, когда функция объявлена с __declspec(dllimport)
, компилятор объявил переменную указателя extern:
extern void* __imp___FUNCDNAME__;
где __FUNCDNAME__
оформлено название функции + __imp_
префикс;и каждый раз, когда вы вызываете такую функцию, компилятор генерирует инструкцию call __imp___FUNCDNAME__
(после передачи аргументов функции в регистры или стек).с Редактировать и продолжить компилятор опций обычно генерирует менее оптимизированный код:
call func
func:
jmp __imp___FUNCDNAME__ ; exactly what you try - single jmp in function body
, который фактически эквивалентен одному call __imp___FUNCDNAME__
, теперь очевидно, что для каждой импортируемой функцииvoid* __imp___FUNCDNAME__
должен быть где-то определен и содержать реальный адрес функции.в противном случае вы получили известную ошибку компоновщика LNK2001: неразрешенный внешний символ
обычно мы используем LIB файл, где точно определены __imp___FUNCDNAME__
символы - в этом случае компоновщик поместит всю эту переменную __imp_*
в IAT
раздел PE и опишите его в разделе импорта.в результате загрузчик назначает правильный адрес для каждого __imp___FUNCDNAME__
при загрузке изображения.
, если вы пытаетесь импортировать эту функцию из некоторой библиотеки DLL и из этой библиотеки DLL экспортировать этой функции - вы должны иметь LIB файл для этого.даже если у вас нет LIB - вы можете легко создать себя сами - создайте отдельный проект с именем выходного файла, точно совпадающим с именем dll, из которого вы будете вызывать код, и "реализовать" все эти функции с помощью __declspec(dllexport)
длякаждая функция или класс.Реализация каждой функции - может быть пустой или одиночной return 0;
- на самом деле, когда мы собираем lib - она не содержит никакого кода (в результате реализация может быть фиктивной / пустой).он содержит точно имена функций и имя dll (потому что это имя выходного файла для проекта должно быть точно именем dll. но сказать, что цель проекта - exe или dll - не имеет значения).в общем - это должно выглядеть так:
void __declspec(dllexport) TrimLeft(char)
{
}
class __declspec(dllexport) zSTRING
{
public:
zSTRING()
{
}
int Overwrite(unsigned int, class zSTRING const &)
{
return 0;
}
//...
};
Вы легко создаете этот код и получаете LIB файл (библиотека импорта) все, что вам нужно.
на случай, если этофункции не экспортируются - неясно, откуда вы получили адреса, но в любом случае - это не может быть жестко закодированных абсолютных адресов.в крайнем случае вы можете использовать жестко RVA из DLL ... в любом случае, если эта функция не экспортируется - вам нужно самим определить все __imp___FUNCDNAME__
сам.и вы сами назначаете для него правильные адреса функций в начале.
, потому что __FUNCDNAME__
обычно содержит недопустимые символы C/C++
- вам нужно будет объявить его в asm, например:
_BSS segment
__imp_?TrimLeft@@YAXD@Z DQ ?
__imp_??0zSTRING@@QEAA@XZ DQ ?
__imp_??1zSTRING@@QEAA@XZ DQ ?
__imp_??0zSTRING@@QEAA@AEBV0@@Z DQ ?
__imp_?Insert@zSTRING@@QEAAHIAEBV1@@Z DQ ?
public __imp_?TrimLeft@@YAXD@Z
public __imp_??0zSTRING@@QEAA@XZ
public __imp_??1zSTRING@@QEAA@XZ
public __imp_??0zSTRING@@QEAA@AEBV0@@Z
public __imp_?Insert@zSTRING@@QEAAHIAEBV1@@Z
_BSS ends
и реализовать функцию для разрешения импорта самостоятельно
resolveimport proc
lea rax,[rcx + rva_1]
mov __imp_?TrimLeft@@YAXD@Z,rax
lea rax,[rcx + rva_2]
mov __imp_??0zSTRING@@QEAA@XZ,rax
;...
ret
resolveimport endp
скажем, вы звоните resolveimport
из c ++ кода с адресом dll - resolveimport(LoadLibraryW(L"my.dll"));