~ubuntu-core-dev/module-init-tools/ubuntu

« back to all changes in this revision

Viewing changes to depmod.c

  • Committer: Scott James Remnant
  • Date: 2009-07-16 15:24:17 UTC
  • mfrom: (152.1.38)
  • Revision ID: scott@netsplit.com-20090716152417-7ak1sklxb59cs4fz
MergeĀ 3.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include "depmod.h"
27
27
#include "logging.h"
28
28
#include "index.h"
29
 
#include "moduleops.h"
 
29
#include "elfops.h"
30
30
#include "tables.h"
31
31
#include "config_filter.h"
32
32
 
68
68
{
69
69
        struct symbol *next;
70
70
        struct module *owner;
 
71
        uint64_t ver;
71
72
        char name[0];
72
73
};
73
74
 
86
87
        return (1103515243 * value + 12345);
87
88
}
88
89
 
89
 
void add_symbol(const char *name, struct module *owner)
 
90
void add_symbol(const char *name, uint64_t ver, struct module *owner)
90
91
{
91
92
        unsigned int hash;
92
93
        struct symbol *new = NOFAIL(malloc(sizeof *new + strlen(name) + 1));
93
94
 
94
95
        new->owner = owner;
 
96
        new->ver = ver;
95
97
        strcpy(new->name, name);
96
98
 
97
99
        hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
99
101
        symbolhash[hash] = new;
100
102
}
101
103
 
102
 
static int print_unknown;
 
104
static int print_unknown, check_symvers;
103
105
 
104
 
struct module *find_symbol(const char *name, const char *modname, int weak)
 
106
struct module *find_symbol(const char *name, uint64_t ver,
 
107
                const char *modname, int weak)
105
108
{
106
109
        struct symbol *s;
107
110
 
111
114
 
112
115
        for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) {
113
116
                if (streq(s->name, name))
114
 
                        return s->owner;
 
117
                        break;
 
118
        }
 
119
        if (s) {
 
120
                if (ver && s->ver && s->ver != ver && print_unknown && !weak)
 
121
                        warn("%s disagrees about version of symbol %s\n",
 
122
                                        modname, name);
 
123
                return s->owner;
115
124
        }
116
125
 
117
126
        if (print_unknown && !weak)
132
141
        mod->deps[mod->num_deps++] = depends_on;
133
142
}
134
143
 
 
144
static void add_fake_syms(void)
 
145
{
 
146
        /* __this_module is magic inserted by kernel loader. */
 
147
        add_symbol("__this_module", 0, NULL);
 
148
        /* On S390, this is faked up too */
 
149
        add_symbol("_GLOBAL_OFFSET_TABLE_", 0, NULL);
 
150
}
 
151
 
135
152
static void load_system_map(const char *filename)
136
153
{
137
154
        FILE *system_map;
158
175
 
159
176
                /* Covers gpl-only and normal symbols. */
160
177
                if (strstarts(ptr+1, ksymstr))
161
 
                        add_symbol(ptr+1+ksymstr_len, NULL);
 
178
                        add_symbol(ptr+1+ksymstr_len, 0, NULL);
162
179
        }
163
180
 
164
181
        fclose(system_map);
165
 
 
166
 
        /* __this_module is magic inserted by kernel loader. */
167
 
        add_symbol("__this_module", NULL);
168
 
        /* On S390, this is faked up too */
169
 
        add_symbol("_GLOBAL_OFFSET_TABLE_", NULL);
 
182
        add_fake_syms();
 
183
}
 
184
 
 
185
static void load_module_symvers(const char *filename)
 
