【GCC编译优化系列】前后编译的两个版本固件bin大小不一样,怎么办?

【GCC编译优化系列】前后编译的两个版本固件bin大小不一样,怎么办?

摘要:这两天在论坛收到一个朋友的问题回答邀请,我仔细读了下该问题,跟我之前在论坛上发布的好几个问题关联还挺大的,所以抽空带着这个问题,重新梳理下思路,也希望这些思路能帮到这位朋友尽快解决问题。

文章目录

  • 1、问题描述
  • 2、排查思路
  • 3、如何获取预编译文件、汇编文件等中间文件?
  • 4、object文件如何对比?
  • 5、关于链接顺序对elf文件的影响
  • 6、还有什么其他的东西可以辅助分析?
  • 7、总结
  • 8、更多分享

1、问题描述

这两天在论坛收到一个朋友的问题回答邀请,我仔细读了下该问题,跟我之前在论坛上发布的好几个问题关联还挺大的,所以抽空带着这个问题,重新梳理下思路,也希望这些思路能帮到这位朋友尽快解决问题。

它的问题描述如下,感兴趣的可以参考原文链接:RT-Thread4.1.0工程用scons连续编译生成的map文件差异很大

【GCC编译优化系列】前后编译的两个版本固件bin大小不一样,怎么办?

2、排查思路

我之前也遇到类似的工程编译出来的bin文件变大的一个问题:【GCC编译优化系列】从KEIL转战GCC,一个C库函数bin文件增大了十几KB

不过稍微不同的是,我之前的那个问题是编译器与自带的系统库(C库)的差异引入的,但这其中的排查思路倒是可以参考借鉴。

我先总结一下我的思路,参考如下:

  1. 既然是编译出来的bin固件大小不一,那我们需要抓一下生成固件bin的流程中,究竟是哪一个环节引入的变化?
  2. 笼统地说【编译】,其实有4个子环节:我在 【GCC编译优化系列】一文带你了解C代码到底是如何被编译的? 这篇文章中有介绍,主要分为 预编译、编译、汇编、链接
  3. 我们说两份一模一样的代码,理论上应该对比 预编译处理之后的代码,因为这个环节之后的代码,是没得变了,那些什么 __FILE__ __DATE__ __TIME__ 等等各种宏定义已经完全被展开了,下一步就直接送到 编译器 去执行编译,得到 汇编代码
  4. 上边对比预编译之后的代码,大概就能看出两次编译的代码,有哪些不同了;下一步,如果感兴趣,可以同样去对比下两份代码 生成的汇编代码,但是我不建议直接走这一步,因为难度会比较大,建议先往下走,到最后真的无路可走了,再回来这一步对比;
  5. 跳过对比 汇编代码,我们直接对比汇编代码之后的生成文件,叫 object文件 ,这类文件基本就已经把各个C文件的函数给捆起来了,我们是可以通过 linux 下的命令行工具 size 来查看的,类似会有这样的输出:
size build/kernel/src/memheap.o
   text    data     bss     dec     hex filename
   6730       0       0    6730    1a4a build/kernel/src/memheap.o

​ 我们需要对比每一个object文件的size,找出有差异的那些object文件。

  1. 最后一步,把所有的object文件执行链接(注意:obj的链接顺序也有可能会引起elf文件的变化,后面细讲),才是得到编译输出的固件文件,其实这里说的固件文件常见的分为3种:elf文件、hex文件、bin文件,其中elf文件是最原始的输出文件,而后面的hex文件、bin文件都可以由elf文件导出生成。这里顺便提一句,单单对比bin文件的大小,意义不是很大,如果仅仅是相差几个字节或者十几字节,我觉得是正常;真正我们需要比较的是 elf文件的 大小,这个大小不是说它占磁盘的大小,而是使用 size 命令查出来的大小,类似这样:

    size rtthread.elf 
       text    data     bss     dec     hex filename
     557886    2100   87160  647146   9dfea rtthread.elf
    

​ 这里还有说明一下,如果前后的elf文件差异几个字节这种,很有可能是某些内存地址对齐导致的,4个字节或8个字节这样的差异。

  1. 总结一下,排查顺序:预编译后的代码文件 -》汇编代码文件(可暂时跳过)-》object文件 -> elf 文件 -> bin文件。主要采用的是对比法,至于如何对比这些文件,见下文分解。

