亚洲精品久久久久久久久久久,亚洲国产精品一区二区制服,亚洲精品午夜精品,国产成人精品综合在线观看,最近2019中文字幕一页二页

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

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

3天內(nèi)不再提示

ARMv7-A那些事-棧回溯淺析

嵌入式那些事 ? 來源:嵌入式那些事 ? 2023-11-21 15:51 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

嵌入式開發(fā)過程中,經(jīng)常需要對代碼進行調試來解決各種各樣的問題,常用的調試手段有:

(1)、開發(fā)環(huán)境搭配硬件仿真器進行在線調試。優(yōu)點:調試過程中能夠清楚的知道各個寄存器的值以及各個變量的值,程序的執(zhí)行流程也能夠一目了然。缺點:板卡需要引出硬件仿真器的連接口,并且需要購買硬件仿真器。

(2)、通過調試串口打印信息梳理程序的執(zhí)行流程,結合代碼分析問題產(chǎn)生的原因。優(yōu)點:足夠簡單,通過增加較多的打印信息來分析問題出現(xiàn)的位置,再結合代碼分析問題產(chǎn)生的原因。缺點:沒法準確的定位問題產(chǎn)生的位置和原因。

(3)、在應用或者操作系統(tǒng)死機的時候,根據(jù)操作系統(tǒng)輸出的異常棧信息進行分析,再結合鏡像或者應用的反匯編代碼進行定位。通常這種方法和方法(2)結合使用。

本文主要簡單的講講棧回溯,對于以后去理解操作系統(tǒng)的異常棧處理打個基礎吧。

ARM處理器的?;厮葜饕袃煞N方式:一種是基于棧幀寄存器(FP)的?;厮?,另一種是unwind形式的?;厮荨1疚闹饕v講基于棧幀寄存器(FP)的棧回溯。

?;厮菹嚓P寄存器

在?;厮葸^程中,主要涉及如下寄存器:

R15:又叫程序計數(shù)器(Program Counter)PC,PC主要用于存放CPU取指的地址。

R14:又叫鏈接寄存器(Link register)LR,LR主要用于存放函數(shù)的返回地址,即當函數(shù)返回時,知道自己該回到哪兒去繼續(xù)運行。

R13:又叫堆棧指針寄存器(Stack pointer)SP,SP通常用于保存堆棧地址,在使用入棧和出棧指令時,SP中的堆棧地址會自動的更新。

R12:又叫內(nèi)部過程調用暫存寄存器(Intra-Procedure-call scratch register)IP,主要用于暫存SP。

R11:又叫幀指針寄存器(Frame pointer)FP,通常指向一個函數(shù)的棧幀底部,表示一個函數(shù)棧的開始位置。

ARM棧幀結構

依據(jù)AAPCS (ARM Archtecture Procedure Call Standard)規(guī)范,當調用子函數(shù)時,子函數(shù)一開始的代碼總是會執(zhí)行壓棧操作來保留父函數(shù)的相關信息,壓棧步驟示例如下所示:

movip,sp
push{fp,ip,lr,pc}
subfp,ip,#4
subsp,sp,#16
...

每個函數(shù)都有自己的??臻g,這一部分稱為棧幀。棧幀在函數(shù)被調用的時候創(chuàng)建,在函數(shù)返回后銷毀。每個函數(shù)的棧幀是由SP寄存器和FP寄存器來界定的,ARM棧幀結構典型示意圖如下所示:

6422d2b4-8842-11ee-939d-92fbcf53809c.png

ARMv7-A架構-ARM棧幀結構

上圖描述的棧幀,main函數(shù)和func1函數(shù)的示意代碼如下:

intfunc1(intp1,intp2,intp3,intp4,intp5)
{
inti;
intj;

i=0xf3;
j=0xf6;

return0;
}

intmain(intargc,char*argv[])
{
inti;
intj;

i=0x33;
j=0x66;
func1(0xa1,0xa2,0xa3,0xa4,0xa5);

return0;
}

