static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
/* Then try to match against the id table */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0); <<===panic 在这里,通过上面的汇编看得出来r0是入口参数 const char *cs, 对应这里的实参是pdev->name, 说明pdev->name是一个无效的地址,所以trigger panic
}
依然如此,就有这样的疑问,因为pdev是平台数据的结构体,是pdev这个结构体本身就错了呢?还是pdev这个结构里面的一些成员变量的内存值变了呢?看下面的分析:
/* match against the id table first */
if (pdrv->id_table)
c032d688: e5914038 ldr r4, [r1, #56]
* and compare it against the name of the driver. Return whether they match
* or not.
*/
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
c032d68c: e2405008 sub r5, r0, #8 ; 0x8 <==通过上面的的汇编看到r0实际上是platform_match的入口参数,这里通过,to-platform_device这个函数将dev下面存的平台数据取出来,然后送给r5,此时r5就是pdev的机构体,因为panic的前一刻r5的值没有被变过,所以我们可以在stack里面找出其值来。
struct platform_driver *pdrv = to_platform_driver(drv);
/* match against the id table first */
if (pdrv->id_table)
c032d690: e3540000 cmp r4, #0 ; 0x0
c032d694: 1a000006 bne c032d6b4 <platform_match+0x30>
c032d698: ea00000d b c032d6d4 <platform_match+0x50>
static const struct platform_device_id *platform_match_id(
const struct platform_device_id *id,
struct platform_device *pdev)
{
while (id->name[0]) {
if (strcmp(pdev->name, id->name) == 0) {
c032d69c: e5950000 ldr r0, [r5] <==注意看这里将r5的值取出来给r0,实际上也是pdev->name,所以通过这里看来第一次这里用到了这个内存单元的值是正确的,因为假设整个结构出问题的话,那么code运行到这里就应该出错了,所以排除第一种可能。
c032d6a0: ebfd5dbf bl c0284da4 <strcmp>
c032d6a4: e3500000 cmp r0, #0 ; 0x0
pdev->id_entry = id;
c032d6a8: 05854168 streq r4, [r5, #360]
c032d6ac: 0a000005 beq c032d6c8 <platform_match+0x44>
return id;
}
id++;
c032d6b0: e2844018 add r4, r4, #24 ; 0x18
static const struct platform_device_id *platform_match_id(
const struct platform_device_id *id,
struct platform_device *pdev)
{
while (id->name[0]) {
c032d6b4: e5d43000 ldrb r3, [r4]
if (strcmp(pdev->name, id->name) == 0) {
c032d6b8: e1a01004 mov r1, r4
static const struct platform_device_id *platform_match_id(
const struct platform_device_id *id,
struct platform_device *pdev)
{
while (id->name[0]) {
c032d6bc: e3530000 cmp r3, #0 ; 0x0
c032d6c0: 1afffff5 bne c032d69c <platform_match+0x18>
pdev->id_entry = id;
return id;
}
id++;
}
return NULL;
c032d6c4: e1a04003 mov r4, r3
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
/* match against the id table first */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
c032d6c8: e2540000 subs r0, r4, #0 ; 0x0
c032d6cc: 13a00001 movne r0, #1 ; 0x1
c032d6d0: e8bd8070 pop {r4, r5, r6, pc}
/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);
c032d6d4: e5100008 ldr r0, [r0, #-8] <==这里是将 r0-8位置的内存的值取出来(一个pdev结构的指针)放到r0寄存器中,这里实际是在给strcmp 准备实参, 我们可以看下pdev这个结构体如下,name是结构体的第一个成员变量,那么pdev的指针实际上就是指向pdev->name, 那么通过这里看出pdev结构体来自r0-8的位置,因为我们上面有两种假设:一是pdev这个结构本身就出问题了,另外一个就是pdev里面的一个成员错了,继续往上推。
struct platform_device {
const char * name;
int id;
struct device dev;
u32 num_resources;
struct resource * resource;
..........
};
c032d6d8: e5911000 ldr r1, [r1]
c032d6dc: ebfd5db0 bl c0284da4 <strcmp> <==这里将跳转到strcmp执行相应的code
c032d6e0: e2700001 rsbs r0, r0, #1 ; 0x1 <==实际上c032d6e0就是panic时的LR
c032d6e4: 33a00000 movcc r0, #0 ; 0x0
R5: 0xdc4a6228:
6228 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
6248 00000000 00000000 00000000 00000000 00000000 00000000 165f8171 57515555
6268 5d555755 06055d55 635688c0 d84156c5 c755d51d c008eacc 564d4157 577de515
6288 d415d35d 4d254555 75861555 5755d977 635688c0 d84156c5 f00dcafe 00000000
62a8 fc4ba1c0 00000002 c093a570 dc4a4340 dc4ba160 1c4a607c dc4a64fc c093a578
62c8 dc437e40 c093a3f0 dc4aabf0 00000005 00000007 00000000 00000000 00000001
62e8 00000000 00000000 dc4a62f0 dc4a62f0 00000000 00000000 dc4a62e4 c093a6c8
6308 c097ebec dc4a9f80 00000000 00000000 00000001 dc4a60dc dc4a655c 7fffffff
panic时r5的值是0xdc4a62a8,那么panic时对应的pdev的结构体就是
fc4ba1c0 00000002 c093a570 dc4a4340 dc4ba160 1c4a607c dc4a64fc c093a578
根据上面的结构体层次关系,所以第一个fc4ba1c0就是pdev->name, 第二个是 pdev->id = 00000002, 第三个是结构体 device