C does not support any form of introspection or doing stuff automatically through magic in the runtime or on the virtual machine; there is no virtual machine, and the runtime support is basically just libraries of "dead" code that provide standard functionality.
And as Subtwo pointed out, if you want to do something (like log entry/exit), it will have to be done and thus take time. You can't just "hide" that penalty, there is very little overhead to put it in.
A standard profiler might give you some insight, by sampling your program statistically to see which functions execute, but that will not give you the call order, just random locations where your program was executing code at the time it was sampled.
You could perhaps turn to some preprocessor trickery, this is a common way to do "boilerplate" stuff like logging, by for instance defining some macros that you then put at the entry/exit points of each function. Still, you'd have to remember including the macros, and any performance penalty from doing the logging will of course be present.