女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

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

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

3天內不再提示

Kernel Exception(KE)概述

哆啦安全 ? 來源:哆啦安全 ? 2023-07-16 16:38 ? 次閱讀

一、Kernel Exception(KE)概述

Android OS由3層組成,最底層是Kernel,上面是Native bin/lib,最上層是Java層:

ac1f09be-239a-11ee-962d-dac502259ad0.jpg

Android OS 3層結構

任何軟件都有可能發生異常,比如野指針,跑飛、死鎖等等。

當異常發生在kernel層,我們就叫它為KE(kernel exception),同理,發生在Native就是NE,Java層就是JE。這篇文章僅關注底層的KE。

1. KE類別

kernel有以下2種(oops、panic)崩潰類別

  1. oops (類似assert,有機會恢復)

oops是美國人比較常有的口語。就是有點意外,吃驚,或突然的意思。內核行為表現為通知感興趣模塊,打印各種信息,如寄存器值,堆棧信息…

當出現oops時,我們就可以根據寄存器等信息調試并解決問題。

/proc/sys/kernel/panic_on_oops為1時導致panic。我們默認設置為1,即oops會發生panic。

  • Panic – 困惑,恐慌,它表示Linux kernel遇到了一個不知道該怎么繼續的情況。內核行為表現為通知感興趣模塊,死機或者重啟。
    在kernel代碼里,有些代碼加了錯誤檢查,發現錯誤可能直接調用了panic(),并輸出信息提供調試

  1. panic

2. KE常用調試方法

凡是程序就有bug。bug總是出現在預料之外的地方。據說世界上第一個bug是繼電器式計算機中飛進一只蛾子,倒霉的飛蛾夾在繼電器之間導致了計算機故障。由于這個小蟲子,程序中的錯誤就被稱為了bug。

有Bug就需要Debug,而調試是一種很個性化的工作,十個人可能有十種調試方法。但從手段上來講,大致可分為兩類,在線調試 (Online Debug) 和離線調試 (Offline Debug).

3.在線調試

Online debug, 指的是在程序的運行過程中監視程序的行為,分析是否符合預期。通常會借助一些工具,如GDB和Trace32等。有時候也會借助一些硬件設備的協助,如仿真器/JTAG,但是準備環境非常困難,而且用起來也很麻煩,除非一些runtime問題需要外很少使用。

4.離線調試,

Offline debug, 指的是在程序的運行中收集需要的信息,在Bug發生后根據收集到的信息來分析的一種手段。通常也分為兩種方式,一種是Logging,一種是Memory Dump。

Logging
日志或者相關信息的收集,可以比較清晰的看到代碼的執行過程,對于邏輯問題是一種有效的分析手段,由于其簡單易操作,也是最為重要的一種分析手法。

Memory Dump
翻譯過來叫做內存轉儲,指的是在異常發生的時刻將內存信息全部轉儲到外部存儲器,即將異常現場信息備份下來以供事后分析。是針對CPU執行異常的一種非常有效的分析手段。在Windows平臺,程序異常發生之后可以選擇啟動調試器來馬上調試。在Linux平臺,程序發生異常之后會轉儲core dump,而此coredump可以用調試器GDB來進行調試。而內核的異常也可以進行類似的轉儲。

二、Kernel空間布局

在分析KE前,你要了解kernel內存布局,才知道哪些地址用來做什么,可能會是什么問題。

在內核空間中存在如下重要的段:

1. vmlinux代碼/數據段:

任何程序都有TEXT(可執行代碼),RW(數據段),ZI段(未初始化數據段),kernel也有,對應的是.text,.data,.bss

2.module區域:

kernel可以支持ko(模塊),因此需要一段空間用于存儲代碼和數據段。

3. vmalloc區域:

kernel除了可以申請連續物理地址的內存外,還可以申請不連續的內存(虛擬地址是連續的),可以避免內存碎片化而申請不到內存。

4. io map區域:

留給io寄存器映射的區域,有些版本沒有io map區域而是直接用vmalloc區域了。

5.memmap:

kernel是通過page結構體描述內存的,每一個頁框都有對應的page結構體,而memmap就是page結構體數組。