每個函數(shù)的棧幀中都會保存調用該函數(shù)之前的PC、LR、SP、FP寄存器的值;如果函數(shù)具有參數(shù)并且函數(shù)內(nèi)部使用了局部變量,那么函數(shù)棧幀中也會保存函數(shù)的參數(shù)和局部變量;如果被調用的子函數(shù)參數(shù)過多,那么多余的參數(shù)會通過父函數(shù)的棧進行傳遞。比如func1函數(shù)的參數(shù)p5通過main函數(shù)的棧幀進行傳遞的。(注:編譯器的版本不同,函數(shù)棧幀中參數(shù)和局部變量的壓棧順序可能不同,PC,LR,SP和FP這4個寄存器的壓棧順序一般是固定的)

函數(shù)棧幀中的PC和LR均指向代碼段,PC表示執(zhí)行入棧指令時CPU正在取指的地址,LR表示當前函數(shù)返回后繼續(xù)執(zhí)行的地址。

?;厮菰?/p>

在?;厮莸倪^程中,我們主要利用FP寄存器進行棧回溯。通過FP就可以知道當前函數(shù)的棧底,從而可以找到存儲在棧幀中的LR寄存器的數(shù)據(jù),這個數(shù)據(jù)就是函數(shù)的返回地址。同時也可以找到保存在函數(shù)棧幀中的上一級函數(shù)FP的數(shù)據(jù),這個數(shù)據(jù)指向了上一級函數(shù)的棧底,按照同樣的方法可以找出上一級函數(shù)棧幀中存儲的LR和FP數(shù)據(jù),就知道哪個函數(shù)調用了上一級函數(shù)以及這個函數(shù)的棧底地址。這就是棧回溯的流程,整個流程以FP為核心,依次找出每個函數(shù)棧幀中存儲的LR和FP數(shù)據(jù),計算出函數(shù)返回地址和上一級函數(shù)棧底地址,從而找出每一級函數(shù)調用關系。

?;厮菥幾g選項

當gcc的編譯選項帶有-mapcs-frame時,編譯出來的代碼能夠將PC,LR,SP和FP寄存器的值壓入函數(shù)的棧幀中。默認情況下gcc的編譯選項為-mno-apcs-frame ,此時編譯出來的代碼不一定會將PC,LR,SP和FP這四個寄存器的值壓入函數(shù)的棧幀中,可能只會將LR和FP寄存器的值壓入函數(shù)的棧幀中。關于-mapcs-frame選項,gcc的手冊描述如下:

Generateastackframethatiscompliant
withtheARMProcedureCallStandardfor
allfunctions,evenifthisisnotstrictly
necessaryforcorrectexecutionofthecode.
Specifying‘-fomit-frame-pointer’withthis
optioncausesthestackframesnottobe
generatedforleaffunctions.Thedefault
is‘-mno-apcs-frame’.
Thisoptionisdeprecated.

我這里使用的gcc信息如下:

$arm-none-eabi-gcc-v
...
gccversion10.3.120210824(release)(GNUArmEmbeddedToolchain10.3-2021.10)

雖然gcc手冊上說-mapcs-frame選項被廢棄了,但是只有添加了該選項,編譯出來的代碼才會將PC,LR,SP和FP寄存器的值壓入函數(shù)的棧幀中。

我這里編譯代碼仍然使用-mapcs-frame選項,有知道該選項對應的新的棧幀配置選項的兄弟可以告知我一下。

棧回溯示例

根據(jù)前面的內(nèi)容,這里簡單的寫了一個?;厮莸氖纠?,函數(shù)調用流程為:main -> test_a -> test_b -> test_c。

函數(shù)的源代碼如下:

inttest_a(intarg0,intarg1,intarg2,intarg3,intarg4)
{
inta;

a=0xff11;

test_b(0xbb00);

returna;
}

inttest_b(intarg0)
{
intb;

b=0xff22;

test_c(0xcc00);

returnb;
}

inttest_c(intarg0)
{
intc;

c=0xff33;

returnc;
}

