Get depth of call stack in gcc - c

I want to write a debug printing function that prints LINE, FILE, func and some other stuff. The twist is that I'd like to automatically indent the printouts according to their depth in the call stack, so something like
main.c:55:main()
functions.c:33:function1()
functions.c:133:function2()
functions.c:33:function1()
functions.c:33:function1()
if function1 returns immediately, and function2 calls function1 twice.
I guess this could be done by using a global variable which is manually incremented each time a function is called and decremented whenever it is returned, but this would require quite the code base rehaul. I was wondering if there was an easier way to do it?
I don't mind if the solution is non-standard C, so long as it is standard GNU.

You can probably do this with the code profiling options in Gcc.
https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Code-Gen-Options.html
-finstrument-functions
Generate instrumentation calls for entry and exit to functions. Just after function entry and just before function
exit, the following profiling functions will be called with the
address of the current function and its call site. (On some platforms,
__builtin_return_address does not work beyond the current function, so the call site information may not be available to the profiling
functions otherwise.)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);

Related

C callbacks - optional argument?

Hey I have implemented some callbacks in my C program.
typedef void (*server_end_callback_t)(void *callbackArg);
then I have variable inside structure to store this callback
server->server_end_callback = on_sever_end;
What I have noticed it that I can pass in on_server_end callback function implementation that skips void *callbackArg and the code works correctly (no errors).
Is it correct to skip some arguments like void * implementing callback functions which prototypes takes such arguments?
void on_server_end(void) {
// some code goes here
}
I believe it is an undefined behavior from the C point of view, but it works because of the calling convention you are using.
For example, AMD64 ABI states that the first six arguments get passed to the calling function using CPU registers, not stack. So neither caller nor callee need no clean-up for the first six arguments and it works fine.
For more info please refer the Wikipedia.
The code works correctly because of the convention of passing arguments. Caller knows that callee expects some arguments - exactly one. So, it prepares the argument(s) (either in register or on stack - depending on ABI on your platform). Then callee uses those parameters or not. After return from callee, caller cleans up the stack if necessary. That's the mistery.
However, you shall not abuse this specific behaviour by passing incompatible function. It is a good practice to always compile your code with options -W -Wall -Werror (clang/gcc and compatible). Enabling such option would provide you a compilation error.
C allows a certain amount of playing fast and loose with function arguments. So
void (*fptr) ();
means "a pointer to a function which takes zero or more arguments". However this is for backwards compatibility, it's not wise to use it in new C code. The other way round
void (*fptr)(void *ptr)
{
/* don't use the void */
}
/* in another scope */
(*fptr)(); /* call with no arguments */
also works, as long as you don't use the void *, and I believe it is guaranteed to work though I'm not completely sure about that (on a modern machine the calling convention is to pass the first arguments in registers, so you just get a garbage register, and it will work). Again, it is a very bad idea to rely on it.
You can pass a void *, which you then cast to a structure of appropriate type containing as many arguments as you wish. That is a good idea and a sensible use of C's flexibility.
Is it correct to skip some arguments like void * implementing callback functions which prototypes takes such arguments?
No it is not. Any function with a given function declaration is not compatile with a function of a different function declaration. This rule applies for pointers to functions too.
So if you have a function such as pthread_create(..., my_callback, ...); and it expects you to pass a function pointer of type void* (*) (void*), then you cannot pass a function pointer of a different format. This invokes undefined behavior and compilers may generate incorrect code.
That being said, function pointer compatibility is a common non-standard extension on many systems. If the calling convention of the system is specified in a way that the function format doesn't matter, and the specific compiler port supports it, then such code might work just fine.
Such code is however not portable and not standard. It is best to avoid it whenever possible.

Force function to return

For an analysis I'm doing I want to be able to "catch" specific malloc calls. I therefore created a function wrapper to malloc, named malloc_wrapper:
void *malloc_wrap(size_t size) {
return malloc(size);
}
All left is just slightly modify the source code by switching some malloc calls with malloc_wrap. I then use Intel Pin to capture what I need.
Unfortunately, it didn't work. I didn't see malloc_wrap being called in the assembly code, so it was probably inlined. Quick search, and I added this to the function header:
__attribute__ ((noinline))
Great, now I'm able to spot the function entry, but not the exit. I can't see any ret call at the end of the function. How can I force the compiler to compile my wrapper function regularly?

C Function changes runtime its return address when called from the same Function

I would like to know under which circumstances a C function can runtime change its return address, when called from the same function.
I have noticed itĀ happening in a series of test on a low level code I've developed.
This is a snippet that shows how I retrieve the two pointers:
#include <stdint.h>
uintptr_t foo() {
// Fetch the current IP and SP
uintptr_t ip = (uintptr_t)__builtin_return_address(0);
register void* rsp asm("sp");
uintptr_t sp = (uintptr_t)rsp;
return ip + sp; // just to avoid that they are optimized away.
}
void bar () {
foo();
}
When I run my test and call bar from different functions, I see the values of IP changing (not very frequently, only once in a long series of test).
I though about the fact my compiler may inline the functions. But, I see the error happening even with __attribute__((noinline)) applied to both functions.
I know not being reliable as it may be optimized away.
Do you have any other explanation or solution for this problem?
I'm compiling using gcc 4.7.2 under GNU/Linux Kernel 3.10.39.
The "return address" is the address where the function returns to. If you call it from several places, it is immediately clear why this happens.
The stack pointer depends on the depth of the stack we are currently in and thus depends on the call history: if main() calls a() which calls b() which calls foo(), you have a different SP than if main() calls foo() directly.

