我有一个在基于ARM Cortex-M的MCU上运行的应用程序,用C和C ++编写。我使用gcc
和g++
来编译它,并希望完全禁用任何堆使用。
在MCU启动文件中,堆大小已经设置为0.除此之外,我还想禁止在代码中使用任何意外的堆。
换句话说,我希望链接器(和/或编译器)在malloc
,calloc
,free
函数或{{1}时给出错误<},new
,new[]
,delete
运算符。
到目前为止,我已经尝试了delete[]
,这给了我-nostdlib
等问题。我也试过了undefined reference to _start
,但当我尝试拨打-nodefaultlibs
时,我仍然没有抱怨。这样做的正确方法是什么?
注意:
答案 0 :(得分:6)
我不确定这是最好的方法,但是您可以使用ld
的{{1}}标记(可以通过gcc
使用-Wl
{1}})。
我们的想法是--wrap
允许您要求ld
重定向&#34;真实&#34;符号到你的自定义;例如,如果您执行--wrap=malloc
,则ld
将查找要调用的__wrap_malloc
函数,而不是原始的`malloc。
现在,如果您在没有定义--wrap=malloc
的情况下执行__wrap_malloc
,如果没有人使用它,您将会侥幸成功,但如果有人引用malloc
您就是&#39 ; ll会收到链接错误。
$ cat test-nomalloc.c
#include <stdlib.h>
int main() {
#ifdef USE_MALLOC
malloc(10);
#endif
return 0;
}
$ gcc test-nomalloc.c -Wl,--wrap=malloc
$ gcc test-nomalloc.c -DUSE_MALLOC -Wl,--wrap=malloc
/tmp/ccIEUu9v.o: In function `main':
test-nomalloc.c:(.text+0xa): undefined reference to `__wrap_malloc'
collect2: error: ld returned 1 exit status
对于new
,您可以使用损坏的名称_Znwm
(operator new(unsigned long)
)和_Znam
(operator new[](unsigned long)
),这应该是每个new
应该归结为最终。
答案 1 :(得分:0)
(作为答案发布,因为它不符合评论)
如果您运行的操作系统支持the use of LD_PRELOAD
,则此代码应检测使用堆的尝试:
/* remove the LD_PRELOAD from the environment so it
doesn't kill any child process the app may spawn */
static void lib_init(void) __attribute__((constructor));
static void lib_init( void )
{
unsetenv( "LD_PRELOAD" );
}
void *malloc( size_t bytes )
{
kill( getpid(), SIGSEGV );
return( NULL );
}
void *calloc( size_t n, size_t bytes )
{
kill( getpid(), SIGSEGV );
return( NULL );
}
void *realloc( void *ptr, size_t bytes )
{
kill( getpid(), SIGSEGV );
return( NULL );
}
void *valloc( size_t bytes )
{
kill( getpid(), SIGSEGV );
return( NULL );
}
void *memalign( size_t alignment, size_t bytes )
{
kill( getpid(), SIGSEGV );
return( NULL );
}
int posix_memalign( void **ptr, size_t alignment, size_t bytes )
{
*ptr = NULL;
kill( getpid(), SIGSEGV );
return( -1 );
}
假设new
使用malloc()
实现,delete
使用free()
实现,这将捕获所有堆使用情况,并为您提供带有堆栈跟踪的核心文件,假设核心文件已启用。
添加正确的标题,编译文件:
gcc [-m32|-m64] -shared heapdetect.c -o heapdetect.so
运行你的应用:
LD_PRELOAD=/path/to/heapdetect.so /your/app/here args ...