GCC:如何在MCU上完全禁用堆使用?

时间:2016-10-19 11:37:41

标签: gcc arm g++ heap microcontroller

我有一个在基于ARM Cortex-M的MCU上运行的应用程序,用C和C ++编写。我使用gccg++来编译它,并希望完全禁用任何堆使用。

在MCU启动文件中,堆大小已经设置为0.除此之外,我还想禁止在代码中使用任何意外的堆。

换句话说,我希望链接器(和/或编译器)在malloccallocfree函数或{{1}时给出错误<},newnew[]delete运算符。

到目前为止,我已经尝试了delete[],这给了我-nostdlib等问题。我也试过了undefined reference to _start,但当我尝试拨打-nodefaultlibs时,我仍然没有抱怨。这样做的正确方法是什么?

注意:

  • 此应用程序在“裸机”上运行,没有操作系统。
  • 我还想避免在第三方代码中使用任何malloc(特定于供应商的库,标准库,printf等)。
  • 我完全可以不使用需要动态内存分配的C / C ++标准库部分。
  • 我更喜欢编译时而不是运行时解决方案。

2 个答案:

答案 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,您可以使用损坏的名称_Znwmoperator new(unsigned long))和_Znamoperator 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 ...