www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Function size?

reply Niall FitzGibbon <billdoor gmail.com> writes:
Is there some way to get the length of a particular function in D?
Perhaps as a property of the function?

The reason I ask is that I'm trying to implement something similar to 
Microsoft Detours' ContinueWithDLL/CreateWithDLL in D, but in Detours 
they use static functions in order to get the size of the function that 
needs to be copied into the foreign memory context. They take the 
address of AfterThreadFunc and subtract the address of ThreadFunc in 
order to get the size of the code to be copied into the foreign process. 
I'm not sure if the "static" function attribute is part of Standard C++ 
  or simply a MS/VC++ thing, but this kind of functionality, either 
through fixed-position functions or a "size" property that can be 
accessed through the function or a delegate to it, would be very useful. 
Perhaps D already places function code in declaration order in the 
resulting executable, though I haven't seen this behaviour described in 
the language spec?

Here's a copy of the function declarations from MS Detours:

/////////////////////////////////////////////////////////////// Injected 
Code.
//
#pragma check_stack(off)
#pragma pack(push, 8)

typedef HINSTANCE (WINAPI *PROCLOADLIBRARY)(PWCHAR);

typedef struct {
	PROCLOADLIBRARY 	fnLoadLibrary;
	WCHAR				wzLibFile[MAX_PATH];
} INJLIBINFO, *PINJLIBINFO;

// Calls to the stack-checking routine must be disabled.

static DWORD WINAPI ThreadFunc(PINJLIBINFO pInjLibInfo) {
	// There must be less than a page-worth of local
	// variables used in this function.
	HINSTANCE hinstLib;

	// Call LoadLibrary(A/W) to load the DLL.
	hinstLib = pInjLibInfo->fnLoadLibrary(pInjLibInfo->wzLibFile);
	return((DWORD) hinstLib);
}

#pragma warning(disable: 4702)

static DWORD WINAPI DeadThreadFunc(PINJLIBINFO pInjLibInfo)
{
     (void)pInjLibInfo;
   x:
     goto x;
     return 0;
}

// This function marks the memory address after ThreadFunc.
// ThreadFuncCodeSizeInBytes = (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.
static void AfterThreadFunc (void) {
}

#pragma pack(pop)
#pragma check_stack
Feb 01 2005
parent reply "Walter" <newshound digitalmars.com> writes:
Unfortunately, there is no straightforward way to make this work in D. Let
me think about it.
Feb 01 2005
parent reply Niall FitzGibbon <billdoor gmail.com> writes:
Walter wrote:
 Unfortunately, there is no straightforward way to make this work in D. Let
 me think about it.
 
 
Thanks for the swift reply, Walter. I know this kind of feature would hardly be used at all and its implementation would probably conflict with your code generation and optimisation procedures. I was kind of hoping that by some twist of luck or fate it was already possible within the current language in a way that I had overlooked :) If the symbol table output of DMD is in COFF format, I believe I know enough to be able to read the function beginning and end symbols from the debug section and use them to get the length of the function. I can then hopefully create an AA, indexed by function address (after taking relocation into account), that can be used to look up code length or other information given a pointer to the start of the function. Perhaps another method would be to add some inline asm after the function return, something very simple like this int func() { // function code return 1; asm { db "FUNCEND"; } } In this way I'd be able to scan forward from the function start address until the "signature" bytes in the inline asm at the very end of the function are found. However, I'm wondering if the code generator might optimise away any code following the final return statement of the function?
Feb 01 2005
parent "Walter" <newshound digitalmars.com> writes:
"Niall FitzGibbon" <billdoor gmail.com> wrote in message
news:ctplf4$22bt$1 digitaldaemon.com...
 Walter wrote:
 Unfortunately, there is no straightforward way to make this work in D.
Let
 me think about it.
Thanks for the swift reply, Walter. I know this kind of feature would hardly be used at all and its implementation would probably conflict with your code generation and optimisation procedures. I was kind of hoping that by some twist of luck or fate it was already possible within the current language in a way that I had overlooked :) If the symbol table output of DMD is in COFF format, I believe I know enough to be able to read the function beginning and end symbols from the debug section and use them to get the length of the function. I can then hopefully create an AA, indexed by function address (after taking relocation into account), that can be used to look up code length or other information given a pointer to the start of the function.
You can look at the beginning and end symbols by examining the linker .map file output (-L/map).
 Perhaps another method would be to add some inline asm after the
 function return, something very simple like this

 int func()
 {
 // function code
 return 1;
 asm
 {
 db "FUNCEND";
 }
 }

 In this way I'd be able to scan forward from the function start address
 until the "signature" bytes in the inline asm at the very end of the
 function are found. However, I'm wondering if the code generator might
 optimise away any code following the final return statement of the
function? The asm thing should work. Give it a try.
Feb 01 2005