186
{
 
187
        FILE *module_symvers;
 
188
        char line[10240];
 
189
 
 
190
        module_symvers = fopen(filename, "r");
 
191
        if (!module_symvers)
 
192
                fatal("Could not open '%s': %s\n", filename, strerror(errno));
 
193
 
 
194
        /* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */
 
195
        while (fgets(line, sizeof(line)-1, module_symvers)) {
 
196
                const char *ver, *sym, *where;
 
197
 
 
198
                ver = strtok(line, " \t");
 
199
                sym = strtok(NULL, " \t");
 
200
                where = strtok(NULL, " \t");
 
201
                if (!ver || !sym || !where)
 
202
                        continue;
 
203
 
 
204
                if (streq(where, "vmlinux"))
 
205
                        add_symbol(sym, strtoull(ver, NULL, 16), NULL);
 
206
        }
 
207
 
 
208
        fclose(module_symvers);
 
209
        add_fake_syms();
170
210
}
171
211
 
172
212
static struct option options[] = { { "all", 0, NULL, 'a' },
173
213
                                   { "quick", 0, NULL, 'A' },
174
214
                                   { "basedir", 1, NULL, 'b' },
 
215
                                   { "config", 1, NULL, 'C' },
 
216
                                   { "symvers", 1, NULL, 'E' },
 
217
                                   { "filesyms", 1, NULL, 'F' },
175
218
                                   { "errsyms", 0, NULL, 'e' },
176
 
                                   { "filesyms", 1, NULL, 'F' },
177
 
                                   { "help", 0, NULL, 'h' },
178
 
                                   { "show", 0, NULL, 'n' },
179
 
                                   { "dry-run", 0, NULL, 'n' },
 
219
                                   { "unresolved-error", 0, NULL, 'u' },
180
220
                                   { "quiet", 0, NULL, 'q' },
181
221
                                   { "root", 0, NULL, 'r' },
182
 
                                   { "unresolved-error", 0, NULL, 'u' },
183
222
                                   { "verbose", 0, NULL, 'v' },
 
223
                                   { "show", 0, NULL, 'n' },
 
224
                                   { "dry-run", 0, NULL, 'n' },
 
225
                                   { "help", 0, NULL, 'h' },
184
226
                                   { "version", 0, NULL, 'V' },
185
 
                                   { "config", 1, NULL, 'C' },
186
 
                                   { "warn", 1, NULL, 'w' },
 
227
                                   { "warn", 0, NULL, 'w' },
187
228
                                   { "map", 0, NULL, 'm' },
188
229
                                   { NULL, 0, NULL, 0 } };
189
230
 
242
283
        "\t    --basedir basedirectory    Use an image of a module tree.\n"
243
284
        "\t-F kernelsyms\n"
244
285
        "\t    --filesyms kernelsyms      Use the file instead of the\n"
245
 
        "\t                               current kernel symbols.\n",
 
286
        "\t                               current kernel symbols.\n"
 
287
        "\t-E Module.symvers\n"
 
288
        "\t    --symvers Module.symvers   Use Module.symvers file to check\n"
 
289
        "\t                               symbol versions.\n",
246
290
        "depmod", "depmod");
247
291
}
248
292
 
276
320
        INIT_LIST_HEAD(&new->dep_list);
277
321
        new->order = INDEX_PRIORITY_MIN;
278
322
 
279
 
        new->data = grab_file(new->pathname, &new->len);
280
 
        if (!new->data) {
 
323
        new->file = grab_elf_file(new->pathname);
 
324
        if (!new->file) {
281
325
                warn("Can't read module %s: %s\n",
282
326
                     new->pathname, strerror(errno));
283
 
                goto fail_data;
 
327
                free(new);
 
328
                return NULL;
284
329
        }
285
 
 
286
 
        switch (elf_ident(new->data, new->len, &new->conv)) {
287
 
        case ELFCLASS32:
288
 
                new->ops = &mod_ops32;
289
 
                break;
290
 
        case ELFCLASS64:
291
 
                new->ops = &mod_ops64;
292
 
                break;
293
 
        case -ENOEXEC:
294
 
                warn("Module %s is not an elf object\n", new->pathname);
295
 
                goto fail;
296
 
        case -EINVAL:
297
 
                warn("Module %s has unknown endianness\n", new->pathname);
298
 
                goto fail;
299
 
        default:
300
 
                warn("Module %s has unknown word size\n", new->pathname);
301
 
                goto fail;
302
 
        }
303
330
        return new;
304
 
 
305
 
fail:
306
 
        release_file(new->data, new->len);
307
 
fail_data:
308
 
        free(new);
309
 
        return NULL;
310
331
}
311
332
 
