remove test output files from git tree
[mit.git] / moduleops_core.c
blob56f4988b52b1d9f7a291560e84b0a811c63f9fbf
1 /* Load the given section: NULL on error. */
2 static void *PERBIT(load_section)(ElfPERBIT(Ehdr) *hdr,
3 const char *secname,
4 unsigned long *size,
5 int conv)
7 ElfPERBIT(Shdr) *sechdrs;
8 unsigned int i;
9 char *secnames;
11 /* Grab section headers and strings so we can tell who is who */
12 sechdrs = (void *)hdr + END(hdr->e_shoff, conv);
13 secnames = (void *)hdr
14 + END(sechdrs[END(hdr->e_shstrndx, conv)].sh_offset, conv);
16 /* Find the section they want */
17 for (i = 1; i < END(hdr->e_shnum, conv); i++) {
18 if (streq(secnames+END(sechdrs[i].sh_name, conv), secname)) {
19 *size = END(sechdrs[i].sh_size, conv);
20 return (void *)hdr + END(sechdrs[i].sh_offset, conv);
23 *size = 0;
24 return NULL;
27 static void PERBIT(load_symbols)(struct module *module)
29 struct PERBIT(kernel_symbol) *ksyms;
30 char *ksymstrings;
31 unsigned long i, size;
33 /* New-style: strings are in this section. */
34 ksymstrings = PERBIT(load_section)(module->data, "__ksymtab_strings",
35 &size, module->conv);
36 if (ksymstrings) {
37 unsigned int i = 0;
38 for (;;) {
39 /* Skip any zero padding. */
40 while (!ksymstrings[i])
41 if (++i >= size)
42 return;
43 add_symbol(ksymstrings+i, module);
44 i += strlen(ksymstrings+i);
46 /* GPL symbols too */
47 ksymstrings = PERBIT(load_section)(module->data,
48 "__ksymtab_strings_gpl",
49 &size, module->conv);
50 for (;;) {
51 /* Skip any zero padding. */
52 while (!ksymstrings[i])
53 if (++i >= size)
54 return;
55 add_symbol(ksymstrings+i, module);
56 i += strlen(ksymstrings+i);
58 return;
61 /* Old-style. */
62 ksyms = PERBIT(load_section)(module->data, "__ksymtab", &size,
63 module->conv);
64 for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
65 add_symbol(ksyms[i].name, module);
66 ksyms = PERBIT(load_section)(module->data, "__gpl_ksymtab", &size,
67 module->conv);
68 for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
69 add_symbol(ksyms[i].name, module);
72 static char *PERBIT(get_aliases)(struct module *module, unsigned long *size)
74 return PERBIT(load_section)(module->data, ".modalias", size,
75 module->conv);
78 static char *PERBIT(get_modinfo)(struct module *module, unsigned long *size)
80 return PERBIT(load_section)(module->data, ".modinfo", size,
81 module->conv);
84 #ifndef STT_REGISTER
85 #define STT_REGISTER 13 /* Global register reserved to app. */
86 #endif
88 /* Calculate the dependencies for this module */
89 static void PERBIT(calculate_deps)(struct module *module, int verbose)
91 unsigned int i;
92 unsigned long size;
93 char *strings;
94 ElfPERBIT(Sym) *syms;
95 ElfPERBIT(Ehdr) *hdr;
96 int handle_register_symbols;
98 strings = PERBIT(load_section)(module->data, ".strtab", &size,
99 module->conv);
100 syms = PERBIT(load_section)(module->data, ".symtab", &size,
101 module->conv);
103 module->num_deps = 0;
104 module->deps = NULL;
106 if (!strings || !syms) {
107 warn("Couldn't find symtab and strtab in module %s\n",
108 module->pathname);
109 return;
112 hdr = module->data;
113 handle_register_symbols = 0;
114 if (END(hdr->e_machine, module->conv) == EM_SPARC ||
115 END(hdr->e_machine, module->conv) == EM_SPARCV9)
116 handle_register_symbols = 1;
118 for (i = 1; i < size / sizeof(syms[0]); i++) {
119 if (END(syms[i].st_shndx, module->conv) == SHN_UNDEF) {
120 /* Look for symbol */
121 const char *name;
122 struct module *owner;
123 int weak;
125 name = strings + END(syms[i].st_name, module->conv);
127 /* Not really undefined: sparc gcc 3.3 creates
128 U references when you have global asm
129 variables, to avoid anyone else misusing
130 them. */
131 if (handle_register_symbols
132 && (ELFPERBIT(ST_TYPE)(END(syms[i].st_info,
133 module->conv))
134 == STT_REGISTER))
135 continue;
137 weak = (ELFPERBIT(ST_BIND)(END(syms[i].st_info,
138 module->conv))
139 == STB_WEAK);
140 owner = find_symbol(name, module->pathname, weak);
141 if (owner) {
142 if (verbose)
143 printf("%s needs \"%s\": %s\n",
144 module->pathname, name,
145 owner->pathname);
146 add_dep(module, owner);
152 static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr,
153 ElfPERBIT(Shdr) *sechdrs,
154 ElfPERBIT(Sym) *sym,
155 unsigned int *secsize,
156 int conv)
158 /* In BSS? Happens for empty device tables on
159 * recent GCC versions. */
160 if (END(sechdrs[END(sym->st_shndx, conv)].sh_type,conv) == SHT_NOBITS)
161 return NULL;
163 if (secsize)
164 *secsize = END(sym->st_size, conv);
165 return (void *)hdr
166 + END(sechdrs[END(sym->st_shndx, conv)].sh_offset, conv)
167 + END(sym->st_value, conv);
170 /* FIXME: Check size, unless we end up using aliases anyway --RR */
171 static void PERBIT(fetch_tables)(struct module *module)
173 unsigned int i;
174 unsigned long size;
175 char *strings;
176 ElfPERBIT(Ehdr) *hdr;
177 ElfPERBIT(Sym) *syms;
178 ElfPERBIT(Shdr) *sechdrs;
180 hdr = module->data;
182 sechdrs = (void *)hdr + END(hdr->e_shoff, module->conv);
183 strings = PERBIT(load_section)(hdr, ".strtab", &size, module->conv);
184 syms = PERBIT(load_section)(hdr, ".symtab", &size, module->conv);
186 /* Don't warn again: we already have above */
187 if (!strings || !syms)
188 return;
190 module->pci_table = NULL;
191 module->usb_table = NULL;
192 module->ccw_table = NULL;
193 module->ieee1394_table = NULL;
194 module->pnp_table = NULL;
195 module->pnp_card_table = NULL;
196 module->input_table = NULL;
197 module->serio_table = NULL;
198 module->of_table = NULL;
200 for (i = 0; i < size / sizeof(syms[0]); i++) {
201 char *name = strings + END(syms[i].st_name, module->conv);
203 if (!module->pci_table && streq(name, "__mod_pci_device_table")) {
204 module->pci_size = PERBIT(PCI_DEVICE_SIZE);
205 module->pci_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
206 NULL, module->conv);
208 else if (!module->usb_table && streq(name, "__mod_usb_device_table")) {
209 module->usb_size = PERBIT(USB_DEVICE_SIZE);
210 module->usb_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
211 NULL, module->conv);
213 else if (!module->ccw_table && streq(name, "__mod_ccw_device_table")) {
214 module->ccw_size = PERBIT(CCW_DEVICE_SIZE);
215 module->ccw_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
216 NULL, module->conv);
218 else if (!module->ieee1394_table && streq(name, "__mod_ieee1394_device_table")) {
219 module->ieee1394_size = PERBIT(IEEE1394_DEVICE_SIZE);
220 module->ieee1394_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
221 NULL, module->conv);
223 else if (!module->pnp_table && streq(name, "__mod_pnp_device_table")) {
224 module->pnp_size = PERBIT(PNP_DEVICE_SIZE);
225 module->pnp_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
226 NULL, module->conv);
228 else if (!module->pnp_card_table && streq(name, "__mod_pnp_card_device_table")) {
229 module->pnp_card_size = PERBIT(PNP_CARD_DEVICE_SIZE);
230 module->pnp_card_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
231 NULL, module->conv);
232 module->pnp_card_offset = PERBIT(PNP_CARD_DEVICE_OFFSET);
234 else if (!module->input_table && streq(name, "__mod_input_device_table")) {
235 module->input_size = PERBIT(INPUT_DEVICE_SIZE);
236 module->input_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
237 &module->input_table_size,
238 module->conv);
240 else if (!module->serio_table && streq(name, "__mod_serio_device_table")) {
241 module->serio_size = PERBIT(SERIO_DEVICE_SIZE);
242 module->serio_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
243 NULL, module->conv);
245 else if (!module->of_table && streq(name, "__mod_of_device_table")) {
246 module->of_size = PERBIT(OF_DEVICE_SIZE);
247 module->of_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
248 NULL, module->conv);
253 struct module_ops PERBIT(mod_ops) = {
254 .load_symbols = PERBIT(load_symbols),
255 .calculate_deps = PERBIT(calculate_deps),
256 .fetch_tables = PERBIT(fetch_tables),
257 .get_aliases = PERBIT(get_aliases),
258 .get_modinfo = PERBIT(get_modinfo),