Linker 使用malloc时创建的STM32大型二进制文件
已解决。请参阅下面的解决方案部分。 我遇到了一个问题,我的构建环境输出了一个大的二进制文件,我希望有人能帮助我重新开始 我正在使用STM32F105处理器、Eclipse、FreeRTOS和CodeSourcery编译器来尝试在这个设备上运行一些AHRS评估代码。我有很多代码在运行,但在实现eval代码中使用malloc分配内存的部分时遇到了问题。我不得不为sbrk添加一些代码来编译它,现在我的二进制代码从35K增加到了近400MB。我认为这是一个链接器问题,因为.out文件(在objcopy之前)的大小差不多。甚至从objdump输出的.s文件看起来也相当相似 以下是一些(希望如此)相关的细节:Linker 使用malloc时创建的STM32大型二进制文件,linker,arm,malloc,stm32,codesourcery,Linker,Arm,Malloc,Stm32,Codesourcery,已解决。请参阅下面的解决方案部分。 我遇到了一个问题,我的构建环境输出了一个大的二进制文件,我希望有人能帮助我重新开始 我正在使用STM32F105处理器、Eclipse、FreeRTOS和CodeSourcery编译器来尝试在这个设备上运行一些AHRS评估代码。我有很多代码在运行,但在实现eval代码中使用malloc分配内存的部分时遇到了问题。我不得不为sbrk添加一些代码来编译它,现在我的二进制代码从35K增加到了近400MB。我认为这是一个链接器问题,因为.out文件(在objcopy之
MEMORY
{
RAM (RWX) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 128K
}
_estack = ORIGIN(RAM)+LENGTH(RAM);
SECTIONS
{
.text ORIGIN(FLASH):
{
*(.isr_vector)
*(.text)
*(.text.*)
*(.rodata)
_sidata = .;
}
.data ORIGIN(RAM):
AT (_sidata)
{
_sdata = . ;
*(.data)
_edata = . ;
}
.bss (_edata) (NOLOAD):
{
_sbss = .;
*(.bss)
*(.bss.*)
*(COMMON)
_ebss = . ;
. = ALIGN(4);
_end = .;
}
}
/* end of allocated ram _end */
PROVIDE( _HEAP_START = _end );
/* end of the heap -> align 4 byte */
PROVIDE ( _HEAP_END = ALIGN(ORIGIN(RAM) + LENGTH(RAM) - 4 ,4) );
生成文件:
BOOT = boot
RTOS = FreeRTOSSource
FREERTOS = $(RTOS)/port.c $(RTOS)/tasks.c $(RTOS)/croutine.c $(RTOS)/heap_2.c $(RTOS)/list.c $(RTOS)/queue.c
APP_SOURCE = app_source/sysmon.c app_source/hscan.c app_source/gps.c app_source/mems.c app_source/gpio.c app_source/mainstates.c app_source/leds.c app_source/database.c
INEMO_LIB = inemo/mems/LSM303DLH.c inemo/mems/L3GD20.c
OBJS = main.o \
$(BOOT)/core_cm3.o \
$(BOOT)/system_stm32f10x.o \
$(BOOT)/stm32f10x_rcc.o \
$(BOOT)/stm32f10x_gpio.o \
$(BOOT)/stm32f10x_can.o \
$(BOOT)/stm32f10x_iwdg.o \
$(BOOT)/stm32f10x_i2c.o \
$(BOOT)/startup.o \
$(BOOT)/mx_gpio.o \
$(FREERTOS:%.c=%.o) \
$(INEMO_LIB:%.c=%.o) \
$(APP_SOURCE:%.c=%.o)
CFLAGS = -O0 -gdwarf-2 -mcpu=cortex-m3 -mthumb -fno-common -I$(BOOT) -std=gnu99 -c -mfloat-abi=soft -Wall -g
LFLAGS = -mthumb -mcpu=cortex-m3 -Tscripts/stm32f103.ld -nostartfiles -lgcc -lm -lc -mfloat-abi=soft -Wall -g -O0
CPFLAGS = -O binary
TARGET = arm-none-eabi
#TARGET = arm-elf
CC = $(TARGET)-gcc
LD = $(TARGET)-gcc
CP = $(TARGET)-objcopy
OD = $(TARGET)-objdump
all: version $(OBJS) link
$(BOOT)/startup.o:
$(CC) $(CFLAGS) $(BOOT)/startup_stm32f10x_cl.s -lm -lc -lnosys -o $@
%.o: %.c
$(CC) $(CFLAGS) $< -o $@
version:
$(CC) --version
link: $(OBJS)
$(LD) -o main.out $(OBJS) $(LFLAGS)
$(CP) $(CPFLAGS) main.out main.bin
$(OD) -D -h main.out > main.S
clean:
rm -rf $(OBJS) main.bin main.out main.S
新的完整链接器脚本如下所示:
MEMORY
{
RAM (RWX) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 128K
}
_estack = ORIGIN(RAM)+LENGTH(RAM);
SECTIONS
{
.text ORIGIN(FLASH):
{
*(.isr_vector)
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.str1.4)
_sidata = .;
}
.data ORIGIN(RAM):
AT (_sidata)
{
_sdata = . ;
*(.data)
_edata = . ;
}
.bss (_edata) (NOLOAD):
{
_sbss = .;
*(.bss)
*(.bss.*)
*(COMMON)
_ebss = . ;
. = ALIGN(4);
_end = .;
}
}
/* end of allocated ram _end */
PROVIDE( _HEAP_START = _end );
/* end of the heap -> align 4 byte */
PROVIDE ( _HEAP_END = ALIGN(ORIGIN(RAM) + LENGTH(RAM) - 4 ,4) );
谢谢你的帮助 看起来好像有什么东西以链接器脚本无法捕捉的方式插入到RAM部分中。您可以使用最后一个ELF上的
objdump
或类似工具来检查符号表,并检查任何可疑的内容,例如,使用此链接器脚本构建一些琐碎的代码可以提供:
$ arm-none-eabi-objdump -t a.out
a.out: file format elf32-littlearm
SYMBOL TABLE:
20000000 l d .note.gnu.build-id 00000000 .note.gnu.build-id
08000000 l d .text 00000000 .text
20000000 l d .data 00000000 .data
20000004 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test.c
00000000 l df *ABS* 00000000 sum.c
00000000 l df *ABS* 00000000
20000000 g O .data 00000004 j
080000c0 g .text 00000000 _sidata
20000004 g .bss 00000000 _sbss
08000038 g F .text 0000003c sum
20000000 g .data 00000000 _sdata
080000bc g O .text 00000004 k
20000008 g .bss 00000000 _ebss
20000004 g O .bss 00000004 i
08000000 g F .text 00000038 main
08000074 g F .text 00000048 sum2
20005000 g *ABS* 00000000 _estack
20000004 g .data 00000000 _edata
20000008 g .bss 00000000 _end
在本例中,有一些符号具有RAM地址,但在本例中,导致最终二进制文件膨胀到~400MB的是.note.gnu.build-id条目。检查章节标题可以揭示原因:
$ arm-none-eabi-objdump -h a.out
a.out: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 20000000 20000000 00030000 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 00000074 08000000 08000000 00010000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .data 00000004 20000000 08000074 00020000 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00000004 20000004 08000078 00020004 2**2
ALLOC
4 .comment 00000036 00000000 00000000 00030024 2**0
CONTENTS, READONLY
5 .ARM.attributes 00000033 00000000 00000000 0003005a 2**0
CONTENTS, READONLY
.data和.bss部分有RAM,但加载地址仍在闪存(LMA)中。另一方面,note部分也有一个RAM加载地址,因此将ELF转换为原始二进制文件会导致它位于图像中其他部分之后约400MB
从提供的额外细节来看,库函数似乎正在生成自己的.rodata部分,这些部分与脚本中的任何部分都不匹配,因此链接器的启发式方法会相当任意地分配这些部分。我会尝试将
*(.rodata.*)
添加到.text部分来捕捉这些内容。好主意。在构建过程之后,我查看了.s文件,没有看到任何类似的情况。源代码中附加变量的列表很小,介于“好”(正常大小的二进制)构建和“坏”(大二进制)构建之间。有没有什么简单的(非人类眼球依赖的)测试方法?真的,400MB?不是400KB?是的,400MB。相当大!我将*(.rodata.str1.4)
拼写为*(.rodata.*)
,以涵盖在维护代码时可能出现的任何其他令人惊讶的只读数据小节。我还想知道,对于类似的强化,在*(.data.*)
之后加入*(.data)
是否明智。但至少您知道,您的工具偶尔会生成需要在链接器脚本中说明的“有趣”命名部分。这是一个好主意!谢谢好的,我感觉有点紧张,但是你不想在.data(RAM)内存区域中使用j吗?在以前的工作构建中,我声明并定义了一个全局变量(单元的内部CAN地址),正如您在示例中所做的那样,该变量似乎放在了.data中。2000002c l O.数据00000001 NMEA_Source_AddressOops,抱歉,尽管重复了这个问题,但结果证明我的推理有点错误。链接器脚本足够聪明,可以处理一个可重定位的.data部分,但是其他的crud却漏掉了。哇,不是这样的,谢谢你在这方面的帮助。我无法告诉你我有多感激你。我已将源代码中的问题隔离到一个对sqrt的调用中。如果我将其注释掉,那么二进制文件将以正常大小构建。如果我把它放回去,二进制文件会变得非常大。我确信你所说的正在发生,因为我更改了链接器脚本中的地址,并且构建的二进制大小也发生了变化,所以有些东西正在跨越RAM和FLASH。在一个“坏”版本中,会出现一个名为.rodata.str1.4的新部分。看起来这会影响到RAM。我想我开始理解你的评论了。我不明白的是该部分是如何创建的(因为链接器脚本中不存在该名称)以及如何修复它。干得好-可能值得为子孙后代添加这些细节。我认为您缺少的是编译器/汇编器创建输入部分,而链接器将它们排列成输出部分。如果链接器脚本没有指定将特定输入节放置在何处,它或多或少会被推到任何可以工作的地方(请参阅我链接到的文档;不,我也不太理解它;)
$ arm-none-eabi-objdump -t a.out
a.out: file format elf32-littlearm
SYMBOL TABLE:
20000000 l d .note.gnu.build-id 00000000 .note.gnu.build-id
08000000 l d .text 00000000 .text
20000000 l d .data 00000000 .data
20000004 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test.c
00000000 l df *ABS* 00000000 sum.c
00000000 l df *ABS* 00000000
20000000 g O .data 00000004 j
080000c0 g .text 00000000 _sidata
20000004 g .bss 00000000 _sbss
08000038 g F .text 0000003c sum
20000000 g .data 00000000 _sdata
080000bc g O .text 00000004 k
20000008 g .bss 00000000 _ebss
20000004 g O .bss 00000004 i
08000000 g F .text 00000038 main
08000074 g F .text 00000048 sum2
20005000 g *ABS* 00000000 _estack
20000004 g .data 00000000 _edata
20000008 g .bss 00000000 _end
$ arm-none-eabi-objdump -h a.out
a.out: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 20000000 20000000 00030000 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 00000074 08000000 08000000 00010000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .data 00000004 20000000 08000074 00020000 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00000004 20000004 08000078 00020004 2**2
ALLOC
4 .comment 00000036 00000000 00000000 00030024 2**0
CONTENTS, READONLY
5 .ARM.attributes 00000033 00000000 00000000 0003005a 2**0
CONTENTS, READONLY