還有其他段小的段沒有列出來,可能根據不同的版本而差別。

6. ARM64bit kernel布局

目前智能機已進入64bit,因此就存在32bit布局和64bit布局,下面一一講解。

ARM64可以使用多達48bit物理、虛擬地址(擴充成64bit,高位全為1或0)。對linux kernel來講,目前配置為39bit的kernel空間。

由于多達512GB的空間,因此完全可以將整個RAM映射進來,0xFFFFFFC000000000之后就是一一映射了,就無所謂high memory了。

vmalloc區域功能除了外設寄存器也直接映射到vmalloc了,就沒有32bit布局里的IO map space了。

不同版本的kernel,布局稍有差別:

  • kernel-3.10

ac347092-239a-11ee-962d-dac502259ad0.jpg

kernel-3.10

  • = kernel-3.18 && < kernel-4.6

ac6b427a-239a-11ee-962d-dac502259ad0.jpg

>= kernel-3.18 && < kernel-4.6

  • = kernel-4.6/N0.MP8 kernel-4.4(patch back)

ac846570-239a-11ee-962d-dac502259ad0.jpg

>= kernel-4.6/N0.MP8 kernel-4.4(patch back)

7. ARM32bit kernel布局

這是一張示意圖(有些地址可能會有差異)

ac9b4f74-239a-11ee-962d-dac502259ad0.jpg

ARM32bit kernel布局

整個地址空間是4G,kernel被配置為1G,程序占3G。

內核代碼開始的地址是0xC0008000,前面放頁表(起始地址為0xC0004000),如果支持模塊(*.ko)那么地址在0xBF000000。

由于kernel沒辦法將所有內存都映射進來,畢竟kernel自己只占1G,如果RAM超過1G,就無法全部映射。怎么辦呢?只能先映射一部分了,這部分叫low memory。其他的就按需映射,VMALLOC區域就是用于按需映射的。

ARM的外設寄存器和內存一樣,都統一地址編碼,因此0xF0000000以上的一段空間用于映射外設寄存器,便于操作硬件模塊。

0xFFFF0000是特殊地址,CPU用于存放異常向量表,kernel異常絕大部分都是CPU異常(MMU發出的abort/undef inst.等異常)。

以上是粗略的說明,還需查看代碼獲取完整的分析信息(內核在不停演進,有些部分可能還會變化)

三、printk 概述

1. kernel log

最初學編程時,大家一定用過printf(),在kernel里有對應的函數,叫printk()。

最簡單的調試方法就是用printk()印出你想知道的信息了,而前面章節講到oops/panic時,它們就通過printk()將寄存器信息/堆棧信息打印到kernel log buffer里。

可以看到kernel log可以通過串口輸出,也可以在發生oops/panic后將buffer保存成文件打包到db里,然后拿到串口log或db對kernel進行調試分析了。

通常手機會保留串口測試點,但要抓串口log一般都要拆機,比較麻煩。前面講到可以將kernel log保存成文件打包在db里,db是什么東西?

四、AEE db log機制

db是叫AEE(Android Exception Engine,集成在Mediatek手機軟件里)的模塊檢查到異常并收集異常信息生成的文件,里面包含調試所需的log等關鍵信息。db有點像飛機的黑匣子。

對于KE來說,db里包含了如下文件(db可以通過GAT工具解開,請參考附錄里的FAQ):

  • __exp_main.txt:異常類型,調用棧等關鍵信息。

  • _exp_detail.txt:詳細異常信息

  • SYS_ANDROID_LOG:android main log

  • SYS_KERNEL_LOG:kernel log

  • SYS_LAST_KMSG:上次重啟前的kernel log

  • SYS_MINI_RDUMP:類似coredump,可以用gdb/trace32調試

  • SYS_REBOOT_REASON:重啟時的硬件記錄的信息。

  • SYS_VERSION_INFO:kernel版本,用于和vmlinux對比,只有匹配的vmlinux才能用于分析這個異常。

  • SYS_WDT_LOG:看門狗復位信息

以上這些文件一般足以調試KE了,除非一些特別的問題需要其他信息,比如串口log等等。

1. 系統重啟時關鍵信息

