色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

【GCC編譯優化系列】前后編譯的兩版本固件bin大小不一樣?

嵌入式物聯網開發 ? 來源:嵌入式物聯網開發 ? 作者:嵌入式物聯網開發 ? 2022-09-09 09:01 ? 次閱讀

文章目錄

  • 1、問題描述
  • 2、排查思路
  • 3、如何獲取預編譯文件、匯編文件等中間文件?
  • 4、object文件如何對比?
  • 5、關于鏈接順序對elf文件的影響
  • 6、還有什么其他的東西可以輔助分析?
  • 7、總結
  • 8、更多分享


1、問題描述

這兩天在論壇收到一個朋友的問題回答邀請,我仔細讀了下該問題,跟我之前在論壇上發布的好幾個問題關聯還挺大的,所以抽空帶著這個問題,重新梳理下思路,也希望這些思路能幫到這位朋友盡快解決問題。

它的問題描述如下,感興趣的可以參考原文鏈接:RT-Thread4.1.0工程用scons連續編譯生成的map文件差異很大

poYBAGMZ0dGAE9G_AAHoIbQ0iiE728.png

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-RWep0HnX-1662636304782)(C:/Users/takeout.NEWNEW/AppData/Roaming/Typora/typora-user-images/image-20220908142659151.png)]

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文件。

最后一步,把所有的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.bin\n' +\
                  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打出來:

poYBAGMZ0fOAUf5bAAFxy9Clnzw723.png

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dQYQXcIa-1662636304791)(C:/Users/takeout.NEWNEW/AppData/Roaming/Typora/typora-user-images/image-20220908134546908.png)]

