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

« back to all changes in this revision

Viewing changes to elfops_core.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:
 
1
#if defined(ELF32BIT)
 
2
 
 
3
#define PERBIT(x) x##32
 
4
#define ElfPERBIT(x) Elf32_##x
 
5
#define ELFPERBIT(x) ELF32_##x
 
6
/* 32-bit unsigned integer */
 
7
#define Elf32_Uint Elf32_Word
 
8
 
 
9
#elif defined(ELF64BIT)
 
10
 
 
11
#define PERBIT(x) x##64
 
12
#define ElfPERBIT(x) Elf64_##x
 
13
#define ELFPERBIT(x) ELF64_##x
 
14
/* 64-bit unsigned integer */
 
15
#define Elf64_Uint Elf64_Xword
 
16
 
 
17
#else
 
18
#  error "Undefined ELF word length"
 
19
#endif
 
20
 
 
21
static void *PERBIT(get_section)(struct elf_file *module,
 
22
                                 const char *secname,
 
23
                                 ElfPERBIT(Shdr) **sechdr,
 
24
                                 unsigned long *secsize)
 
25
{
 
26
        void *data = module->data;
 
27
        unsigned long len = module->len;
 
28
        int conv = module->conv;
 
29
 
 
30
        ElfPERBIT(Ehdr) *hdr;
 
31
        ElfPERBIT(Shdr) *sechdrs;
 
32
        ElfPERBIT(Off) e_shoff;
 
33
        ElfPERBIT(Half) e_shnum, e_shstrndx;
 
34
        ElfPERBIT(Off) secoffset;
 
35
 
 
36
        const char *secnames;
 
37
        unsigned int i;
 
38
 
 
39
        *secsize = 0;
 
40
 
 
41
        if (len <= 0 || len < sizeof(*hdr))
 
42
                return NULL;
 
43
 
 
44
        hdr = data;
 
45
        e_shoff = END(hdr->e_shoff, conv);
 
46
        e_shnum = END(hdr->e_shnum, conv);
 
47
        e_shstrndx = END(hdr->e_shstrndx, conv);
 
48
 
 
49
        if (len < e_shoff + e_shnum * sizeof(sechdrs[0]))
 
50
                return NULL;
 
51
 
 
52
        sechdrs = data + e_shoff;
 
53
 
 
54
        if (len < END(sechdrs[e_shstrndx].sh_offset, conv))
 
55
                return NULL;
 
56
 
 
57
        /* Find section by name; return header, pointer and size. */
 
58
        secnames = data + END(sechdrs[e_shstrndx].sh_offset, conv);
 
59
        for (i = 1; i < e_shnum; i++) {
 
60
                if (streq(secnames + END(sechdrs[i].sh_name, conv), secname)) {
 
61
                        *secsize = END(sechdrs[i].sh_size, conv);
 
62
                        secoffset = END(sechdrs[i].sh_offset, conv);
 
63
                        if (sechdr)
 
64
                                *sechdr = sechdrs + i;
 
65
                        if (len < secoffset + *secsize)
 
66
                                return NULL;
 
67
                        return data + secoffset;
 
68
                }
 
69
        }
 
70
        return NULL;
 
71
}
 
72
 
 
73
/* Load the given section: NULL on error. */
 
74
static void *PERBIT(load_section)(struct elf_file *module,
 
75
                                  const char *secname,
 
76
                                  unsigned long *secsize)
 
77
{
 
78
        return PERBIT(get_section)(module, secname, NULL, secsize);
 
79
}
 
80
 
 
81
static struct string_table *PERBIT(load_strings)(struct elf_file *module,
 
82
                                                 const char *secname,
 
83
                                                 struct string_table *tbl,
 
84
                                                 errfn_t error)
 
85
{
 
86
        unsigned long size;
 
87
        const char *strings;
 
88
 
 
89
        strings = PERBIT(load_section)(module, secname, &size);
 
90
        if (strings) {
 
91
                /* Skip any zero padding. */
 
92
                while (!strings[0]) {
 
93
                        strings++;
 
94
                        if (size-- <= 1)
 
95
                                return tbl;
 
96
                }
 
97
                for (; strings; strings = next_string(strings, &size))
 
98
                        tbl = NOFAIL(strtbl_add(strings, tbl));
 
99
        }
 
100
        return tbl;
 
101
}
 