312
333
struct module_traverse
667
688
        return tlist;
668
689
}
669
690
 
 
691
/* Calculate the dependencies for this module */
 
692
static void calculate_deps(struct module *module)
 
693
{
 
694
        unsigned int i;
 
695
        struct string_table *symnames;
 
696
        struct string_table *symtypes;
 
697
        uint64_t *symvers = NULL;
 
698
        struct elf_file *file;
 
699
 
 
700
        module->num_deps = 0;
 
701
        module->deps = NULL;
 
702
        file = module->file;
 
703
 
 
704
        symnames = file->ops->load_dep_syms(file, &symtypes,
 
705
                        check_symvers ? &symvers : NULL);
 
706
        if (!symnames || !symtypes)
 
707
                return;
 
708
 
 
709
        for (i = 0; i < symnames->cnt; i++) {
 
710
                const char *name;
 
711
                uint64_t ver;
 
712
                struct module *owner;
 
713
                int weak;
 
714
 
 
715
                name = symnames->str[i];
 
716
                ver = symvers ? symvers[i] : 0;
 
717
                weak = (*(symtypes->str[i]) == 'W');
 
718
                owner = find_symbol(name, ver, module->pathname, weak);
 
719
                if (owner) {
 
720
                        info("%s needs \"%s\": %s\n",
 
721
                               module->pathname, name,
 
722
                               owner->pathname);
 
723
                        add_dep(module, owner);
 
724
                }
 
725
        }
 
726
 
 
727
        free(symnames);
 
728
        free(symtypes);
 
729
        free(symvers);
 
730
}
 
731
 
