lkml.org 
[lkml]   [1998]   [Jul]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
SubjectMysterious unresolved externals in driver
Date
I am 'writing' a simple char driver as a self-tutorial by copy-n-tweaking out of 'LINUX Device Drivers'. I had a simple 'scull' driver running (not correctly, but running), then made a few edits and rebuilt. When I run insmod, I get an error, 'Unresolved symbol: __divdi3'. There is indeed no such symbol in my file, but there never was. Running 'nm' flags a whole host of symbols as unresolved, including register_chrdev() and others, all from the  kernel(kmalloc, kfree, etc). Yes, the file is compiling and linking with the same makefile, on the same machine, with the same set of input files as before. Yes, it did compile, link, load, and run before. Moreover, the sample stuff I got with the book  still works fine (compile, link, and load). Yes, I did rm -f /dev/mydev, rmmod mydev, reboot, and recreate the device and run insmod again. Yes, I touched the input files and forced a complete rebuild. 
Naturally, we must suspect my edits are to blame, but I have reviewed my changes and am unable to see what could be screwing up linkages to kernel symbols.
So ... what's wrong? In general, how do I make sure I am linking in the kernel stuff properly? Any ideas why this went south? I am on Red Hat 5.0, 2.0.31 kernel, using stock GNU tools which I have not changed lately. The entire project is attached for masochists - it's not very big.

Thanks gobs
=Eric
PS. Yes, I did define __KERNEL__ and MODULE at the top of my only source
file, before the #include's.

/****cut here*******
/*
main.c
*/
#ifndef __KERNEL__
#define __KERNEL__
#endif

#ifndef MODULE
#define MODULE
#endif


#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/segment.h>

#include "d0.h"

int d0_major = D0_MAJOR;
int d0_nr_devs = D0_NR_DEVS;

d0_dev *devlist, *curdev;

struct file_operations d0_fops =
{
NULL,
d0_read,
d0_write,
NULL,
NULL,
NULL,
NULL,
d0_open,
d0_release,
NULL,
};

int init_module(void)
{
int num;
printk(KERN_CRIT "Entering init_module()\n");
if((devlist = (d0_dev *)kmalloc(sizeof(d0_dev), GFP_KERNEL)) == 0)
return -ENOMEM;

curdev = devlist;

printk(KERN_CRIT"init_module() created device at %p\n", curdev);

num = register_chrdev(d0_major, "d0", &d0_fops);
//need error trap here
return num;
}

void cleanup_module(void)
{
unregister_chrdev(d0_major, "d0");
trimlist(devlist);
kfree(devlist);
}

int d0_open(struct inode *inode, struct file *fp)
{
int type = TYPE(inode->i_rdev);
//int num = NUM(inode->i_rdev);

printk(KERN_CRIT"d0_open() entered\n");

if(type)
{
if(type > MAX_TYPE)
return -ENODEV;
fp->f_op = &d0_fops;
return fp->f_op->open(inode, fp);
}

if((fp->f_flags & O_ACCMODE) == O_WRONLY)
trimlist(curdev = devlist);

fp->private_data = devlist;

MOD_INC_USE_COUNT;
return 0;
}

void d0_release(struct inode *inode, struct file * fp)
{
trimlist(curdev = devlist);
MOD_DEC_USE_COUNT;
}

int d0_read(struct inode *inode, struct file * fp, char *buf, int buflen)
{
unsigned long f_pos = fp->f_pos;
printk(KERN_CRIT"d0_read() entered\n");
curdev = get_cur_dev(curdev ? curdev : devlist, fp->f_pos/sizeof(devlist->data));

if(f_pos + buflen > sizeof(devlist->data))
buflen = sizeof(devlist->data) - f_pos;

printk(KERN_CRIT"d0_read() sets buflen to %d\n", buflen);
memcpy_tofs(buf, curdev->data + f_pos, buflen);
fp->f_pos += buflen;
return buflen;
}

int d0_write(struct inode *inode, struct file * fp, const char * buf, int buflen)
{
unsigned long dev_no;
unsigned long f_pos = fp->f_pos;

f_pos = (unsigned long)fp->f_pos % sizeof(devlist->data); //offset
dev_no = (unsigned long)fp->f_pos / sizeof(devlist->data); //index
printk(KERN_CRIT "d0_write() says f_pos is %ld, dev_no is %ld\n", f_pos, dev_no);
curdev = get_cur_dev(curdev ? curdev : devlist, dev_no);

if(f_pos + buflen > sizeof(devlist->data))
{
buflen = sizeof(devlist->data) - f_pos;
printk(KERN_CRIT "d0_write trimmed buflen\n");
}

printk(KERN_CRIT "d0_write() set buflen to %d\n", buflen);

if(buflen == 0)
{
printk(KERN_CRIT "Buffer overrun, size is %d\n", buflen);
curdev->next = (d0_dev *)kmalloc(sizeof(d0_dev), GFP_KERNEL);
if(curdev->next == 0)
return -ENOMEM;

curdev = curdev->next;
return 0;
}

memcpy_fromfs(curdev->data + f_pos, buf, buflen);
fp->f_pos += buflen;

return buflen;
}

struct d0_dev *get_cur_dev(struct d0_dev *d, unsigned long index)
{
unsigned long current_offset;
d0_dev *dret;
printk(KERN_CRIT"get_cur_dev() entered\n");

if(!d)
{
printk(KERN_CRIT"get_cur_dev() got a null pointer!\n");
return 0;
}

printk(KERN_CRIT"get_cur_dev() about to get offset using ptr %p\n", d);

//can walk forward, but 'backward' walks of SLL require going to the
//head and starting over

for(dret = devlist, current_offset = 0; (current_offset < index) && dret; dret = d->next)
;
printk(KERN_CRIT"Leaving get_cur_dev(), returning %p\n", dret);
return dret;
}

int trimlist(d0_dev * list)
{
int i;
for(i = 0, list = list->next; list; list = list->next, ++i)
kfree(list);

printk(KERN_CRIT"trimlist wiped out %d items\n", i);
return i;
}




/********cut here *************/
/*
d0.h
*/
#define D0_MAJOR 64
#define D0_NR_DEVS 1
#define MAX_TYPE 5

#define TYPE(dev) (MINOR(dev) >> 4)
#define NUM(dev) (MINOR(dev) & 0xf)

typedef struct d0_dev{
char data[0x100 - sizeof(struct d0_dev *)];
struct d0_dev *next;
} d0_dev;

int d0_open(struct inode *inode, struct file *fp);
void d0_release(struct inode *inode, struct file *fp);
int d0_read(struct inode *inode, struct file * fp, char *buf, int buflen);
int d0_write(struct inode *inode, struct file * fp, const char * buf, int buflen);
struct d0_dev *get_cur_dev(struct d0_dev *d, unsigned long offset);
int trimlist(d0_dev * list);


#makefile
MAKEFILE=Makefile
SRCS = main.c
HEADERS = d0.h

d0.o : $(SRCS) $(HEADERS) $(MAKEFILE)
cc -c -O -Wall -o d0.o $(SRCS)




-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu

\
 
 \ /
  Last update: 2005-03-22 13:43    [W:0.044 / U:0.020 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site