- 论坛徽章:
- 0
|
本帖最后由 Godbach 于 2010-08-30 11:45 编辑
unsigned long
get_syscall_from_kallsyms(arch_t arch)
{
unsigned long syscall_entry;
struct nameidata nd;
const char *path_str = "/proc/kallsyms";
const char *symbol_str;
struct vfsmount *old_mnt;
struct dentry *old_dentry;
int err = 0;
void *p;
struct seq_file *m;
struct kallsym_iter *iter;
struct file *kallsyms_file;
loff_t index = 0;
void *old_buf;
switch(arch) {
case ARCH_X86_64:
symbol_str = "system_call";
break;
case ARCH_X86:
symbol_str = "ia32_syscall";
break;
default:
return 0;
}
old_mnt = current->fs->rootmnt;
old_dentry = current->fs->root;
nd.mnt = mntget(current->fs->rootmnt);
nd.dentry = dget(current->fs->root);
nd.last_type = LAST_ROOT;
nd.flags = LOOKUP_FOLLOW | LOOKUP_NOALT;
nd.depth = 0;
if ((err = path_walk(path_str, &nd)) == 0) {
kallsyms_file = dentry_open(nd.dentry, nd.mnt, O_RDWR);
if (kallsyms_file == NULL) {
printk("[%s] can not open kallsyms file\n",
__FUNCTION__);
syscall_entry = -EIO;
goto out;
}
m = kallsyms_file->private_data;
m->version = kallsyms_file->f_version;
mutex_lock(&m->lock);
old_buf = m->buf;
m->buf = kmalloc(m->size = KSYM_SYMBOL_LEN, GFP_KERNEL);
iter = m->private;
while (1) {
p = m->op->start(m, &index);
err = PTR_ERR(p);
if (!p || IS_ERR(p)) {
syscall_entry = err;
break;
}
m->count = 0;
m->op->show(m, p);
if (!strncmp(m->buf + sizeof("%s+%#lx/%#lx [%s]") + 1,
symbol_str,
strlen(symbol_str))) {
m->buf[2 * sizeof(void *)] = 0;
sscanf(m->buf, "%lx", &syscall_entry);
break;
}
m->op->stop(m, p);
index++;
}
m->op->stop(m, p);
m->count = 0;
m->size = 0;
kfree(m->buf);
m->buf = old_buf;
mutex_unlock(&m->lock);
filp_close(kallsyms_file, NULL);
} else {
printk("[%s] path_walk failed %d\n", __FUNCTION__, err);
}
out:
dput(old_dentry);
mntput(old_mnt);
return syscall_entry;
} |
|
|