3、如何获取预编译文件、汇编文件等中间文件?

env 开发环境为例(如果是以 RT-Thread Studio 为开发环境的,自行查找相关方法),bsp选用 qemu-vexpress-a9 作为参考:

rtthread.py 中的 CFLAGS 和 AFLAGS 添加 -save-temps=obj 如下所示:

    CFLAGS = DEVICE + ' -Wall -Werror -save-temps=obj'
    AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ -I. -save-temps=obj'

重新clean,再编译,就可以看到build目录下,有 .i文件(预编译后的文件)和.s文件(汇编文件) 生成了。

前后编译的两个版本,把这些.i文件文件拎出来对比,即可。


4、object文件如何对比?

考虑在env开发环境下使用 find 命令并不好使,我特意写了一个python脚本,用于批量查询object文件的size:

只需要在rtthread.py的最后加上这个python脚本的调用:

    POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.binn' +
                  SIZE + ' $TARGET n ' + 
                  'python size.py build ' + SIZE + 'n' 

size.py 脚本的内容如下:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import os
import sys
import shutil

file_type_list = ['o']

def get_all_object_file_size(size_cmd, folder):
    filelist = [] 
    for dirpath,dirnames,filenames in os.walk(folder):
        for file in filenames:
            file_type = file.split('.')[-1]
            if(file_type in file_type_list):
                file_fullname = os.path.join(dirpath, file)
                file_fullname = file_fullname[2:]
                filelist.append(file_fullname)

    system_cmd = size_cmd + ' '
	
    for file in filelist:
    	system_cmd = system_cmd + file + ' '

    print(system_cmd)
    os.system(system_cmd)

if(__name__=="__main__"):	
    find_path = sys.argv[1]
    size_cmd = sys.argv[2]
    os.chdir(find_path)
    get_all_object_file_size(size_cmd, '.')

保存一下这个脚本文件,存放在与rtthread.py同级的目录下。

直接执行scons编译,编译完后,就会把所有object文件的size打出来:

【GCC编译优化系列】前后编译的两个版本固件bin大小不一样,怎么办?

抓取前后两次的大小对比,即可大致知道哪几个 C文件 编译出来的size变了。

其实,如果是在Linux下的开发环境,就不需要python脚本的协助了,直接命令行就能搞定。

find ./build -name "*.o" | xargs size

5、关于链接顺序对elf文件的影响

我之前有写过一篇因链接顺序引入的问题,可以参考下:【GCC编译优化系列】另类的链接报错undefined reference to

虽然我的案例中,讲述的是 undefin reference to 问题,但本质也是跟 链接有关,这里也提到了obj的链接顺序的问题。

回到本案例的问题,既然 怀疑是链接顺序不一样,导致最后链接处理的elf文件大小不一样,那些我们需要找到证据来支撑,两次链接的顺序真的不一样吗?

可以这样去对比分析。

在env开发环境下,scons编译是支持 VERBOSE 输出,我们利用VERBOSE输出就可以知道最后的链接顺序是怎么样的。

在env中执行,scons –verbose 代替 scons:

