27

I want to know the length of C function (written by me) at runtime. Any method to get it? It seems sizeof doesn't work here.

Thomson
  • 20,586
  • 28
  • 90
  • 134
  • 2
    Please define "length of C function" **precisely** – pmg Nov 11 '10 at 16:24
  • 4
    I mean the memory occupied by the code of this function. – Thomson Nov 11 '10 at 16:26
  • 2
    If you are asking this for the same reason I wondered about it many years ago, let me point out [Writing a New Jit](http://stackoverflow.com/questions/4097301/writing-a-new-jit) – Ben Jackson Nov 11 '10 at 16:26
  • 1
    You can calculate by subtracting pointers for the function you need to get the length and the next function. But it depends on the compiler. I'm not sure that the optimization parameters won't affect the arrangement as well. So this is not an answer to your question. – khachik Nov 11 '10 at 16:30
  • 3
    Note that functions are not objects (the Standard explicitly says so), you cannot get their sizes. –  Dec 08 '12 at 23:16
  • 1
    @khachik shame that we can't downvote comments. The last time I reasoned about addresses of globals was in ~1995, and even then the practice was iffy – sehe Dec 08 '12 at 23:16
  • Related: [Get the “size” (length) of a C++ function?](http://stackoverflow.com/questions/8705215/get-the-size-length-of-a-c-function/8705375#8705375) – sehe Dec 08 '12 at 23:19

13 Answers13

28

There is a way to determine the size of a function. The command is:

 nm -S <object_file_name>

This will return the sizes of each function inside the object file. Consult the manual pages in the GNU using 'man nm' to gather more information on this.

Clocks
  • 411
  • 4
  • 8
  • 2
    `nm -S --size-sort -t d | grep ` displays the size in base 10 (`-t d` for *decimal*) of symbols containing `pattern` in their name, sorted by size. Pretty cool. – hdl Jun 22 '16 at 15:52
24

You can get this information from the linker if you are using a custom linker script. Add a linker section just for the given function, with linker symbols on either side:

mysec_start = .;
*(.mysection)
mysec_end = .;

Then you can specifically assign the function to that section. The difference between the symbols is the length of the function:

#include <stdio.h>

int i;

 __attribute__((noinline, section(".mysection"))) void test_func (void)
{
    i++;
}

int main (void)
{
    extern unsigned char mysec_start[];
    extern unsigned char mysec_end[];

    printf ("Func len: %lu\n", mysec_end - mysec_start);
    test_func ();

    return 0;
}

This example is for GCC, but any C toolchain should have a way to specify which section to assign a function to. I would check the results against the assembly listing to verify that it's working the way you want it to.

FazJaxton
  • 7,544
  • 6
  • 26
  • 32
  • 6
    You can do this without a custom linker script by calling the section by a valid C identifier name, for example `mysection` instead of `.mysection`, and using `__start_mysection` and `__stop_mysection` instead of `mysec_start` and `mysec_end`. The linker automatically defines these symbols for each section encountered. – jakobbotsch Jan 28 '18 at 12:30
  • Great! I tried it for myself with a valid identifier name, and indeed it works with plain GCC without a linker script. [acapola's answer](https://stackoverflow.com/a/69290721/836531) has a working example, adapted from this one. – Rennex Jan 07 '22 at 00:44
15

There is no way in standard C to get the amount of memory occupied by a function.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Erhm.. Yes there is, it's called pointer arithmetic. :P – Christoffer Bubach Jul 12 '20 at 01:17
  • Please see: https://stackoverflow.com/a/22047976/604033 – mrkotfw Nov 06 '20 at 08:43
  • @ChristofferBubach [Ummm, that's wrong](https://port70.net/~nsz/c/c11/n1570.html#6.5.6p9). In standard-conforming C you can only do pointer arithmetic on pointers referring to the same object or one item past the end of an object. You can't do pointer arithmetic on pointers to different objects. And function pointers don't refer to objects anyway. – Andrew Henle Mar 10 '21 at 23:19
  • As others have pointed out, it can be done using linker script. The question is not restricted to C standard so linker based solutions are valid – acapola Sep 22 '21 at 19:48
  • Pointers are numbers, numbers can be used to do math. See? Haha ok to be fair I should have guessed it’s deemed ”undefined”, but really - why wouldn’t it work - know of platforms that include segments too or…? – Christoffer Bubach Feb 27 '22 at 22:14
7

I have just came up with a solution for the exact same problem but the code i have written is platform depended.

The idea behind, putting known opcodes at the end of the function and searching for them from start while counting bytes we have skipped. Here is the medium link which i have explained with some code https://medium.com/@gurhanpolat/calculate-c-function-size-x64-x86-c1f49921aa1a

Gurhan Polat
  • 696
  • 5
  • 12
5

Executables (at least ones which have debug info stripped) doesn't store function lengths in any way. So there's no possibility to parse this info in runtime by self. If you have to manipulate with functions, you should do something with your objects in linking phase or by accessing them as files from your executable. For example, you may tell linker to link symbol tables as ordinary data section into the executable, assign them some name, and parse when program runs. But remember, this would be specific to your linker and object format.

Also note, that function layout is also platform specific and there are some things that make the term "function length" unclear:

  1. Functions may have store used constants in code sections directly after function code and access them using PC-relative addressing (ARM compilers do this).
  2. Functions may have "prologs" and "epilogs" which may may be common to several functions and thus lie outside main body.
  3. Function code may inline other function code

They all may count or not count in function length.

Also function may be completely inlined by compiler, so it loose its body.

Vovanium
  • 3,798
  • 17
  • 23
  • they can but these functions still have fixed length, they will just misbehave without those external dependencies. These functions can be rebuilt to be self contained by taking their dependencies as arguments, and many functions, especially callback functions, are exactly this. – Dmytro Sep 25 '16 at 03:54
5

A fully worked out solution without linker or dirty platform dependent tricks:

#include <stdio.h>

int i;

 __attribute__((noinline, section("mysec"))) void test_func (void)
{
    i++;
}

int main (void)
{
    extern char __start_mysec[];
    extern char __stop_mysec[];

    printf ("Func len: %lu\n", __stop_mysec - __start_mysec);
    test_func ();

    return 0;
}

That's what you get when you read FazJaxton's answer with jakobbotsch's comment

acapola
  • 1,078
  • 1
  • 12
  • 23
  • If you use a linker script, you will probably still have to modify that linker script to get this trick to work, so you might as well use FazJaxton's answer. – dsmtoday Mar 31 '22 at 03:19
4

In e.g. Codewarrior, you can place labels around a function, e.g.

label1:
void someFunc()
{
    /* code goes here. */
}
label2:

and then calculate the size like (int)(label2-label1), but this is obviously very compiler dependent. Depending on your system and compiler, you may have to hack linker scripts, etc.

Sam Skuce
  • 1,666
  • 14
  • 20
  • 1
    Didn't know that. Funny. Sort of. – haylem Nov 11 '10 at 16:55
  • 4
    There's a similar [GCC extension](http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Labels-as-Values.html#Labels-as-Values), using it you'd be able to calculate the size as `&&label2 - &&label1` – Hasturkun Nov 11 '10 at 17:00
  • I hope this would work, but it seems it can't work in Visual C++ (C language). – Thomson Nov 11 '10 at 17:04
4

The start of the function is the function pointer, you already know that.

The problem is to find the end, but that can be done this way:

#include <time.h>

int foo(void)
{
   int i = 0;
   ++i + time(0); // time(0) is to prevent optimizer from just doing: return 1;
   return i;
}

int main(int argc, char *argv[])
{
   return (int)((long)main - (long)foo);
}

It works here because the program has ONLY TWO functions so if the code is re-ordered (main implemented before foo) then you will get an irrelevant (negative) calculation, letting you know that it did not work this way but that it WOULD work if you move the foo() code into main() - just substract the main() size you got with the initial negative reply.

If the result is positive, then it will be correct -if no padding is done (yes, some compilers happily inflate the code, either for alignment or for other, less obvious reasons).

The ending (int)(long) cast is for portability between 32-bit and 64-bit code (function pointers will be longer on a 64-bit platform).

This is faily portable and should work reasonably well.

PierreG
  • 65
  • 1
2

Just subtract the address of your function from the address of the next function. But note it may not work on your system, so use it only if you are 100% sure:

#include <stdint.h>

int function() {
    return 0;
}

int function_end() {
    return 0;
}

int main(void) {
    intptr_t size = (intptr_t) function_end - (intptr_t) function;
}
Vad
  • 4,052
  • 3
  • 29
  • 34
2

There's no facility defined within the C language itself to return the length of a function; there are simply too many variables involved (compiler, target instruction set, object file/executable file format, optimization settings, debug settings, etc.). The very same source code may result in functions of different sizes for different systems.

C simply doesn't provide any sort of reflection capability to support this kind of information (although individual compilers may supply extensions, such as the Codewarrior example cited by sskuce). If you need to know how many bytes your function takes up in memory, then you'll have to examine the generated object or executable file directly.

sizeof func won't work because the expression func is being treated as a pointer to the function, so you're getting the size of a pointer value, not the function itself.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • In a conforming compiler, `sizeof func` does not work because a function designator is not a valid operand of the `sizeof` operator. – caf Nov 12 '10 at 02:42
  • @JohnBode while you are right that this information is not portable; the compiler is still well aware of all of these factors at compile time, and the result makes perfect sense for that particular platform. Knowing the size of a function is meaningful on that platform because it allows you to memcpy the shellcode of "read only" functions, which has very interesting and consistant implications that we cannot study without having such a feature. – Dmytro Sep 25 '16 at 03:51
1

There is no standard way of doing it either in C or C++. There might naturally exist implementation/platform-specific ways of doiung it, but I am not aware of any

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
0
size_t try_get_func_size_x86(void* pfn, bool check_prev_opcode = true, size_t max_opcodes_runout = 10000)
{
    const unsigned char* op = (const unsigned char*)pfn;
    
    for(int i = 0; i < max_opcodes_runout; i++, op++)
    {
        size_t sz_at = (size_t)(op - (const unsigned char*)pfn) + 1;
        
        switch(*op)
        {
            case 0xC3: // ret Opcode
            case 0xC2: // ret x Opcode
            
            if(!check_prev_opcode)
                return sz_at;
                
            switch(*(op-1)) // Checking Previous Opcode
            {
                case 0x5D: //  pop    ebp
                case 0x5B: //  pop    ebx
                case 0x5E: //  pop    esi
                case 0x5F: //  pop    edi
                case 0xC9: //  leave
                    return sz_at;
            }
        }
    }

    return 0;
}
Jôsùå
  • 1
  • 1
  • 3
  • `unsigned char prevInstruc = *(Func - 1);` will not check for "previous instruction", as it always points to one byte before `Func`. Likewise, `if (Func[1] == 0xCC /* ... */)` will always check against one byte after `Func`. But that aside, what will happen if there's a function with for example `int value = 0xc3cc; printf("Value = %d\n", value);`? – annoyingnoob Jan 07 '23 at 11:21
  • Thanks for your observation, i refactored the solution, and want to add that this kind of aprouch work most of the time for me, but can lead to fake positives – Jôsùå Jan 07 '23 at 12:37
-3

You can find the length of your C function by subtracting the addresses of functions. Let me provide you an example

int function1()
    {
    } 

int function2()
{
    int a,b;    //just defining some variable for increasing the memory size
    printf("This function would take more memory than earlier function i.e function01 ");
}

int main()
{
    printf("Printing the address of function01 %p\n",function01);
    printf("Printing the address of function02 %p\n",function02);
    printf("Printing the address of main %p\n",main);
    return 0;
}

Hope you would get your answer after compiling it. After compiling you will able to see the difference in size of function01 and function2.

Note : Normally there is 16bytes diff between one function and other.

vpatial
  • 33
  • 3