views:

888

answers:

15

Hi guys,

Is there any method to calculate size of a function? I have a pointer to a function and I have to copy entire function using memcpy. I have to malloc some space and know 3rd parameter of memcpy - size. I know that sizeof(function) doesn't work. Do you have any suggestions?

+21  A: 

Functions are not first class objects in C. Which means they can't be passed to another function, they can't be returned from a function, and they can't be copied into another part of memory.

A function pointer though can satisfy all of this, and is a first class object. A function pointer is just a memory address and it usually has the same size as any other pointer on your machine.

Brian R. Bondy
My apologies- I thought this was tagged C++, not C. I don't know of any conditions in C where a function pointer is larger than the size of any other pointer.
luke
Note that the C spec does allow a function pointer to be incompatible with data pointer types, however.
Stephen Canon
PlayStation 3 function pointer is a different size that a data pointer.
Jim Buck
A: 

Function isn't just object you can copy. What about cross-references / symbols and so on? Of course you can take something like standard linux "binutils" package and torture your binaries but is it what you want?

By the way if you simply are trying to replace memcpy() implementation, look around LD_PRELOAD mechanics.

Roman Nikitchenko
+5  A: 

Even if there was a way to get the sizeof() a function, it may still fail when you try to call a version that has been copied to another area in memory. What if the compiler has local or long jumps to specific memory locations. You can't just move a function in memory and expect it to run. The OS can do that but it has all the information it takes to do it.


I was going to ask how operating systems do this but, now that I think of it, when the OS moves stuff around it usually moves a whole page and handles memory such that addresses translate to a page/offset. I'm not sure even the OS ever moves a single function around in memory.


Even in the case of the OS moving a function around in memory, the function itself must be declared or otherwise compiled/assembled to permit such action, usually through a pragma that indicates the code is relocatable. All the memory references need to be relative to its own stack frame (aka local variables) or include some sort of segment+offset structure such that the CPU, either directly or at the behest of the OS, can pick the appropriate segment value. If there was a linker involved in creating the app, the app may have to be re-linked to account for the new function address.

There are operating systems which can give each application its own 32-bit address space but it applies to the entire process and any child threads, not to an individual function.

As mentioned elsewhere, you really need a language where functions are first class objects, otherwise you're out of luck.

Kelly French
+1  A: 

If your linker doesn't do global optimizations, then just calculate the difference between the function pointer and the address of the next function.

Note that copying the function will produce something which can't be invoked if your code isn't compiled relocatable (i.e. all addresses in the code must be relative, for example branches; globals work, though since they don't move).

Aaron Digulla
+2  A: 

A similar discussion was done here:

http://www.motherboardpoint.com/getting-code-size-function-c-t95049.html

They propose creating a dummy function after your function-to-be-copied, and then getting the memory pointers to both. But you need to switch off compiler optimizations for it to work.

If you have GCC >= 4.4, you could try switching off the optimizations for your function in particular using #pragma:

http://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmas

Another proposed solution was not to copy the function at all, but define the function in the place where you would want to copy it to.

Good luck!

littlegreen
+3  A: 

You want to copy a function? I do not think that this is possible in C generally. Assume, you have a Harvard-Architecture microcontroller, where code (in other words "functions") is located in ROM. In this case you cannot do that at all. Also I know several compilers and linkers, which do optimization on file (not only function level). This results in opcode, where parts of C functions are mixed into each other.

The only way which I consider as possible may be:

  • Generate opcode of your function (e.g. by compiling/assembling it on its own).

  • Copy that opcode into an C array.

  • Use a proper function pointer, pointing to that array, to call this function.

  • Now you can perform all operations, common to typical "data", on that array.

But apart from this: Did you consider a redesign of your software, so that you do not need to copy a functions content?

Marco
+3  A: 

I don't quite understand what you are trying to accomplish, but assuming you compile with -fPIC and don't have your function do anything fancy, no other function calls, not accessing data from outside function, you might even get away with doing it once. I'd say the safest possibility is to limit the maximum size of supported function to, say, 1 kilobyte and just transfer that, and disregard the trailing junk.

If you really needed to know the exact size of a function, figure out your compiler's epilogue and prologue. This should look something like this on x86:

:your_func_epilogue
mov esp, ebp
pop ebp
ret
:end_of_func

;expect a varying length run of NOPs here

:next_func_prologue
push ebp
mov ebp, esp

Disassemble your compiler's output to check, and take the corresponding assembled sequences to search for. Epilogue alone might be enough, but all of this can bomb if searched sequence pops up too early, e.g. in the data embedded by the function. Searching for the next prologue might also get you into trouble, i think.

Now please ignore everything that i wrote, since you apparently are trying to approach the problem in the wrong and inherently unsafe way. Paint us a larger picture please, WHY are you trying to do that, and see whether we can figure out an entirely different approach.

3yE
+7  A: 

It doesn't directly answer your question, but you should not implement call-backs from kernel code to user-space.

Injecting code into kernel-space is not a great work-around either.

It's better to represent the user/kernel barrier like a inter-process barrier. Pass data, not code, back and forth between a well defined protocol through a char device. If you really need to pass code, just wrap it up in a kernel module. You can then dynamically load/unload it, just like a .so-based plugin system.

On a side note, at first I misread that you did want to pass memcpy() to the kernel. You have to remind that it is a very special function. It is defined in the C standard, quite simple, and of a quite broad scope, so it is a perfect target to be provided as a built-in by the compiler.

Just like strlen(), strcmp() and others in GCC.

That said, the fact that is a built-in does not impede you ability to take a pointer to it.

Steve Schnepp
+1 for formatting this post : )
littlegreen
+1  A: 

