I meet a ghost bug, this almost kills me…
The source code is as simple as the following:
struct fbusb_par {
struct usb_interface *interface;
u32 palette[PSEUDO_PALETTE_SIZE];
};
static int fbusb_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct fb_info *info;
info = framebuffer_alloc(sizeof(struct fbusb_par), &interface->dev);
if (!info)
return -ENOMEM;
par = info->par;
par->interface = interface;
return 0;
}
static void fbusb_disconnect(struct usb_interface *interface)
{
dev_info(&interface->dev,
"framebuffer device now disconnected.\n");
}
static const struct usb_device_id fbusb_ids[] = {
{ USB_DEVICE(0x04b4, 0x1004) },
{ }
};
MODULE_DEVICE_TABLE(usb, fbusb_ids);
static struct usb_driver fbusb_driver = {
.name = "fbusb",
.probe = fbusb_probe,
.disconnect = fbusb_disconnect,
.id_table = fbusb_ids,
};
module_usb_driver(fbusb_driver);
The mysterious bug is this driver crashed at par->interface = interface; and after debug, par is a null pointer, but info is not a null pointer! Let’s check framebuffer_alloc source code, if return info is correct, there is no way par to be null pointer.
struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
{
#define BYTES_PER_LONG (BITS_PER_LONG/8)
#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
int fb_info_size = sizeof(struct fb_info);
struct fb_info *info;
char *p;
if (size)
fb_info_size += PADDING;
p = kzalloc(fb_info_size + size, GFP_KERNEL);
if (!p)
return NULL;
info = (struct fb_info *) p;
if (size)
info->par = p + fb_info_size;
info->device = dev;
#ifdef CONFIG_FB_BACKLIGHT
mutex_init(&info->bl_curve_mutex);
#endif
return info;
#undef PADDING
#undef BYTES_PER_LONG
}
EXPORT_SYMBOL(framebuffer_alloc);
Also step into this framebuffer_alloc function, in this function info->par is not null and its value is correct. So what is happening once info returned? who changed info->par to null? This is really weird bug…I have never seen such thing before.
PS: I guess I find the problem. If I put the source into Linux source code, it will report some .ko is missing, but if I move it to package/kernel as a package, it will happen that weird problem. So it is package missing problem.