内存分配优化:从堆到堆栈

lll*_*lll 6 c malloc optimization memory-management heap-memory

我正在为32-bit x86架构上的二进制文件做一些逆向工程任务.

最近我发现了一些从C源代码到汇编程序的有趣优化.

例如,原始源代码就像(此源代码来自openssl library):

powerbufFree = (unsigned char *)malloc(powerbufLen);
Run Code Online (Sandbox Code Playgroud)

在编译(gcc version 4.8.4 -O3)之后,汇编代码如下:

807eaa0: cmp eax, 0xbff                         # eax holds the length of the buf.
807eaa5: mov dword ptr [ebp-0x68], eax          # store the length of powerbuf on the stack
807eaa8: jnle 0x807ec60                         # 0x807ec60 refers to the malloc
807eaae: mov edx, eax
807eab0: add eax, 0x5e
807eab3: and eax, 0xfffffff0
807eab6: sub esp, eax
807eab8: lea eax, ptr [esp+0x23]
807eabc: and eax, 0xffffffc0
807eabf: add eax, 0x40
807ead3: mov dword ptr [ebp-0x60], eax  # store the base addr of the buf on the stack.
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,buf确实被分配在堆栈上!对我来说,这似乎是堆分配器的优化,但我不确定.

所以这是我的问题,上面的优化(malloc - >堆栈分配)似乎对任何人都很熟悉吗?是否有意义?任何人都可以提供一些这样的优化手册/规范吗?

jxh*_*jxh 5

bn_exp.c源码:

0634 #ifdef alloca
0635     if (powerbufLen < 3072)
0636         powerbufFree = alloca(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH);
0637     else
0638 #endif
0639     if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)
0640         goto err;
Run Code Online (Sandbox Code Playgroud)

请注意,0xbff它等于3071.在支持它的系统上,进行alloca堆栈分配.这是真正的GNU版本,这是由使用的LinuxBSD实现(复制从AT&T 32V UNIX该API 根据FreeBSD的).

您只查看了第639行.但是如果alloca已定义,则C代码与您的程序集匹配.

malloc如果分配相对较小,则优化本身通常用于避免使用临时缓冲区的费用.对于C.1999,可以使用VLA(因为C.2011,VLA是可选功能).

有时,优化只使用一些合理的小尺寸的固定大小的缓冲区.例如:

char tmp_buf[1024];
char *tmp = tmp_buf;

if (bytes_needed > 1024) {
    tmp = malloc(bytes_needed);
}
/* ... */
if (tmp != tmp_buf) {
    free(tmp);
}
Run Code Online (Sandbox Code Playgroud)