ram console除了保持last kmsg外,還有重要的系統信息,這些非常有助于我們調試。這些信息保存在ram console的頭部ram_console_buffer里。

acb714d4-239a-11ee-962d-dac502259ad0.jpg

ram console

這個結構體里的off_linux指向了struct last_reboot_reason,里面保存了重要的信息:

acd4590e-239a-11ee-962d-dac502259ad0.jpg

ram console

以上重要的信息在重啟后將被打包到db里的SYS_REBOOT_REASON文件里。對這只文件的各個欄位解讀請查看:

五、前期異常處理

1.CPU異常捕獲

對于野指針、跑飛之類的異常會被MMU攔截并報告給CPU,這一系列都是硬件行為。

這類問題比較難定位,也是占KE比例的大頭,原因通常是內存被踩壞、指針use atfer free等多種因素,在當時可能不會立即出現異常,而是到使用這塊內存才有可能崩潰。

2.軟件異常捕獲

在kernel代碼里,一般會通過BUG(),BUG_ON(),panic()來攔截超出預期的行為,這是軟件主動回報異常的功能。

在內核調用可以用來方便標記bug,提供斷言并輸出信息。最常用的兩個是BUG()和BUG_ON()。當被調用的時候,它們會引發oops,導致棧的回溯和錯誤信息的打印。使用方式如下

if (condition)
   BUG();
或者 :
BUG_ON(condition); //只是在BUG基礎上多層封存而已:
` #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)`

3. 32bit kernel:

BUG() 的實現采用了埋入未定義指令(0xE7F001F2,記住這個值,log里看到這個值,你就應該知道是調用了BUG()/BUG_ON()了)的方式

acef5236-239a-11ee-962d-dac502259ad0.jpg

64bit kernel:

原生的kernel,BUG()是直接調用panic()的:

ad111cc2-239a-11ee-962d-dac502259ad0.jpg

不過Mediatek修改了BUG()的實現,這樣有更多的調試信息輸出(die()有寄存器等信息輸出)

ad33f1fc-239a-11ee-962d-dac502259ad0.jpg

MTK 修改

當你看到如下log時,就應該知道是BUG()/BUG_ON()引起的了!

[ 147.234926]<0>-(0)[122:kworker/u8:3]Unable to handle kernel paging request at virtual address 0000dead

六、die()流程

經過前面的流程,走到了die()函數,該函數主要輸出便于調試的寄存器信息/堆棧信息等重要資料,我們通過log分析KE就是分析這些資料,因此要知道整個流程。die() => panic()的大致流程如下:

ad5a0694-239a-11ee-962d-dac502259ad0.jpg

die()流程圖

在學習這些流程時,建議結合代碼和KE的log一起看,你就知道log里那些信息在代碼哪處打印出來的了。

1.die()總流程

先從die()入手,看下die()總流程:

ad7aae1c-239a-11ee-962d-dac502259ad0.jpg

die()總流程

走到debug_locks_off()就有log輸出了,如下:

ad96ed02-239a-11ee-962d-dac502259ad0.jpg

debug_locks_off() log輸出

如果這個異常是代碼里調用BUG()/BUG_ON()引起,那么有額外log說明

adaded7c-239a-11ee-962d-dac502259ad0.jpg

輸出的log大致如下:

adc1e278-239a-11ee-962d-dac502259ad0.jpg

log

2. __die()流程

絕大部分的關鍵信息是由__die()函數輸出的,流程如下:

add94224-239a-11ee-962d-dac502259ad0.jpg

__die()流程

異常類型信息

開始印出異常類型等信息,看一份kernel log有沒有oops,直接搜索關鍵字Internal error就可以了:

adf1feae-239a-11ee-962d-dac502259ad0.jpg

輸出的信息大致如下:

ae0754c0-239a-11ee-962d-dac502259ad0.jpg

log

3. module信息

接下來是module信息,不過我們不建議使用module,這邊也不打算介紹了。

4.CPU寄存器信息

然后是重要的CPU寄存器信息(32bit的代碼,64bit類同):

ae184960-239a-11ee-962d-dac502259ad0.jpg

CPU信息

輸出的信息大致如下:

