程式設計中的冰山理論 從 RPM 改變檔案大小說起

2021-07-26 17:58:12 字數 3373 閱讀 6348

你能看到的只是表面很少的一部分——冰山理論。

在程式設計排查問題時,我們經常遇到的情形就是,看似乙個很小的點,深究起來卻發現其背後隱藏著更深層次的技術邏輯。昨天的上線經歷讓我深有體會。

昨日上線,一切如舊。雲淡風輕,茶香四溢。

焚香,沐浴,更衣,食素三日之後總該一切無憂了吧。

然而,對比檔案內容之後,卻發現 rpm 解包後得到的可執行檔案和打包前檔案的 md5 不一樣。

rpm 打包沒報錯,傳輸沒報錯,解包沒報錯。

看看檔案大小,打包前可執行程式14m,但包中解出來的卻只有900多 k,相差甚多。

這是打包前:

這是解包後:

處理過程沒報錯,但是檔案內容不一樣,一定是沒看好,傳錯rpm包了。重新檢查 spec 檔案,重新打包,重新傳輸,每一步都小心翼翼。

解包之前先對比下rpm包的md5 吧。很好,這次傳對了,兩個rpm 包一樣,剛才一定是傳錯檔案了。

解包,品茗,手起鍵落,準備重啟。又一次電光火石,感覺肩膀又被命運之神拍了一下。「好吧,再給你個面子」,對比一下可執行檔案。

歷史總是驚人的相似,解包後還是912 k。打包前14m,解包後大小縮減了這麼多。

再來:打包沒報錯,傳輸沒報錯,解包沒報錯。但解出來程式卻變小了,一定是幻覺。又對比了兩次,幻覺依舊。

你信或不信,事實就在那裡。各個過程都沒錯,可是就變小了。思考邏輯與事實的衝突,恐怕是最折磨人的吧。

過程沒錯,但檔案卻大小變化了,心中默念多次之後,突然想到:誰說檔案變小了一定是錯誤?

對啊,變小不一定是錯誤。那一定是誰在某個過程中做了什麼手腳。上面已經驗證,傳輸前後rpm包內容一樣,那只能是rpm在打包或解包時做了什麼操作了,並且rpm 在做這個操作時沒有報告。

決定從就從打包過程開始排查。打包輸出資訊中有這麼幾行:

strip,objdump,我們好像在哪見過。依稀記得strip 好像是用來去掉可執行檔案中除錯資訊的,objdump 是用來處理可執行檔案的。正好我程式中含有除錯資訊,那麼會不會是rpm 呼叫的strip 把除錯資訊自作主張的去掉了呢?畢竟rpm 包通常是release 版本,除錯資訊的作用不大,自動刪除也是有可能的。

曙光初現。用file 命令看一下解包後的檔案資訊:

」not stripped「 ,檔案沒有被strip。欲哭無淚,不禁想起了一句話—— 前途是光明的,道路是曲折的。

除錯資訊還在,那變小的原因是什麼?你到底少了什麼?!

調整心情,從頭再來,一條路不行,再嘗試另外一條路。建立包時的輸出資訊中,除了strip,還有objdump。這兩個都是處理二進位制可執行檔案的。建包和解包都沒有報錯,但檔案變小了,那少的只能是程式執行時無用的資訊,無用的資訊又只能是除錯資訊和無用的符號之類的,而file 顯示額外資訊還在,沒被strip 掉。還在,還在。

又默念了多次之後,突然又靈光一閃:誰說strip資訊還在就等於除錯資訊沒變化呢?

strip 資訊還在,並不代表除錯資訊沒變化。思維定勢害死人啊。那就看看打包前和解包後兩個可執行檔案中的除錯資訊數量有沒有區別。

抱著試試看的心理,用如下命令把兩個可執行檔案中的除錯資訊寫到了檔案中:

objcopy --only-keep-debug rubik_superfst info.dbg
這是打包前程式生成的除錯資訊大小:

這是解包後程式生成除錯資訊大小:

這裡寫描述

果然不一樣!已經隱約見到勝利燈塔上閃現的微光了。file 命令的障眼法,還是被我給瞧破了。

除錯資訊大小不一樣,那麼rpm 到底去除了哪些資訊呢?看看objcopy 還有什麼使用方法。

man objcopy
發現 objcopy 的引數中有好幾個 strip 開頭的選項:

既然是除錯資訊大小不一樣,我們就先在打包前的程式上試試去除除錯資訊的選項 –strip-debug,即 -g 選項。

objcopy -g rubik_superfst
看看打包前的程式在執行這一命令後發生了哪些變化:

一次無意的嘗試,竟獲得了意想不到的結果。在未打包程式上執行完 objcopy -g 得到的檔案,竟然和rpm 包解包後變小的程式完全一樣。這說明了什麼?這說明了 rpm 做的操作就是執行了 objcopy -g 命令!

既然除錯資訊還是被 strip 了,那麼就 google 一下如何保留除錯資訊吧。只要在 spec 檔案中加入:

%define

__strip /bin/true

萬事大吉。再對比打包前和解包後的可執行檔案,md5 完全一樣。

一切如舊。雲淡風輕,茶香四溢。

rpm,終究你還是沒逃出我的掌心。食素、焚香、沐浴、更衣,終究是有用的。

那麼,file 命令為什麼對已經去掉了除錯資訊的程式還會顯示 「not stripped」 呢?file 命令的 man page 中並沒有對 strip 進行明確的說明。發現上面 objcopy 命令有好幾個strip 選項,那就試試吧。

夢想還是要有的,萬一實現了呢?嘗試的勇氣還是要有的,萬一有發現新大陸呢?

先看 strip-all 選項,這個看上去是去除了所有無用資訊,應該對 file 有效:

果然有效!但是 strip-debug 對file 命令就無效,用gdb檢視時,strip-all 也刪除了除錯資訊的符號,看來strip-all 中應該還刪除了除除錯符號外的其他符號,而 file 命令關注的就是這些內容。感興趣的同學可以繼續研究。本篇就不做擴充套件了。

我就是我,疾馳中的企鵝。

我就是我,不一樣的焰火。

理解C 物件導向程式設計中的抽象理論

很多書在一開始就開始學習josephus問題,為了讓大家前面學起來較為容易我把前面涉及到此問題的地方都故意去掉了,現在我們已經學習過了結構體和類,所以放在這裡學習可能更合適一些。在正式開始學習之前我們先回顧一下如何利用陣列和結構體的方式來解決,最後我們再看一下如何利用物件導向的抽象理念進行解決此問題...

併發程式設計的理論 python中實現多程序

1併發程式設計就是讓你的程式可以同時處理多個任務 2.併發程式設計的基石是 多道技術 空間復用 同乙個時間 記憶體儲存了多個程式 時間復用 當乙個程式遇到了io操作,或者長時間占用cpu後切換到其他程式上,來提高cpu利用率 多道技術的缺點 當應用程式都是計算任務時候切換反而會降低效率 但是必須切換...

轉從程式設計中悟出的八字箴言

我從程式設計中悟出八個字 1專 2靜 3謙 4籌 5悟 6慎 7透 8恆 1 忽如一夜春風來,千樹萬樹梨花開.現在的技術百花齊放,切忌不可貪.不要盲目的追求新技術,唯有演算法才是靈魂。2 非淡泊無以明志,非寧靜無以致遠.要想達到高的境界,必須能夠心靜.年輕的程式設計師都很浮躁,這一點對於他們來說尤為...