计算Linux程序的栈使用量
Charles Chan @ 2023-01-14 #Debug #Stack @Linux
Contents:
下面代码是从网上抄来的。原文见参照区的链接。
/* gcc stack.c -o stack -pthread */
#define _GNU_SOURCE // for pthread_getattr_np
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
void print_stack(void)
{
size_t used, avail;
pthread_attr_t attr;
void *stack_addr;
size_t stack_size;
size_t esp_val;
if(sizeof(void*) == 8) {
asm("movq %%rsp, %0" : "=m"(esp_val) :); // x86_64
}
else {
asm("movl %%esp, %0" : "=m"(esp_val) :); // x86
}
memset(&attr, 0, sizeof(pthread_attr_t));
pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack(&attr, &stack_addr, &stack_size);
pthread_attr_destroy(&attr);
printf("statck top = %p \n", stack_addr);
printf("espVal = %p \n", (void*)esp_val);
printf("stack bottom = %p \n", stack_addr + stack_size);
avail = esp_val - (size_t)stack_addr;
used = stack_size - avail;
printf("print_stack1: used = %ld, avail = %ld, total = %ld \n",
used, avail, stack_size);
for(size_t i=0; i<=used; i+=16) {
printf("%p : ", (void*)esp_val + i);
for(size_t j=0; j<16; j++) {
printf("%02X ", ((unsigned char*)esp_val)[i + j]);
}
printf("\n");
}
printf("\n");
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
print_stack();
return 0;
}
多次运行,会发现一个奇怪的现象。即:每次的“espVal”都不相同。 而理论上,在这个程序固定下来之后,对栈的使用量应该就是固定的了。
调查发现,在Linux系统中,存在一个叫做ASLR的机制。 引入这个机制的一个目的是防止黑客的攻击。但这也导致程序运行时,每次堆栈的起始位置都是随机的。
存在两个办法来避免随机值带来的影响。
第一个办法是,关闭系统的ASLR功能。
echo 0 > /proc/sys/kernel/randomize_va_space
第二个办法是,仅在运行时,关闭被运行的应用程序的ASLR。
setarch `uname -m` -R ./stack