intmain(void)
{
intval;

val=0xff00;

test_a(0xaa00,0xaa11,0xaa22,0xaa33,0xaa44);

return0;
}

上述函數(shù)的反匯編內(nèi)容如下:

80002164:

inttest_a(intarg0,intarg1,intarg2,intarg3,intarg4)
{
80002164:e1a0c00dmovip,sp
80002168:e92dd800push{fp,ip,lr,pc}
8000216c:e24cb004subfp,ip,#4
80002170:e24dd018subsp,sp,#24
80002174:e50b0018strr0,[fp,#-24];0xffffffe8
80002178:e50b101cstrr1,[fp,#-28];0xffffffe4
8000217c:e50b2020strr2,[fp,#-32];0xffffffe0
80002180:e50b3024strr3,[fp,#-36];0xffffffdc
inta;

a=0xff11;
80002184:e30f3f11movwr3,#65297;0xff11
80002188:e50b3010strr3,[fp,#-16]

test_b(0xbb00);
8000218c:e3a00cbbmovr0,#47872;0xbb00
80002190:eb000003bl800021a4

returna;
80002194:e51b3010ldrr3,[fp,#-16]
}
80002198:e1a00003movr0,r3
8000219c:e24bd00csubsp,fp,#12
800021a0:e89da800ldmsp,{fp,sp,pc}

800021a4:

inttest_b(intarg0)
{
800021a4:e1a0c00dmovip,sp
800021a8:e92dd800push{fp,ip,lr,pc}
800021ac:e24cb004subfp,ip,#4
800021b0:e24dd010subsp,sp,#16
800021b4:e50b0018strr0,[fp,#-24];0xffffffe8
intb;

b=0xff22;
800021b8:e30f3f22movwr3,#65314;0xff22
800021bc:e50b3010strr3,[fp,#-16]

test_c(0xcc00);
800021c0:e3a00b33movr0,#52224;0xcc00
800021c4:eb000003bl800021d8

returnb;
800021c8:e51b3010ldrr3,[fp,#-16]
}
800021cc:e1a00003movr0,r3
800021d0:e24bd00csubsp,fp,#12
800021d4:e89da800ldmsp,{fp,sp,pc}

800021d8:

inttest_c(intarg0)
{
800021d8:e1a0c00dmovip,sp
800021dc:e92dd800push{fp,ip,lr,pc}
800021e0:e24cb004subfp,ip,#4
800021e4:e24dd010subsp,sp,#16
800021e8:e50b0018strr0,[fp,#-24];0xffffffe8
intc;

c=0xff33;
800021ec:e30f3f33movwr3,#65331;0xff33
800021f0:e50b3010strr3,[fp,#-16]

returnc;
800021f4:e51b3010ldrr3,[fp,#-16]
}
800021f8:e1a00003movr0,r3
800021fc:e24bd00csubsp,fp,#12
80002200:e89da800ldmsp,{fp,sp,pc}

80002204
: intmain(void) { 80002204:e1a0c00dmovip,sp 80002208:e92dd800push{fp,ip,lr,pc} 8000220c:e24cb004subfp,ip,#4 80002210:e24dd010subsp,sp,#16 intval; val=0xff00; 80002214:e3a03cffmovr3,#65280;0xff00 80002218:e50b3010strr3,[fp,#-16] test_a(0xaa00,0xaa11,0xaa22,0xaa33,0xaa44); 8000221c:e30a3a44movwr3,#43588;0xaa44 80002220:e58d3000strr3,[sp] 80002224:e30a3a33movwr3,#43571;0xaa33 80002228:e30a2a22movwr2,#43554;0xaa22 8000222c:e30a1a11movwr1,#43537;0xaa11 80002230:e3a00caamovr0,#43520;0xaa00 80002234:ebffffcabl80002164 return0; 80002238:e3a03000movr3,#0 } 8000223c:e1a00003movr0,r3 80002240:e24bd00csubsp,fp,#12 80002244:e89da800ldmsp,{fp,sp,pc}

當程序運行到test_c()函數(shù)的return c;代碼處時,F(xiàn)P的值為0x9FDFFF94,此時內(nèi)存數(shù)據(jù)如下:

6441f4be-8842-11ee-939d-92fbcf53809c.png

Snipaste_2023-08-30_15-56-26

test_c()函數(shù)的棧底為0x9FDFFF94,可以得到test_c()函數(shù)棧幀中LR為0x800021C8、FP為0x9FDFFFB4,LR是test_c()函數(shù)執(zhí)行完成后的返回地址,與反匯編代碼中test_b()函數(shù)調用完test_c()之后的下一個執(zhí)行地址一致:

800021c0:e3a00b33movr0,#52224;0xcc00
800021c4:eb000003bl800021d8

returnb;
800021c8:e51b3010ldrr3,[fp,#-16]//test_c()函數(shù)返回后繼續(xù)執(zhí)行的地址

FP為0x9FDFFFB4表示test_b()函數(shù)的棧底為0x9FDFFFB4,有了test_b()函數(shù)的棧底就可以得到test_b()函數(shù)棧幀中LR為0x80002194、FP為0x9FDFFFDC,從而知道test_b()函數(shù)執(zhí)行完成后的返回地址以及test_a()函數(shù)的棧底,依次逐級回溯,就可以知道程序的整個運行流程了。

在棧回溯的過程中我們可以利用addr2line工具輔助我們對程序執(zhí)行流程的分析。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5527

    瀏覽量

    128579
  • 計數(shù)器
    +關注

    關注

    32

    文章

    2304

    瀏覽量

    97431
  • ARM處理器
    +關注

    關注

    6

    文章

    361

    瀏覽量

    43096

原文標題:ARMv7-A 那些事 - 7.?;厮轀\析

文章出處:【微信號:嵌入式那些事,微信公眾號:嵌入式那些事】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    armv7 generic timer使用筆記

    armv7-A架構中每個CPU核心都包含自己的私有定時器,所有cpu的定時器共享一個System counter, System counter負責產(chǎn)生計數(shù),傳遞到每個核心的私有定時器
    的頭像 發(fā)表于 09-27 15:10 ?4041次閱讀
    <b class='flag-5'>armv7</b> generic timer使用筆記

    ARMv7-A架構的實現(xiàn)中SIMD和VFP的擴展實現(xiàn)是可選的嗎?如何了解某控制器是否支持這些實現(xiàn)?

    ,如果更換其他ARMv7-A實現(xiàn)的內(nèi)核(如Cortex A8),如何確定該實現(xiàn)是否支持?第一次提問,如果表述不清楚請見諒!謝謝!
    發(fā)表于 07-01 16:33

    ARMv8-A AArch32主要特性

    Cortex-A32產(chǎn)品介紹ARMv8-A AArch32主要特性ARMv7-M與AArch32的不同之處軟件從ARMv7-M移植到ARMv7-A
    發(fā)表于 02-19 06:20

    淺析ARMv7-A體系架構下的MMU的基本原理

    。MMU 主要功能之一是虛擬地址到物理地址的轉換,這個需要軟件和硬件配合完成,軟件需要針對不同的硬件進行策略。這里主要分析 ARMv7-A 體系架構下的 MMU 的基本原理。VMSA 是針對
    發(fā)表于 05-24 16:54

    如何在Armv7-A系列芯片上根據(jù)錯誤調用來debug呢

    本周解決了兩個在 Armv7-A 系列芯片上出現(xiàn)的錯誤,包括一個由于軟浮點配置導致的未定義指令錯誤以及一個由于數(shù)據(jù)未對齊導致的 data abort 錯誤,通過解決這兩個問題,學會了如何在 A 系列
    發(fā)表于 06-13 17:42

    Armv8-A構架中Armv8.6-A引進的最新功能介紹

    :細化的trap從Armv7-A開始引入虛擬化以來,arm持續(xù)改進虛擬化的支持。一個虛擬化關鍵的支持是trap虛擬機執(zhí)行的一些操作。目的是為了虛擬化這些操作或是讓hypervisor充當Guest
    發(fā)表于 07-29 15:29

    ARM體系結構參考手冊ARMv7-AARMv7-R版本

    提前(AOT)編譯的特定支持。 ·決定處理器如何運行的模式和狀態(tài),包括當前的執(zhí)行特權和安全性。 ·例外模式。 ·內(nèi)存模型,定義內(nèi)存排序和內(nèi)存管理: -ARMv7-A架構配置文件定義虛擬內(nèi)存系統(tǒng)架構
    發(fā)表于 08-12 07:46

    ARM Cortex-A系列ARMv8-A程序員指南

    。 GNU和Linux文檔(Redhat和Fedora發(fā)行版除外)有時將AArch64稱為ARM64。 因為ARMv8-A體系結構的許多概念都與ARMv7-A體系結構相同,所以這里不涉及所有這些概念的細節(jié)
    發(fā)表于 08-22 07:22

    在基于ARMv7的平臺1.0版上使用CSAT進行低級調試

    Armv7-A 平臺上執(zhí)行某些調試操作。 側重于平臺推移硅、 FPGA 和硬件模擬環(huán)境的用戶如果想要測試其調試設計的某些方面, 可能會發(fā)現(xiàn)此調試操作是有用的 。 此教程覆蓋的調試操作包括: ? 使用調試
    發(fā)表于 08-28 06:50

    如何將軟件應用程序從ARMv5遷移到ARMv7-A/R

    5。 本應用筆記還假設您具有ARMv5的軟件開發(fā)經(jīng)驗。 假設主目標平臺是圍繞ARMv7-A處理器構建的。 由于ARMv7-AARMv7-R有許多重疊的區(qū)域,本文檔的一部分也適用于
    發(fā)表于 08-29 06:51

    一文詳解Linux內(nèi)核的回溯與妙用

    網(wǎng)上或多或少都能找到回溯的一些文章,但是講的都并不完整,沒有將內(nèi)核回溯的功能用于實際的內(nèi)核、應用程序調試,這是本篇文章的核心:盡可能引導讀者將
    的頭像 發(fā)表于 10-05 10:02 ?6226次閱讀
    一文詳解Linux內(nèi)核的<b class='flag-5'>棧</b><b class='flag-5'>回溯</b>與妙用

    ARMv7ARMv7的體系結構參考手冊免費下載

    ARM? Architecture Reference Manual ARMv7-A and ARMv7-R edition
    發(fā)表于 09-28 08:00 ?30次下載
    <b class='flag-5'>ARMv7</b>和<b class='flag-5'>ARMv7</b>的體系結構參考手冊免費下載

    Cortex A7 MPCore的技術參考手冊

    Cortex-A7 MPCore處理器是實現(xiàn)ARMv7-a架構的高性能、低功耗處理器。Cortex-A7 MPCore處理器在一個多處理器設備中有一到四個處理器,一個一級緩存子系統(tǒng),一個可選的集成GIC和一個可選的二級緩存控制器
    發(fā)表于 12-09 08:00 ?9次下載
    Cortex <b class='flag-5'>A7</b> MPCore的技術參考手冊

    ARMv7-A工作模式介紹

    級(非安全模式)的應用就不能訪問高等級(安全模式)的資源,以此來保證敏感資源的安全性。 ARMv7-A 工作模式 以前的 A
    的頭像 發(fā)表于 09-11 16:31 ?1605次閱讀
    <b class='flag-5'>ARMv7-A</b>工作模式介紹

    RVBacktrace RISC-V極簡回溯組件

    RVBacktrace組件簡介一個極簡的RISC-V回溯組件。功能在需要的地方調用組件提供的唯一API,開始當前環(huán)境的回溯支持輸出addr2line需要的命令,使用addr2lin
    的頭像 發(fā)表于 09-15 08:12 ?1179次閱讀
    RVBacktrace RISC-V極簡<b class='flag-5'>棧</b><b class='flag-5'>回溯</b>組件