102
 
 
103
static struct string_table *PERBIT(load_symbols)(struct elf_file *module,
 
104
                                                 uint64_t **versions)
 
105
{
 
106
        struct string_table *symtbl = NULL;
 
107
 
 
108
        if (versions) {
 
109
                static const char crc[] = "__crc_";
 
110
                static const int crc_len = sizeof(crc) - 1;
 
111
                unsigned int num_syms, i;
 
112
                unsigned long size;
 
113
                ElfPERBIT(Sym) *syms;
 
114
                char *strings;
 
115
                int conv;
 
116
 
 
117
                *versions = NULL;
 
118
                strings = PERBIT(load_section)(module, ".strtab", &size);
 
119
                syms = PERBIT(load_section)(module, ".symtab", &size);
 
120
                if (!strings || !syms)
 
121
                        goto fallback;
 
122
                num_syms = size / sizeof(syms[0]);
 
123
                *versions = NOFAIL(calloc(sizeof(**versions), num_syms));
 
124
 
 
125
                conv = module->conv;
 
126
                for (i = 1; i < num_syms; i++) {
 
127
                        const char *name;
 
128
                        name = strings + END(syms[i].st_name, conv);
 
129
                        if (strncmp(name, crc, crc_len) != 0)
 
130
                                continue;
 
131
                        name += crc_len;
 
132
                        symtbl = NOFAIL(strtbl_add(name, symtbl));
 
133
                        (*versions)[symtbl->cnt - 1] = END(syms[i].st_value,
 
134
                                        conv);
 
135
                }
 
136
                if (!symtbl) {
 
137
                        /* Either this module does not export any symbols, or
 
138
                         * it was compiled without CONFIG_MODVERSIONS. If the
 
139
                         * latter, we will print a warning in load_dep_syms,
 
140
                         * so just silently fallback to __ksymtab_strings in
 
141
                         * both cases.
 
142
                         */
 
143
                        free(*versions);
 
144
                        *versions = NULL;
 
145
                        goto fallback;
 
146
                }
 
147
                return symtbl;
 
148
        }
 
149
fallback:
 
150
        return PERBIT(load_strings)(module, "__ksymtab_strings", symtbl,
 
151
                        fatal);
 
152
}
 
153
 
 
154
static char *PERBIT(get_aliases)(struct elf_file *module, unsigned long *size)
 
155
{
 
156
        return PERBIT(load_section)(module, ".modalias", size);
 
157
}
 
158
 
 
159
static char *PERBIT(get_modinfo)(struct elf_file *module, unsigned long *size)
 
160
{
 
161
        return PERBIT(load_section)(module, ".modinfo", size);
 
162
}
 
163
 
 
164
#ifndef STT_REGISTER
 
165
#define STT_REGISTER    13              /* Global register reserved to app. */
 
166
#endif
 
167
 
 
168
static struct string_table *PERBIT(load_dep_syms)(struct elf_file *module,
 
169
                                                  struct string_table **types,
 
170
                                                  uint64_t **versions)
 