> scons --verbose
scons: Reading SConscript files ...
Newlib version:2.4.0
scons: done reading SConscript files.
scons: Building targets ...
scons: building associated VariantDir targets: build
arm-none-eabi-g++ -o rtthread.elf -march=armv7-a -marm -msoft-float -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds build0mem_leak_debugmem_leak_debug.o build0mem_leak_debugmem_heap_hook.o buildapplicationsmain.o buildapplicationsmnt.o buildapplicationslcd_init.o builddriversdrv_timer.o builddriversboard.o builddriversdrv_smc911x.o builddriverssecondary_cpu.o builddriversdrv_mouse.o builddriversdrv_sdio.o builddriversserial.o builddriversdrv_keyboard.o buildkernelsrcirq.o buildkernelsrcmem.o buildkernelsrckservice.o buildkernelsrcthread.o buildkernelsrcslab.o buildkernelsrcclock.o buildkernelsrccpu.o buildkernelsrcscheduler.o buildkernelsrcdevice.o buildkernelsrctimer.o buildkernelsrcipc.o buildkernelsrcobject.o buildkernelsrcidle.o buildkernelsrccomponents.o buildkernelsrcmemheap.o buildkernelsrcsignal.o buildkernelsrcmempool.o buildkernellibcpuarmcommonbacktrace.o buildkernellibcpuarmcommondiv0.o buildkernellibcpuarmcommonshowmem.o buildkernellibcpuarmcortex-avector_gcc.o buildkernellibcpuarmcortex-acp15_gcc.o buildkernellibcpuarmcortex-agic.o buildkernellibcpuarmcortex-acache.o buildkernellibcpuarmcortex-ammu.o buildkernellibcpuarmcortex-acontext_gcc.o buildkernellibcpuarmcortex-atrap.o buildkernellibcpuarmcortex-astart_gcc.o buildkernellibcpuarmcortex-astack.o buildkernellibcpuarmcortex-acpu.o buildkernellibcpuarmcortex-ainterrupt.o buildkernelcomponentsdfssrcdfs_posix.o buildkernelcomponentsdfssrcdfs_fs.o buildkernelcomponentsdfssrcdfs.o buildkernelcomponentsdfssrcdfs_file.o buildkernelcomponentsdfsfilesystemsdevfsdevfs.o buildkernelcomponentsdfsfilesystemselmfatdfs_elm.o buildkernelcomponentsdfsfilesystemselmfatff.o buildkernelcomponentsdfsfilesystemselmfatffunicode.o buildkernelcomponentsdfsfilesystemsramfsdfs_ramfs.o buildkernelcomponentsdfsfilesystemsromfsromfs.o buildkernelcomponentsdfsfilesystemsromfsdfs_romfs.o buildkernelcomponentsfinshshell.o buildkernelcomponentsfinshmsh.o buildkernelcomponentsfinshmsh_parse.o buildkernelcomponentsfinshcmd.o buildkernelcomponentsfinshmsh_file.o buildkernelcomponentslibccompilerscommoncstdio.o buildkernelcomponentslibccompilerscommonctime.o buildkernelcomponentslibccompilerscommoncctype.o buildkernelcomponentslibccompilerscommoncstring.o buildkernelcomponentslibccompilerscommoncstdlib.o buildkernelcomponentslibccompilerscommoncwchar.o buildkernelcomponentslibccompilersnewlibsyscalls.o buildkernelcomponentslibccpluspluscxx_crt_init.o buildkernelcomponentslibccpluspluscxx_Semaphore.o buildkernelcomponentslibccpluspluscxx_crt.o buildkernelcomponentslibccpluspluscxx_Mutex.o buildkernelcomponentslibccpluspluscxx_Thread.o buildkernelcomponentslibcposixdelaydelay.o buildkernelcomponentslibcposixioaioaio.o buildkernelcomponentslibcposixiopollselect.o buildkernelcomponentslibcposixiopollpoll.o buildkernelcomponentslibcposixiostdiolibc.o buildkernelcomponentslibcposixiotermiostermios.o buildkernelcomponentslibcposixipcmqueue.o buildkernelcomponentslibcposixipcsemaphore.o buildkernelcomponentslibcposixpthreadspthread_cond.o buildkernelcomponentslibcposixpthreadspthread_spin.o buildkernelcomponentslibcposixpthreadspthread_attr.o buildkernelcomponentslibcposixpthreadspthread_rwlock.o buildkernelcomponentslibcposixpthreadspthread_mutex.o buildkernelcomponentslibcposixpthreadspthread.o buildkernelcomponentslibcposixpthreadspthread_barrier.o buildkernelcomponentslibcposixpthreadspthread_tls.o buildkernelcomponentslibcposixpthreadssched.o buildkernelcomponentslibcposixsignalposix_signal.o buildkernelcomponentslwparcharmcortex-alwp_gcc.o buildkernelcomponentslwplwp_memheap.o buildkernelcomponentslwplwp_mem.o buildkernelcomponentslwplwp_syscall.o buildkernelcomponentslwplwp.o buildkernelcomponentsnetlwiplwip-2.0.3srcapinetdb.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreip.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4autoip.o buildkernelcomponentsnetlwiplwip-2.0.3srcnetifethernet.o buildkernelcomponentsnetlwiplwip-2.0.3srccorenetif.o buildkernelcomponentsnetlwiplwip-2.0.3srccoresys.o buildkernelcomponentsnetlwiplwip-2.0.3srcapisockets.o buildkernelcomponentsnetlwiplwip-2.0.3srcapinetifapi.o buildkernelcomponentsnetlwiplwip-2.0.3srcapitcpip.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4ip4_addr.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4dhcp.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreinit.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4etharp.o buildkernelcomponentsnetlwiplwip-2.0.3srccorememp.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4ip4.o buildkernelcomponentsnetlwiplwip-2.0.3srcapinetbuf.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreraw.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4ip4_frag.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretcp_out.o buildkernelcomponentsnetlwiplwip-2.0.3srcnetiflowpan6.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4icmp.o buildkernelcomponentsnetlwiplwip-2.0.3srcapiapi_lib.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreinet_chksum.o buildkernelcomponentsnetlwiplwip-2.0.3srccorestats.o buildkernelcomponentsnetlwiplwip-2.0.3srcapierr.o buildkernelcomponentsnetlwiplwip-2.0.3srcappspingping.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretcp_in.o buildkernelcomponentsnetlwiplwip-2.0.3srccoredns.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretimeouts.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4igmp.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreudp.o buildkernelcomponentsnetlwiplwip-2.0.3srccorepbuf.o buildkernelcomponentsnetlwiplwip-2.0.3srccoredef.o buildkernelcomponentsnetlwiplwip-2.0.3srcapiapi_msg.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretcp.o buildkernelcomponentsnetlwipportethernetif.o buildkernelcomponentsnetlwipportsys_arch.o buildkernelcomponentsnetnetdevsrcnetdev_ipaddr.o buildkernelcomponentsnetnetdevsrcnetdev.o buildkernelcomponentsnetsaldfs_netdfs_net.o buildkernelcomponentsnetsalsocketnet_sockets.o buildkernelcomponentsnetsalsrcsal_socket.o buildkernelcomponentsnetsalsocketnet_netdb.o buildkernelcomponentsnetsalimplaf_inet_lwip.o buildkernelcomponentsdriversi2ci2c-bit-ops.o buildkernelcomponentsdriversi2ci2c_core.o buildkernelcomponentsdriversi2ci2c_dev.o buildkernelcomponentsdriversipccompletion.o buildkernelcomponentsdriversipcdataqueue.o buildkernelcomponentsdriversipcpipe.o buildkernelcomponentsdriversipcringblk_buf.o buildkernelcomponentsdriversipcringbuffer.o buildkernelcomponentsdriversipcwaitqueue.o buildkernelcomponentsdriversipcworkqueue.o buildkernelcomponentsdriversmiscpin.o buildkernelcomponentsdriversmtdmtd_nand.o buildkernelcomponentsdriversmtdmtd_nor.o buildkernelcomponentsdriversrtcrtc.o buildkernelcomponentsdriversrtcsoft_rtc.o buildkernelcomponentsdriverssdioblock_dev.o buildkernelcomponentsdriverssdiommc.o buildkernelcomponentsdriverssdiommcsd_core.o buildkernelcomponentsdriverssdiosd.o buildkernelcomponentsdriverssdiosdio.o buildkernelcomponentsdriversserialserial.o buildkernelcomponentsdriversspisfudsrcsfud.o buildkernelcomponentsdriversspisfudsrcsfud_sfdp.o buildkernelcomponentsdriversspispi_core.o buildkernelcomponentsdriversspispi_dev.o buildkernelcomponentsdriversspispi_flash_sfud.o buildkernelcomponentsdriversspispi_msd.o buildkernelcomponentsdriverswatchdogwatchdog.o -lc -lm
arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin
arm-none-eabi-size rtthread.elf
   text    data     bss     dec     hex filename
 588296    2144  189636  780076   be72c rtthread.elf