ae3c30e6-239a-11ee-962d-dac502259ad0.jpg

log信息

5.寄存器附近的內存

有助于我們分析問題的內存信息,問題很可能就出在里面。

ae61fb96-239a-11ee-962d-dac502259ad0.jpg

輸出的信息大致如下:

ae968546-239a-11ee-962d-dac502259ad0.jpg

6. 調用棧

有時問題可以直接從調用棧看出來,由此可見調用棧是多么重要。

aeb3345c-239a-11ee-962d-dac502259ad0.jpg

輸出的信息大致如下:

aed3b556-239a-11ee-962d-dac502259ad0.jpg

7.PC附近指令

可以看到PC附近的指令:

af0a8946-239a-11ee-962d-dac502259ad0.jpg

輸出的信息大致如下:

af1cecbc-239a-11ee-962d-dac502259ad0.jpg

8.分析log

到這里die()函數就完成了它的使命,將重要信息輸出來了。接下來你要如何調試呢?這個就看個人的功力了,你可以:

  • 通過PC指向的函數,用addr2line(后面的GNU tools有介紹)定位到哪只文件的哪一行,大致可以知道發生了什么,如果無法一下子定位,也可以通過結合printk()多次觀察KE時的log排查。如果是由BUG()/BUG_ON()引起的KE,則就可以著手修復問題了。

  • 查看調用棧,有些時候調用??梢哉f明流程,看看代碼是否有按預期跑,如果沒有,可以結合printk()定位問題。

  • 如果你想看函數參數或全局變量信息,那么你需要用《進階篇: ramdump分析》的知識調試了。

七、panic()流程

流程走到panic()就里死(異常重啟)不遠了,關鍵的信息已輸出到kernel log。那么panic()做了什么呢?

1. panic()流程

af31a5a8-239a-11ee-962d-dac502259ad0.jpg

panic()流程

panic()有標志性的log輸出,大致如下:

af54adaa-239a-11ee-962d-dac502259ad0.jpg

kernel panic 異常

因此我們也可以通過搜索關鍵字Kernel panic查找是否有panic發生。

2. panic通知鏈

panic()會調用棧通知鏈上的回調函數同時感興趣的模塊,比如我們的aee注冊了回調函數,用于保存kernel log/mini dump等關鍵信息,并將其保存到emmc的expdb分區,等等重啟后將其回讀并保存成KE db。

3. expdb

重啟過程DRAM會丟失,因此信息只能保存在flash上了,在分區表里有一項就是expdb了:

af737c9e-239a-11ee-962d-dac502259ad0.jpg

流程大致如下(版本不停演進,可能有很大變化,僅供參考):

af9a8c1c-239a-11ee-962d-dac502259ad0.jpg

重啟后,aee將回讀aeedb分區資料并轉化為KE db。

八、nested panic

有時die()/panic()流程不一定能正常走完,可能走到某一步又發生了異常,則就形成了嵌套,這種情況,我們一般不會關注后面的異常,而是關注最開始的那個異常。

為了避免異常嵌套,在發生第2次異常時,我們就攔截下來,我們在3個地方用于攔截nested panic:

  • do_PrefetchAbort()

  • do_DataAbort()

  • do_undefinstr()

afc85e94-239a-11ee-962d-dac502259ad0.jpg

攔截后不走die()/panic()流程,因為這些流程可能會再次發生異常,走我們寫的函數aee_stop_nested_panic()函數:

afde8aca-239a-11ee-962d-dac502259ad0.jpg

在里面盡量少用kernel模塊,很有可能也會發生異常,僅僅將寄存器等重要信息輸出到ram console就等死(死循環等等看門狗復位!)。這時你抓回來的db里的SYS_LAST_KMSG就可以看到這些資料,大致如下(不同版本稍有區別):

affa4166-239a-11ee-962d-dac502259ad0.jpg


里面包含了寄存器信息、堆棧信息和調用棧,我們就可以通過工具(addr2line)還原當時異常的位置。

