Getting The Size of a C++ Function

后端 未结 16 2100
醉酒成梦
醉酒成梦 2020-12-06 09:37

I was reading this question because I\'m trying to find the size of a function in a C++ program, It is hinted at that there may be a way that is platform specific. My target

相关标签:
16条回答
  • 2020-12-06 09:55

    I think it will work on windows programs created with msvc, as for branches the 'ret' seems to always come at the end (even if there are branches that return early it does a jne to go the end). However you will need some kind of disassembler library to figure the current opcode length as they are variable length for x86. If you don't do this you'll run into false positives.

    I would not be surprised if there are cases this doesn't catch.

    0 讨论(0)
  • 2020-12-06 09:57

    This won't work... what if there's a jump, a dummy ret, and then the target of the jump? Your code will be fooled.

    In general, it's impossible to do this with 100% accuracy because you have to predict all code paths, which is like solving the halting problem. You can get "pretty good" accuracy if you implement your own disassembler, but no solution will be nearly as easy as you imagine.

    A "trick" would be to find out which function's code is after the function that you're looking for, which would give pretty good results assuming certain (dangerous) assumptions. But then you'd have to know what function comes after your function, which, after optimizations, is pretty hard to figure out.


    Edit 1:

    What if the function doesn't even end with a ret instruction at all? It could very well just jmp back to its caller (though it's unlikely).


    Edit 2:

    Don't forget that x86, at least, has variable-length instructions...


    Update:

    For those saying that flow analysis isn't the same as solving the halting problem:

    Consider what happens when you have code like:

    foo:
        ....
        jmp foo
    

    You will have to follow the jump each time to figure out the end of the function, and you cannot ignore it past the first time because you don't know whether or not you're dealing with self-modifying code. (You could have inline assembly in your C++ code that modifies itself, for instance.) It could very well extend to some other place of memory, so your analyzer will (or should) end in an infinite loop, unless you tolerate false negatives.

    Isn't that like the halting problem?

    0 讨论(0)
  • 2020-12-06 09:57

    Using GCC, not so hard at all.

    void do_something(void) { 
       printf("%s!", "Hello your name is Cemetech"); 
       do_something_END: 
    } 
    
    ... 
    
       printf("size of function do_something: %i", (int)(&&do_something_END - (int)do_something));
    
    0 讨论(0)
  • 2020-12-06 09:58

    Wow, I use function size counting all the time and it has lots and lots of uses. Is it reliable? No way. Is it standard c++? No way. But that's why you need to check it in the disassembler to make sure it worked, every time that you release a new version. Compiler flags can mess up the ordering.

    static void funcIwantToCount()
    {
       // do stuff
    }
    static void funcToDelimitMyOtherFunc()
    {
       __asm _emit 0xCC
       __asm _emit 0xCC
       __asm _emit 0xCC
       __asm _emit 0xCC
    }
    
    int getlength( void *funcaddress )
    {
       int length = 0;
       for(length = 0; *((UINT32 *)(&((unsigned char *)funcaddress)[length])) != 0xCCCCCCCC; ++length);
       return length;
    }
    

    It seems to work better with static functions. Global optimizations can kill it.

    P.S. I hate people, asking why you want to do this and it's impossible, etc. Stop asking these questions, please. Makes you sound stupid. Programmers are often asked to do non-standard things, because new products almost always push the limits of what's availble. If they don't, your product is probably a rehash of what's already been done. Boring!!!

    0 讨论(0)
  • 2020-12-06 09:59

    It is possible to obtain all blocks of a function, but is an unnatural question to ask what is the 'size' of a function. Optimized code will rearrange code blocks in the order of execution and will move seldom used blocks (exception paths) into outer parts of the module. For more details, see Profile-Guided Optimizations for example how Visual C++ achieves this in link time code generation. So a function can start at address 0x00001000, branch at 0x00001100 into a jump at 0x20001000 and a ret, and have some exception handling code 0x20001000. At 0x00001110 another function starts. What is the 'size' of your function? It does span from 0x00001000 to +0x20001000, but it 'owns' only few blocks in that span. So your question should be unasked.

    There are other valid questions in this context, like the total number of instructions a function has (can be determined from the program symbol database and from the image), and more importantly, what is the number of instructions in the frequent executed code path inside the function. All these are questions normally asked in the context of performance measurement and there are tools that instrument code and can give very detailed answers.

    Chasing pointers in memory and searching for ret will get you nowhere I'm afraid. Modern code is way way way more complex than that.

    0 讨论(0)
  • 2020-12-06 10:02

    No, this will not work:

    1. There is no guarantee that your function only contains a single ret instruction.
    2. Even if it only does contain a single ret, you can't just look at the individual bytes - because the corresponding value could appear as simply a value, rather than an instruction.

    The first problem can possibly be worked around if you restrict your coding style to, say, only have a single point of return in your function, but the other basically requires a disassembler so you can tell the individual instructions apart.

    0 讨论(0)
提交回复
热议问题