从输出中,就可以知道各个object文件的链接顺序,抓取前后两次的编译(第二次编译 需要 scons -c 清除一下),这样一对比就可以知道两次编译的obj链接顺序了。

不过,我猜测,很大可能 链接顺序是一样的

如果真的发现前后两次的链接顺序不一样,而且第一次的能工作,第二次的不能工作,我就想把链接顺序永远使用第一次那个顺序,该怎么办?

其实说来也简单,没有什么是一个脚本解决不了的

env开发环境下是支持 BAT脚本的,只需要把上面的 scons的VERBOSE输出的最后那几句(链接elf、导出bin文件、查看size)命令填到BAT脚本(新建一个bat后缀的脚本文件)中,然后在rtthread.py中新增这个BAT脚本的执行即可。

relink.bat 内容如下,仅供参考,需要跟进实际情况修改:

arm-none-eabi-g++ -o rtthread.elf -march=armv7-a -marm -msoft-float -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds build0mem_leak_debugmem_leak_debug.o build0mem_leak_debugmem_heap_hook.o buildapplicationsmain.o buildapplicationsmnt.o buildapplicationslcd_init.o builddriversdrv_timer.o builddriversboard.o builddriversdrv_smc911x.o builddriverssecondary_cpu.o builddriversdrv_mouse.o builddriversdrv_sdio.o builddriversserial.o builddriversdrv_keyboard.o buildkernelsrcirq.o buildkernelsrcmem.o buildkernelsrckservice.o buildkernelsrcthread.o buildkernelsrcslab.o buildkernelsrcclock.o buildkernelsrccpu.o buildkernelsrcscheduler.o buildkernelsrcdevice.o buildkernelsrctimer.o buildkernelsrcipc.o buildkernelsrcobject.o buildkernelsrcidle.o buildkernelsrccomponents.o buildkernelsrcmemheap.o buildkernelsrcsignal.o buildkernelsrcmempool.o buildkernellibcpuarmcommonbacktrace.o buildkernellibcpuarmcommondiv0.o buildkernellibcpuarmcommonshowmem.o buildkernellibcpuarmcortex-avector_gcc.o buildkernellibcpuarmcortex-acp15_gcc.o buildkernellibcpuarmcortex-agic.o buildkernellibcpuarmcortex-acache.o buildkernellibcpuarmcortex-ammu.o buildkernellibcpuarmcortex-acontext_gcc.o buildkernellibcpuarmcortex-atrap.o buildkernellibcpuarmcortex-astart_gcc.o buildkernellibcpuarmcortex-astack.o buildkernellibcpuarmcortex-acpu.o buildkernellibcpuarmcortex-ainterrupt.o buildkernelcomponentsdfssrcdfs_posix.o buildkernelcomponentsdfssrcdfs_fs.o buildkernelcomponentsdfssrcdfs.o buildkernelcomponentsdfssrcdfs_file.o buildkernelcomponentsdfsfilesystemsdevfsdevfs.o buildkernelcomponentsdfsfilesystemselmfatdfs_elm.o buildkernelcomponentsdfsfilesystemselmfatff.o buildkernelcomponentsdfsfilesystemselmfatffunicode.o buildkernelcomponentsdfsfilesystemsramfsdfs_ramfs.o buildkernelcomponentsdfsfilesystemsromfsromfs.o buildkernelcomponentsdfsfilesystemsromfsdfs_romfs.o buildkernelcomponentsfinshshell.o buildkernelcomponentsfinshmsh.o buildkernelcomponentsfinshmsh_parse.o buildkernelcomponentsfinshcmd.o buildkernelcomponentsfinshmsh_file.o buildkernelcomponentslibccompilerscommoncstdio.o buildkernelcomponentslibccompilerscommonctime.o buildkernelcomponentslibccompilerscommoncctype.o buildkernelcomponentslibccompilerscommoncstring.o buildkernelcomponentslibccompilerscommoncstdlib.o buildkernelcomponentslibccompilerscommoncwchar.o buildkernelcomponentslibccompilersnewlibsyscalls.o buildkernelcomponentslibccpluspluscxx_crt_init.o buildkernelcomponentslibccpluspluscxx_Semaphore.o buildkernelcomponentslibccpluspluscxx_crt.o buildkernelcomponentslibccpluspluscxx_Mutex.o buildkernelcomponentslibccpluspluscxx_Thread.o buildkernelcomponentslibcposixdelaydelay.o buildkernelcomponentslibcposixioaioaio.o buildkernelcomponentslibcposixiopollselect.o buildkernelcomponentslibcposixiopollpoll.o buildkernelcomponentslibcposixiostdiolibc.o buildkernelcomponentslibcposixiotermiostermios.o buildkernelcomponentslibcposixipcmqueue.o buildkernelcomponentslibcposixipcsemaphore.o buildkernelcomponentslibcposixpthreadspthread_cond.o buildkernelcomponentslibcposixpthreadspthread_spin.o buildkernelcomponentslibcposixpthreadspthread_attr.o buildkernelcomponentslibcposixpthreadspthread_rwlock.o buildkernelcomponentslibcposixpthreadspthread_mutex.o buildkernelcomponentslibcposixpthreadspthread.o buildkernelcomponentslibcposixpthreadspthread_barrier.o buildkernelcomponentslibcposixpthreadspthread_tls.o buildkernelcomponentslibcposixpthreadssched.o buildkernelcomponentslibcposixsignalposix_signal.o buildkernelcomponentslwparcharmcortex-alwp_gcc.o buildkernelcomponentslwplwp_memheap.o buildkernelcomponentslwplwp_mem.o buildkernelcomponentslwplwp_syscall.o buildkernelcomponentslwplwp.o buildkernelcomponentsnetlwiplwip-2.0.3srcapinetdb.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreip.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4autoip.o buildkernelcomponentsnetlwiplwip-2.0.3srcnetifethernet.o buildkernelcomponentsnetlwiplwip-2.0.3srccorenetif.o buildkernelcomponentsnetlwiplwip-2.0.3srccoresys.o buildkernelcomponentsnetlwiplwip-2.0.3srcapisockets.o buildkernelcomponentsnetlwiplwip-2.0.3srcapinetifapi.o buildkernelcomponentsnetlwiplwip-2.0.3srcapitcpip.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4ip4_addr.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4dhcp.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreinit.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4etharp.o buildkernelcomponentsnetlwiplwip-2.0.3srccorememp.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4ip4.o buildkernelcomponentsnetlwiplwip-2.0.3srcapinetbuf.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreraw.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4ip4_frag.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretcp_out.o buildkernelcomponentsnetlwiplwip-2.0.3srcnetiflowpan6.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4icmp.o buildkernelcomponentsnetlwiplwip-2.0.3srcapiapi_lib.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreinet_chksum.o buildkernelcomponentsnetlwiplwip-2.0.3srccorestats.o buildkernelcomponentsnetlwiplwip-2.0.3srcapierr.o buildkernelcomponentsnetlwiplwip-2.0.3srcappspingping.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretcp_in.o buildkernelcomponentsnetlwiplwip-2.0.3srccoredns.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretimeouts.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreipv4igmp.o buildkernelcomponentsnetlwiplwip-2.0.3srccoreudp.o buildkernelcomponentsnetlwiplwip-2.0.3srccorepbuf.o buildkernelcomponentsnetlwiplwip-2.0.3srccoredef.o buildkernelcomponentsnetlwiplwip-2.0.3srcapiapi_msg.o buildkernelcomponentsnetlwiplwip-2.0.3srccoretcp.o buildkernelcomponentsnetlwipportethernetif.o buildkernelcomponentsnetlwipportsys_arch.o buildkernelcomponentsnetnetdevsrcnetdev_ipaddr.o buildkernelcomponentsnetnetdevsrcnetdev.o buildkernelcomponentsnetsaldfs_netdfs_net.o buildkernelcomponentsnetsalsocketnet_sockets.o buildkernelcomponentsnetsalsrcsal_socket.o buildkernelcomponentsnetsalsocketnet_netdb.o buildkernelcomponentsnetsalimplaf_inet_lwip.o buildkernelcomponentsdriversi2ci2c-bit-ops.o buildkernelcomponentsdriversi2ci2c_core.o buildkernelcomponentsdriversi2ci2c_dev.o buildkernelcomponentsdriversipccompletion.o buildkernelcomponentsdriversipcdataqueue.o buildkernelcomponentsdriversipcpipe.o buildkernelcomponentsdriversipcringblk_buf.o buildkernelcomponentsdriversipcringbuffer.o buildkernelcomponentsdriversipcwaitqueue.o buildkernelcomponentsdriversipcworkqueue.o buildkernelcomponentsdriversmiscpin.o buildkernelcomponentsdriversmtdmtd_nand.o buildkernelcomponentsdriversmtdmtd_nor.o buildkernelcomponentsdriversrtcrtc.o buildkernelcomponentsdriversrtcsoft_rtc.o buildkernelcomponentsdriverssdioblock_dev.o buildkernelcomponentsdriverssdiommc.o buildkernelcomponentsdriverssdiommcsd_core.o buildkernelcomponentsdriverssdiosd.o buildkernelcomponentsdriverssdiosdio.o buildkernelcomponentsdriversserialserial.o buildkernelcomponentsdriversspisfudsrcsfud.o buildkernelcomponentsdriversspisfudsrcsfud_sfdp.o buildkernelcomponentsdriversspispi_core.o buildkernelcomponentsdriversspispi_dev.o buildkernelcomponentsdriversspispi_flash_sfud.o buildkernelcomponentsdriversspispi_msd.o buildkernelcomponentsdriverswatchdogwatchdog.o -lc -lm
arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin
arm-none-eabi-size rtthread.elf

