Unhandled kernel unaligned access问题记录

调试新驱动出现如下打印(内核未对齐访问):
[ 765.810527] Unhandled kernel unaligned access[#1]:
[ 765.815483] CPU: 0 PID: 120 Comm: insmod Tainted: G O 3.10.14__isvp_swan_1.0__ #1
[ 765.824120] task: 826daf40 ti: 820ec000 task.ti: 820ec000
[ 765.829700] $ 0 : 00000000 10001c00 804925b0 80200000
[ 765.835113] $ 4 : 00000001 00000000 00000032 00000135
[ 765.840520] $ 8 : 00000135 ffffffe0 804e0000 00000000
[ 765.845932] $12 : 00000000 804e0000 00000000 6d676172
[ 765.851339] $16 : 82505000 80382c30 c0110000 00000003
[ 765.856748] $20 : c010a164 c0110000 c010a578 c010a4a0
[ 765.862159] $24 : 00000001 00000048
[ 765.867569] $28 : 820ec000 820edc90 c01083f4 c00fe760
[ 765.872977] Hi : 00000000
[ 765.875950] Lo : 000002ba
[ 765.878933] epc : 801fcbc0 platform_driver_register+0x8/0x50
[ 765.884960] Tainted: G O
[ 765.888855] ra : c00fe760 audio_dsp_probe+0x2e4/0x3d0 [audio]
[ 765.895063] Status: 10001c03 KERNEL EXL IE
[ 765.899391] Cause : 00800014
[ 765.902364] BadVA : 00000019
[ 765.905337] PrId : 00d00100 (Ingenic Xburst)
[ 765.909835] Modules linked in: audio(O+) [last unloaded: audio]
[ 765.915968] Process insmod (pid: 120, threadinfo=820ec000, task=826daf40, tls=77076460)
[ 765.924243] Stack : 8183ba80 00000002 00000001 00000000 02625a00 00000000 02625a00 00000000
80200000 801fade0 c010a4b0 c010a4e4 c010a114 804f0000 c010a114 80480000
00000001 8277c124 00000028 801fb41c 8277c080 8205c188 8277c080 8038626c
c010a4b0 c010a4e4 c010a114 8277c080 80480000 801fb634 80480000 801f95d4
8042d518 8277c080 00000000 c010a114 801fb5bc 801f9684 8203525c 80381338

[ 765.961044] Call Trace:
[ 765.963570] [<801fcbc0>] platform_driver_register+0x8/0x50
[ 765.969260] [] audio_dsp_probe+0x2e4/0x3d0 [audio]
[ 765.975129] [<801fb41c>] driver_probe_device+0xbc/0x1f8
[ 765.980532] [<801fb634>] __driver_attach+0x78/0xb0
[ 765.985485] [<801f9684>] bus_for_each_dev+0x94/0xa4
[ 765.990526] [<801faa4c>] bus_add_driver+0x114/0x274
[ 765.995569] [<801fbab4>] driver_register+0xb8/0x15c
[ 766.000632] [] audio_dsp_init+0x5c/0x90 [audio]
[ 766.006234] [<80010508>] do_one_initcall+0xf0/0x1b8
[ 766.011278] [<80081f94>] load_module+0x1784/0x1d38
[ 766.016230] [<80082624>] SyS_init_module+0xdc/0xf8
[ 766.021184] [<80023b1c>] stack_done+0x20/0x44
[ 766.025684]
[ 766.027217]
Code: 27bd0018 3c028049 244225b0 8c820000 10400003 3c028020 2442c644 ac820030
[ 766.038964] —[ end trace d4cbe934ee2beefb ]—
Segmentation fault

经过追加打印发现:
struct platform_driver *audio_drivers[] = {
&audio_aic_driver,
&audio_codec_driver,
NULL,
};

此处数组自动识别元素个数,为3个,但是后续代码处理的时候会自动添加新的元素,并且新元素后面的一个也会设置为NULL。这里出现了问题。
实际情况是驱动参数fragment_time默认设置为2,但是程序运行过程中莫名出现了fragment_time变成0的情况,经过查找,没有发现在其他地方有赋值。于是乎只能加打印看是在哪个地方下数值被更改的:
while (audio_drivers[i++] != NULL);
printk("–probe 1.1-- fragment_time=%d\n", fragment_time);
audio_drivers[i] = NULL;
printk("–probe 1.2-- fragment_time=%d\n", fragment_time);
audio_drivers[–i] = &audio_dmic_driver; //此处执行过之后, fragment_time就变成了0,很是奇怪,追查数组可以看到,数组长度只有3,但是这里会把数组第四个元素设置为NULL,也就是0 ,将数组元素个数设置为4即可解决
printk("–probe 1.3-- fragment_time=%d\n", fragment_time);
i = 0;

上述过程有一个问题,夸大数组个数可以解决问题,但是为什么这里的赋值会影响到参数fragment_time的数值(默认为2,上述代码运行之后变成0)?

于是乎,反汇编查看查看:

	mips-linux-gnu-objdump -D audio.o > audio.txt

vim打开audio.txt找到fragment_time所在处(注意,要找到数据段(.data段下面)的fragment_time,因为代码其他地方也有用到这个变量,所以会出现很多次),如下:

	14467 00000054 :                                                                                 
	14468     ...
	14469 
	14470 00000060 :
	14471   60:   00000002    srl zero,zero,0x0

audio_drivers数组有三个元素,指针,所以地址长度=3*4=12,地址0x54为数组首地址,便宜12就是0x60地址(也就是fragment_time的地址),当我们 audio_drivers[i] = NULL;的时候,其实就是把fragment_time给设置成0了,bingo。怎么验证这种想法是正确的?那就把audio_drivers[i] = NULL;改成audio_drivers[i] = 1; 在编译驱动,运行程序发现,fragment_time变成1了。

思考:解决问题的时候,也要关注一下问题的本质,这样也可以顺便了解一下其他知识。

你可能感兴趣的:(Linux)