抓取前后兩次的大小對比,即可大致知道哪幾個 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 build\0mem_leak_debug\mem_leak_debug.o build\0mem_leak_debug\mem_heap_hook.o build\applications\main.o build\applications\mnt.o build\applications\lcd_init.o build\drivers\drv_timer.o build\drivers\board.o build\drivers\drv_smc911x.o build\drivers\secondary_cpu.o build\drivers\drv_mouse.o build\drivers\drv_sdio.o build\drivers\serial.o build\drivers\drv_keyboard.o build\kernel\src\irq.o build\kernel\src\mem.o build\kernel\src\kservice.o build\kernel\src\thread.o build\kernel\src\slab.o build\kernel\src\clock.o build\kernel\src\cpu.o build\kernel\src\scheduler.o build\kernel\src\device.o build\kernel\src\timer.o build\kernel\src\ipc.o build\kernel\src\object.o build\kernel\src\idle.o build\kernel\src\components.o build\kernel\src\memheap.o build\kernel\src\signal.o build\kernel\src\mempool.o build\kernel\libcpu\arm\common\backtrace.o build\kernel\libcpu\arm\common\div0.o build\kernel\libcpu\arm\common\showmem.o build\kernel\libcpu\arm\cortex-a\vector_gcc.o build\kernel\libcpu\arm\cortex-a\cp15_gcc.o build\kernel\libcpu\arm\cortex-a\gic.o build\kernel\libcpu\arm\cortex-a\cache.o build\kernel\libcpu\arm\cortex-a\mmu.o build\kernel\libcpu\arm\cortex-a\context_gcc.o build\kernel\libcpu\arm\cortex-a\trap.o build\kernel\libcpu\arm\cortex-a\start_gcc.o build\kernel\libcpu\arm\cortex-a\stack.o build\kernel\libcpu\arm\cortex-a\cpu.o build\kernel\libcpu\arm\cortex-a\interrupt.o build\kernel\components\dfs\src\dfs_posix.o build\kernel\components\dfs\src\dfs_fs.o build\kernel\components\dfs\src\dfs.o build\kernel\components\dfs\src\dfs_file.o build\kernel\components\dfs\filesystems\devfs\devfs.o build\kernel\components\dfs\filesystems\elmfat\dfs_elm.o build\kernel\components\dfs\filesystems\elmfat\ff.o build\kernel\components\dfs\filesystems\elmfat\ffunicode.o build\kernel\components\dfs\filesystems\ramfs\dfs_ramfs.o build\kernel\components\dfs\filesystems\romfs\romfs.o build\kernel\components\dfs\filesystems\romfs\dfs_romfs.o build\kernel\components\finsh\shell.o build\kernel\components\finsh\msh.o build\kernel\components\finsh\msh_parse.o build\kernel\components\finsh\cmd.o build\kernel\components\finsh\msh_file.o build\kernel\components\libc\compilers\common\cstdio.o build\kernel\components\libc\compilers\common\ctime.o build\kernel\components\libc\compilers\common\cctype.o build\kernel\components\libc\compilers\common\cstring.o build\kernel\components\libc\compilers\common\cstdlib.o build\kernel\components\libc\compilers\common\cwchar.o build\kernel\components\libc\compilers\newlib\syscalls.o build\kernel\components\libc\cplusplus\cxx_crt_init.o build\kernel\components\libc\cplusplus\cxx_Semaphore.o build\kernel\components\libc\cplusplus\cxx_crt.o build\kernel\components\libc\cplusplus\cxx_Mutex.o build\kernel\components\libc\cplusplus\cxx_Thread.o build\kernel\components\libc\posix\delay\delay.o build\kernel\components\libc\posix\io\aio\aio.o build\kernel\components\libc\posix\io\poll\select.o build\kernel\components\libc\posix\io\poll\poll.o build\kernel\components\libc\posix\io\stdio\libc.o build\kernel\components\libc\posix\io\termios\termios.o build\kernel\components\libc\posix\ipc\mqueue.o build\kernel\components\libc\posix\ipc\semaphore.o build\kernel\components\libc\posix\pthreads\pthread_cond.o build\kernel\components\libc\posix\pthreads\pthread_spin.o build\kernel\components\libc\posix\pthreads\pthread_attr.o build\kernel\components\libc\posix\pthreads\pthread_rwlock.o build\kernel\components\libc\posix\pthreads\pthread_mutex.o build\kernel\components\libc\posix\pthreads\pthread.o build\kernel\components\libc\posix\pthreads\pthread_barrier.o build\kernel\components\libc\posix\pthreads\pthread_tls.o build\kernel\components\libc\posix\pthreads\sched.o build\kernel\components\libc\posix\signal\posix_signal.o build\kernel\components\lwp\arch\arm\cortex-a\lwp_gcc.o build\kernel\components\lwp\lwp_memheap.o build\kernel\components\lwp\lwp_mem.o build\kernel\components\lwp\lwp_syscall.o build\kernel\components\lwp\lwp.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\netdb.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ip.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\autoip.o build\kernel\components\net\lwip\lwip-2.0.3\src\netif\ethernet.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\netif.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\sys.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\sockets.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\netifapi.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\tcpip.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\ip4_addr.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\dhcp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\init.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\etharp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\memp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\ip4.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\netbuf.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\raw.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\ip4_frag.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\tcp_out.o build\kernel\components\net\lwip\lwip-2.0.3\src\netif\lowpan6.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\icmp.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\api_lib.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\inet_chksum.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\stats.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\err.o build\kernel\components\net\lwip\lwip-2.0.3\src\apps\ping\ping.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\tcp_in.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\dns.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\timeouts.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\igmp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\udp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\pbuf.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\def.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\api_msg.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\tcp.o build\kernel\components\net\lwip\port\ethernetif.o build\kernel\components\net\lwip\port\sys_arch.o build\kernel\components\net\netdev\src\netdev_ipaddr.o build\kernel\components\net\netdev\src\netdev.o build\kernel\components\net\sal\dfs_net\dfs_net.o build\kernel\components\net\sal\socket\net_sockets.o build\kernel\components\net\sal\src\sal_socket.o build\kernel\components\net\sal\socket\net_netdb.o build\kernel\components\net\sal\impl\af_inet_lwip.o build\kernel\components\drivers\i2c\i2c-bit-ops.o build\kernel\components\drivers\i2c\i2c_core.o build\kernel\components\drivers\i2c\i2c_dev.o build\kernel\components\drivers\ipc\completion.o build\kernel\components\drivers\ipc\dataqueue.o build\kernel\components\drivers\ipc\pipe.o build\kernel\components\drivers\ipc\ringblk_buf.o build\kernel\components\drivers\ipc\ringbuffer.o build\kernel\components\drivers\ipc\waitqueue.o build\kernel\components\drivers\ipc\workqueue.o build\kernel\components\drivers\misc\pin.o build\kernel\components\drivers\mtd\mtd_nand.o build\kernel\components\drivers\mtd\mtd_nor.o build\kernel\components\drivers\rtc\rtc.o build\kernel\components\drivers\rtc\soft_rtc.o build\kernel\components\drivers\sdio\block_dev.o build\kernel\components\drivers\sdio\mmc.o build\kernel\components\drivers\sdio\mmcsd_core.o build\kernel\components\drivers\sdio\sd.o build\kernel\components\drivers\sdio\sdio.o build\kernel\components\drivers\serial\serial.o build\kernel\components\drivers\spi\sfud\src\sfud.o build\kernel\components\drivers\spi\sfud\src\sfud_sfdp.o build\kernel\components\drivers\spi\spi_core.o build\kernel\components\drivers\spi\spi_dev.o build\kernel\components\drivers\spi\spi_flash_sfud.o build\kernel\components\drivers\spi\spi_msd.o build\kernel\components\drivers\watchdog\watchdog.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 build\0mem_leak_debug\mem_leak_debug.o build\0mem_leak_debug\mem_heap_hook.o build\applications\main.o build\applications\mnt.o build\applications\lcd_init.o build\drivers\drv_timer.o build\drivers\board.o build\drivers\drv_smc911x.o build\drivers\secondary_cpu.o build\drivers\drv_mouse.o build\drivers\drv_sdio.o build\drivers\serial.o build\drivers\drv_keyboard.o build\kernel\src\irq.o build\kernel\src\mem.o build\kernel\src\kservice.o build\kernel\src\thread.o build\kernel\src\slab.o build\kernel\src\clock.o build\kernel\src\cpu.o build\kernel\src\scheduler.o build\kernel\src\device.o build\kernel\src\timer.o build\kernel\src\ipc.o build\kernel\src\object.o build\kernel\src\idle.o build\kernel\src\components.o build\kernel\src\memheap.o build\kernel\src\signal.o build\kernel\src\mempool.o build\kernel\libcpu\arm\common\backtrace.o build\kernel\libcpu\arm\common\div0.o build\kernel\libcpu\arm\common\showmem.o build\kernel\libcpu\arm\cortex-a\vector_gcc.o build\kernel\libcpu\arm\cortex-a\cp15_gcc.o build\kernel\libcpu\arm\cortex-a\gic.o build\kernel\libcpu\arm\cortex-a\cache.o build\kernel\libcpu\arm\cortex-a\mmu.o build\kernel\libcpu\arm\cortex-a\context_gcc.o build\kernel\libcpu\arm\cortex-a\trap.o build\kernel\libcpu\arm\cortex-a\start_gcc.o build\kernel\libcpu\arm\cortex-a\stack.o build\kernel\libcpu\arm\cortex-a\cpu.o build\kernel\libcpu\arm\cortex-a\interrupt.o build\kernel\components\dfs\src\dfs_posix.o build\kernel\components\dfs\src\dfs_fs.o build\kernel\components\dfs\src\dfs.o build\kernel\components\dfs\src\dfs_file.o build\kernel\components\dfs\filesystems\devfs\devfs.o build\kernel\components\dfs\filesystems\elmfat\dfs_elm.o build\kernel\components\dfs\filesystems\elmfat\ff.o build\kernel\components\dfs\filesystems\elmfat\ffunicode.o build\kernel\components\dfs\filesystems\ramfs\dfs_ramfs.o build\kernel\components\dfs\filesystems\romfs\romfs.o build\kernel\components\dfs\filesystems\romfs\dfs_romfs.o build\kernel\components\finsh\shell.o build\kernel\components\finsh\msh.o build\kernel\components\finsh\msh_parse.o build\kernel\components\finsh\cmd.o build\kernel\components\finsh\msh_file.o build\kernel\components\libc\compilers\common\cstdio.o build\kernel\components\libc\compilers\common\ctime.o build\kernel\components\libc\compilers\common\cctype.o build\kernel\components\libc\compilers\common\cstring.o build\kernel\components\libc\compilers\common\cstdlib.o build\kernel\components\libc\compilers\common\cwchar.o build\kernel\components\libc\compilers\newlib\syscalls.o build\kernel\components\libc\cplusplus\cxx_crt_init.o build\kernel\components\libc\cplusplus\cxx_Semaphore.o build\kernel\components\libc\cplusplus\cxx_crt.o build\kernel\components\libc\cplusplus\cxx_Mutex.o build\kernel\components\libc\cplusplus\cxx_Thread.o build\kernel\components\libc\posix\delay\delay.o build\kernel\components\libc\posix\io\aio\aio.o build\kernel\components\libc\posix\io\poll\select.o build\kernel\components\libc\posix\io\poll\poll.o build\kernel\components\libc\posix\io\stdio\libc.o build\kernel\components\libc\posix\io\termios\termios.o build\kernel\components\libc\posix\ipc\mqueue.o build\kernel\components\libc\posix\ipc\semaphore.o build\kernel\components\libc\posix\pthreads\pthread_cond.o build\kernel\components\libc\posix\pthreads\pthread_spin.o build\kernel\components\libc\posix\pthreads\pthread_attr.o build\kernel\components\libc\posix\pthreads\pthread_rwlock.o build\kernel\components\libc\posix\pthreads\pthread_mutex.o build\kernel\components\libc\posix\pthreads\pthread.o build\kernel\components\libc\posix\pthreads\pthread_barrier.o build\kernel\components\libc\posix\pthreads\pthread_tls.o build\kernel\components\libc\posix\pthreads\sched.o build\kernel\components\libc\posix\signal\posix_signal.o build\kernel\components\lwp\arch\arm\cortex-a\lwp_gcc.o build\kernel\components\lwp\lwp_memheap.o build\kernel\components\lwp\lwp_mem.o build\kernel\components\lwp\lwp_syscall.o build\kernel\components\lwp\lwp.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\netdb.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ip.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\autoip.o build\kernel\components\net\lwip\lwip-2.0.3\src\netif\ethernet.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\netif.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\sys.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\sockets.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\netifapi.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\tcpip.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\ip4_addr.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\dhcp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\init.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\etharp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\memp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\ip4.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\netbuf.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\raw.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\ip4_frag.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\tcp_out.o build\kernel\components\net\lwip\lwip-2.0.3\src\netif\lowpan6.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\icmp.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\api_lib.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\inet_chksum.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\stats.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\err.o build\kernel\components\net\lwip\lwip-2.0.3\src\apps\ping\ping.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\tcp_in.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\dns.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\timeouts.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\ipv4\igmp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\udp.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\pbuf.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\def.o build\kernel\components\net\lwip\lwip-2.0.3\src\api\api_msg.o build\kernel\components\net\lwip\lwip-2.0.3\src\core\tcp.o build\kernel\components\net\lwip\port\ethernetif.o build\kernel\components\net\lwip\port\sys_arch.o build\kernel\components\net\netdev\src\netdev_ipaddr.o build\kernel\components\net\netdev\src\netdev.o build\kernel\components\net\sal\dfs_net\dfs_net.o build\kernel\components\net\sal\socket\net_sockets.o build\kernel\components\net\sal\src\sal_socket.o build\kernel\components\net\sal\socket\net_netdb.o build\kernel\components\net\sal\impl\af_inet_lwip.o build\kernel\components\drivers\i2c\i2c-bit-ops.o build\kernel\components\drivers\i2c\i2c_core.o build\kernel\components\drivers\i2c\i2c_dev.o build\kernel\components\drivers\ipc\completion.o build\kernel\components\drivers\ipc\dataqueue.o build\kernel\components\drivers\ipc\pipe.o build\kernel\components\drivers\ipc\ringblk_buf.o build\kernel\components\drivers\ipc\ringbuffer.o build\kernel\components\drivers\ipc\waitqueue.o build\kernel\components\drivers\ipc\workqueue.o build\kernel\components\drivers\misc\pin.o build\kernel\components\drivers\mtd\mtd_nand.o build\kernel\components\drivers\mtd\mtd_nor.o build\kernel\components\drivers\rtc\rtc.o build\kernel\components\drivers\rtc\soft_rtc.o build\kernel\components\drivers\sdio\block_dev.o build\kernel\components\drivers\sdio\mmc.o build\kernel\components\drivers\sdio\mmcsd_core.o build\kernel\components\drivers\sdio\sd.o build\kernel\components\drivers\sdio\sdio.o build\kernel\components\drivers\serial\serial.o build\kernel\components\drivers\spi\sfud\src\sfud.o build\kernel\components\drivers\spi\sfud\src\sfud_sfdp.o build\kernel\components\drivers\spi\spi_core.o build\kernel\components\drivers\spi\spi_dev.o build\kernel\components\drivers\spi\spi_flash_sfud.o build\kernel\components\drivers\spi\spi_msd.o build\kernel\components\drivers\watchdog\watchdog.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.bin\n' +\
                  SIZE + ' $TARGET \n ' + \
                  'python size.py build ' + SIZE + '\n' +\
                  'relink.bat \n' 