rtthread.py的修改如下:

    POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.binn' +
                  SIZE + ' $TARGET n ' + 
                  'python size.py build ' + SIZE + 'n' +
                  'relink.bat n' 

这里其实就是,后面一次链接会覆盖前一次链接的结果,达到多次编译都是同一个链接顺序。


6、还有什么其他的东西可以辅助分析?

涉及编译、内存变化这类问题,我们不得漏掉还有一个文件也非常重要,那就是 MAP文件

其实,如果前后两次编译生成的elf文件大小不一,在MAP文件中就可以看得出来:

可能类似这样,两个map文件是一样的:

【GCC编译优化系列】前后编译的两个版本固件bin大小不一样,怎么办?

也有可能类似这样,存在差异:

【GCC编译优化系列】前后编译的两个版本固件bin大小不一样,怎么办?

需要注意的是,比较MAP文件的时候,一定要学会 抓大放小,不能太抠细节,有些差异是可以忽略的。

通过MAP文件的差异,也能得出一些线索,再回过头来找代码。

另一个方面,如果整个工程中,链接了一些 第三方库或者原厂的SDK库文件,这部分虽然在我们的代码中是看不到的,但是最终会链接进我们的固件,也有可能会产生固件的不一样,这个就要具体问题具体分析了。

至于有没有链接第三方库,从scons的VERBOSE输出就可以知道,找到那些 -l 开头的,就是库名称。


