为啥链接器无法识别我的链接器脚本中定义的入口点

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 中定义)

vs2005无法定位程序输入点怎么解决?

为啥我的 C++ 代码中出现链接器命令失败错误? [复制]

为啥在 Windows 上无法识别节点版本管理器 (NVM)?

为啥 STM32CubeIDE 有 2 个生成的链接器脚本?