Call C address as function without prototype

I need to call a function in C by just knowing it address, and no information
on it prototype (I can't cast it to a C function pointer).
The information I have on this function is it address.
I also know the parameters I want to pass to it (Thanks to a void pointer) and
the size of the arguments array (accessed trough the void pointer).
I also want to respect the C calling convention. For x86 version, I pretty much
know how to do it (allocate the space on the stack, copy the parameters to
that space and finally call the function).
The problem is with x64 convention (Linux one for now) where parameters are
passed through registers. I have no idea of the size of each parameter to fill
appropriately registers, I only know the size of the parameter array.
Also, I don't want to depend on gcc so I can't use __builtin_apply that seems
to be not standard and also be pretty dark.
I want to write my own piece of code to support multi compiler and also to
learn interesting stuff.
So basically, the function I want to write as the same prototype as
__builtin_apply which is:
void *call_ptr(void (*fun)(), void *params, size_t size);
I want also the code to write it in C (thanks to asm inline) or pure x64 asm.
So is there a way to do this properly and with respect of the calling
convention ? Or is this impossible with the x64 convention without knowing
exactly the prototype of the function called ?
Especially for x64 calling convention on Linux this will not work at all.
The reason is the very complicated calling convention.
Some examples:
void funcA(float64 x);
void funcB(int64 x);
In these two cases the value "x" is passed to the functions differently because floating point and integer are passed to the functions in different registers.
void funcC(float64 x,int64 y);
void funcD(int64 y,float64 x);
In these two cases the arguments "x" and "y" are in different order. However they are passed to the function in the same way (both functions use the same register for "x" and the same register for "y").
Conclusion: To create a function that does what you want you'd have to pass a string containing the argument types of each argument to the assembler function. The number/size of arguments is definitely not enough. However it would definitely be possible - as long as it must work only on Linux.
I think, all of your decision will not be supported multi-compiler, because the mechanism of passing arguments to function (registers, their order, stack, memory) - it's compiler dependence feature...

weird stack corruption due to a dll call

I'm trying to make a call to a DLL function (via GetProcAddress etc) from C, using lcc compiler. The function gets called and everything goes well, but it looks like the top of the stack gets corrupted. I've tried to play with calling conventions (__stdcall / __cdecl), but that didn't help.
Unfortunately I don't have access to the dll code, and have to use the lcc compiler.
I found that this simple hack avoids stack corruption:
void foo(params)
{
int dummy;
dll_foo(params);
}
Here dll_foo is the pointer returned by GetProcAddress, and the stack is kind of protected by the dummy variable. So it's not the stack pointer that gets corrupted, but the data at the top of the stack. It works like this, but I'd like to know the reason of the corruption.
Any ideas?
UPD:
As asked in the comments, here are the actual function types:
typedef unsigned char (CALLBACK Tfr)(unsigned char);
typedef void (CALLBACK Tfw)(unsigned char,unsigned char);
typedef int (CALLBACK Tfs)(int);
typedef void (CALLBACK Tfwf)(int*,int);
All they show a similar behavior.
Unfortunately, it is not so straightforward to attach a debugger, as the code is compiled and launched by Matlab, using the LCC compiler, and there is no debugging support. Probably I will have to reproduce this problem in a standalone configuration, but it is not that easy to make it.
Sounds like you use MSVC, Debug + Windows + Registers. Look at the value of ESP before and after the call. If it doesn't match then first change the calling convention in the function pointer declaration (did you do that right?) If it still doesn't match then it is __stdcall and you haven't guessed the arguments you need to pass correctly.
Or the function could just clobbers the stack frame, it isn't impossible.
Posting your function pointer declaration that shows the real arguments would probably help diagnose this better.
It sounds to me like you were on the right track with looking at the calling convention. The main thing you need to do is ensure that the caller and callee are both using the same convention. Typically for a DLL, you want to use __stdcall for both, but if (as you say) you have no control over the DLL, then you need to modify your code to match what it's doing. Unfortunately, it's almost impossible to guess what that is -- I'm pretty sure lcc (like most C and C++ compilers) can produce code to use a variety of conventions.
Based on your hack working by putting an extra dword on the stack, it sounds like you currently have a mismatch where both the caller and the callee are trying to clear arguments off the stack (e.g., the caller using __cdecl and the callee using __stdcall.
You could try to "follow" the call to dll_foo() i assembler using a debugger, at check out exactly what the routine does stack-wise.

Resources