power平台訪問全域性變數出現signal11

2021-07-09 20:10:34 字數 1916 閱讀 3745

最近,遇到乙個程序crash的cr(跑十來個小時才會crash,且每次都在同乙個點crash)。crash本是很正常的事情,但是這次crash卻讓我莫名其妙,crash的點**如下:

ala_bpddstore[0] = ((bt_upm<<8)|(bt_cei_pusch_decode<<16)|1);  //ala_bpddstore是乙個全域性陣列,右運算元全是巨集。

你告訴我訪問乙個全域性符號如何會產生signal11?

3f 00 10 fc         lis     r24,4348            //給r24暫存器賦值0x10fc***x

3b 18 07 a4      addi    r24,r24,1956          //給r24暫存器賦值0x10fc07a4

…90 f8 00 00     stw     r7,0(r24)           //訪問r24暫存器,程式在此crash

看到了吧?先把0x10fc07a4賦值給r24暫存器,然後通過r24訪問記憶體。0x10fc07a4是乙個合法的.data段位址,訪問乙個合法的位址怎麼會出現signal11呢?

但是,平台log直接表明crash時暫存器被踩!crash時r24的值為0x00170017,而且後面連著幾個暫存器的值都為0x00170017:

gpr24 = 00170017   gpr25 = 00170017   gpr26 = 00170017   gpr27 = 00170017

於是,重新研究這個函式和彙編,最後終於得出root cause。先奉上函式框架:

void cei_pusch_decode(void *msg, u32 length, u32 airnum)

ala_bpddstore[0] = ((bt_upm<<8)|(bt_cei_pusch_decode<<16)|1);  //crash語句

再結合該函式的彙編來看,給r24賦值以及訪問[r24]之間隔了很多條彙編指令,於是猜想gcc做了優化,迴圈之前對r24進行一次性賦值,後面每次訪問[r24]的時候直接取其內容!

上面一串子函式呼叫如下:

tl_getulcrnti() ==> mac_rlc_ul_getcrnti() ==> fso_sbl2_mac_rlc_ul_getcrnti==>fso_sbl2_macul_getcrntifromdemuxprocess()

挨個觀察他們的彙編,其中發現mac_rlc_ul_getcrnti()函式中有如下儲存、恢復暫存器的彙編指令:

93 01 00 40 stw     r24,64(r1)             //儲存r24到棧幀

93 21 00 44 stw     r25,68(r1)

93 41 00 48 stw     r26,72(r1)

....

83 01 00 a0      lwz     r24,160(r1)           //從棧幀上恢復r24

83 21 00 a4      lwz     r25,164(r1)

83 41 00 a8      lwz     r26,168(r1)

....

於是,發現問題所在:很可能這一串呼叫過程中棧幀被踩,導致恢復暫存器r24~r26時出錯!

但是問題來了,誰會踩這個函式的棧幀?由於棧生長方向向上,所以應該是被子函式踩了(最後一子函式,有乙個區域性陣列,我們的**的確存在越界風險)。

那麼接著問題又來了,子函式棧幀往上一路踩啊踩,怎麼沒把鏈結暫存器(lr)給踩了呢?從彙編中找到了答案:最後乙個函式不涉及子函式呼叫,不用儲存鏈結暫存器,而倒數第二個函式非常短小,彙編**被優化為區區兩行,基本就一條跳轉指令。

最後,把最後乙個子函式fso_sbl2_macul_getcrntifromdemuxprocess()中陣列越界加上保護,signal11果然不再出現。

python flask全域性變數訪問

基本使用參考 原因 在註冊該新模組的藍圖時,尚未給該變數賦予全域性屬性,且未賦值,所以為none,實際應在註冊藍圖之前賦予 test none param conf file return scheduler.start from mig import migde as migde blueprin...

vue 建立 全域性變數 全域性訪問

有個問題我還是想深入研究一下 就是關於 vue 中全域性變數這個概念 和實現方法的 不少人想都沒想,直接用vuex啊。對啊,我也是這個樣想的 直接用vuex不就啥事沒有了。vuex支援 定義 修改。還會實時重新整理,用來記錄狀態 再好不過 但是其他方式 還是有它的優勢的。最簡單的方法,也是最常見的 ...

C 中如何訪問全域性變數和全域性函式

全域性變數和全域性函式是相對區域性變數和區域性函式而言的,不在 或者for,if 等範圍內的都是全域性變數或者全域性函式,最簡單的是在同乙個檔案中去宣告。例如在mian.cpp中 include int gresult int gadd int a,int b 例如 定義乙個返回char型別的乙個叫...