171
{
 
172
        unsigned int i, num_syms;
 
173
        unsigned int j, num_symvers, versions_size;
 
174
        unsigned long size;
 
175
        char *strings;
 
176
        ElfPERBIT(Sym) *syms;
 
177
        ElfPERBIT(Ehdr) *hdr;
 
178
        struct PERBIT(modver_info) **symvers;
 
179
        int handle_register_symbols;
 
180
        struct string_table *names;
 
181
        int conv;
 
182
 
 
183
        names = NULL;
 
184
        *types = NULL;
 
185
        symvers = NULL;
 
186
        num_symvers = versions_size = 0;
 
187
 
 
188
        if (versions) {
 
189
                int ok = 1;
 
190
                *versions = NULL;
 
191
                struct PERBIT(modver_info) *symvers_sec;
 
192
 
 
193
                symvers_sec = module->ops->load_section(module, "__versions",
 
194
                                &size);
 
195
                if (!symvers_sec) {
 
196
                        warn("%s is built without modversions",
 
197
                                        module->pathname);
 
198
                        ok = 0;
 
199
                }
 
200
                if (size % sizeof(symvers[0]) != 0) {
 
201
                        warn("invalid __versions section size in %s",
 
202
                                        module->pathname);
 
203
                        ok = 0;
 
204
                }
 
205
                if (ok) {
 
206
                        num_symvers = size / sizeof(symvers_sec[0]);
 
207
                        /* symvers is used to keep track of each visited entry.
 
208
                         * The table also contains the fake struct_module /
 
209
                         * module_layout symbol which we don't want to miss.
 
210
                         */
 
211
                        symvers = NOFAIL(malloc(num_symvers *
 
212
                                                sizeof(symvers[0])));
 
213
                        for (j = 0; j < num_symvers; j++)
 
214
                                symvers[j] = &symvers_sec[j];
 
215
                } else {
 
216
                        versions = NULL;
 
217
                }
 
218
        }
 
219
 
 
220
        strings = PERBIT(load_section)(module, ".strtab", &size);
 
221
        syms = PERBIT(load_section)(module, ".symtab", &size);
 
222
        if (!strings || !syms) {
 
223
                warn("Couldn't find symtab and strtab in module %s\n",
 
224
                     module->pathname);
 
225
                goto out;
 
226
        }
 
227
 
 
228
        num_syms = size / sizeof(syms[0]);
 
229
        hdr = module->data;
 
230
        conv = module->conv;
 
231
        if (versions) {
 
232
                versions_size = num_syms;
 
233
                *versions = NOFAIL(calloc(sizeof(**versions), versions_size));
 
234
        }
 
235
 
 
236
        handle_register_symbols =
 
237
                (END(hdr->e_machine, conv) == EM_SPARC ||
 
238
                 END(hdr->e_machine, conv) == EM_SPARCV9);
 
239
 
 
240
        for (i = 1; i < num_syms; i++) {
 
241
                if (END(syms[i].st_shndx, conv) == SHN_UNDEF) {
 
242
                        /* Look for symbol */
 
243
                        const char *name;
 
244
                        int weak;
 
245
 
 
246
                        name = strings + END(syms[i].st_name, conv);
 
247
 
 
248
                        /* Not really undefined: sparc gcc 3.3 creates
 
249
                           U references when you have global asm
 
250
                           variables, to avoid anyone else misusing
 
251
                           them. */
 
252
                        if (handle_register_symbols
 
253
                            && (ELFPERBIT(ST_TYPE)(END(syms[i].st_info, conv))
 
254
                                == STT_REGISTER))
 
255
                                continue;
 
256
 
 
257
                        weak = (ELFPERBIT(ST_BIND)(END(syms[i].st_info, conv))
 
258
                                == STB_WEAK);
 
259
                        names = NOFAIL(strtbl_add(name, names));
 
260
                        *types = NOFAIL(strtbl_add(weak ? weak_sym : undef_sym,
 
261
                                *types));
 
262
 
 
263
                        if (!versions)
 
264
                                continue;
 
265
                        /* Not optimal, but the number of required symbols
 
266
                         * is usually not huge and this is only called by
 
267
                         * depmod.
 
268
                         */
 
269
                        for (j = 0; j < num_symvers; j++) {
 
270
                                struct PERBIT(modver_info) *info = symvers[j];
 
271
 
 
272
                                if (!info)
 
273
                                        continue;
 
274
                                if (streq(name, info->name)) {
 
275
                                        (*versions)[names->cnt - 1] =
 
276
                                                END(info->crc, conv);
 
277
                                        symvers[j] = NULL;
 
278
                                        break;
 
279
                                }
 
280
                        }
 
281
                }
 
282
        }
 
283
        /* add struct_module / module_layout */
 
284
        for (j = 0; j < num_symvers; j++) {
 
285
                struct PERBIT(modver_info) *info = symvers[j];
 
286
 
 
287
                if (!info)
 
288
                        continue;
 
289
                if ((names ? names->cnt : 0) >= versions_size) {
 
290
                        versions_size++;
 
291
                        *versions = NOFAIL(realloc(*versions, versions_size));
 
292
                }
 
293
                names = NOFAIL(strtbl_add(info->name, names));
 
294
                *types = NOFAIL(strtbl_add(undef_sym, *types));
 
295
                (*versions)[names->cnt - 1] = END(info->crc, conv);
 
296
        }
 
297
out:
 
298
        free(symvers);
 
299
        return names;
 
300
}
 