這里其實就是,后面一次鏈接會覆蓋前一次鏈接的結果,達到多次編譯都是同一個鏈接順序。


6、還有什么其他的東西可以輔助分析?

涉及編譯、內存變化這類問題,我們不得漏掉還有一個文件也非常重要,那就是 MAP文件

其實,如果前后兩次編譯生成的elf文件大小不一,在MAP文件中就可以看得出來:

可能類似這樣,兩個map文件是一樣的:

pYYBAGMZ0gmAKW3nAAEPeNkL87Y878.png

也有可能類似這樣,存在差異:

poYBAGMZ0hyASOm5AAOZCu1fX-A505.png

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-w1dynEKL-1662636304801)(C:/Users/takeout.NEWNEW/AppData/Roaming/Typora/typora-user-images/image-20220908141847669.png)]

需要注意的是,比較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開發筆記】

有問題的話,可以跟我討論,知無不答,謝謝大家。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • GCC
    GCC
    +關注

    關注

    0

    文章

    108

    瀏覽量

    24862
  • 編譯
    +關注

    關注

    0

    文章

    661

    瀏覽量

    32977
  • RT-Thread
    +關注

    關注

    31

    文章

    1305

    瀏覽量

    40315
收藏 人收藏

    評論

    相關推薦

    種形式電路咪頭拾音的信號大小不一樣,為什么?

    如上圖所示,種形式電路,用示波器測試,相同條件下測得咪頭的信號大小不一樣,請問是為什么呢?下面那種情況咪頭信號大。
    發表于 09-20 08:23

    TLV320AIC3104在沒有輸入聲音的時候,采集出來的信號底噪大小不一樣,差異比較大是為什么?

    我們使用aic3104碰到以下問題,在沒有輸入聲音的時候,采集出來的信號底噪大小不一樣,差異比較大。 客戶那邊的測試情況是這樣。
    發表于 10-10 06:18

    怎么讓選項卡的大小不一樣

    用選項卡的時候,選項卡1和選項卡2的內容多少不同,怎么分別讓選項卡1選項卡2的大小不一樣
    發表于 05-06 21:57

    cyclone iv的m9k使用大小不一樣

    芯片使用的是EP4CE15F17C8,為啥個提示的M9K大小不一樣呢?
    發表于 03-19 04:55

    keil自帶的ARMCC V5和V6 和 GCC編譯編譯用時和目標文件的大小對比

    CMSIS需要不一樣的頭文件之外,所有用戶代碼完全致。2:用秒表計時,開始計時和全部重新編譯按鈕同時按下,編譯完成時停止。因為手動掐表,肯定會有誤差,但是大致的可以參考。(正常使用的
    發表于 09-06 23:46

    請問在輸入信號和地之間接電容是濾波嗎,這個電容大小不一樣有什么區別嗎?

    在輸入電壓和地之間接電容是濾波嗎,這個電容大小不一樣有什么區別嗎?
    發表于 06-18 13:49

    GCC和ARMCC編譯后生成BIN文件大小不一樣是什么原因造成的呢

    最近發現個細節。同樣的工程文件,使用ENV工具生成keil的工程,編譯后轉成bin文件后是80k.同樣的工程使用scons編譯后用GCC
    發表于 06-28 15:10

    GCC編譯優化前后編譯版本固件bin大小不一樣

    1、前后編譯版本固件bin大小不一樣怎么辦既然
    發表于 09-09 16:12

    gcc編譯優化系列】如何獲取gcc默認的鏈接腳本

    我們都知道在般的嵌入式開發中,使用gcc編譯固件般流程是,先把所有的.c文件和.s文件編譯
    的頭像 發表于 07-11 09:15 ?3824次閱讀

    GCC編譯優化系列】實戰分析C代碼遇到的編譯問題及解決思路

    GCC編譯優化系列】實戰分析C工程代碼可能遇到的編譯問題及其解決思路
    的頭像 發表于 07-10 23:15 ?1484次閱讀
    【<b class='flag-5'>GCC</b><b class='flag-5'>編譯</b><b class='flag-5'>優化</b><b class='flag-5'>系列</b>】實戰分析C代碼遇到的<b class='flag-5'>編譯</b>問題及解決思路

    GCC編譯優化系列】multiple-definition

    GCC編譯優化系列】這種讓人看不懂的multiple-definition真的有點讓人頭疼
    的頭像 發表于 07-11 09:26 ?7366次閱讀
    【<b class='flag-5'>GCC</b><b class='flag-5'>編譯</b><b class='flag-5'>優化</b><b class='flag-5'>系列</b>】multiple-definition

    GCC編譯優化系列】-specs=kernel.specs

    GCC編譯優化系列GCC編譯鏈接時候--specs=kernel.specs鏈接屬性究竟是個
    的頭像 發表于 07-11 09:25 ?3569次閱讀
    【<b class='flag-5'>GCC</b><b class='flag-5'>編譯</b><b class='flag-5'>優化</b><b class='flag-5'>系列</b>】-specs=kernel.specs

    色環電感供應商科普為什么同款插件色環電感的電流大小不一樣

    色環電感供應商科普為什么同款插件色環電感的電流大小不一樣 編輯:谷景電子 電感對很多人來說真的是既熟悉又陌生,即便是很多經常接觸電子產品人來說,圍繞電感應用方面的知識也不一定知道的很多。比如本篇要跟
    的頭像 發表于 12-12 15:15 ?1008次閱讀

    電容容量一樣大小不一樣能用嗎

    有時候家里面電器中的電容損壞,很多人很難找到一模一樣的來更換,能找到容量致的電容器就不容易了,電容容量一樣大小不一樣能用嗎?
    的頭像 發表于 09-21 09:54 ?2634次閱讀

    電容容量一樣大小不一樣能用嗎?

    電容容量一樣大小不一樣能用嗎? 電容器(Capacitor)是種用來存儲電荷能量的電子元件。它是由個導體板(般是金屬)和
    的頭像 發表于 09-22 16:30 ?7202次閱讀
    主站蜘蛛池模板: 亚洲午夜久久久久中文字幕 | 花蝴蝶在线观看免费8 | 国产精品99久久久精品无码 | 日日天干夜夜狠狠爱 | 8050午夜二级一片 | 久久只精品99品免费久 | 欧美 日韩 亚洲 在线 | 国产自拍视频在线一区 | 高清不卡伦理电影在线观看 | 女人把腿张开叫男人桶免费视频 | 女性BBWBBWBBWBBW | 伊人久久大香线蕉综合色啪 | 97超碰免费人妻中文 | 人妻天天爽夜夜爽三区麻豆A片 | YELLOW在线观看高清视频免费 | 99久久久国产精品免费调教 | 91素人约啪 | 无限资源日本2019版免费 | 日日AV夜夜添久久奶无码 | 亚洲精品成人无码区一在线观看 | yellow在线观看免费观看大全 | 亚洲国产果果在线播放在线 | 国产亚洲精品久久久久久久 | 日韩免费视频一区 | 黑色丝袜美女被网站 | 成人毛片免费播放 | 国产福利不卡在线视频 | 亚欧日韩毛片在线看免费网站 | 亚洲一区免费观看 | 一个人看的www视频动漫版 | AV色蜜桃一区二区三区 | 国产精品色欲AV亚洲三区软件 | 国产69精品久久久久麻豆 | 国产欧美精品一区二区三区-老狼 | 国产精品久久久久久亚洲毛片 | 久久亚洲精品中文字幕60分钟 | 99久久免费国产精品特黄 | 小学生偷拍妈妈视频遭性教育 | 日本无码专区亚洲麻豆 | 人妻少妇久久久久久97人妻 | 电影日本妻子 |