使用sprintf()时链接错误

时间:2014-08-12 07:57:16

标签: linker printf linker-scripts

在我的cortex-m3上,我试图将一个浮点变量输出到我的UART端口..所以我需要将float DATA转换为char outputstr[]

为此,我使用了libc.a中的sprintf

  1. 如果我注释掉sprintf(),我可以编译和链接。
  2. 如果我使用sprintf(outputstr, "t"),我可以编译和链接。
  3. 如果我使用sprintf(outputstr, "The value is %f", DATA),我将得到以下链接错误:没有为可加载部分指定内存区域`.rodata',' .bss',' .text&# 39;,' .data'
  4. 但是我已经在我的链接器脚本中添加了*(。rodata),*(。bss)等...如下所示:

    ...
    OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
    OUTPUT_ARCH(arm)
    ENTRY(reset_handler)
    
    MEMORY {
       ROM : ORIGIN = 0x08000000, LENGTH = 128K
       RAM : ORIGIN = 0x20000000, LENGTH = 16K
    }
    
    SECTIONS {
    
        .ROMdata 0x8000000: AT(0x8000000){
        startup.o(.romvect)
        . = ALIGN(0x4);
        system_stm32l1xx.o(.rodata*)
        *(.rodata*)
        _ROMdataend_ = ALIGN(0x4);
        }
    
        .ROMstartup (_ROMdataend_): AT(_ROMdataend_){
        startup.o(.startup)
        lowlevelinit.o(.lowlevelinit .tempexchandler)
        system_stm32l1xx.o(.text*)
        . = ALIGN(0x4);
        }
    
        .RAMbss 0x20000000 (NOLOAD):{
    
        lowlevelinit.o(.ramvectortable)
        . = ALIGN(0x4);
        _RAMbssstart_ = .;
        startup.o(.stack .heap)
        . = ALIGN(0x4);
        sensor_MTH01.o(.bss*)
        . = ALIGN(0x4);
        comm_BT-HC-05.o(.bss)
        tim6.o(.bss)
        main.o(.bss)
        system_stm32l1xx.o(.bss*)
        *(.bss*)
        _RAMbssend_ = ALIGN(0x4);
        }
    
        .RAMcode (_RAMbssend_): AT(LOADADDR(.ROMstartup)+SIZEOF(.ROMstartup)){
        _RAMcodeVMAstart_ = .;
        _RAMcodeLMAstart_ = LOADADDR(.RAMcode);
        main.o(.ramcode .text)
        tim6.o(.tim6isr)
        tim6.o(.text)
        sensor_MTH01.o(.text)
        comm_BT-HC-05.o(.text)
        exti0_isr.o(.exti0isr)
        *(.text*)
        KEEP (*(.eh_*))
        _RAMcodeVMAend_ = ALIGN(0x4);
        }
    
        .RAMdata (_RAMcodeVMAend_): AT(LOADADDR(.RAMcode)+SIZEOF(.RAMcode)){
        _RAMcodeLMAend_ = (LOADADDR(.RAMcode)+SIZEOF(.RAMcode));
        _RAMdataVMAstart_ = .;
        _RAMdataLMAstart_ = LOADADDR(.RAMdata);
        sensor_MTH01.o(.data)
        system_stm32l1xx.o(.data*)
        *(.data*)
        _RAMdataVMAend_ = ALIGN(0x4);
        _RAMdataLMAend_ = LOADADDR(.RAMdata) + SIZEOF(.RAMdata);
        }
    
    
    }
    ...
    

    另外,我确实包含了lib路径并在makefile中包含路径,如下所示:

    另一方面,我也在使用libc.a和libgcc.a中的strlen()other float division operations,这些函数可以编译,链接并正常工作。

        ...
        CC = arm-none-eabi-gcc
        AS = arm-none-eabi-as
        LD = arm-none-eabi-ld
        OBJCPY = arm-none-eabi-objcopy
    
        CCFLAGS = -c -mcpu=cortex-m3 -mthumb -O0 -g -Wall
        ASMFLAGS = -mcpu=cortex-m3 -mthumb --gdwarf-2
        LDFLAGS = -T CortexM3.ld -M=memmap.map
        OBJCPYFLAGS = -O ihex
        FLOATFLAGS = -mfloat-abi=soft -mfpu=vfp
        LIBDIR = -L C:\\yagarto-20121222\\lib\\gcc\\arm-none-eabi\\4.7.2\\thumb\\v7m -L C:\\yagarto-20121222\\arm-none-eabi\\lib\\thumb\\v7m
        INCDIR = -I C:\\yagarto-20121222\\lib\\gcc\\arm-none-eabi\\4.7.2\\include -I C:\\yagarto-20121222\\arm-none-eabi\\include
    
        all: m3.elf
        m3.elf: startup.o lowlevelinit.o system_stm32l1xx.o main.o tim6.o exti0_isr.o sensor_MTH01.o comm_BT-HC-05.o
            $(LD) $(LDFLAGS) $(LIBDIR) $^ -lc -lgcc -o $@
            $(OBJCPY) $(OBJCPYFLAGS) m3.elf m3.hex
        startup.o: startup.s
        lowlevelinit.o: lowlevelinit.c system_stm32l1xx.h stm32l1xx.h core_cm3.h
        system_stm32l1xx.o: system_stm32l1xx.c stm32l1xx.h core_cm3.h system_stm32l1xx.h
        main.o: main.c stm32l1xx.h
        tim6.o: tim6.c
        exti0_isr.o: exti0_isr.c
        sensor_MTH01.o: sensor_MTH01.c
        comm_BT-HC-05.o: comm_BT-HC-05.c
    
        clean:
            -rm -f startup.o lowlevelinit.o system_stm32l1xx.o main.o tim6.o tim6_isr.o exti0_isr.o sensor_MTH01.o comm_BT-HC-05.o memmap.map m3.elf m3.hex
    
        %.o: %.s
            $(AS) $(ASMFLAGS) $< -o $@
        %.o: %.c
            $(CC) $(CCFLAGS) $(INCDIR) $(FLOATFLAGS) $< -o $@
    
    
        .PHONY: all clean 
        ...
    
    1. 有人可以提供建议吗?

    2. 另外,如果我遇到链接错误消息,例如:没有为可加载部分指定内存区域`.rodata&#39; ...我怎么知道哪个对象(.o).rodata部分被遗忘的链接器脚本?


    3. 更新: 我意识到如果在main()中调用sprintf()函数,程序可以成功编译和链接..但是如果我在其他函数中调用sprintf()函数,我将得到上面的链接错误(没有指定的内存区域)可加载的部分.bss),即使我使用*(。bss)作为输出部分的输入部分。

1 个答案:

答案 0 :(得分:0)

要解决链接错误('没有为可加载部分.bss等指定的内存区域',我必须在BSS输出部分添加*(COMMON)