301
 
 
302
static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr,
 
303
                               ElfPERBIT(Shdr) *sechdrs,
 
304
                               ElfPERBIT(Sym) *sym,
 
305
                               unsigned int *secsize,
 
306
                               int conv)
 
307
{
 
308
        /* In BSS?  Happens for empty device tables on
 
309
         * recent GCC versions. */
 
310
        if (END(sechdrs[END(sym->st_shndx, conv)].sh_type,conv) == SHT_NOBITS)
 
311
                return NULL;
 
312
 
 
313
        if (secsize)
 
314
                *secsize = END(sym->st_size, conv);
 
315
        return (void *)hdr
 
316
                + END(sechdrs[END(sym->st_shndx, conv)].sh_offset, conv)
 
317
                + END(sym->st_value, conv);
 
318
}
 
319
 
 
320
/* FIXME: Check size, unless we end up using aliases anyway --RR */
 
321
static void PERBIT(fetch_tables)(struct elf_file *module,
 
322
                                 struct module_tables *tables)
 
323
{
 
324
        unsigned int i;
 
325
        unsigned long size;
 
326
        char *strings;
 
327
        ElfPERBIT(Ehdr) *hdr;
 
328
        ElfPERBIT(Sym) *syms;
 
329
        ElfPERBIT(Shdr) *sechdrs;
 
330
        int conv;
 
331
 
 
332
        hdr = module->data;
 
333
        conv = module->conv;
 
334
 
 
335
        sechdrs = (void *)hdr + END(hdr->e_shoff, conv);
 
336
        strings = PERBIT(load_section)(module, ".strtab", &size);
 
337
        syms = PERBIT(load_section)(module, ".symtab", &size);
 
338
 
 
339
        /* Don't warn again: we already have above */
 
340
        if (!strings || !syms)
 
341
                return;
 
342
 
 
343
        memset(tables, 0x00, sizeof(struct module_tables));
 
344
 
 
345
        for (i = 0; i < size / sizeof(syms[0]); i++) {
 
346
                char *name = strings + END(syms[i].st_name, conv);
 
347
 
 
348
                if (!tables->pci_table && streq(name, "__mod_pci_device_table")) {
 
349
                        tables->pci_size = PERBIT(PCI_DEVICE_SIZE);
 
350
                        tables->pci_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
351
                                                              NULL, conv);
 
352
                }
 
353
                else if (!tables->usb_table && streq(name, "__mod_usb_device_table")) {
 
354
                        tables->usb_size = PERBIT(USB_DEVICE_SIZE);
 
355
                        tables->usb_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
356
                                                              NULL, conv);
 
357
                }
 
358
                else if (!tables->ccw_table && streq(name, "__mod_ccw_device_table")) {
 
359
                        tables->ccw_size = PERBIT(CCW_DEVICE_SIZE);
 
360
                        tables->ccw_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
361
                                                              NULL, conv);
 
362
                }
 
363
                else if (!tables->ieee1394_table && streq(name, "__mod_ieee1394_device_table")) {
 
364
                        tables->ieee1394_size = PERBIT(IEEE1394_DEVICE_SIZE);
 
365
                        tables->ieee1394_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
366
                                                                   NULL, conv);
 
367
                }
 
