testsuite: rebuild all the 64-be|le data files
[mit.git] / elfops_core.c
blobc5e84bad79a09123eb90449aa0b65adc7275af78
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,
84 errfn_t error)
86 unsigned long size;
87 const char *strings;
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;
97 for (; strings; strings = next_string(strings, &size))
98 tbl = NOFAIL(strtbl_add(strings, tbl));
100 return tbl;
103 static struct string_table *PERBIT(load_symbols)(struct elf_file *module)
105 struct PERBIT(kernel_symbol) *ksyms;
106 struct string_table *symtbl;
107 unsigned long i, size;
109 symtbl = NULL;
111 /* New-style: strings are in this section. */
112 symtbl = PERBIT(load_strings)(module, "__ksymtab_strings", symtbl, fatal);
113 if (symtbl) {
114 /* GPL symbols too */
115 return PERBIT(load_strings)(module, "__ksymtab_strings_gpl",
116 symtbl, fatal);
119 /* Old-style. */
120 ksyms = PERBIT(load_section)(module, "__ksymtab", &size);
121 for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
122 symtbl = NOFAIL(strtbl_add(ksyms[i].name, symtbl));
123 ksyms = PERBIT(load_section)(module, "__gpl_ksymtab", &size);
124 for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
125 symtbl = NOFAIL(strtbl_add(ksyms[i].name, symtbl));
127 return symtbl;
130 static char *PERBIT(get_aliases)(struct elf_file *module, unsigned long *size)
132 return PERBIT(load_section)(module, ".modalias", size);
135 static char *PERBIT(get_modinfo)(struct elf_file *module, unsigned long *size)
137 return PERBIT(load_section)(module, ".modinfo", size);
140 #ifndef STT_REGISTER
141 #define STT_REGISTER 13 /* Global register reserved to app. */
142 #endif
144 static struct string_table *PERBIT(load_dep_syms)(const char *pathname,
145 struct elf_file *module,
146 struct string_table **types)
148 unsigned int i;
149 unsigned long size;
150 char *strings;
151 ElfPERBIT(Sym) *syms;
152 ElfPERBIT(Ehdr) *hdr;
153 int handle_register_symbols;
154 struct string_table *names;
155 int conv;
157 names = NULL;
158 *types = NULL;
160 strings = PERBIT(load_section)(module, ".strtab", &size);
161 syms = PERBIT(load_section)(module, ".symtab", &size);
163 if (!strings || !syms) {
164 warn("Couldn't find symtab and strtab in module %s\n",
165 pathname);
166 return NULL;
169 hdr = module->data;
170 conv = module->conv;
172 handle_register_symbols =
173 (END(hdr->e_machine, conv) == EM_SPARC ||
174 END(hdr->e_machine, conv) == EM_SPARCV9);
176 for (i = 1; i < size / sizeof(syms[0]); i++) {
177 if (END(syms[i].st_shndx, conv) == SHN_UNDEF) {
178 /* Look for symbol */
179 const char *name;
180 int weak;
182 name = strings + END(syms[i].st_name, conv);
184 /* Not really undefined: sparc gcc 3.3 creates
185 U references when you have global asm
186 variables, to avoid anyone else misusing
187 them. */
188 if (handle_register_symbols
189 && (ELFPERBIT(ST_TYPE)(END(syms[i].st_info, conv))
190 == STT_REGISTER))
191 continue;
193 weak = (ELFPERBIT(ST_BIND)(END(syms[i].st_info, conv))
194 == STB_WEAK);
195 names = NOFAIL(strtbl_add(name, names));
196 *types = NOFAIL(strtbl_add(weak ? weak_sym : undef_sym,
197 *types));
200 return names;
203 static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr,
204 ElfPERBIT(Shdr) *sechdrs,
205 ElfPERBIT(Sym) *sym,
206 unsigned int *secsize,
207 int conv)
209 /* In BSS? Happens for empty device tables on
210 * recent GCC versions. */
211 if (END(sechdrs[END(sym->st_shndx, conv)].sh_type,conv) == SHT_NOBITS)
212 return NULL;
214 if (secsize)
215 *secsize = END(sym->st_size, conv);
216 return (void *)hdr
217 + END(sechdrs[END(sym->st_shndx, conv)].sh_offset, conv)
218 + END(sym->st_value, conv);
221 /* FIXME: Check size, unless we end up using aliases anyway --RR */
222 static void PERBIT(fetch_tables)(struct elf_file *module,
223 struct module_tables *tables)
225 unsigned int i;
226 unsigned long size;
227 char *strings;
228 ElfPERBIT(Ehdr) *hdr;
229 ElfPERBIT(Sym) *syms;
230 ElfPERBIT(Shdr) *sechdrs;
231 int conv;
233 hdr = module->data;
234 conv = module->conv;
236 sechdrs = (void *)hdr + END(hdr->e_shoff, conv);
237 strings = PERBIT(load_section)(module, ".strtab", &size);
238 syms = PERBIT(load_section)(module, ".symtab", &size);
240 /* Don't warn again: we already have above */
241 if (!strings || !syms)
242 return;
244 memset(tables, 0x00, sizeof(struct module_tables));
246 for (i = 0; i < size / sizeof(syms[0]); i++) {
247 char *name = strings + END(syms[i].st_name, conv);
249 if (!tables->pci_table && streq(name, "__mod_pci_device_table")) {
250 tables->pci_size = PERBIT(PCI_DEVICE_SIZE);
251 tables->pci_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
252 NULL, conv);
254 else if (!tables->usb_table && streq(name, "__mod_usb_device_table")) {
255 tables->usb_size = PERBIT(USB_DEVICE_SIZE);
256 tables->usb_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
257 NULL, conv);
259 else if (!tables->ccw_table && streq(name, "__mod_ccw_device_table")) {
260 tables->ccw_size = PERBIT(CCW_DEVICE_SIZE);
261 tables->ccw_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
262 NULL, conv);
264 else if (!tables->ieee1394_table && streq(name, "__mod_ieee1394_device_table")) {
265 tables->ieee1394_size = PERBIT(IEEE1394_DEVICE_SIZE);
266 tables->ieee1394_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
267 NULL, conv);
269 else if (!tables->pnp_table && streq(name, "__mod_pnp_device_table")) {
270 tables->pnp_size = PERBIT(PNP_DEVICE_SIZE);
271 tables->pnp_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
272 NULL, conv);
274 else if (!tables->pnp_card_table && streq(name, "__mod_pnp_card_device_table")) {
275 tables->pnp_card_size = PERBIT(PNP_CARD_DEVICE_SIZE);
276 tables->pnp_card_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
277 NULL, conv);
278 tables->pnp_card_offset = PERBIT(PNP_CARD_DEVICE_OFFSET);
280 else if (!tables->input_table && streq(name, "__mod_input_device_table")) {
281 tables->input_size = PERBIT(INPUT_DEVICE_SIZE);
282 tables->input_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
283 &tables->input_table_size,
284 conv);
286 else if (!tables->serio_table && streq(name, "__mod_serio_device_table")) {
287 tables->serio_size = PERBIT(SERIO_DEVICE_SIZE);
288 tables->serio_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
289 NULL, conv);
291 else if (!tables->of_table && streq(name, "__mod_of_device_table")) {
292 tables->of_size = PERBIT(OF_DEVICE_SIZE);
293 tables->of_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
294 NULL, conv);
300 * strip_section - tell the kernel to ignore the named section
302 static void PERBIT(strip_section)(struct elf_file *module, const char *secname)
304 void *p;
305 ElfPERBIT(Shdr) *sechdr;
306 unsigned long secsize;
308 p = PERBIT(get_section)(module, secname, &sechdr, &secsize);
309 if (p) {
310 ElfPERBIT(Uint) mask;
311 mask = ~((ElfPERBIT(Uint))SHF_ALLOC);
312 sechdr->sh_flags &= END(mask, module->conv);
316 static int PERBIT(dump_modversions)(struct elf_file *module)
318 unsigned long secsize;
319 struct PERBIT(modver_info) *info;
320 int n = 0;
322 info = module->ops->load_section(module, "__versions", &secsize);
323 if (!info)
324 return 0; /* not a kernel module */
325 if (secsize % sizeof(*info) != 0)
326 return -1; /* invalid section size */
328 for (n = 0; n < secsize / sizeof(*info); n++) {
329 #if defined(ELF32BIT)
330 printf("0x%08lx\t%s\n", (unsigned long)
331 #else /* defined(ELF64BIT) */
332 printf("0x%08llx\t%s\n", (unsigned long long)
333 #endif
334 END(info[n].crc, module->conv),
335 skip_dot(info[n].name));
337 return n;
340 struct module_ops PERBIT(mod_ops) = {
341 .load_section = PERBIT(load_section),
342 .load_strings = PERBIT(load_strings),
343 .load_symbols = PERBIT(load_symbols),
344 .load_dep_syms = PERBIT(load_dep_syms),
345 .fetch_tables = PERBIT(fetch_tables),
346 .get_aliases = PERBIT(get_aliases),
347 .get_modinfo = PERBIT(get_modinfo),
348 .strip_section = PERBIT(strip_section),
349 .dump_modvers = PERBIT(dump_modversions),
352 #undef PERBIT
353 #undef ElfPERBIT
354 #undef ELFPERBIT