It sounds like you want to have a callback from your kernel driver to userspace, so that it can inform userspace when some asynchronous job has finished.

That might sound sensible, because it's the way a regular userspace library would probably do things - but for the kernel/userspace interface, it's quite wrong. Even if you manage to get your function code copied into the kernel, and even if you make it suitably position-independent, it's still wrong, because the kernel and userspace code execute in fundamentally different contexts. For just one example of the differences that might cause problems, if a page fault happens in kernel context due to a swapped-out page, that'll cause a kernel oops rather than swapping the page in.

The correct approach is for the kernel to make some file descriptor readable when the asynchronous job has finished (in your case, this file descriptor almost certainly be the character device your driver provides). The userspace process can then wait for this event with select / poll, or with read - it can set the file descriptor non-blocking if wants, and basically just use all the standard UNIX tools for dealing with this case. This, after all, is how the asynchronous nature of network sockets (and pretty much every other asychronous case) is handled.

If you need to provide additional information about what the event that occured, that can be made available to the userspace process when it calls read on the readable file descriptor.

caf
A: 

I can think of a way to accomplish what you want, but I won't tell you because it's a horrific abuse of the language.

A: 

A cleaner method than disabling optimizations and relying on the compiler to maintain order of functions is to arrange for that function (or a group of functions that need copying) to be in its own section. This is compiler and linker dependant, and you'll also need to use relative addressing if you call between the functions that are copied. For those asking why you would do this, its a common requirement in embedded systems that need to update the running code.

JSON
A: 

My suggestion is: don't.

Injecting code into kernel space is such an enormous security hole that most modern OSes forbid self-modifying code altogether.

Crashworks
A: 

As near as I can tell, the original poster wants to do something that is implementation-specific, and so not portable; this is going off what the C++ standard says on the subject of casting pointers-to-functions, rather than the C standard, but that should be good enough here.

In some environments, with some compilers, it might be possible to do what the poster seems to want to do (that is, copy a block of memory that is pointed to by the pointer-to-function to some other location, perhaps allocated with malloc, cast that block to a pointer-to-function, and call it directly). But it won't be portable, which may not be an issue. Finding the size required for that block of memory is itself dependent on the environment, and compiler, and may very well require some pretty arcane stuff (e.g., scanning the memory for a return opcode, or running the memory through a disassembler). Again, implementation-specific, and highly non-portable. And again, may not matter for the original poster.

The links to potential solutions all appear to make use of implementation-specific behaviour, and I'm not even sure that they do what the purport to do, but they may be suitable for the OP.

Having beaten this horse to death, I am curious to know why the OP wants to do this. It would be pretty fragile even if it works in the target environment (e.g., could break with changes to compiler options, compiler version, code refactoring, etc). I'm glad that I don't do work where this sort of magic is necessary (assuming that it is)...

Oliver Seiler
A: 

I have done this on a Nintendo GBA where I've copied some low level render functions from flash (16 bit access slowish memory) to the high speed workspace ram (32 bit access, at least twice as fast). This was done by taking the address of the function immdiately after the function I wanted to copy, size = (int) (NextFuncPtr - SourceFuncPtr). This did work well but obviously cant be garunteed on all platforms (does not work on Windows for sure).

Tim Ring
A: 

I think one solution can be as below.

For ex: if you want to know func() size in program a.c, and have indicators before and after the function.

Try writing a perl script which will compile this file into object format(cc -o) make sure that pre-processor statements are not removed. You need them later on to calculate the size from object file.

Now search for your two indicators and find out the code size in between.

Algorist