www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - get size of function

reply maarten van damme <maartenvd1994 gmail.com> writes:
I'm playing around with writing memory to other processes and now I want to
write a whole function to the other processes memory. The problem is that
function.sizeof always returns 4. Is there a way to get the actual size?
Aug 30 2011
next sibling parent Simon <s.d.hammett gmail.com> writes:
On 30/08/2011 16:50, maarten van damme wrote:
 I'm playing around with writing memory to other processes and now I want
 to write a whole function to the other processes memory. The problem is
 that function.sizeof always returns 4. Is there a way to get the actual
 size?
The short answer is no. You might find something useful in DDL: http://www.dsource.org/projects/ddl Though that looks like it hasn't been updated in ages. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Aug 30 2011
prev sibling parent reply Johannes Pfau <spam example.com> writes:
maarten van damme wrote:
I'm playing around with writing memory to other processes and now I
want to write a whole function to the other processes memory. The
problem is that function.sizeof always returns 4. Is there a way to
get the actual size?
You could use the same hacks as in C: Declare another function, make sure their located sequentially in memory and compare their function addresses to get the size of the first function (+ potential padding for alignment, but that shouldn't matter). I do not recommend to do this though, it's a baaaad hack, and I don't even remember how exactly it worked. -- Johannes Pfau
Aug 30 2011
next sibling parent maarten van damme <maartenvd1994 gmail.com> writes:
2011/8/30 Johannes Pfau <spam example.com>

 You could use the same hacks as in C:
 Declare another function, make sure their located sequentially in
 memory and compare their function addresses to get the size of the first
 function (+ potential padding for alignment, but that shouldn't matter).
I think thats the way to go, a sequential function's adress minus the functions address. how can I make sure they're sequentially alligned?
 I do not recommend to do this though, it's a baaaad hack, and I don't
 even remember how exactly it worked.
But better a (dirty) way then no way at all. I've also been playing with the idea of writing the function, and trying to compile that one function in a text file and importing at compile time in my main program. Then I can also count the bytes in the file. sounds an awfull lot of work :p
Aug 30 2011
prev sibling parent reply maarten van damme <maartenvd1994 gmail.com> writes:
substracting the pointers to two sequential functions didn't work out. the
following snippet:
//
auto first=function void(){
asm{
naked;
nop;
}
};
auto next=function void(){
asm{
naked;
nop;
}
};
writeln(cast(int)&next-cast(int)&first,"/",cast(int)&next,"/",&next,"/",cast(int)&first,"/",&first);
//
outputs
4/1244672/12FE00/1244668/12FDFC
so the conversions from hex to int work correctly and I still get a size of
4 while it shouldve been a size of 1.
Are there other options?
Aug 31 2011
parent reply Johannes Pfau <spam example.com> writes:
maarten van damme wrote:
substracting the pointers to two sequential functions didn't work out.
the following snippet:
//
auto first=function void(){
asm{
naked;
nop;
}
};
auto next=function void(){
asm{
naked;
nop;
}
};
writeln(cast(int)&next-cast(int)&first,"/",cast(int)&next,"/",&next,"/",cast(int)&first,"/",&first);
//
outputs
4/1244672/12FE00/1244668/12FDFC
so the conversions from hex to int work correctly and I still get a
size of 4 while it shouldve been a size of 1.
Are there other options?
Do you need to use function _pointers_? In your example next & first are function pointers and function pointers have a size of 4 (on a 32bit system). This seems to work: ----------------------------- int first(int a, int b) { return a - b; } int next(int a, int b) { return a + b; } void main(string args[]) { writeln(cast(int)&next-cast(int)&first,"/",cast(int)&next,"/",&next,"/",cast(int)&first,"/",&first); } ----------------------------- Output: 20/134772104/8087588/134772084/8087574 As next and first in your example should already be pointers, you could also try to change your writeln to this: writeln(cast(int)next-cast(int)first,"/",cast(int)next,"/",next,"/",cast(int)first,"/",first); BTW: Why not cast to void* (or at least size_t) instead of int? -- Johannes Pfau
Aug 31 2011
parent reply maarten van damme <maartenvd1994 gmail.com> writes:
I always cast everything to ints that I use in calculations, a (bad) habit
of me.size_t makes more sense.
your example seems to work great, thank you.
I forgot I was using function pointers.
Am I sure those functions aren't shift around during optimization?

for now the function is working like a charm. int memory I can see that d
makes function size's multiples of four and fills the remaining bytes with
cc's. is this coincidence and if not, why is this?
Aug 31 2011
parent reply Trass3r <un known.com> writes:
Am 31.08.2011, 12:05 Uhr, schrieb maarten van damme  
<maartenvd1994 gmail.com>:

 Am I sure those functions aren't shift around during optimization?
No. It's just an ugly hack and likely to go up in flames. Also what you try could only work with PIC but even then...
 for now the function is working like a charm. int memory I can see that d
 makes function size's multiples of four and fills the remaining bytes  
 with
 cc's. is this coincidence and if not, why is this?
http://stackoverflow.com/questions/2863408/why-are-functions-loaded-at-aligned-addresses-in-x86-linux-for-elf-executables
Aug 31 2011
parent reply Johannes Pfau <spam example.com> writes:
Trass3r wrote:
Am 31.08.2011, 12:05 Uhr, schrieb maarten van damme  
<maartenvd1994 gmail.com>:

 Am I sure those functions aren't shift around during optimization?
No. It's just an ugly hack and likely to go up in flames. Also what you try could only work with PIC but even then...
That's true, as I already said it for sure is an ugly hack. There's no guarantee that the compiler outputs the functions in this order. The linker could change the order as well. And if you send this function to another process (or even a different machine), you might get even more issues (for example some kind of offset calculated by the compiler and "hard-coded" into the function could be wrong in the other process). The Linux kernel does some tricks to store 'dynamic' lists in ELF files. For this to work it also needs access to the size of the list. You could use a similar approach: You'd have to write your own linker script to put your function in an own sections, than output 2 symbols exactly before and after the function. But that's a lot of work and I personally think that's still an ugly hack. It's used in the Linux kernel however, so it has to work. DMD also uses a similar trick with the _deh_beg and _deh_end symbols, maybe dmd does something to make that mechanism less fragile, you could look it up in the compiler source. -- Johannes Pfau
Aug 31 2011
parent Simon <s.d.hammett gmail.com> writes:
On 31/08/2011 15:42, Johannes Pfau wrote:
 Trass3r wrote:
 Am 31.08.2011, 12:05 Uhr, schrieb maarten van damme
 <maartenvd1994 gmail.com>:

 Am I sure those functions aren't shift around during optimization?
No. It's just an ugly hack and likely to go up in flames. Also what you try could only work with PIC but even then...
That's true, as I already said it for sure is an ugly hack. There's no guarantee that the compiler outputs the functions in this order. The linker could change the order as well. And if you send this function to another process (or even a different machine), you might get even more issues (for example some kind of offset calculated by the compiler and "hard-coded" into the function could be wrong in the other process). The Linux kernel does some tricks to store 'dynamic' lists in ELF files. For this to work it also needs access to the size of the list. You could use a similar approach: You'd have to write your own linker script to put your function in an own sections, than output 2 symbols exactly before and after the function. But that's a lot of work and I personally think that's still an ugly hack. It's used in the Linux kernel however, so it has to work. DMD also uses a similar trick with the _deh_beg and _deh_end symbols, maybe dmd does something to make that mechanism less fragile, you could look it up in the compiler source.
Then you will run into problems with data execution prevention, so you'll have to write OS specific code for each platform to run the code. The easiest and most portable way to export runnable code is use an interpreted language. After that you could look at llvm, but there's no D interface to that. All in all, it's a big messy can of worms you are trying to open. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Aug 31 2011