不過nested panic能參考的信息很少,不像普通的KE那樣豐富。


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

    關注

    31

    文章

    5421

    瀏覽量

    123299
  • 存儲器
    +關注

    關注

    38

    文章

    7632

    瀏覽量

    166380
  • JAVA
    +關注

    關注

    20

    文章

    2984

    瀏覽量

    106841

原文標題:八、nested panic

文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    Linux中Kernel的運行原理概述

    接觸過Linux的都知道Kernel的含義,在我看來就是操作系統的核心或者最重要的部分。眾所周知的是,幾乎整個互聯網都運行在 Linux上,從網絡協議,到服務器,到你平常訪問的絕大多數網站,都能
    發表于 07-24 07:45

    Real Time Kernel概述

    Real Time Kernel概述DA145x軟件平臺利用了由Riviera Waves許可的小型高效實時內核。 內核提供以下功能:●任務創建和狀態轉換?!袢蝿罩g的消息交換。●計時器管理
    發表于 01-10 08:02

    Linux Kernel Panic的產生的原因?

    是Oops信息輸出) 2. 常見Linux Kernel Panic報錯內容: (1) Kernel panic-not syncing fatal exception in interrupt
    發表于 06-15 06:24

    Java中包、接口與異常處理(exception) 實驗

    實驗 4 包、接口與異常處理(exception) 一、實驗目的     了解 Java 中包(package)、接口(interface)和異常處理(exception)的作用,掌握包、接口
    發表于 09-23 19:00 ?1275次閱讀

    Kernel--Interrupts

    Kernel--Interrupts,好東西,喜歡的朋友可以下載來學習。
    發表于 02-22 15:03 ?0次下載

    KE-25數據手冊

    GS 氧氣傳感器 KE-系列
    發表于 12-25 21:36 ?0次下載

    ESP8266的重啟原因及常見的Fatal Exception的原因的說明

    本文檔的主要內容詳細介紹的是ESP8266的重啟原因及常見的Fatal Exception的原因的官方說明資料免費下載。
    發表于 09-23 08:00 ?28次下載
    ESP8266的重啟原因及常見的Fatal <b class='flag-5'>Exception</b>的原因的說明

    如何自定義Exception Hooks

    【導語】:在日常開發的過程中,當代碼報錯時,我們通常要不斷打印、閱讀traceback提示信息,來調試代碼,這篇文章介紹了如何實現一個Exception Hooks,使得traceback模塊的提示信息更加精確;同時還介紹了一些第三方庫,這些庫也提供了Exception
    的頭像 發表于 10-21 12:01 ?1090次閱讀

    kernel panic流程分析

    我們在項目開發過程中,很多時候會出現由于某種原因經常會導致手機系統死機重啟的情況(重啟分Android重啟跟kernel重啟,而我們這里只討論kernel重啟也就是 kernel panic 的情況
    的頭像 發表于 01-19 16:14 ?1415次閱讀
    <b class='flag-5'>kernel</b> panic流程分析

    RKP436KE 數據表

    RKP436KE 數據表
    發表于 04-20 18:48 ?0次下載
    RKP436<b class='flag-5'>KE</b> 數據表

    RKP453KE 數據表

    RKP453KE 數據表
    發表于 04-26 20:38 ?0次下載
    RKP453<b class='flag-5'>KE</b> 數據表

    RKP451KE 數據表

    RKP451KE 數據表
    發表于 04-26 20:39 ?0次下載
    RKP451<b class='flag-5'>KE</b> 數據表

    RKP452KE 數據表

    RKP452KE 數據表
    發表于 04-26 20:39 ?0次下載
    RKP452<b class='flag-5'>KE</b> 數據表

    kernel日志寫入logd介紹

    kernel日志寫入logd介紹 通過logcat命令獲取kernel日志比較特殊,故作為一個例子進行梳理。 2.3.1 整體流程 2.3.2 命令打印kernel日志 通過logcat -b
    的頭像 發表于 11-23 17:11 ?1006次閱讀
    <b class='flag-5'>kernel</b>日志寫入logd介紹

    高速FLEX貼片機KE-2050/KE-2060操作手冊

    電子發燒友網站提供《高速FLEX貼片機KE-2050/KE-2060操作手冊.pdf》資料免費下載
    發表于 01-23 10:44 ?14次下載