Возможно, это не соответствует вашему определению, простому или эффективному, но одним из способов может быть следующее:
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
/* utility functions */
static void getctx(ucontext_t* ucp)
{
if (getcontext(ucp) == -1) {
perror("getcontext");
exit(EXIT_FAILURE);
}
}
static void print_sp()
{
#if defined(__x86_64)
unsigned long long x; asm ("mov %%rsp, %0" : "=m" (x));
printf("sp: %p\n",(void*)x);
#elif defined(__i386)
unsigned long x; asm ("mov %%esp, %0" : "=m" (x));
printf("sp: %p\n",(void*)x);
#elif defined(__powerpc__) && defined(__PPC64__)
unsigned long long x; asm ("addi %0, 1, 0" : "=r" (x));
printf("sp: %p\n",(void*)x);
#elif defined(__powerpc__)
unsigned long x; asm ("addi %0, 1, 0" : "=r" (x));
printf("sp: %p\n",(void*)x);
#else
printf("unknown architecture\n");
#endif
}
/* stack for 'my_alloc', size arbitrarily chosen */
static int malloc_stack[1024];
static ucontext_t malloc_context; /* context malloc will run in */
static ucontext_t current_context; /* context to return to */
static void my_malloc(size_t sz)
{
printf("in my_malloc(%zu) ", sz);
print_sp();
}
void call_my_malloc(size_t sz)
{
/* prepare context for malloc */
getctx(&malloc_context);
malloc_context.uc_stack.ss_sp = malloc_stack;
malloc_context.uc_stack.ss_size = sizeof(malloc_stack);
malloc_context.uc_link = ¤t_context;
makecontext(&malloc_context, (void(*)())my_malloc, 1, sz);
if (swapcontext(¤t_context, &malloc_context) == -1) {
perror("swapcontext");
exit(EXIT_FAILURE);
}
}
int main()
{
printf("malloc_stack = %p\n", (void*)malloc_stack);
printf("in main ");
print_sp();
call_my_malloc(42);
printf("in main ");
print_sp();
return 0;
}
Это должно работать на всех платформах, где поддерживается makecontext(3)
. Цитата из справочной страницы (где я также получил вдохновение для примера кода):
Интерпретация ucp-> uc_stack такая же, как в sigaltstack (2), а именно, эта структура содержит начало и длину области памяти, которая будет использоваться в качестве стека, независимо от направления роста стека. Таким образом, пользовательская программа не должна беспокоиться об этом направлении.
Пример вывода из PPC64:
$ gcc -o stack stack.c -Wall -Wextra -W -ggdb -std=gnu99 -pedantic -Werror -m64 && ./stack
malloc_stack = 0x10010fe0
in main sp: 0xfffffe44420
in my_malloc(42) sp: 0x10011e20
in main sp: 0xfffffe44420