7、总结

  • 排查问题,需要保持清晰的思路,层层突破
  • 拆解问题的能力,很关键,逐步缩小问题的范围,方可快速出击
  • 不同固件导致运行结果不一样这类问题,可能有多个方面引起的:代码写得不规范、编译不严谨或者优化等级太高、链接问题这几个环境都可能引入,需要做的是找到根源;
  • 链接了第三方库或原厂SDK库,也不得不考虑它的引入问题;毕竟它们都是闭源的,出问题也不容易发现;
  • 祝早日解决bug。

8、更多分享

架构师李肯

架构师李肯全网同名),一个专注于嵌入式IoT领域的架构师。有着近10年的嵌入式一线开发经验,深耕IoT领域多年,熟知IoT领域的业务发展,深度掌握IoT领域的相关技术栈,包括但不限于主流RTOS内核的实现及其移植、硬件驱动移植开发、网络通讯协议开发、编译构建原理及其实现、底层汇编及编译原理、编译优化及代码重构、主流IoT云平台的对接、嵌入式IoT系统的架构设计等等。拥有多项IoT领域的发明专利,热衷于技术分享,有多年撰写技术博客的经验积累,连续多月获得RT-Thread官方技术社区原创技术博文优秀奖,荣获CSDN博客专家、CSDN物联网领域优质创作者、2021年度CSDN&RT-Thread技术社区之星、2022年RT-Thread全球技术大会讲师、RT-Thread官方嵌入式开源社区认证专家、RT-Thread 2021年度论坛之星TOP4、华为云云享专家(嵌入式物联网架构设计师)等荣誉。坚信【知识改变命运,技术改变世界】!


欢迎关注我的gitee仓库01workstation ,日常分享一些开发笔记和项目实战,欢迎指正问题。

同时也非常欢迎关注我的CSDN主页和专栏:

【CSDN主页-架构师李肯】

【RT-Thread主页-架构师李肯】

【C/C++语言编程专栏】

【GCC专栏】

【信息安全专栏】

【RT-Thread开发笔记】

【freeRTOS开发笔记】

有问题的话,可以跟我讨论,知无不答,谢谢大家。

本文章来源于互联网,如有侵权,请联系删除!