Clean up get_section()
[mit.git] / moduleops_core.c
blob0313e2798864b527235ed7b9d3eeafae62f989a6
1 /* Load the given section: NULL on error. */
2 static void *PERBIT(load_section)(ElfPERBIT(Ehdr) *hdr,
3 const char *secname,
4 unsigned long *secsize,
5 int conv)
7 return PERBIT(get_section)(hdr, 0, secname, secsize, conv);
10 static void PERBIT(load_symbols)(struct module *module)
12 struct PERBIT(kernel_symbol) *ksyms;
13 char *ksymstrings;
14 unsigned long i, size;
16 /* New-style: strings are in this section. */
17 ksymstrings = PERBIT(load_section)(module->data, "__ksymtab_strings",
18 &size, module->conv);
19 if (ksymstrings) {
20 unsigned int i = 0;
21 for (;;) {
22 /* Skip any zero padding. */
23 while (!ksymstrings[i])
24 if (++i >= size)
25 return;
26 add_symbol(ksymstrings+i, module);
27 i += strlen(ksymstrings+i);
29 /* GPL symbols too */
30 ksymstrings = PERBIT(load_section)(module->data,
31 "__ksymtab_strings_gpl",
32 &size, module->conv);
33 for (;;) {
34 /* Skip any zero padding. */
35 while (!ksymstrings[i])
36 if (++i >= size)
37 return;
38 add_symbol(ksymstrings+i, module);
39 i += strlen(ksymstrings+i);
41 return;
44 /* Old-style. */
45 ksyms = PERBIT(load_section)(module->data, "__ksymtab", &size,
46 module->conv);
47 for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
48 add_symbol(ksyms[i].name, module);
49 ksyms = PERBIT(load_section)(module->data, "__gpl_ksymtab", &size,
50 module->conv);
51 for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
52 add_symbol(ksyms[i].name, module);
55 static char *PERBIT(get_aliases)(struct module *module, unsigned long *size)
57 return PERBIT(load_section)(module->data, ".modalias", size,
58 module->conv);
61 static char *PERBIT(get_modinfo)(struct module *module, unsigned long *size)
63 return PERBIT(load_section)(module->data, ".modinfo", size,
64 module->conv);
67 #ifndef STT_REGISTER
68 #define STT_REGISTER 13 /* Global register reserved to app. */
69 #endif
71 /* Calculate the dependencies for this module */
72 static void PERBIT(calculate_deps)(struct module *module)
74 unsigned int i;
75 unsigned long size;
76 char *strings;
77 ElfPERBIT(Sym) *syms;
78 ElfPERBIT(Ehdr) *hdr;
79 int handle_register_symbols;
81 strings = PERBIT(load_section)(module->data, ".strtab", &size,
82 module->conv);
83 syms = PERBIT(load_section)(module->data, ".symtab", &size,
84 module->conv);
86 module->num_deps = 0;
87 module->deps = NULL;
89 if (!strings || !syms) {
90 warn("Couldn't find symtab and strtab in module %s\n",
91 module->pathname);
92 return;
95 hdr = module->data;
96 handle_register_symbols = 0;
97 if (END(hdr->e_machine, module->conv) == EM_SPARC ||
98 END(hdr->e_machine, module->conv) == EM_SPARCV9)
99 handle_register_symbols = 1;
101 for (i = 1; i < size / sizeof(syms[0]); i++) {
102 if (END(syms[i].st_shndx, module->conv) == SHN_UNDEF) {
103 /* Look for symbol */
104 const char *name;
105 struct module *owner;
106 int weak;
108 name = strings + END(syms[i].st_name, module->conv);
110 /* Not really undefined: sparc gcc 3.3 creates
111 U references when you have global asm
112 variables, to avoid anyone else misusing
113 them. */
114 if (handle_register_symbols
115 && (ELFPERBIT(ST_TYPE)(END(syms[i].st_info,
116 module->conv))
117 == STT_REGISTER))
118 continue;
120 weak = (ELFPERBIT(ST_BIND)(END(syms[i].st_info,
121 module->conv))
122 == STB_WEAK);
123 owner = find_symbol(name, module->pathname, weak);
124 if (owner) {
125 info("%s needs \"%s\": %s\n",
126 module->pathname, name,
127 owner->pathname);
128 add_dep(module, owner);
134 static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr,
135 ElfPERBIT(Shdr) *sechdrs,
136 ElfPERBIT(Sym) *sym,
137 unsigned int *secsize,
138 int conv)
140 /* In BSS? Happens for empty device tables on
141 * recent GCC versions. */
142 if (END(sechdrs[END(sym->st_shndx, conv)].sh_type,conv) == SHT_NOBITS)
143 return NULL;
145 if (secsize)
146 *secsize = END(sym->st_size, conv);
147 return (void *)hdr
148 + END(sechdrs[END(sym->st_shndx, conv)].sh_offset, conv)
149 + END(sym->st_value, conv);
152 /* FIXME: Check size, unless we end up using aliases anyway --RR */
153 static void PERBIT(fetch_tables)(struct module *module)
155 unsigned int i;
156 unsigned long size;
157 char *strings;
158 ElfPERBIT(Ehdr) *hdr;
159 ElfPERBIT(Sym) *syms;
160 ElfPERBIT(Shdr) *sechdrs;
162 hdr = module->data;
164 sechdrs = (void *)hdr + END(hdr->e_shoff, module->conv);
165 strings = PERBIT(load_section)(hdr, ".strtab", &size, module->conv);
166 syms = PERBIT(load_section)(hdr, ".symtab", &size, module->conv);
168 /* Don't warn again: we already have above */
169 if (!strings || !syms)
170 return;
172 module->pci_table = NULL;
173 module->usb_table = NULL;
174 module->ccw_table = NULL;
175 module->ieee1394_table = NULL;
176 module->pnp_table = NULL;
177 module->pnp_card_table = NULL;
178 module->input_table = NULL;
179 module->serio_table = NULL;
180 module->of_table = NULL;
182 for (i = 0; i < size / sizeof(syms[0]); i++) {
183 char *name = strings + END(syms[i].st_name, module->conv);
185 if (!module->pci_table && streq(name, "__mod_pci_device_table")) {
186 module->pci_size = PERBIT(PCI_DEVICE_SIZE);
187 module->pci_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
188 NULL, module->conv);
190 else if (!module->usb_table && streq(name, "__mod_usb_device_table")) {
191 module->usb_size = PERBIT(USB_DEVICE_SIZE);
192 module->usb_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
193 NULL, module->conv);
195 else if (!module->ccw_table && streq(name, "__mod_ccw_device_table")) {
196 module->ccw_size = PERBIT(CCW_DEVICE_SIZE);
197 module->ccw_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
198 NULL, module->conv);
200 else if (!module->ieee1394_table && streq(name, "__mod_ieee1394_device_table")) {
201 module->ieee1394_size = PERBIT(IEEE1394_DEVICE_SIZE);
202 module->ieee1394_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
203 NULL, module->conv);
205 else if (!module->pnp_table && streq(name, "__mod_pnp_device_table")) {
206 module->pnp_size = PERBIT(PNP_DEVICE_SIZE);
207 module->pnp_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
208 NULL, module->conv);
210 else if (!module->pnp_card_table && streq(name, "__mod_pnp_card_device_table")) {
211 module->pnp_card_size = PERBIT(PNP_CARD_DEVICE_SIZE);
212 module->pnp_card_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
213 NULL, module->conv);
214 module->pnp_card_offset = PERBIT(PNP_CARD_DEVICE_OFFSET);
216 else if (!module->input_table && streq(name, "__mod_input_device_table")) {
217 module->input_size = PERBIT(INPUT_DEVICE_SIZE);
218 module->input_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
219 &module->input_table_size,
220 module->conv);
222 else if (!module->serio_table && streq(name, "__mod_serio_device_table")) {
223 module->serio_size = PERBIT(SERIO_DEVICE_SIZE);
224 module->serio_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
225 NULL, module->conv);
227 else if (!module->of_table && streq(name, "__mod_of_device_table")) {
228 module->of_size = PERBIT(OF_DEVICE_SIZE);
229 module->of_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
230 NULL, module->conv);
235 struct module_ops PERBIT(mod_ops) = {
236 .load_symbols = PERBIT(load_symbols),
237 .calculate_deps = PERBIT(calculate_deps),
238 .fetch_tables = PERBIT(fetch_tables),
239 .get_aliases = PERBIT(get_aliases),
240 .get_modinfo = PERBIT(get_modinfo),