368
                else if (!tables->pnp_table && streq(name, "__mod_pnp_device_table")) {
 
369
                        tables->pnp_size = PERBIT(PNP_DEVICE_SIZE);
 
370
                        tables->pnp_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
371
                                                              NULL, conv);
 
372
                }
 
373
                else if (!tables->pnp_card_table && streq(name, "__mod_pnp_card_device_table")) {
 
374
                        tables->pnp_card_size = PERBIT(PNP_CARD_DEVICE_SIZE);
 
375
                        tables->pnp_card_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
376
                                                                   NULL, conv);
 
377
                        tables->pnp_card_offset = PERBIT(PNP_CARD_DEVICE_OFFSET);
 
378
                }
 
379
                else if (!tables->input_table && streq(name, "__mod_input_device_table")) {
 
380
                        tables->input_size = PERBIT(INPUT_DEVICE_SIZE);
 
381
                        tables->input_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
382
                                                                &tables->input_table_size,
 
383
                                                                conv);
 
384
                }
 
385
                else if (!tables->serio_table && streq(name, "__mod_serio_device_table")) {
 
386
                        tables->serio_size = PERBIT(SERIO_DEVICE_SIZE);
 
387
                        tables->serio_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
388
                                                                NULL, conv);
 
389
                }
 
390
                else if (!tables->of_table && streq(name, "__mod_of_device_table")) {
 
391
                        tables->of_size = PERBIT(OF_DEVICE_SIZE);
 
392
                        tables->of_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
 
393
                                                             NULL, conv);
 
394
                }
 
395
        }
 
396
}
 
397
 
 
398
/*
 
399
 * strip_section - tell the kernel to ignore the named section
 
400
 */
 
401
static void PERBIT(strip_section)(struct elf_file *module, const char *secname)
 
402
{
 
403
        void *p;
 
404
        ElfPERBIT(Shdr) *sechdr;
 
405
        unsigned long secsize;
 
406
 
 
407
        p = PERBIT(get_section)(module, secname, &sechdr, &secsize);
 
408
        if (p) {
 
409
                ElfPERBIT(Uint) mask;
 
410
                mask = ~((ElfPERBIT(Uint))SHF_ALLOC);
 
411
                sechdr->sh_flags &= END(mask, module->conv);
 
412
        }
 
413
}
 
414
 
 
415
static int PERBIT(dump_modversions)(struct elf_file *module)
 
416
{
 
417
        unsigned long secsize;
 
418
        struct PERBIT(modver_info) *info;
 
419
        int n = 0;
 
420
 
 
421
        info = module->ops->load_section(module, "__versions", &secsize);
 
422
        if (!info)
 
423
                return 0; /* not a kernel module */
 
424
        if (secsize % sizeof(*info) != 0)
 
425
                return -1; /* invalid section size */
 
426
 
 
427
        for (n = 0; n < secsize / sizeof(*info); n++) {
 
428
#if defined(ELF32BIT)
 
429
                printf("0x%08lx\t%s\n", (unsigned long)
 
430
#else /* defined(ELF64BIT) */
 
431
                printf("0x%08llx\t%s\n", (unsigned long long)
 
432
#endif
 
433
                        END(info[n].crc, module->conv),
 
434
                        skip_dot(info[n].name));
 
435
        }
 
436
        return n;
 
437
}
 
438
 
 
439
struct module_ops PERBIT(mod_ops) = {
 
440
        .load_section   = PERBIT(load_section),
 
441
        .load_strings   = PERBIT(load_strings),
 
442
        .load_symbols   = PERBIT(load_symbols),
 
443
        .load_dep_syms  = PERBIT(load_dep_syms),
 
444
        .fetch_tables   = PERBIT(fetch_tables),
 
445
        .get_aliases    = PERBIT(get_aliases),
 
446
        .get_modinfo    = PERBIT(get_modinfo),
 
447
        .strip_section  = PERBIT(strip_section),
 
448
        .dump_modvers   = PERBIT(dump_modversions),
 
449
};
 
450
 
 
451
#undef PERBIT
 
452
#undef ElfPERBIT
 
453
#undef ELFPERBIT