670
732
static struct module *parse_modules(struct module *list)
671
733
{
672
734
        struct module *i;
 
735
        struct elf_file *file;
 
736
        struct string_table *syms;
 
737
        int j;
673
738
 
674
739
        for (i = list; i; i = i->next) {
675
 
                i->ops->load_symbols(i);
676
 
                i->ops->fetch_tables(i);
 
740
                uint64_t *symvers = NULL;
 
741
                file = i->file;
 
742
                syms = file->ops->load_symbols(file,
 
743
                                check_symvers ? &symvers : NULL);
 
744
                if (syms) {
 
745
                        for (j = 0; j < syms->cnt; j++)
 
746
                                add_symbol(syms->str[j],
 
747
                                        symvers ? symvers[j] : 0, i);
 
748
                        strtbl_free(syms);
 
749
                }
 
750
                free(symvers);
 
751
                file->ops->fetch_tables(file, &i->tables);
677
752
        }
678
753
        
679
754
        for (i = list; i; i = i->next)
680
 
                i->ops->calculate_deps(i);
 
755
                calculate_deps(i);
681
756
        
682
757
        /* Strip out modules with dependency loops. */
683
758
 again:
747
822
static void output_aliases(struct module *modules, FILE *out, char *dirname)
748
823
{
749
824
        struct module *i;
750
 
        const char *p;
751
 
        unsigned long size;
 
825
        struct elf_file *file;
 
826
        struct string_table *tbl;
 
827
        int j;
752
828
 
753
829
        fprintf(out, "# Aliases extracted from modules themselves.\n");
754
830
        for (i = modules; i; i = i->next) {
755
831
                char modname[strlen(i->pathname)+1];
756
832
 
 
833
                file = i->file;
757
834
                filename2modname(modname, i->pathname);
758
835
 
759
836
                /* Grab from old-style .modalias section. */
760
 
                for (p = i->ops->get_aliases(i, &size);
761
 
                     p;
762
 
                     p = next_string(p, &size))
763
 
                        fprintf(out, "alias %s %s\n", p, modname);
 
837
                tbl = file->ops->load_strings(file, ".modalias", NULL, fatal);
 
838
                for (j = 0; tbl && j < tbl->cnt; j++)
 
839
                        fprintf(out, "alias %s %s\n", tbl->str[j], modname);
 
840
                strtbl_free(tbl);
764
841
 
765
 
                /* Grab form new-style .modinfo section. */
766
 
                for (p = i->ops->get_modinfo(i, &size);
767
 
                     p;
768
 
                     p = next_string(p, &size)) {
 
842
                /* Grab from new-style .modinfo section. */
 
843
                tbl = file->ops->load_strings(file, ".modinfo", NULL, fatal);
 
844
                for (j = 0; tbl && j < tbl->cnt; j++) {
 
845
                        const char *p = tbl->str[j];
769
846
                        if (strstarts(p, "alias="))
770
847
                                fprintf(out, "alias %s %s\n",
771
848
                                        p + strlen("alias="), modname);
772
849
                }
 
850
                strtbl_free(tbl);
773
851
        }
774
852
}
775
853
 
776
854
static void output_aliases_bin(struct module *modules, FILE *out, char *dirname)
777
855
{
778
856
        struct module *i;
779
 
        const char *p;
 
857
        struct elf_file *file;
 
858
        struct string_table *tbl;
 
859
        int j;
780
860
        char *alias;
781
 
        unsigned long size;
782
861
        struct index_node *index;
783
862
        int duplicate;
784
863
 
787
866
        for (i = modules; i; i = i->next) {
788
867
                char modname[strlen(i->pathname)+1];
789
868
 
 
869
                file = i->file;
790
870
                filename2modname(modname, i->pathname);
791
871
 
792
872
                /* Grab from old-style .modalias section. */
793
 
                for (p = i->ops->get_aliases(i, &size);
794
 
                     p;
795
 
                     p = next_string(p, &size)) {
796
 
                        alias = NOFAIL(strdup(p));
 
873
                tbl = file->ops->load_strings(file, ".modalias", NULL, fatal);
 
874
                for (j = 0; tbl && j < tbl->cnt; j++) {
 
875
                        alias = NOFAIL(strdup(tbl->str[j]));
797
876
                        underscores(alias);
798
877
                        duplicate = index_insert(index, alias, modname, i->order);
799
878
                        if (duplicate && warn_dups)
801
880
                                        alias, modname);
802
881
                        free(alias);
803
882
                }
 
883
                strtbl_free(tbl);
804
884
 
805
885
                /* Grab from new-style .modinfo section. */
806
 
                for (p = i->ops->get_modinfo(i, &size);
807
 
                     p;
808
 
                     p = next_string(p, &size)) {
 
886
                tbl = file->ops->load_strings(file, ".modinfo", NULL, fatal);
 
887
                for (j = 0; tbl && j < tbl->cnt; j++) {
 
888
                        const char *p = tbl->str[j];
809
889
                        if (strstarts(p, "alias=")) {
810
890
                                alias = NOFAIL(strdup(p + strlen("alias=")));
811
891
                                underscores(alias);
816
896
                                free(alias);
817
897
                        }
818
898
                }
 
899
                strtbl_free(tbl);
819
900
        }
820
901
        
821
902
        index_write(index, out);
1147
1228
int main(int argc, char *argv[])
1148
1229
{
1149
1230
        int opt, all = 0, maybe_all = 0, doing_stdout = 0;
1150
 
        char *basedir = "", *dirname, *version, *badopt = NULL,
1151
 
                *system_map = NULL;
 
1231
        char *basedir = "", *dirname, *version;
 
1232
        char *system_map = NULL, *module_symvers = NULL;
1152
1233
        int i;
1153
1234
        const char *config = NULL;
1154
1235
 
1155
1236
        if (native_endianness() == 0)
1156
1237
                abort();
1157
1238
 
1158
 
        /* Don't print out any errors just yet, we might want to exec
1159
 
           backwards compat version. */
1160
 
        opterr = 0;
1161
 
        while ((opt = getopt_long(argc, argv, "ab:ArehnqruvVF:C:wm", options, NULL))
 
1239
        while ((opt = getopt_long(argc, argv, "aAb:C:E:F:euqrvnhVwm", options, NULL))
1162
1240
               != -1) {
1163
1241
                switch (opt) {
1164
1242
                case 'a':
1165
1243
                        all = 1;
1166
1244
                        break;
 
1245
                case 'A':
 
1246
                        maybe_all = 1;
 
1247
                        break;
1167
1248
                case 'b':
1168
1249
                        basedir = optarg;
1169
1250
                        skipchars = strlen(basedir);
1170
1251
                        break;
1171
 
                case 'A':
1172
 
                        maybe_all = 1;
 
1252
                case 'C':
 
1253
                        config = optarg;
 
1254
                        break;
 
1255
                case 'E':
 
1256
                        module_symvers = optarg;
 
1257
                        check_symvers = 1;
1173
1258
                        break;
1174
1259
                case 'F':
1175
1260
                        system_map = optarg;
1177
1262
                case 'e':
1178
1263
                        print_unknown = 1;
1179
1264
                        break;
1180
 
                case 'v':
1181
 
                        verbose = 1;
1182
 
                        break;
1183
1265
                case 'u':
1184
1266
                case 'q':
1185
1267
                case 'r':
1186
1268
                        break;
1187
 
                case 'C':
1188
 
                        config = optarg;
1189
 
                        break;
1190
 
                case 'h':
1191
 
                        print_usage(argv[0]);
1192
 
                        exit(0);
 
1269
                case 'v':
 
1270
                        verbose = 1;
1193
1271
                        break;
1194
1272
                case 'n':
1195
1273
                        doing_stdout = 1;
1196
1274
                        break;
 
1275
                case 'h':
 
1276
                        print_usage(argv[0]);
 
1277
                        exit(0);
 
1278
                        break;
1197
1279
                case 'V':
1198
1280
                        printf("%s %s\n", PACKAGE, VERSION);
1199
1281
                        exit(0);
1204
1286
                        force_map_files = 1;
1205
1287
                        break;
1206
1288
                default:
1207
 
                        badopt = argv[optind-1];
 
1289
                        print_usage(argv[0]);
 
1290
                        exit(1);
1208
1291
                }
1209
1292
        }
1210
1293
 
1211
 
        /* We can't print unknowns without a System.map */
1212
 
        if (!system_map)
 
1294
        if (module_symvers)
 
1295
                load_module_symvers(module_symvers);
 
1296
        else if (system_map)
 
1297
                load_system_map(system_map);
 
1298
        else if (print_unknown) {
 
1299
                warn("-e needs -E or -F");
1213
1300
                print_unknown = 0;
1214
 
        else
1215
 
                load_system_map(system_map);
 
1301
        }
1216
1302
 
1217
1303
        /* They can specify the version naked on the command line */
1218
1304
        if (optind < argc && is_version_number(argv[optind])) {
1231
1317
                exit(2);
1232
1318
        }
1233
1319
 
1234
 
        if (badopt) {
1235
 
                fprintf(stderr, "%s: malformed/unrecognized option '%s'\n",
1236
 
                        argv[0], badopt);
1237
 
                print_usage(argv[0]);
1238
 
                exit(1);
1239
 
        }
1240
 
 
1241
1320
        /* Depmod -a by default if no names. */
1242
1321
        if (optind == argc)
1243
1322
                all = 1;