writing position independent code -- x86 Windows.
AMD64 is much easier -- most code is naturally position independent
ARM32 is also viable, but not shown here.
I'm not an expert, but this weekend I finally wrote
some position independent code.
Accesses of global data incur relocations.
jmp and call do not.
So wrap data in functions. Including imports.
Possibly collect all your data together in one struct.
struct globals_t { ... } globals;
globals_t* GetGlobals();
Here is a working example.
Notice the lack of .reloc in link /dump.
We need the custom import library.
Without it, when the linker finds __imp__printf in msvcrt.lib,
it complains about the duplicate _printf.
By claiming that printf is data, the import .lib only has __imp__printf and no _printf.
link /lib /def:msvcrt.def /machine:x86
ml -c 4asm.asm
cl 4.c -link 4asm.obj -entry:Entry -subsystem:console -incremental:no -nod .\msvcrt.lib
link /dump 4.exe
.\4.exe
4.c:
int __cdecl printf(const char*, ...);
void * GetImageBase(void);
extern const char string[] = "%p\n";
char* p_string(void);
int Entry()
{
printf(p_string(), GetImageBase());
return 0;
}
4asm.asm:
.model flat
.686
_text segment
public _GetImageBase
_GetImageBase proc
call @F
@@:
pop eax
sub eax, imagerel $ - 1
ret
_GetImageBase endp
IMPORT macro name
externdef __imp__&name:dword, _&name:proc
_&name proc
call _GetImageBase
add eax, imagerel __imp__&name
jmp dword ptr [eax]
_&name endp
endm
DATA macro name
externdef _&name:byte, _p_&name:proc
_p_&name proc
call _GetImageBase
add eax, imagerel _&name
ret
_p_&name endp
endm
IMPORT printf
DATA string
_text ends
end
msvcrt.def:
EXPORTS
printf DATA
No comments:
Post a Comment