1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

Getting the code size of a function in C

Discussion in 'Embedded' started by Tosca Berisha, Nov 1, 2005.

  1. I need to determine the size of a function or module since I need to
    temporary relocate the function or module from flash into sram for
    firmware updates.

    How can I find that out during runtime. The
    sizeof( myfunction)
    generates an error saying "size of function unknown".

    Tosca Berisha, Nov 1, 2005
    1. Advertisements

  2. You'll need to do something in your linker script to create
    global symbols before and after the function. In your C code,
    you should then be able to take the address of those global
    symboals and do some math to determine the size.
    Grant Edwards, Nov 1, 2005
    1. Advertisements

  3. "Grant Edwards" ...
    I've often seen compiler generated (optimized) code that jumps to common
    sections of code, shared between functions. Labels around a function won't
    help you when that happens.
    Also, don't expect multiple functions in a module to stay in the same
    sequence as they were in the source file, not even with all optimisation

    You could put the function as the only function in a **module** (a single
    source file), which is also the only way I know with a (GNU) linker script
    to put labels before and after it.

    Arie de Muynck
    Arie de Muynck, Nov 1, 2005
  4. Such labels will allow him to determine the size of a function
    (which is what he asked for). I didn't guarantee that answering
    his question would solve his problem. :)
    Ordering is probably not guaranteed, but I've never seen it
    If you're using GCC, the easiest thing to do is to put the
    function in question in its own section using
    __attribute__((section "whatever")). Then you can put labels
    at the start and end of section "whatever". Or you can define
    a global symbol having the value of the size of the section
    (which even more directly answers the original question).

    Of course you could also put all functions in individual
    sections using -ffunction-sections.
    Grant Edwards, Nov 1, 2005
  5. So then the only proper way would be to access the symbol table and see
    whats the next entry after my function and get the difference between
    the two.

    Is there a standard way of accessing the symbol table?

    For now (after reading Grants answer, thank you) I created a dummy
    function after the needed function, and I am getting the size by
    subtracting the pointers to those functions to get the size. This linker
    I am using seems to keep the functions in the same order as written in
    the .c file.

    But I don't like relying on this solution, so I still seek for an

    Thanks Arie,
    Tosca Berisha, Nov 1, 2005
  6. Tosca Berisha

    Tauno Voipio Guest

    If you're using GCC, probably you do not need to
    copy anything, just locate your function to the initialized
    data section:

    /* Write unlock sequence */

    static void unlock(void) __attribute__((section(".data")));
    static void unlock(void)

    This is the Flash unlock routine from an embedded
    Tauno Voipio, Nov 1, 2005
  7. That works, but it can be a bit of a waste since the function
    is sitting in both flash and RAM 100% of the time. If there
    are multiple routines that need to be run from RAM at different
    points in time, you can save a bit of RAM by overlaying them.
    Grant Edwards, Nov 1, 2005
  8. Tosca Berisha

    johnspeth Guest

    What you want to do is highly non-portable but try this working code
    snippet I use for the MSP430:

    // Blinks the LED
    void codeFunction(void)
    uartPrintf(": BLINK Press ESC to quit\r\n");

    if(uartGetByte() == ESC) break;


    void codeFunction_END(void) { }

    // Executes the BLINK command
    void funcBLINK(int count,char *cmd,char *arg1,char *arg2)
    byte codeRam[90];
    size_t loadSize;
    void (*pfnFunction)(void);


    loadSize = (size_t)(codeFunction_END) - (size_t)(codeFunction);
    uartPrintf(": BLINK Load size = %u\r\n",loadSize);

    if(loadSize >= sizeof(codeRam))
    uartPrintf(": BLINK Can't load code\r\n");
    // Copy the code to RAM

    // Point to the function starting in RAM
    pfnFunction = (void (*)(void))(codeRam);

    // Execute from RAM

    uartPrintf(": BLINK ok\r\n");

    Note that delay() and uartPrintf() and uartGetByte() do NOT get copied
    to RAM. That's part of the challenge.

    johnspeth, Nov 1, 2005
  9. Tosca Berisha

    Tauno Voipio Guest

    The amount of code needed in RAM for Flash writing is pretty
    small: about 250 bytes on an ARM for garden-variety AMD Flashes.
    Tauno Voipio, Nov 1, 2005
  10. But where is the "flash writing" code getting the data?

    In cases I've dealt with the "flash writing" code has to
    impliment some sort of communications protocol in order to
    receive the data to be programmed into flash. In the product
    I'm working with right now, it takes 3KB of code to do a flash
    update. That's a pretty significant chunk out of my 32KB of
    Grant Edwards, Nov 1, 2005
  11. Tosca Berisha

    Tauno Voipio Guest

    You do not need to keep the whole chunk in RAM at the same time.
    Also, only the inner loop of a Flash writer is necessary to be
    kept in RAM, the rest can reside in the Flash. The code responsible
    for the handling from the unlock sequence till the chip responds
    ready to poll has to be in RAM, but this is for erasing a segment
    or writing a single byte. The rest of code can be safely in the
    Flash without any problems.

    The incoming data is usually transferred in some kind of chunks
    (e.g. 128 bytes with Xmodem). It's no too difficult to keep
    one chunk in the RAM and read more when that's written.
    Tauno Voipio, Nov 1, 2005
  12. Tosca Berisha

    diablovision Guest

    In ELF files generated by GCC, the symbol table has not only the name,
    type (FUNC), and address of each symbol, but its size as well. Thus the
    symbol table in the ELF file will tell you how big the code for the
    function is; something like objdump usually does not print out this
    information, but it is there.
    diablovision, Nov 1, 2005
  13. You're right. I could split up the loader and keep part of it
    in flash, but it's extra work and it doesn't buy me anything.
    Once the decision is made to update flash, the entire RAM space
    becomes available. The data that's there belongs to an
    application that's being erased. It's a lot simpler to just
    copy the entire loader into RAM and run it from there. Up
    until that point, the loader is using 0 bytes of RAM.
    It could, but there's no advantage to doing so.
    Grant Edwards, Nov 1, 2005
  14. The ELF file isn't available to the program at run-time. It's
    quite simple to put global simbols at the beginning and end of
    a section. Then all you have to do in C is declare those
    symbols as external char arrays.
    Grant Edwards, Nov 1, 2005
  15. .... so just assume the function occupies all the RAM, and copy that many bytes.
    Mike Harrison, Nov 2, 2005
  16. No way. A portable program has no way at all of finding this out,
    i.e. it cannot be done "in C" at all. And even a non-portable
    program, using features outside the C programming language proper,
    typically won't be able to do this at run-time. Stuff like this has
    to be set up at link time, the latest, and often you'll need to do it
    at compile time already. There's even a non-negligible probability
    that it can't be done at all, or only in assembly.

    Some toolsets have special extensions (#pragma or __attribute__()) in
    the source, or some magic incantation to put in the linker commands)
    that tell the linker a particular function will be stored in a
    location different from the one it's meant to run from.
    Hans-Bernhard Broeker, Nov 2, 2005
  17. Sure, but once you've put in a label so you know where the
    function starts, putting in a second one so you know where it
    ends only takes a couple more keystrokes.
    Grant Edwards, Nov 2, 2005
  18. Except that unlike the single starting point, which usually must exist
    for the C function to be callable from unrelated translation units,
    there's no particular reason for a given C function to even *have*
    exactly one end where such a label could be put. Nor is there a
    requirement that the entry point be at the start of the code region
    for that function.

    There's not even a requirement that a C compiler would have to
    translate a single function to a single, consequtive block of code.
    Optimization by function tail merging exists.

    As I stated elsewhere in this thread: it's easily possible that on a
    given platform the only way of pulling this off is by coding all the
    relevant parts in assembler.
    Hans-Bernhard Broeker, Nov 2, 2005
  19. Nonsense. There is some address X such that all bytes in the
    function have addresses less than X. Unless you've got some
    weird non-linear memory addressing scheme.
    That's why adding global labels before and after the function
    is much safer than useing the function pointer for anything.
    It may not be a requirement, but I've never seen a C compiler
    that didn't. This is comp.arch.EMBEDDED. We've got to work
    with real-world toolchains here, not some imaginary "could do
    anything the ISO spec allows" toolchain. comp.lang.c is that
    way --->
    I've been doing embedded C for 20 years on a dozen different
    target architectures and at least as many toolchains. I've
    never seen a target/toolchain where what the OP wants isn't
    easily doable with some trivial linker-script hacking.
    Grant Edwards, Nov 2, 2005
  20. Tosca Berisha

    Tauno Voipio Guest

    OK. Have a look at the Hi-Cross C Compiler. It translates
    every function into a separately linked unit. The units
    are linked in only if there are references to them. The
    addresses allocated by the linker for consecutive functions
    are not consecutive. For the reasons in this discussion
    (Flash writer) I tried to find the function sizes, but
    failed miserably.

    The binary file created was also a jumble of criss-
    crossed function-size pieces, so that I had to make
    an extra pre-sorting and merge pass before writing
    to Flash.

    My guess is that the functions were ordered by the
    stored call tree order collapsed in a weird way.
    Tauno Voipio, Nov 2, 2005
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.