连接时出错,(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0' .

连接时出错: 

D:\Program Files (x86)\DS-5\bin\led_on_c>make
arm-none-linux-gnueabi-gcc -g -c -o crt0.o crt0.S
arm-none-linux-gnueabi-gcc -g -c -o led_on_c.o led_on_c.c
arm-none-linux-gnueabi-ld -Ttext 0x0000000 -g  crt0.o led_on_c.o -o led_on_c_elf

led_on_c.o:(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'
make: *** [led_on_c.bin] Error 1

 

 

 

文件1:crt0.S

@******************************************************************************
@ File:crt0.S
@ 功能:通过它转入C程序
@******************************************************************************      

.text
.global _start
_start:
            ldr     r0, =0x56000010     @ WATCHDOG寄存器地址
            mov     r1, #0x0                    
            str   r1, [r0]              @ 写入0,禁止WATCHDOG,否则CPU会不断重启
           
            ldr     sp, =1024*4         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
                                        @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
            bl      main                @ 调用C程序中的main函数
halt_loop:
            b       halt_loop

文件2:led_on_c.c

#define GPBCON      (*(volatile unsigned long *)0x56000010)
#define GPBDAT      (*(volatile unsigned long *)0x56000014)

int main()
{
    GPBCON = 0x00000400;    // 设置GPB5为输出口, 位[11:10]=0b01
    GPBDAT = 0x00000000;    // GPB5输出0,LED1点亮

    return 0;
}


文件3:makefile
led_on_c.bin : crt0.S  led_on_c.c

arm-none-linux-gnueabi-gcc -g -c -o crt0.o crt0.S
arm-none-linux-gnueabi-gcc -g -c -o led_on_c.o led_on_c.c
arm-none-linux-gnueabi-ld -Ttext 0x0000000 -g  crt0.o led_on_c.o -o led_on_c_elf
arm-none-linux-gnueabi-objcopy -O binary -S led_on_c_elf led_on_c.bin
arm-none-linux-gnueabi-objdump -D -m arm  led_on_c_elf > led_on_c.dis
clean:
 rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o

所使用编译工具

Windows平台下DS-5提供的GNU编译工具

解决办法

arm-none-linux-gnueabi-gcc加上-nostdlib选项即可,修改Makefile如下:

led_on_c.bin : crt0.S  led_on_c.c
arm-none-linux-gnueabi-gcc -g -nostdlib -c -o crt0.o crt0.S
arm-none-linux-gnueabi-gcc -g -nostdlib -c -o led_on_c.o led_on_c.c
arm-none-linux-gnueabi-ld -Ttext 0x0000000 -g  crt0.o led_on_c.o -o led_on_c_elf
arm-none-linux-gnueabi-objcopy -O binary -S led_on_c_elf led_on_c.bin
arm-none-linux-gnueabi-objdump -D -m arm  led_on_c_elf > led_on_c.dis
clean:
 rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o

机理
-nostdlib
不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。这个选项常用于编译内核、bootloader等程序,它们不需要启动文件、标准库文件。

C语言程序执行的第一条指令。并不是main函数。生产一个C程序的可执行文件时编译器通常会在我们的代码上加几个被称为启动文件的代码--crt1.o、crti.o、

crtend.o等,他们是标准库文件。这些代码设置C程序的堆栈等,然后调用main函数。他么依赖于操作系统,在裸板上无法执行,所以我们自己写一个。

 

问题已经找到答案了,我们自己写的crt0.S就是一个启动文件,他设置好堆栈后调用main函数。因此,我们不需要系统自带的启动文件。

### 关于 L6218E 错误:未定义符号 `__aeabi_assert` 当编译器报告链接器错误 **L6218E: Undefined Symbol __aeabi_assert** ,这通常意味着程序中调用了函数 `__aeabi_assert`,但在链接阶段未能找到该函数的实际实现。以下是可能的原因及其解决方案: #### 原因分析 1. 缺少必要的库文件 函数 `__aeabi_assert`ARM EABI (Embedded Application Binary Interface) 的一部分,用于处理断言失败的情况。如果项目缺少标准 C 库或其相关支持文件,则可能会发生此问题[^1]。 2. 配置不正确 如果项目的链接配置中遗漏了某些必需的选项或者路径设置有误,也可能导致无法解析此类符号[^2]。 3. 自定义构建环境中的缺失项 在一些自定义工具链下,开发者可能手动裁剪掉了部分功能模块(比如调试相关的宏),从而间接移除了对这些辅助方法的支持[^3]。 #### 解决方案 ##### 方法一:确认并添加正确的运行库 确保在您的工程设置里包含了完整的C/C++ runtime libraries。对于基于ARM架构的目标平台来说,应该核查是否有引入像`libgcc.a`, 或者更具体的针对异常处理和支持assert机制的相关档案文件[^4]。 ```bash -lm -lc -lgcc ``` 上述命令片段展示了如何通过GCC指定附加的标准数学(-lm),核心C语言特性(-lc)以及GNU Compiler Collection内部使用的特定组件(-lgcc)[^5]。 ##### 方法二:重新审视源码逻辑 检查是否存在显式或隐式的调用到`__aeabi_assert()`的地方。一般情况下,除非特别定制化修改过assert行为,默认是不会直接看到这个名称被引用的;它更多是由其他高层级API触发而来。因此可以考虑搜索整个项目范围内关于“assert”的关键词实例,并评估它们是否合理且必要存在于此上下文中[^6]。 另外一种可能性是由于第三方依赖关系带入了这种需求——即某个外部DLL/静态LIB本身期望使用者提供全套的基础服务包来满足自身的运作条件。此需仔细阅读对应文档说明了解确切的要求清单[^7]。 ##### 方法三:强制屏蔽不必要的断言语句 假如确定当前开发周期内不需要任何形式的runtime assertion checkings, 可尝试预处理器指令禁用所有关联操作: ```c #define NDEBUG #include <assert.h> ``` 这样做的效果是在编译期就消除了所有的assert macro展开动作,进而规避掉潜在的undefined reference隐患[^8]。 请注意这种方法虽然简单粗暴有效,但从长远看并不推荐作为最终修复策略,因为它实际上掩盖了原本设计意图而非真正解决问题根源所在。 --- ### 提供一段示范代码调整例子 假设我们遇到如下场景: ```c void example_function(int value){ assert(value !=0 && "Value must not be zero"); } ``` 如果我们怀疑正是这里的assert引起了后续麻烦,那么可以根据实际情况采取下面两种方式之一进行改造: 要么彻底删除验证环节(仅适用于非常明确知晓输入数据始终安全的前提下): ```c void example_function(int value){ // Removed the assert statement. } ``` 要么替换为更加轻量级的手动检测手段而不借助standard library的帮助 : ```c void example_function(int value){ if (!value){ printf("Error: Value is unexpectedly ZERO.\n"); exit(EXIT_FAILURE); } } ``` 以上改动均能帮助绕开原始报错点的同维持基本的功能一致性[^9]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值