探索kernel3.18設(shè)備樹讀取過(guò)程以及driver的match過(guò)程2
(由于個(gè)人原因沒按時(shí)發(fā)布,flag很危險(xiǎn)吶)
上一篇探索到了match的過(guò)程,1形成了自己的打印函數(shù)思路,2知道了dump_stack()函數(shù),3縮小了of讀取函數(shù)的范圍。
本篇?jiǎng)t通過(guò)dump_stack()函數(shù)打印出來(lái)的函數(shù)一個(gè)一個(gè)找下去,看會(huì)不會(huì)找到哪個(gè)地方讀取of
[ 4.664679] <6>-(4)[1:swapper/0][<ffffffc00008becc>] dump_backtrace+0x0/0x190
[ 4.664688] <6>-(4)[1:swapper/0][<ffffffc00008c180>] show_stack+0x14/0x1c
[ 4.664697] <6>-(4)[1:swapper/0][<ffffffc000d173e4>] dump_stack+0xbc/0xf8
[ 4.664706] <6>-(4)[1:swapper/0][<ffffffc000a621d0>] __of_match_node+0xa8/0xe8
[ 4.664714] <6>-(4)[1:swapper/0][<ffffffc000a631c0>] of_match_node+0x38/0x5c
[ 4.664721] <6>-(4)[1:swapper/0][<ffffffc000a64d50>] of_match_device+0x18/0x28
[ 4.664731] <6>-(4)[1:swapper/0][<ffffffc0003d3e8c>] platform_match+0x4c/0xb8
[ 4.664739] <6>-(4)[1:swapper/0][<ffffffc0003d2224>] __driver_attach+0x3c/0xb8
[ 4.664747] <6>-(4)[1:swapper/0][<ffffffc0003d0228>] bus_for_each_dev+0x58/0x98
[ 4.664754] <6>-(4)[1:swapper/0][<ffffffc0003d239c>] driver_attach+0x30/0x38
[ 4.664761] <6>-(4)[1:swapper/0][<ffffffc0003d0a54>] bus_add_driver+0x128/0x23c
[ 4.664769] <6>-(4)[1:swapper/0][<ffffffc0003d2eec>] driver_register+0x74/0x138
[ 4.664777] <6>-(4)[1:swapper/0][<ffffffc0003d495c>] __platform_driver_register+0x60/0x68
[ 4.664785] <6>-(4)[1:swapper/0][<ffffffc001441adc>] mtkfb_init+0x8c/0x168
[ 4.664792] <6>-(4)[1:swapper/0][<ffffffc001407d18>] do_one_initcall+0xec/0x238
[ 4.664800] <6>-(4)[1:swapper/0][<ffffffc001407fb0>] kernel_init_freeable+0x14c/0x218
[ 4.664809] <6>-(4)[1:swapper/0][<ffffffc000d106f8>] kernel_init+0x14/0x194
[ 4.664814] <6>-(4)[1:swapper/0]fuhua-checkcode-score = 1073741823
現(xiàn)在是從a5a_cn_import/kernel3.18/driver/base/dd.c中的__driver_attach中打印出了device->of_node->properties->value,所以應(yīng)該從bus_for_each_dev往上追溯dev的值。
但如果沒有drv的限制,會(huì)不會(huì)出現(xiàn)value又為空而kernel又處理不了的情況呢?
所以現(xiàn)在急需知道如何讓kernel跳過(guò)處理"Unable to handle kernel NULL pointer dereference at virtual address 00000020"
現(xiàn)在就繞不過(guò)上一篇的mark了
我們可以先探索一下c語(yǔ)言的try catch機(jī)制(c語(yǔ)言的異常處理機(jī)制),然后看這個(gè)辦法是否可行(在嘗試異常處理機(jī)制之前,嘗試過(guò)用ISR_ERR函數(shù),但是并沒有太多的用處)
猜想異常處理機(jī)制和堆棧的關(guān)系,只能返回堆棧里面的異常?不然就崩潰?goto語(yǔ)句
發(fā)現(xiàn)setjmp這個(gè)函數(shù)根本不能使用,所以只能繼續(xù)往上看了~
追溯到bus_for_each_dev這段代碼,發(fā)現(xiàn)里面的dev都是從klist_iter_init_node函數(shù)里面讀取出來(lái)的,所以需要查清楚該函數(shù)做了什么
通過(guò)查找資料,klist只是kernel三大鏈表里面的一個(gè),list_head,hlist,klist。所以推斷這個(gè)函數(shù)只是單純操作klist的,對(duì)of沒有太多涉及。
網(wǎng)上找到一篇和我想做同樣事情的blog,不過(guò)是基于3.14的,通過(guò)一些驗(yàn)證發(fā)現(xiàn)說(shuō)的一些函數(shù)并沒有調(diào)用到,難道是已經(jīng)做了修改?
經(jīng)過(guò)一些波折,還是打印除了populate函數(shù)的log,處理方式是重新生成obj文件(暫時(shí)是不知道原因的,可能和make文件有關(guān)系)
現(xiàn)在是將child打印出來(lái)看看
PS: 這個(gè)populate函數(shù)是根據(jù)網(wǎng)上查到的,由于之前驗(yàn)證沒有打出log,所以之前以為是假的,但是通過(guò)log看到populate這個(gè)函數(shù)的確是被調(diào)用了,而且整個(gè)代碼里面就只有兩處,所以驗(yàn)證到了是因?yàn)閛ut的obj問題。
現(xiàn)在由于沒有打印出來(lái)mtkfb這個(gè)關(guān)鍵字,所以還在繼續(xù)尋找如何打印出來(lái)子節(jié)點(diǎn)什么的,剛剛因?yàn)樗阉鱯oc關(guān)鍵字所以又走了岔路,所以我們現(xiàn)在回來(lái)繼續(xù)看看tree的節(jié)點(diǎn)是怎么構(gòu)建的。
根據(jù)log和populate這個(gè)函數(shù)里面的邏輯,總算是打印出來(lái)了似乎是讀取的log,在of_platform_bus_create()的for_each_child_of_node(bus, child)下面,打印出child->properties->value
另外of_platform_bus_create居然還是遞歸調(diào)用~~~好久沒看到這種了
首先,這個(gè)函數(shù)不是在bus match mtkfb_driver的時(shí)候出現(xiàn)的,是在之前出現(xiàn)的,然后由于在log當(dāng)中也發(fā)現(xiàn)了之前打印的log,所以這個(gè)函數(shù)可能走的是上一篇文章探索的主要函數(shù)之前的流程, 我們先探索一下log,看具體的調(diào)用順序,然后再結(jié)合上一篇形成一個(gè)總體的概述。
那么先解決第一個(gè)疑問,到底有沒有真正找到創(chuàng)建device_node的地方呢,我們可以在log之前打印一次child->properties->value如果為null就可以證明之前是沒有創(chuàng)建這個(gè)節(jié)點(diǎn)的,如果有則證明還在前面;當(dāng)然根據(jù)經(jīng)驗(yàn),基本上就是這個(gè)地方了,后面再去驗(yàn)證吧。如果繼續(xù)深挖下去就是哪里將設(shè)備樹加載進(jìn)來(lái)的,以及通過(guò)怎樣的代碼讀取的,是否在這些個(gè)函數(shù)里面呢?這里先mark一下,以后有時(shí)間有興趣有需求再探索
第二個(gè)點(diǎn)就是of_platform_bus_create()函數(shù)的調(diào)用順序以及該函數(shù)和mtkfb_match關(guān)系或者調(diào)用順序(關(guān)系我只能想到前后關(guān)系,前置條件等關(guān)系)
那么of_platform_bus_create()的函數(shù)調(diào)用順序是怎樣的呢?我們通過(guò)log可以看到有打印出'mediatek,mtk'之前有dump_stack的影子,log如下:
[ 1.935095] <7>-(7)[1:swapper/0]CPU: 7 PID: 1 Comm: swapper/0 Not tainted 3.18.35+ #12
[ 1.936079] <7>-(7)[1:swapper/0]Hardware name: MT6738 (DT)
[ 1.936763] <7>-(7)[1:swapper/0][name:traps&]Call trace:
[ 1.937435] <7>-(7)[1:swapper/0][<ffffffc00008becc>] dump_backtrace+0x0/0x190
[ 1.938324] <7>-(7)[1:swapper/0][<ffffffc00008c180>] show_stack+0x14/0x1c
[ 1.939172] <7>-(7)[1:swapper/0][<ffffffc000d173f0>] dump_stack+0xbc/0xf8
[ 1.940019] <7>-(7)[1:swapper/0][<ffffffc000a621f0>] __of_match_node+0x90/0xb4
[ 1.940918] <7>-(7)[1:swapper/0][<ffffffc000a631c4>] of_match_node+0x38/0x5c
[ 1.941796] <7>-(7)[1:swapper/0][<ffffffc000a64d54>] of_match_device+0x18/0x28
[ 1.942698] <7>-(7)[1:swapper/0][<ffffffc0003d3e8c>] platform_match+0x4c/0xb8
[ 1.943586] <7>-(7)[1:swapper/0][<ffffffc0003d1f14>] __device_attach+0x2c/0xb4
[ 1.944486] <7>-(7)[1:swapper/0][<ffffffc0003d0478>] bus_for_each_drv+0x54/0x94
[ 1.945397] <7>-(7)[1:swapper/0][<ffffffc0003d2350>] device_attach+0xb0/0xcc
[ 1.946275] <7>-(7)[1:swapper/0][<ffffffc0003d0780>] bus_probe_device+0x94/0xb8
[ 1.947188] <7>-(7)[1:swapper/0][<ffffffc0003cdd10>] device_add+0x438/0x518
[ 1.948055] <7>-(7)[1:swapper/0][<ffffffc000a64dfc>] of_device_add+0x50/0x88
[ 1.948934] <7>-(7)[1:swapper/0][<ffffffc000a65830>] of_platform_device_create_pdata+0x78/0xc8
[ 1.950007] <7>-(7)[1:swapper/0][<ffffffc000a6595c>] of_platform_bus_create+0xdc/0x490
[ 1.950993] <7>-(7)[1:swapper/0][<ffffffc000a65ce0>] of_platform_bus_create+0x460/0x490
[ 1.951992] <7>-(7)[1:swapper/0][<ffffffc000a65e8c>] of_platform_populate+0x48/0xb0
[ 1.952949] <7>-(7)[1:swapper/0][<ffffffc00140a364>] arm64_device_init+0x20/0x2c
[ 1.953869] <7>-(7)[1:swapper/0][<ffffffc001407d18>] do_one_initcall+0xec/0x238
[ 1.954780] <7>-(7)[1:swapper/0][<ffffffc001407fb0>] kernel_init_freeable+0x14c/0x218
[ 1.955758] <7>-(7)[1:swapper/0][<ffffffc000d10704>] kernel_init+0x14/0x194
[ 1.956622] <7>-(7)[1:swapper/0]fuhua-checkcode-score = 1073741823
[ 1.957538] <5>-(5)[1:swapper/0]CPU: 5 PID: 1 Comm: swapper/0 Not tainted 3.18.35+ #12
[ 1.958523] <5>-(5)[1:swapper/0]Hardware name: MT6738 (DT)
[ 1.959206] <5>-(5)[1:swapper/0][name:traps&]Call trace:
[ 1.959873] <5>-(5)[1:swapper/0][<ffffffc00008becc>] dump_backtrace+0x0/0x190
[ 1.960763] <5>-(5)[1:swapper/0][<ffffffc00008c180>] show_stack+0x14/0x1c
[ 1.961609] <5>-(5)[1:swapper/0][<ffffffc000d173f0>] dump_stack+0xbc/0xf8
[ 1.962454] <5>-(5)[1:swapper/0][<ffffffc0003d3ee4>] platform_match+0xa4/0xb8
[ 1.963343] <5>-(5)[1:swapper/0][<ffffffc0003d1f14>] __device_attach+0x2c/0xb4
[ 1.964243] <5>-(5)[1:swapper/0][<ffffffc0003d0478>] bus_for_each_drv+0x54/0x94
[ 1.965155] <5>-(5)[1:swapper/0][<ffffffc0003d2350>] device_attach+0xb0/0xcc
[ 1.966033] <5>-(5)[1:swapper/0][<ffffffc0003d0780>] bus_probe_device+0x94/0xb8
[ 1.966945] <5>-(5)[1:swapper/0][<ffffffc0003cdd10>] device_add+0x438/0x518
[ 1.967813] <5>-(5)[1:swapper/0][<ffffffc000a64dfc>] of_device_add+0x50/0x88
[ 1.968691] <5>-(5)[1:swapper/0][<ffffffc000a65830>] of_platform_device_create_pdata+0x78/0xc8
[ 1.969765] <5>-(5)[1:swapper/0][<ffffffc000a6595c>] of_platform_bus_create+0xdc/0x490
[ 1.970752] <5>-(5)[1:swapper/0][<ffffffc000a65ce0>] of_platform_bus_create+0x460/0x490
[ 1.971750] <5>-(5)[1:swapper/0][<ffffffc000a65e8c>] of_platform_populate+0x48/0xb0
[ 1.972705] <5>-(5)[1:swapper/0][<ffffffc00140a364>] arm64_device_init+0x20/0x2c
[ 1.973626] <5>-(5)[1:swapper/0][<ffffffc001407d18>] do_one_initcall+0xec/0x238
[ 1.974537] <5>-(5)[1:swapper/0][<ffffffc001407fb0>] kernel_init_freeable+0x14c/0x218
[ 1.975514] <5>-(5)[1:swapper/0][<ffffffc000d10704>] kernel_init+0x14/0x194
接下來(lái)需要查證兩個(gè)問題,一個(gè)是dump_stack()是在哪里調(diào)用的,二是of_platform_bus_create的調(diào)用順序。
一:首先我們搜索一下dump_stack的調(diào)用,第一個(gè)是drivers/base/platform.c里的platform_match()里面調(diào)用了一次 另一個(gè)看log應(yīng)該y也是,當(dāng)屏蔽了之后發(fā)現(xiàn)drivers/of/base.c在前調(diào)用,drivers/base/platform.c在后面調(diào)用。結(jié)合log,發(fā)現(xiàn)有一個(gè)value是'mediatek,dispsys'```,所以猜想是匹配到了調(diào)用的吧,那么就可以看出來(lái)這一條線也是有點(diǎn)奇怪的,可能也是在交叉的
也就是說(shuō)中間有一條沒走fuhua-checkcode-device_attcch_else 這條線,這條線前后打出來(lái)的child是'mediatek,mdp_color','mediatek,dispsys'
那么現(xiàn)在引申出另一個(gè)問題,能進(jìn)入match的compitable又是哪一個(gè)呢?(這一個(gè)問題在完成第二點(diǎn)之后再驗(yàn)證)
二: 在加載了'mediatek,mtkfb'的地方打印dump_stack()
log如下:
[ 1.723465] <6>-(6)[1:swapper/0][<ffffffc000d18408>] dump_stack+0xbc/0xf8
[ 1.724313] <6>-(6)[1:swapper/0][<ffffffc000a65d0c>] of_platform_bus_create+0x498/0x4b4
[ 1.725311] <6>-(6)[1:swapper/0][<ffffffc000a65ea4>] of_platform_populate+0x48/0xb0
[ 1.726268] <6>-(6)[1:swapper/0][<ffffffc00140b364>] arm64_device_init+0x20/0x2c
[ 1.727189] <6>-(6)[1:swapper/0][<ffffffc001408d18>] do_one_initcall+0xec/0x238
[ 1.728100] <6>-(6)[1:swapper/0][<ffffffc001408fb0>] kernel_init_freeable+0x14c/0x218
[ 1.729079] <6>-(6)[1:swapper/0][<ffffffc000d1171c>] kernel_init+0x14/0x194
從log看,調(diào)用的順序是kernel_init->kernel_init_freeable->arm64_device_init->of_platform_populate->of_platform_bus_create 結(jié)合上一篇我們可以發(fā)現(xiàn)都有do_one_initcall這個(gè)函數(shù),所以可以看一下是否有先后順序,發(fā)現(xiàn)這個(gè)函數(shù)的調(diào)用也比較特別,在for循環(huán)里面調(diào)用的fn,所以通過(guò)打印的時(shí)間來(lái)看是of_platform_populate在mtkfb_init(void)之前調(diào)用的。
至此,讀取設(shè)備樹的流程基本清楚了,現(xiàn)在可以針對(duì)of_platform_populate()這個(gè)函數(shù)進(jìn)行進(jìn)一步的解讀,解讀完成之后基本能回答第一篇的問題3了。