为啥链接器无法识别我的链接器脚本中定义的入口点
Posted
技术标签:
【中文标题】为啥链接器无法识别我的链接器脚本中定义的入口点【英文标题】:Why is the linker not recognizing the entry point defined in my linker script为什么链接器无法识别我的链接器脚本中定义的入口点 【发布时间】:2021-09-15 22:17:28 【问题描述】:我正在尝试与目标交叉编译为 STM32F030F4P6,我设置了包含我的向量表的 startup.c 和 startup.h 文件。我已经编写了 2 个链接器脚本,一个用于内存,另一个用于部分。根据数据表,STM32f030F4 在系统复位后将 PC 设置为 0x00000000,并且向量表必须存在于该地址,因为递增后它必须在 0x00000004 处执行 Reset_Handler(系统复位)并初始化系统。
当我链接此链接时,链接器会给我以下警告
" warning: cannot find entry symbol _start; defaulting to 00008000"
Question
Why is the linker not detecting my Entry point defined by ENTRY(Reset_Handler)?
请找到我的源文件、头文件和链接器脚本。
脚本.ld 这包含部分
ENTRY(Reset_Handler) SECTIONS .text : *(.isr_vector) *(.text) *(.rodata) _etext= .; > FLASH .data : _sdata = .; *(.data) _edata = .; > SRAM AT> FLASH .bss : _sbss = .; *(.bss) _ebss = .; > SRAM
内存.ld 该文件包含内存定义。 注意-STM32F030F4P 只有 FLASH & RAM,所以 EXTMEMBx 定义为 0x00000000 of LENGTH 4K
MEMORY FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0K EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0K EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0K EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0K
启动.h 包含向量定义
#include "stdint.h" /* Calculate the vlaue of stack. */ /* Full- descending stack in cortex-m0 means stack must be placed at the end of SRAM. */ /* Stack pointer is decremented as a a PUSH operation is executed */ #define SRAM_Start 0x20000000U #define SRAM_End SRAM_Start+4096U #define Stack_Start SRAM_End /* Vector Definitions */ void Reset_Handler(void); void NMI_Handler(void) __attribute__((weak, alias("Default_Handler"))); void HardFault_Handler(void) __attribute__((weak, alias("Default_Handler"))); void SVCall_Handler(void) __attribute__((weak, alias("Default_Handler"))); void PendSV_Handler(void) __attribute__((weak, alias("Default_Handler"))); void SysTick_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ0_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ1_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ2_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ3_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ4_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ5_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ6_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ7_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ8_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ9_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ10_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ11_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ12_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ13_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ14_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ15_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ16_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ17_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ18_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ19_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ20_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ21_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ22_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ23_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ24_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ25_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ26_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ27_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ28_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ29_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ30_Handler(void) __attribute__((weak, alias("Default_Handler"))); void IRQ31_Handler(void) __attribute__((weak, alias("Default_Handler")));
& 最后 启动.c
//Set initial SP value // PC increments to reset handler // branch to main #include "startup.h" // __attribute__((weak, alias(""))) /* Vector Table */ /* Subsequent to a system RESET PC is set to 0x00000000 */ /* Vector Table must be present at 0x00000000 use __atribute__((section("section_name"))) to place vector table at "section_name" */ /* Use arm-none-eabi-objdump -h/-S to verify if "section_name" is generated for vector table */ /* Value of SP is the first item in the vector table & henceforth msp is loaded */ /* Second value of vector table is RESET HANDLER, */ /* Core Systems must be initialized here such as CLOCK, etc.*/ /* it is from RESET HANDLER the program flow is branched to user application */ uint32_t vector[] __attribute__((section(".isr_vector"))) = Stack_Start, (uint32_t)&Reset_Handler, (uint32_t)&NMI_Handler, (uint32_t)&HardFault_Handler, (uint32_t)0x00000000, (uint32_t)0x00000000, (uint32_t)0x00000000, (uint32_t)0x00000000, (uint32_t)0x00000000, (uint32_t)0x00000000, (uint32_t)0x00000000, (uint32_t)&SVCall_Handler, (uint32_t)0x00000000, (uint32_t)0x00000000, (uint32_t)&PendSV_Handler, (uint32_t)&SysTick_Handler, (uint32_t)&IRQ0_Handler, (uint32_t)&IRQ1_Handler, (uint32_t)&IRQ2_Handler, (uint32_t)&IRQ3_Handler, (uint32_t)&IRQ4_Handler, (uint32_t)&IRQ5_Handler, (uint32_t)&IRQ6_Handler, (uint32_t)&IRQ7_Handler, (uint32_t)&IRQ8_Handler, (uint32_t)&IRQ9_Handler, (uint32_t)&IRQ10_Handler, (uint32_t)&IRQ11_Handler, (uint32_t)&IRQ12_Handler, (uint32_t)&IRQ13_Handler, (uint32_t)&IRQ14_Handler, (uint32_t)&IRQ15_Handler, (uint32_t)&IRQ16_Handler, (uint32_t)&IRQ17_Handler, (uint32_t)&IRQ18_Handler, (uint32_t)&IRQ19_Handler, (uint32_t)&IRQ20_Handler, (uint32_t)&IRQ21_Handler, (uint32_t)&IRQ22_Handler, (uint32_t)&IRQ23_Handler, (uint32_t)&IRQ24_Handler, (uint32_t)&IRQ25_Handler, (uint32_t)&IRQ26_Handler, (uint32_t)&IRQ27_Handler, (uint32_t)&IRQ28_Handler, (uint32_t)&IRQ29_Handler, (uint32_t)&IRQ30_Handler, (uint32_t)&IRQ31_Handler, ; /*Function defenition of reset handler*/ /* it is from RESET HANDLER the program flow is branched to user application */ void Reset_Handler(void) // copy .data section // init .bss/SRAM to 0 // init clocks etc.. // call the application procedure void Default_Handler(void) for(;;) // Just loop as completion of this procedure will give other faults
我的工具链文件 arm-none-eabi.camke
MESSAGE("Running : arm-none-eabi.cmake") SET(CMAKE_SYSTEM_PROCESSOR arm) SET(CMAKE_SYSTEM_NAME Generic) SET(CMAKE_C_COMPILER_WORKS TRUE) SET(CMAKE_CXX_COMPILER_WORKS TRUE) SET(CMAKE_TRY_COMPILE_TARGTE_TYPE STATIC_LIBRARY) SET(TARGET STM32F030x4) SET(ARCH armv6-m) SET(CPU cortex-m0) SET(ARM_ISA mthumb) SET(CMAKE_C_COMPILER arm-none-eabi-gcc) SET(CMAKE_CXX_COMPILER arm-none-eabi-g++) SET(CMAKE_ASM_COMPILER arm-none-eabi-g++) SET(CMAKE_SIZE arm-none-eabi-size) SET(CMAKE_OBJDUMP arm-none-eabi-objdump) SET(CMAKE_OBJCOPY arm-none-eabi-objcopy) SET(OPTIMISATION Og) SET(DEBUG "ggdb") SET(CMAKE_COMMON_FLAGS "-march=$ARCH -mcpu=$CPU -$ARM_ISA -D$TARGET -$OPTIMISATION -$DEBUG -Wall -Wextra -ffunction-sections -fdata-sections -ffreestanding -fno-builtin -nostdlib") SET(CMAKE_ASM_FLAGS "$CMAKE_COMMON_FLAGS") SET(CMAKE_C_FLAGS "$CMAKE_COMMON_FLAGS ") SET(CMAKE_CXX_FLAGS "$CMAKE_COMMON_FLAGS -fno-rtti -fno-exceptions -Wno-volatile -std=c++1z") SET(CMAKE_EXE_LINKER_FLAGS "$CMAKE_COMMON_FLAGS -nostartfiles -Wl,-Map,\"$TARGET.map\" -nostartfiles -nolibc --specs=nosys.specs") message("CMAKE_C_FLAGS = " $CMAKE_C_FLAGS) message("CMAKE_CXX_FLAGS = " $CMAKE_CXX_FLAGS) message("CMAKE_EXE_LINKER_FLAGS = " $CMAKE_EXE_LINKER_FLAGS)
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.20) INCLUDE("CMake/arm-none-eabi.cmake") SET(CMAKE_C_STANDARD 11) SET(CMAKE_CXX_STANDARD 17) PROJECT(BLINKY VERSION 1.0.1 DESCRIPTION "Blinky Example") MESSAGE("Building " $PROJECT_NAME) FILE(GLOB_RECURSE LDSCRIPTS "ldscripts/*.ld" ) FOREACH(file $LDSCRIPTS) SET(CMAKE_LINKER_FLAGS "$CAMKE_LINKER_FLAGS -T \"$file\" ") MESSAGE("Linker is Running " $CMAKE_LINKER_FLAGS) ENDFOREACH() #Setup project headers INCLUDE_DIRECTORIES( "Core/" "Drivers/" ) #Setup porject sources FILE(GLOB_RECURSE APPLICATION_SOURCE "Application/*.c" "Application/*.cpp" "Application/*.s" "Core/*.c" "Core/*cpp" "Core/*.s" "Drivers/*.c" "Drivers/*.cpp" "Drivers/*.s" ) MESSAGE("CMake build directory" $CMAKE_BINARY_DIR) ADD_EXECUTABLE($TARGET.elf $APPLICATION_SOURCE) #ADD_CUSTOM_TARGET($TARGET.bin ALL DEPENDS $TARGET.elf COMMAND $CMAKE_OBJCOPY -O binary $TARGET.elf $TARGET.bin) #ADD_CUSTOM_TARGET($TARGET.hex ALL DEPENDS $TARGET.elf COMMAND $CMAKE_OBJCOPY -O ihex $TARGET.elf $TARGET.hex) ADD_CUSTOM_COMMAND(OUTPUT $TARGET.bin DEPENDS $TARGET.elf COMMAND $CMAKE_OBJCOPY -O binary $TARGET.elf $TARGET.bin) ADD_CUSTOM_COMMAND(OUTPUT $TARGET.hex DEPENDS $TARGET.elf COMMAND $CMAKE_OBJCOPY -O ihex $TARGET.elf $TARGET.hex) ADD_CUSTOM_TARGET($TARGET_bin DEPENDS $TARGET.bin) ADD_CUSTOM_TARGET($TARGET_hex DEPENDS $TARGET.hex) ADD_CUSTOM_TARGET(SIZE ALL $CMAKE_SIZE $TARGET.elf DEPENDS $TARGET.elf)
我知道这绝对不是编写启动文件的最佳方式。但重点是让它运行并改进以编写启动文件。
【问题讨论】:
你能提供你的 Makefile 吗?看起来您缺少标志--specs=nosys.specs --specs=nano.specs
提供了包含所有标志的工具链文件,我尝试使用以下标志 -nostartfiles -nolibc --specs=nosys.specs --specs=nano.specs -nostdlib 构建,它仍然不起作用。
请提供一个演示问题的最小示例(命令行优先于 makefile)
已经分享了 toolcahin faile 但这里是来自 ninja 构建文件的标志。 c FLAGS = -march=armv6-m -mcpu=cortex-m0 -mthumb -DSTM32F030x4 -Og -ggdb -Wall -Wextra -ffunction-sections -fdata-sections -ffreestanding -fno-builtin -nostdlib -fno-rtti -fno-异常 -Wno-volatile -std=c++1z -g LINK_FLAGS = -march=armv6-m -mcpu=cortex-m0 -mthumb -DSTM32F030x4 -Og -ggdb -Wall -Wextra -ffunction-sections -fdata-sections -ffreestanding -fno-builtin -nostdlib -nostartfiles -Wl,-Map,"STM32F030x4.map" -nostartfiles -nolibc --specs=nosys.specs --specs=nano.specs -nostdlib
向链接器请求地图文件。 Reset_Handler
列出了吗?是否列出了 _Reset_Handler
(带有前导下划线)?
【参考方案1】:
_start 是 Newlib C 库的一部分。您是否在链接器命令行上提供了它?
【讨论】:
我已经分享了我的链接器标志,请帮助我。我怎么能不给这些标志以上是关于为啥链接器无法识别我的链接器脚本中定义的入口点的主要内容,如果未能解决你的问题,请参考以下文章
链接器多重定义错误:为啥 <thread> 似乎定义了我的函数?
链接器无法链接我的应用程序(XXXX 已在 XXXX.obj 中定义)