depmod: fix tabs in help output
[module-init-tools.git] / elfops_core.c
blob7150d39eebc01389c8cd2d10d678286ba5c5291f
1 #if defined(ELF32BIT)
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
9 #elif defined(ELF64BIT)
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
17 #else
18 # error "Undefined ELF word length"
19 #endif
21 static void *PERBIT(get_section)(struct elf_file *module,
22 const char *secname,
23 ElfPERBIT(Shdr) **sechdr,
24 unsigned long *secsize)
26 void *data = module->data;
27 unsigned long len = module->len;
28 int conv = module->conv;
30 ElfPERBIT(Ehdr) *hdr;
31 ElfPERBIT(Shdr) *sechdrs;
32 ElfPERBIT(Off) e_shoff;
33 ElfPERBIT(Half) e_shnum, e_shstrndx;
34 ElfPERBIT(Off) secoffset;
36 const char *secnames;
37 unsigned int i;
39 *secsize = 0;
41 if (len <= 0 || len < sizeof(*hdr))
42 return NULL;
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);
49 if (len < e_shoff + e_shnum * sizeof(sechdrs[0]))
50 return NULL;
52 sechdrs = data + e_shoff;
54 if (len < END(sechdrs[e_shstrndx].sh_offset, conv))
55 return NULL;
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;
70 return NULL;
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)
78 return PERBIT(get_section)(module, secname, NULL, secsize);
81 static struct string_table *PERBIT(load_strings)(struct elf_file *module,
82 const char *secname,
83 struct string_table *tbl)
85 unsigned long size;
86 const char *strings;
88 strings = PERBIT(load_section)(module, secname, &size);
89 if (strings) {
90 if (strings[size-1] != 0) {
91 warn("%s may be corrupt; an unterminated string"
92 " was found at the end of section %s\n",
93 module->pathname, secname);
95 /* Skip any zero padding. */
96 while (!strings[0]) {
97 strings++;
98 if (size-- <= 1)
99 return tbl;
101 for (; strings; strings = next_string(strings, &size))
102 tbl = NOFAIL(strtbl_add(strings, tbl));
104 return tbl;
107 static struct string_table *PERBIT(load_symbols)(struct elf_file *module,
108 uint64_t **versions)
110 struct string_table *symtbl = NULL;
112 if (versions) {
113 static const char crc[] = "__crc_";
114 static const int crc_len = sizeof(crc) - 1;
115 unsigned int num_syms, i;
116 unsigned long size;
117 ElfPERBIT(Sym) *syms;
118 char *strings;
119 int conv;
121 *versions = NULL;
122 strings = PERBIT(load_section)(module, ".strtab", &size);
123 syms = PERBIT(load_section)(module, ".symtab", &size);
124 if (!strings || !syms)
125 goto fallback;
126 num_syms = size / sizeof(syms[0]);
127 *versions = NOFAIL(calloc(sizeof(**versions), num_syms));
129 conv = module->conv;
130 for (i = 1; i < num_syms; i++) {
131 const char *name;
132 name = strings + END(syms[i].st_name, conv);
133 if (strncmp(name, crc, crc_len) != 0)
134 continue;
135 name += crc_len;
136 symtbl = NOFAIL(strtbl_add(name, symtbl));
137 (*versions)[symtbl->cnt - 1] = END(syms[i].st_value,
138 conv);
140 if (!symtbl) {
141 /* Either this module does not export any symbols, or
142 * it was compiled without CONFIG_MODVERSIONS. If the
143 * latter, we will print a warning in load_dep_syms,
144 * so just silently fallback to __ksymtab_strings in
145 * both cases.
147 free(*versions);
148 *versions = NULL;
149 goto fallback;
151 return symtbl;
153 fallback:
154 return PERBIT(load_strings)(module, "__ksymtab_strings", symtbl);
157 static char *PERBIT(get_aliases)(struct elf_file *module, unsigned long *size)
159 return PERBIT(load_section)(module, ".modalias", size);
162 static char *PERBIT(get_modinfo)(struct elf_file *module, unsigned long *size)
164 return PERBIT(load_section)(module, ".modinfo", size);
167 #ifndef STT_REGISTER
168 #define STT_REGISTER 13 /* Global register reserved to app. */
169 #endif
171 static struct string_table *PERBIT(load_dep_syms)(struct elf_file *module,
172 struct string_table **types,
173 uint64_t **versions)
175 unsigned int i, num_syms;
176 unsigned int j, num_symvers, versions_size;
177 unsigned long size;
178 char *strings;
179 ElfPERBIT(Sym) *syms;
180 ElfPERBIT(Ehdr) *hdr;
181 struct PERBIT(modver_info) **symvers;
182 int handle_register_symbols;
183 struct string_table *names;
184 int conv;
186 names = NULL;
187 *types = NULL;
188 symvers = NULL;
189 num_symvers = versions_size = 0;
191 if (versions) {
192 int ok = 1;
193 *versions = NULL;
194 struct PERBIT(modver_info) *symvers_sec;
196 symvers_sec = module->ops->load_section(module, "__versions",
197 &size);
198 if (!symvers_sec) {
199 warn("%s is built without modversions",
200 module->pathname);
201 ok = 0;
203 if (size % sizeof(symvers[0]) != 0) {
204 warn("invalid __versions section size in %s",
205 module->pathname);
206 ok = 0;
208 if (ok) {
209 num_symvers = size / sizeof(symvers_sec[0]);
210 /* symvers is used to keep track of each visited entry.
211 * The table also contains the fake struct_module /
212 * module_layout symbol which we don't want to miss.
214 symvers = NOFAIL(malloc(num_symvers *
215 sizeof(symvers[0])));
216 for (j = 0; j < num_symvers; j++)
217 symvers[j] = &symvers_sec[j];
218 } else {
219 versions = NULL;
223 strings = PERBIT(load_section)(module, ".strtab", &size);
224 syms = PERBIT(load_section)(module, ".symtab", &size);
225 if (!strings || !syms) {
226 warn("Couldn't find symtab and strtab in module %s\n",
227 module->pathname);
228 goto out;
231 num_syms = size / sizeof(syms[0]);
232 hdr = module->data;
233 conv = module->conv;
234 if (versions) {
235 versions_size = num_syms;
236 *versions = NOFAIL(calloc(sizeof(**versions), versions_size));
239 handle_register_symbols =
240 (END(hdr->e_machine, conv) == EM_SPARC ||
241 END(hdr->e_machine, conv) == EM_SPARCV9);
243 for (i = 1; i < num_syms; i++) {
244 if (END(syms[i].st_shndx, conv) == SHN_UNDEF) {
245 /* Look for symbol */
246 const char *name;
247 int weak;
249 name = strings + END(syms[i].st_name, conv);
251 /* Not really undefined: sparc gcc 3.3 creates
252 U references when you have global asm
253 variables, to avoid anyone else misusing
254 them. */
255 if (handle_register_symbols
256 && (ELFPERBIT(ST_TYPE)(END(syms[i].st_info, conv))
257 == STT_REGISTER))
258 continue;
260 weak = (ELFPERBIT(ST_BIND)(END(syms[i].st_info, conv))
261 == STB_WEAK);
262 names = NOFAIL(strtbl_add(name, names));
263 *types = NOFAIL(strtbl_add(weak ? weak_sym : undef_sym,
264 *types));
266 if (!versions)
267 continue;
268 /* Not optimal, but the number of required symbols
269 * is usually not huge and this is only called by
270 * depmod.
272 for (j = 0; j < num_symvers; j++) {
273 struct PERBIT(modver_info) *info = symvers[j];
275 if (!info)
276 continue;
277 if (streq(name, info->name)) {
278 (*versions)[names->cnt - 1] =
279 END(info->crc, conv);
280 symvers[j] = NULL;
281 break;
286 /* add struct_module / module_layout */
287 for (j = 0; j < num_symvers; j++) {
288 struct PERBIT(modver_info) *info = symvers[j];
290 if (!info)
291 continue;
292 if ((names ? names->cnt : 0) >= versions_size) {
293 versions_size++;
294 *versions = NOFAIL(realloc(*versions, versions_size));
296 names = NOFAIL(strtbl_add(info->name, names));
297 *types = NOFAIL(strtbl_add(undef_sym, *types));
298 (*versions)[names->cnt - 1] = END(info->crc, conv);
300 out:
301 free(symvers);
302 return names;
305 static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr,
306 ElfPERBIT(Shdr) *sechdrs,
307 ElfPERBIT(Sym) *sym,
308 unsigned int *secsize,
309 int conv)
311 /* In BSS? Happens for empty device tables on
312 * recent GCC versions. */
313 if (END(sechdrs[END(sym->st_shndx, conv)].sh_type,conv) == SHT_NOBITS)
314 return NULL;
316 if (secsize)
317 *secsize = END(sym->st_size, conv);
318 return (void *)hdr
319 + END(sechdrs[END(sym->st_shndx, conv)].sh_offset, conv)
320 + END(sym->st_value, conv);
323 /* FIXME: Check size, unless we end up using aliases anyway --RR */
324 static void PERBIT(fetch_tables)(struct elf_file *module,
325 struct module_tables *tables)
327 unsigned int i;
328 unsigned long size;
329 char *strings;
330 ElfPERBIT(Ehdr) *hdr;
331 ElfPERBIT(Sym) *syms;
332 ElfPERBIT(Shdr) *sechdrs;
333 int conv;
335 hdr = module->data;
336 conv = module->conv;
338 sechdrs = (void *)hdr + END(hdr->e_shoff, conv);
339 strings = PERBIT(load_section)(module, ".strtab", &size);
340 syms = PERBIT(load_section)(module, ".symtab", &size);
342 /* Don't warn again: we already have above */
343 if (!strings || !syms)
344 return;
346 memset(tables, 0x00, sizeof(struct module_tables));
348 for (i = 0; i < size / sizeof(syms[0]); i++) {
349 char *name = strings + END(syms[i].st_name, conv);
351 if (!tables->pci_table && streq(name, "__mod_pci_device_table")) {
352 tables->pci_size = PERBIT(PCI_DEVICE_SIZE);
353 tables->pci_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
354 NULL, conv);
356 else if (!tables->usb_table && streq(name, "__mod_usb_device_table")) {
357 tables->usb_size = PERBIT(USB_DEVICE_SIZE);
358 tables->usb_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
359 NULL, conv);
361 else if (!tables->ccw_table && streq(name, "__mod_ccw_device_table")) {
362 tables->ccw_size = PERBIT(CCW_DEVICE_SIZE);
363 tables->ccw_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
364 NULL, conv);
366 else if (!tables->ieee1394_table && streq(name, "__mod_ieee1394_device_table")) {
367 tables->ieee1394_size = PERBIT(IEEE1394_DEVICE_SIZE);
368 tables->ieee1394_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
369 NULL, conv);
371 else if (!tables->pnp_table && streq(name, "__mod_pnp_device_table")) {
372 tables->pnp_size = PERBIT(PNP_DEVICE_SIZE);
373 tables->pnp_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
374 NULL, conv);
376 else if (!tables->pnp_card_table && streq(name, "__mod_pnp_card_device_table")) {
377 tables->pnp_card_size = PERBIT(PNP_CARD_DEVICE_SIZE);
378 tables->pnp_card_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
379 NULL, conv);
380 tables->pnp_card_offset = PERBIT(PNP_CARD_DEVICE_OFFSET);
382 else if (!tables->input_table && streq(name, "__mod_input_device_table")) {
383 tables->input_size = PERBIT(INPUT_DEVICE_SIZE);
384 tables->input_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
385 &tables->input_table_size,
386 conv);
388 else if (!tables->serio_table && streq(name, "__mod_serio_device_table")) {
389 tables->serio_size = PERBIT(SERIO_DEVICE_SIZE);
390 tables->serio_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
391 NULL, conv);
393 else if (!tables->of_table && streq(name, "__mod_of_device_table")) {
394 tables->of_size = PERBIT(OF_DEVICE_SIZE);
395 tables->of_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
396 NULL, conv);
402 * strip_section - tell the kernel to ignore the named section
404 static void PERBIT(strip_section)(struct elf_file *module, const char *secname)
406 void *p;
407 ElfPERBIT(Shdr) *sechdr;
408 unsigned long secsize;
410 p = PERBIT(get_section)(module, secname, &sechdr, &secsize);
411 if (p) {
412 ElfPERBIT(Uint) mask;
413 mask = ~((ElfPERBIT(Uint))SHF_ALLOC);
414 sechdr->sh_flags &= END(mask, module->conv);
418 static int PERBIT(dump_modversions)(struct elf_file *module)
420 unsigned long secsize;
421 struct PERBIT(modver_info) *info;
422 int n = 0;
424 info = module->ops->load_section(module, "__versions", &secsize);
425 if (!info)
426 return 0; /* not a kernel module */
427 if (secsize % sizeof(*info) != 0)
428 return -1; /* invalid section size */
430 for (n = 0; n < secsize / sizeof(*info); n++) {
431 #if defined(ELF32BIT)
432 printf("0x%08lx\t%s\n", (unsigned long)
433 #else /* defined(ELF64BIT) */
434 printf("0x%08llx\t%s\n", (unsigned long long)
435 #endif
436 END(info[n].crc, module->conv),
437 skip_dot(info[n].name));
439 return n;
442 const struct module_ops PERBIT(mod_ops) = {
443 .load_section = PERBIT(load_section),
444 .load_strings = PERBIT(load_strings),
445 .load_symbols = PERBIT(load_symbols),
446 .load_dep_syms = PERBIT(load_dep_syms),
447 .fetch_tables = PERBIT(fetch_tables),
448 .get_aliases = PERBIT(get_aliases),
449 .get_modinfo = PERBIT(get_modinfo),
450 .strip_section = PERBIT(strip_section),
451 .dump_modvers = PERBIT(dump_modversions),
454 #undef PERBIT
455 #undef ElfPERBIT
456 #undef ELFPERBIT