?? depmod.c
字號:
/* New simplified depmod without backwards compat stuff and not requiring ksyms. (C) 2002 Rusty Russell IBM Corporation */#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <getopt.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <elf.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <dirent.h>#include <sys/utsname.h>#include <sys/mman.h>#include "zlibsupport.h"#include "depmod.h"#include "moduleops.h"#include "tables.h"#include "testing.h"/* I hate strcmp. */#define streq(a,b) (strcmp((a),(b)) == 0)#ifndef MODULE_DIR#define MODULE_DIR "/lib/modules/"#endifstatic int verbose;static unsigned int skipchars;void fatal(const char *fmt, ...){ va_list arglist; fprintf(stderr, "FATAL: "); va_start(arglist, fmt); vfprintf(stderr, fmt, arglist); va_end(arglist); exit(1);}void warn(const char *fmt, ...){ va_list arglist; fprintf(stderr, "WARNING: "); va_start(arglist, fmt); vfprintf(stderr, fmt, arglist); va_end(arglist);}void *do_nofail(void *ptr, const char *file, int line, const char *expr){ if (!ptr) { fatal("Memory allocation failure %s line %d: %s.\n", file, line, expr); } return ptr;}#define SYMBOL_HASH_SIZE 1024struct symbol{ struct symbol *next; struct module *owner; char name[0];};static struct symbol *symbolhash[SYMBOL_HASH_SIZE];/* This is based on the hash agorithm from gdbm, via tdb */static inline unsigned int tdb_hash(const char *name){ unsigned value; /* Used to compute the hash value. */ unsigned i; /* Used to cycle through random values. */ /* Set the initial value from the key size. */ for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); return (1103515243 * value + 12345);}void add_symbol(const char *name, struct module *owner){ unsigned int hash; struct symbol *new = NOFAIL(malloc(sizeof *new + strlen(name) + 1)); new->owner = owner; strcpy(new->name, name); hash = tdb_hash(name) % SYMBOL_HASH_SIZE; new->next = symbolhash[hash]; symbolhash[hash] = new;}static int print_unknown;struct module *find_symbol(const char *name, const char *modname, int weak){ struct symbol *s; /* For our purposes, .foo matches foo. PPC64 needs this. */ if (name[0] == '.') name++; for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) { if (streq(s->name, name)) return s->owner; } if (print_unknown && !weak) warn("%s needs unknown symbol %s\n", modname, name); return NULL;}void add_dep(struct module *mod, struct module *depends_on){ unsigned int i; for (i = 0; i < mod->num_deps; i++) if (mod->deps[i] == depends_on) return; mod->deps = realloc(mod->deps, sizeof(mod->deps[0])*(mod->num_deps+1)); mod->deps[mod->num_deps++] = depends_on;}static void load_system_map(const char *filename){ FILE *system_map; char line[10240]; system_map = fopen(filename, "r"); if (!system_map) fatal("Could not open '%s': %s\n", filename, strerror(errno)); /* eg. c0294200 R __ksymtab_devfs_alloc_devnum */ while (fgets(line, sizeof(line)-1, system_map)) { char *ptr; /* Snip \n */ ptr = strchr(line, '\n'); *ptr = '\0'; ptr = strchr(line, ' '); if (!ptr || !(ptr = strchr(ptr + 1, ' '))) continue; /* Covers gpl-only and normal symbols. */ if (strncmp(ptr+1, "__ksymtab_", strlen("__ksymtab_")) == 0) add_symbol(ptr+1+strlen("__ksymtab_"), NULL); } /* __this_module is magic inserted by kernel loader. */ add_symbol("__this_module", NULL); /* On S390, this is faked up too */ add_symbol("_GLOBAL_OFFSET_TABLE_", NULL);}static struct option options[] = { { "all", 0, NULL, 'a' }, { "quick", 0, NULL, 'A' }, { "basedir", 1, NULL, 'b' }, { "errsyms", 0, NULL, 'e' }, { "filesyms", 1, NULL, 'F' }, { "help", 0, NULL, 'h' }, { "show", 0, NULL, 'n' }, { "dry-run", 0, NULL, 'n' }, { "quiet", 0, NULL, 'q' }, { "root", 0, NULL, 'r' }, { "unresolved-error", 0, NULL, 'u' }, { "verbose", 0, NULL, 'v' }, { "version", 0, NULL, 'V' }, /* Obsolete, but we need to parse it. */ { "config", 1, NULL, 'C' }, { NULL, 0, NULL, 0 } };/* Version number or module name? Don't assume extension. */static int is_version_number(const char *version){ unsigned int dummy; return (sscanf(version, "%u.%u.%u", &dummy, &dummy, &dummy) == 3);}static int old_module_version(const char *version){ /* Expect three part version. */ unsigned int major, sub, minor; sscanf(version, "%u.%u.%u", &major, &sub, &minor); if (major > 2) return 0; if (major < 2) return 1; /* 2.x */ if (sub > 5) return 0; if (sub < 5) return 1; /* 2.5.x */ if (minor >= 48) return 0; return 1;}static void exec_old_depmod(char *argv[]){ char *sep; char pathname[strlen(argv[0])+1]; char oldname[strlen("depmod") + strlen(argv[0]) + sizeof(".old")]; memset(pathname, 0, strlen(argv[0])+1); sep = strrchr(argv[0], '/'); if (sep) memcpy(pathname, argv[0], sep - argv[0]+1); sprintf(oldname, "%s%s.old", pathname, "depmod"); /* Recursion detection: we need an env var since we can't change argv[0] (as older modutils uses it to determine behavior). */ if (getenv("MODULE_RECURSE")) return; setenv("MODULE_RECURSE", "y", 0); execvp(oldname, argv); fprintf(stderr, "Version requires old depmod, but couldn't run %s: %s\n", oldname, strerror(errno)); exit(2);}static void print_usage(const char *name){ fprintf(stderr, "%s " VERSION " -- part of " PACKAGE "\n" "%s -[aA] [-n -e -v -q -V -r -u]\n" " [-b basedirectory] [forced_version]\n" "depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.o module2.o ...\n" "If no arguments (except options) are given, \"depmod -a\" is assumed\n" "\n" "depmod will output a dependancy list suitable for the modprobe utility.\n" "\n" "\n" "Options:\n" "\t-a, --all Probe all modules\n" "\t-n, --show Write the dependency file on stdout only\n" "\t-V, --version Print the release version\n" "\t-h, --help Print this usage message\n" "\n" "The following options are useful for people managing distributions:\n" "\t-b basedirectory\n" "\t --basedir basedirectory Use an image of a module tree.\n" "\t-F kernelsyms\n" "\t --filesyms kernelsyms Use the file instead of the\n" "\t current kernel symbols.\n", "depmod", "depmod");}static int ends_in(const char *name, const char *ext){ unsigned int namelen, extlen; /* Grab lengths */ namelen = strlen(name); extlen = strlen(ext); if (namelen < extlen) return 0; if (streq(name + namelen - extlen, ext)) return 1; return 0;}static struct module *grab_module(const char *dirname, const char *filename, struct module *next){ struct module *new; new = NOFAIL(malloc(sizeof(*new) + strlen(dirname) + 1 + strlen(filename) + 1)); sprintf(new->pathname, "%s/%s", dirname, filename); INIT_LIST_HEAD(&new->dep_list); new->data = grab_file(new->pathname, &new->len); if (!new->data) { warn("Can't read module %s: %s\n", new->pathname, strerror(errno)); goto fail_data; } /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */ if (memcmp(new->data, ELFMAG, SELFMAG) != 0) { warn("Module %s is not an elf object\n", new->pathname); goto fail; } switch (((char *)new->data)[EI_CLASS]) { case ELFCLASS32: new->ops = &mod_ops32; break; case ELFCLASS64: new->ops = &mod_ops64; break; default: warn("Module %s has elf unknown identifier %i\n", new->pathname, ((char *)new->data)[EI_CLASS]); goto fail; } new->ops->load_symbols(new); new->ops->fetch_tables(new); new->next = next; return new;fail: release_file(new->data, new->len);fail_data: free(new); return next;}struct module_traverse{ struct module_traverse *prev; struct module *mod;};static int in_loop(struct module *mod, const struct module_traverse *traverse){ const struct module_traverse *i; for (i = traverse; i; i = i->prev) { if (i->mod == mod) return 1; } return 0;}static char *basename(const char *name){ const char *base = strrchr(name, '/'); if (base) return (char *)base + 1; return (char *)name;}/* Assume we are doing all the modules, so only report each loop once. */static void report_loop(const struct module *mod, const struct module_traverse *traverse){ const struct module_traverse *i; /* Check that start is least alphabetically. eg. a depends on b depends on a will get reported for a, not b. */ for (i = traverse->prev; i->prev; i = i->prev) { if (strcmp(mod->pathname, i->mod->pathname) > 0) return; } /* Is start in the loop? If not, don't report now. eg. a depends on b which depends on c which depends on b. Don't report when generating depends for a. */ if (mod != i->mod) return; warn("Loop detected: %s ", mod->pathname); for (i = traverse->prev; i->prev; i = i->prev) fprintf(stderr, "needs %s ", basename(i->mod->pathname)); fprintf(stderr, "which needs %s again!\n", basename(mod->pathname));}/* This is damn slow, but loops actually happen, and we don't want to just exit() and leave the user without any modules. */static int has_dep_loop(struct module *module, struct module_traverse *prev){ unsigned int i; struct module_traverse traverse = { .prev = prev, .mod = module }; if (in_loop(module, prev)) { report_loop(module, &traverse); return 1; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -