在linux环境下编写at24c02的驱动程序时,出现segmentation fault的错误提示,具体提示如下图
从后往前看发现调用关系是sys_ioctl->do_vfs_ioctl->at24c02_ioctl,将问题定位至at24c02_ioctl函数处,该函数源码如下,该函数被at24c02_drv.c文件包含,生成的驱动文件是at24c02_drv.ko
static long at24c02_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned char addr;
unsigned char data;
unsigned int ker_buf[2];
unsigned int *usr_buf = (unsigned int *)arg;
unsigned char byte_buf[2];
struct i2c_msg msgs[2];
copy_from_user(ker_buf, usr_buf, 8);
addr = ker_buf[0];
switch (cmd)
{
case IOC_AT24C02_READ:
{
/* 璇籄T24C02 */
msgs[0].addr = at24c02_client.addr;
msgs[0].flags = 0; /* 鍐?*/
msgs[0].len = 1;
msgs[0].buf = &addr;
msgs[1].addr = at24c02_client.addr;
msgs[1].flags = I2C_M_RD; /* 璇?*/
msgs[1].len = 1;
msgs[1].buf = &data;
i2c_transfer(at24c02_client->adapter, msgs, 2);
ker_buf[1] = data;
copy_from_user(usr_buf, ker_buf, 8);
break;
}
case IOC_AT24C02_WRITE:
{
/* 鍐橝T24C02 */
byte_buf[0] = addr;
byte_buf[1] = ker_buf[1];
msgs[0].addr = at24c02_client.addr;
msgs[0].flags = 0; /* 鍐?*/
msgs[0].len = 2;
msgs[0].buf = byte_buf;
i2c_transfer(at24c02_client->adapter, msgs, 1);
mdelay(20);
break;
}
}
}
想要定位问题现将驱动文件反汇编,具体命令是arm-linux-objdump -D at24c02_drv.ko > at24c02.dis,再使用vim at24c02.dis查看具体内容,在反汇编文件中直接查找at24c02_ioctl,发现起始机器码是0074,图一中LR指向ioctl+0x1dc,则0x74+0x1dc=250,说明错误发生处是机器码为250的地方,
结合250上下处的汇编语句,判断copy_from_user使用错误,应该为copy_to_user