ARM下C語言棧幀機(jī)制

背景:

????最近在某個RTOS上遇到一個系統(tǒng)BUG,幾經(jīng)折騰通砍,終于將其斬于馬下冤灾。結(jié)局美好前域,過程卻很曲折,在分析定位問題的時候韵吨,順便把ARM上C函數(shù)調(diào)用stack frame機(jī)制捋了一遍匿垄,記錄并分享一下。


概念:

棧:

1)從數(shù)據(jù)結(jié)構(gòu)的角度來理解归粉,棧是一種描述先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)椿疗;

2)從進(jìn)程的內(nèi)存空間角度來理解,棧是一種特殊的內(nèi)存段糠悼,用于存放局部變量变丧、函數(shù)參數(shù)、返回值等绢掰;

第一種角度,用來描述本身的特性童擎,第二種角度滴劲,是將這種數(shù)據(jù)結(jié)構(gòu)的特性用于實際的內(nèi)存空間中。

棧幀:每個進(jìn)程都會有自己的椆烁矗空間班挖,而進(jìn)程中的各個函數(shù)也會維護(hù)自己本身的一個棧的區(qū)域,這個區(qū)域就是棧幀芯砸。那么一個函數(shù)的棧幀的區(qū)域是如何來界定的呢萧芙?當(dāng)然,我首先會普及ARM的幾個特殊寄存器功能假丧。

R11:frame pointer双揪,F(xiàn)P寄存器

R12:IP寄存器,用于暫存SP

R13:stack pointer包帚,SP寄存器

R14:link register渔期,LR寄存器

R15:PC寄存器

而在ARM上,函數(shù)的棧幀是由SP寄存器和FP寄存器來界定的渴邦,相信你應(yīng)該見過下邊這張比較經(jīng)典的圖了:


? ? 上圖描述的是main函數(shù)調(diào)用func1函數(shù)的棧幀情況疯趟,從圖可知,當(dāng)main函數(shù)調(diào)用func1函數(shù)時谋梭,func1函數(shù)會先將PC信峻、LR、SP瓮床、FP四個寄存器壓到棧上邊盹舞,其中SP和FP的值分別指向main函數(shù)棧幀的兩個邊界产镐,LR的值保存的是func1調(diào)用結(jié)束之后的返回值,PC值表示的是當(dāng)前執(zhí)行到的指令地址矾策,放置的是進(jìn)入func1后的指令地址磷账。緊接著就會在棧上分配一片區(qū)域,用于放置局部變量等贾虽。

? ? 如果func1中還調(diào)用了func2子函數(shù)逃糟,那么也會為func2創(chuàng)建一個棧幀,并且func2的SP和FP會指向func1棧幀的兩個邊界蓬豁。這樣當(dāng)函數(shù)返回的時候绰咽,參數(shù)進(jìn)行出棧,也能找到Caller函數(shù)地粪,這個也就是backtrace的原理了取募。


示例:

????反匯編分析某段代碼,如下圖所示:


紅色部分蟆技,表明進(jìn)入到函數(shù)時先將幾個特殊的寄存器壓棧

黃色部分玩敏,sub sp, sp, #16,表明開辟一個4 x 32bit大小的棧區(qū)域

藍(lán)色部分质礼,將傳入的參數(shù)壓棧旺聚,在ARM ATPCS中規(guī)定,寄存器R0-R3用來傳參

綠色部分眶蕉,調(diào)用子函數(shù)

????那么砰粹,我們順道看看子函數(shù)的棧幀區(qū)域吧:


? ? 從圖中可以看出,機(jī)制是一樣的造挽,當(dāng)最終queue_push函數(shù)調(diào)用結(jié)束后碱璃,棧上的數(shù)據(jù)進(jìn)行出棧,根據(jù)fp和ip饭入,便能找到workflow_gather_input函數(shù)的棧幀了嵌器。

????當(dāng)然,并不是所有函數(shù)調(diào)用都需要先push? {fp, ip, lr, pc}谐丢,當(dāng)子函數(shù)調(diào)用過程中嘴秸,并不會去改變這些值的時候,就不需要壓棧庇谆,說白了岳掐,壓棧的目的就是為了在使用完的時候能恢復(fù)原來的狀態(tài)。我會再次提供一個例子:


? ? strlen函數(shù)中沒有子函數(shù)的調(diào)用饭耳,所以進(jìn)入函數(shù)后串述,直接就在棧上分配4 * 32bit大小的區(qū)域了。

????棧里邊能分析出每個參數(shù)的值寞肖,以及函數(shù)調(diào)用時的傳參纲酗,這對分析與定位問題很有幫助衰腌。成熟的系統(tǒng)可能會提供一堆工具來dump stack,并去分析調(diào)用關(guān)系觅赊,但是在RTOS上右蕊,很多卻并不完善,需要一定的低層知識去分析才能解決問題吮螺。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饶囚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鸠补,更是在濱河造成了極大的恐慌萝风,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件紫岩,死亡現(xiàn)場離奇詭異规惰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)泉蝌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門歇万,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人勋陪,你說我怎么就攤上這事堕花。” “怎么了粥鞋?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瞄崇。 經(jīng)常有香客問我呻粹,道長,這世上最難降的妖魔是什么苏研? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任等浊,我火速辦了婚禮,結(jié)果婚禮上摹蘑,老公的妹妹穿的比我還像新娘筹燕。我一直安慰自己,他們只是感情好衅鹿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布撒踪。 她就那樣靜靜地躺著,像睡著了一般大渤。 火紅的嫁衣襯著肌膚如雪制妄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天泵三,我揣著相機(jī)與錄音耕捞,去河邊找鬼衔掸。 笑死,一個胖子當(dāng)著我的面吹牛俺抽,可吹牛的內(nèi)容都是我干的敞映。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼磷斧,長吁一口氣:“原來是場噩夢啊……” “哼振愿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瞳抓,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤埃疫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后孩哑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栓霜,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年横蜒,在試婚紗的時候發(fā)現(xiàn)自己被綠了胳蛮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡丛晌,死狀恐怖仅炊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情澎蛛,我是刑警寧澤抚垄,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站谋逻,受9級特大地震影響呆馁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毁兆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一浙滤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧气堕,春花似錦纺腊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至梅桩,卻和暖如春次氨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背摘投。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工煮寡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虹蓄,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓幸撕,卻偏偏與公主長得像薇组,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坐儿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容