EmbeddedRelated.com
Forums

Getting the size of a C function

Started by john January 22, 2010
On Fri, 22 Jan 2010 22:53:18 +0000, john wrote:

> Hi, > > I need to know the size of a function or module because I need to > temporarily relocate the function or module from flash into sram to do > firmware updates. > > How can I determine that at runtime? The sizeof( myfunction) > generates an error: "size of function unknown". > > Thanks.
Check your tools -- newer ones will often let you set the segment of a function (usually with something like "#pragma ramcode"), and many of those will automatically load a function into ram at startup. If you can't do it on a function-by-function basis, you may be able to do it file-by-file, or coerce the linker to relocate the text segment from one whole object file into a segment of your choosing. Then you either put that segment (with just your magic function(s)) into RAM, or you find out that your linker will. -- www.wescottdesign.com
Tim Wescott <tim@seemywebsite.com> wrote:

> On Sat, 23 Jan 2010 12:03:18 +1300, David Empson wrote: > > > john <john@nospam.com> wrote: > > > >> I need to know the size of a function or module because I need to > >> temporarily relocate the function or module from flash into sram to do > >> firmware updates. > > > > In general, C does not provide a mechanism to find the size of a > > function. Some compilers might implement sizeof(function) but it is not > > standard C. > > > > If your compiler always outputs functions to the object code in the same > > order as they appear in the source code, you could take the address of > > the next function and the address of the function in question, convert > > them to (char *) and get the difference between them. This assumes you > > never rearrange your source code - comment well! > > I've seen it done like this: > > whatever my_eeprom_burning_code() > { > // insert deathless prose here > } > > void end_my_eeprom_burning_code(void) > { > } > > As long as the second function doesn't get optimized away or moved, > you're home free.
Except if the compiler outputs the functions in reverse order, as one I've used does (which means you need a "begin_my_eeprom_burning_code" dummy function instead). You need to know the pattern generated by your particular compiler, which might depend on factors other than the order the functions appear in the source code. -- David Empson dempson@actrix.gen.nz
On Fri, 22 Jan 2010 22:53:18 +0000, john wrote:

> I need to know the size of a function or module because I need to > temporarily relocate the function or module from flash into sram to > do firmware updates.
Do you need to be able to run it from RAM? If so, simply memcpy()ing it may not work. And you would also need to copy anything which the function calls (just because there aren't any explicit function calls in the source code, that doesn't mean that there aren't any in the resulting object code).
In article <pan.2010.01.23.05.08.12.672000@nowhere.com>, 
nobody@nowhere.com says...
> On Fri, 22 Jan 2010 22:53:18 +0000, john wrote: > > > I need to know the size of a function or module because I need to > > temporarily relocate the function or module from flash into sram to > > do firmware updates. > > Do you need to be able to run it from RAM? If so, simply memcpy()ing it > may not work. And you would also need to copy anything which the function > calls (just because there aren't any explicit function calls in the source > code, that doesn't mean that there aren't any in the resulting object code). > >
At the expense of a few words of code and a parameter, you could do int MoveMe(...., bool findend){ if(!findend){ // do all the stuff the function is supposed to do } else Markend(); } Where Markend is a function that pulls the return address off the stack and stashes it somewhere convenient. Markend may have to have some assembly code. External code can then subtract the function address from the address stashed by Markend(), add a safety margin, and know how many bytes to move to RAM. Mark Borgerson
On Fri, 22 Jan 2010 22:53:18 +0000 (UTC), john <john@nospam.com>
wrote:

>I need to know the size of a function or module because I need to >temporarily relocate the function or module from flash into sram to >do firmware updates.
Do you actually want to execute that function while in RAM or just store some bytes into safety during the update ? If you intend to execute, the code must be position independent e.g. with PC relative branch, however accessing some fixed addresses, such as memory mapped peripherals, some absolute addressing mode must be used, no PC relative addressing modes can not be used.
Mark Borgerson a &#4294967295;crit :
> In article <pan.2010.01.23.05.08.12.672000@nowhere.com>, > nobody@nowhere.com says... >> On Fri, 22 Jan 2010 22:53:18 +0000, john wrote: >> >>> I need to know the size of a function or module because I need to >>> temporarily relocate the function or module from flash into sram to >>> do firmware updates. >> Do you need to be able to run it from RAM? If so, simply memcpy()ing it >> may not work. And you would also need to copy anything which the function >> calls (just because there aren't any explicit function calls in the source >> code, that doesn't mean that there aren't any in the resulting object code). >> >> > At the expense of a few words of code and a parameter, you could do > > > int MoveMe(...., bool findend){ > if(!findend){ > > // do all the stuff the function is supposed to do > > } else Markend(); > > } > > > Where Markend is a function that pulls the return > address off the stack and stashes it somewhere > convenient. Markend may have to have some > assembly code. External code can then > subtract the function address from the address > stashed by Markend(), add a safety margin, and > know how many bytes to move to RAM. > > > Mark Borgerson >
Sorry Mark but this is totally WRONG! The return address contains the address where the CPU RETURNS TO when the current function is finished, not the end of the current function!!! The return address will be in the middle of another function, that CALLED this one.
>In general, C does not provide a mechanism to find the size of a >function. Some compilers might implement sizeof(function) but it is not >standard C.
There might not even be a clearly-defined *definition* for "the size of a function". One obvious problem is if it's inlined several times in several places. Where, exactly, does the function "start"? Where does it "end"? It's also possible that code is shared between functions. If several functions have many places where the code does something like: errno = EINVAL; unlock_critical_section(); return -1; the compiler might generate code for that once and branch to it from all of the functions. This is more likely to happen if "return" isn't a one-instruction method of restoring registers, a stack frame pointer if applicable, and adjusting the stack, if there is one. It's the embedded processors that are more likely to need multiple instructions to return from a function. They are also more likely to need aggressive optimization for code space. You could end up with the strange math that a compilation unit containing 4 functions has 16k of code, but any one of the functions need 10k of code.
>If your compiler always outputs functions to the object code in the same >order as they appear in the source code,
That's a rather dubious assumption in the presence of inlining (and C90 doesn't have a way to stop inlining). Also, the assumption that a function consists of a contiguous block of code (worry about the *data* later) dedicated to that function only is not guaranteed to hold. In practice, it will probably work OK if you don't turn on aggressive optimization.
On Sat, 23 Jan 2010 12:03:18 +1300, dempson@actrix.gen.nz (David Empson) wrote:

>john <john@nospam.com> wrote: > >> I need to know the size of a function or module because I need to >> temporarily relocate the function or module from flash into sram to >> do firmware updates. > >In general, C does not provide a mechanism to find the size of a >function. Some compilers might implement sizeof(function) but it is not >standard C. > >If your compiler always outputs functions to the object code in the same >order as they appear in the source code, you could take the address of >the next function and the address of the function in question, convert >them to (char *) and get the difference between them. This assumes you >never rearrange your source code - comment well! > >If your compiler outputs functions in a somewhat unpredictable order >then this won't work. > >The technique I used for a similar problem was to examine the object >code to determine the size of the function manually, added a safety >margin to allow for potential code growth, and embedded that as a >constant in the source code. It then needs to be re-checked after source >changes (or a revised compiler) to confirm that the size hasn't grown >too much.
Another way to do it would be to specify the function to go in a specific user-defined segment of fixed size at a fixed adress. The linker will then at least tell you if it has exceeded the allocated size. Most microcontroller-orientated compilers will have a way to do this as it is a common requirement for bootloaders etc.
john wrote:
> I need to know the size of a function or module because I need to > temporarily relocate the function or module from flash into sram to > do firmware updates. > > How can I determine that at runtime?
You can't in standard C, because functions are not contiguous objects. Most environments have some way of placing a function in a special section (using pragmas or things like __attribute__), and a possibility to acquire position and size of that section (using linker magic). In general, you cannot assume a function generates just a single blob of assembly code in the ".text" sections. For example, functions containing string or floating-point literals, or large switches, often generate some data in ".rodata", static variables end up in ".data" or ".bss", and if you're doing C++, you'll get some exception handling tables as well. Stefan
jacob navia wrote:
> john a &eacute;crit : >> Hi, >> >> I need to know the size of a function or module because I need to >> temporarily relocate the function or module from flash into sram to >> do firmware updates. >> >> How can I determine that at runtime? The >> sizeof( myfunction) >> generates an error: "size of function unknown". >> >> Thanks. > > (1)
<snip lots of methods>
> Method (4) needs a disassembler, and a LOT of parsing work, > and it is very sensitive to compilation options.
You forgot to mention the method which, in my experience, is by far the best, most reliable, and easiest method. Read the manual! This is NOT a glib suggestion, on the one occasion where I needed to do something similar, but for different reasons, I read the manual and low and behold the implementation documented a nice and relatively easy way to achieve when I wanted. In fact, using any other method was almost guaranteed to produce a function that did not work correctly. After all, there could be references to absolute addresses which will be wrong after the code is moved! In my case, it was compile the function and get it in to a specific section (I can't remember how now) and then tell the linker to locate the section at one location for programming in to the ROM but set up all the addresses as if it would be placed in another section. Then use some link-time constants (can't remember the details) for moving it. As I say, it was all fully documented in the manuals! There is every chance that someone on comp.arch.embedded might know how to do it on the target platform, if the OP specifies the target platform. -- Flash Gordon