Rev 1051 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1051 | tullio | 1 | //////////////////////////////////////////////////////////////////////// |
2 | // elf.c |
||
3 | // |
||
4 | // DynaLink for S.H.A.R.K |
||
5 | // Dynamic ELF object linker. |
||
6 | // |
||
7 | // Original code written by Luca Abeni. |
||
8 | // Adapted by Lex Nahumury 19-7-2006. |
||
9 | // |
||
10 | // This is free software; see GPL.txt |
||
11 | //////////////////////////////////////////////////////////////////////// |
||
12 | #include "kernel/kern.h" |
||
13 | #include <kernel/func.h> |
||
14 | #include <stdlib.h> |
||
15 | #include <stdio.h> |
||
16 | #include <string.h> |
||
17 | #include <math.h> |
||
18 | |||
19 | #include <ll/i386/hw-data.h> |
||
20 | #include <ll/i386/mem.h> |
||
21 | #include <ll/i386/hw-instr.h> |
||
22 | #include <ll/i386/cons.h> |
||
23 | #include <ll/i386/error.h> |
||
24 | #include <ll/i386/mem.h> |
||
1689 | fabio | 25 | #include <arch/ctype.h> |
1051 | tullio | 26 | #include <ll/i386/x-bios.h> |
27 | |||
28 | #include "format.h" |
||
29 | #include "elf.h" |
||
30 | |||
31 | |||
32 | //#define __ELF_DEBUG__ |
||
33 | |||
34 | char elf_signature[] = "\177ELF"; |
||
35 | |||
36 | DWORD ELF_read_headers( struct file_ops *kf, |
||
37 | struct table_info *tables) |
||
38 | { |
||
39 | //printk("ELF_read_headers\n"); |
||
40 | int res; |
||
41 | |||
42 | DWORD entry; |
||
43 | struct elf_header header; |
||
44 | struct elf_section_header h; |
||
45 | |||
46 | kf->file_seek(kf->file_offset + 0, kf->seek_set); |
||
47 | kf->file_read(&header, sizeof(struct elf_header)); |
||
48 | |||
49 | if (memcmp(header.e_ident, elf_signature, 4)) { |
||
50 | printk("Not an ELF file\n"); |
||
51 | printk("Wrong signature: 0x%lx)!!!\n", |
||
52 | *(DWORD *)header.e_ident); |
||
53 | return 0; |
||
54 | } |
||
55 | //printk("ELF signature OK\n"); |
||
56 | |||
57 | tables->flags = 0; |
||
58 | if (header.e_ident[4] != ELFCLASS32) { |
||
59 | printk("Wrong ELF class\n"); |
||
60 | printk("Class: 0x%x!!!\n", header.e_ident[4]); |
||
61 | return 0; |
||
62 | } |
||
63 | //printk("ELF Class OK\n"); |
||
64 | |||
65 | if (header.e_ident[5] != ELFDATA2LSB) { |
||
66 | printk("Wrong data ordering (not LSB)\n"); |
||
67 | printk("Ordering: 0x%x!!!\n", header.e_ident[5]); |
||
68 | return 0; |
||
69 | } |
||
70 | //printk("ELF data ordering OK\n"); |
||
71 | |||
72 | #ifdef __ELF_DEBUG__ |
||
73 | if(header.e_machine != EM_386) |
||
74 | { |
||
75 | printk("Warning: machine = 0x%x!!!\n", header.e_machine); |
||
76 | } |
||
77 | #endif |
||
78 | //printk("ELF Type: 0x%x\n", header.e_type); |
||
79 | |||
80 | if(header.e_shoff != 0) |
||
81 | { |
||
82 | #ifdef __ELF_DEBUG__ |
||
83 | printk("Section headers @ %ld\n", header.e_shoff); |
||
84 | printk("Number of sections: %d\n", header.e_shnum); |
||
85 | printk("Section header size: %d (0x%x)\n", |
||
86 | header.e_shentsize, header.e_shentsize); |
||
87 | #endif |
||
88 | tables->section_header = header.e_shoff; |
||
89 | tables->section_header_size = header.e_shentsize; |
||
90 | tables->num_sections = header.e_shnum; |
||
91 | } |
||
92 | |||
93 | #ifdef __ELF_DEBUG__ |
||
94 | if (header.e_phoff != 0) { |
||
95 | printk("Program header table @ %ld\n", header.e_phoff); |
||
96 | printk("Number of segments: %d\n", header.e_phnum); |
||
97 | printk("Segment header size: %d (0x%x)\n", |
||
98 | header.e_phentsize, header.e_phentsize); |
||
99 | } |
||
100 | |||
101 | |||
102 | #ifdef __ELF_DEBUG__ |
||
103 | /* Flags... */ |
||
104 | /* RELOCATION */ |
||
105 | if (header.f_flags & F_RELFLG) { |
||
106 | printk("No relocation info!\n"); |
||
107 | } |
||
108 | |||
109 | if (header.f_flags & F_EXEC) { |
||
110 | printk("Executable file (no unresolved symbols)\n"); |
||
111 | } |
||
112 | |||
113 | if (header.f_flags & F_LNNO) { |
||
114 | printk("No line numbers!\n"); |
||
115 | } |
||
116 | |||
117 | if (header.f_flags & F_LSYMS) { |
||
118 | printk("No local symbols!\n"); |
||
119 | } |
||
120 | |||
121 | if (header.f_flags & F_AR32WR) { |
||
122 | printk("32-bit little endian!\n"); |
||
123 | } else { |
||
124 | printk("File type?\n"); |
||
125 | } |
||
126 | #endif |
||
127 | |||
128 | printk("Section Name String Table is section number %d\n", |
||
129 | header.e_shstrndx); |
||
130 | #endif |
||
131 | if (header.e_shstrndx > tables->num_sections) |
||
132 | { |
||
133 | printk("Error: SNST number > section number...\n"); |
||
134 | return 0; |
||
135 | } |
||
136 | |||
137 | res = kf->file_seek( kf->file_offset + tables->section_header + |
||
138 | header.e_shstrndx * tables->section_header_size, |
||
139 | kf->seek_set); |
||
140 | if (res < 0) { |
||
141 | printk("Cannot seek"); |
||
142 | return 0; |
||
143 | } |
||
144 | //printk("ELF file seek OK\n"); |
||
145 | |||
146 | res = kf->file_read( &h, sizeof(struct elf_section_header)); |
||
147 | if (res < 0) { |
||
148 | printk("Cannot read"); |
||
149 | return 0; |
||
150 | } |
||
151 | //printk("ELF file read OK\n"); |
||
152 | |||
153 | tables->section_names = 0; |
||
154 | if(h.sh_size != 0) |
||
155 | { |
||
156 | //printk("ELF Loading Section Names...\n"); |
||
157 | |||
158 | tables->section_names = (void *)malloc(h.sh_size); |
||
159 | if (tables->section_names == NULL) |
||
160 | { |
||
161 | printk("Failed to allocate space for section names...\n"); |
||
162 | return 0; |
||
163 | } |
||
164 | |||
165 | res = kf->file_seek( kf->file_offset + h.sh_offset, kf->seek_set); |
||
166 | if (res < 0) { |
||
167 | printk("Cannot seek"); |
||
168 | return 0; |
||
169 | } |
||
170 | res = kf->file_read( tables->section_names, h.sh_size); |
||
171 | if (res < 0) { |
||
172 | printk("Cannot read"); |
||
173 | return 0; |
||
174 | } |
||
175 | tables->section_names_size = h.sh_size; |
||
176 | } |
||
177 | else |
||
178 | { |
||
179 | printk("0 size?\n"); |
||
180 | tables->section_names_size = 0; |
||
181 | } |
||
182 | |||
183 | entry = header.e_entry; |
||
184 | if (entry == 0) { |
||
185 | tables->flags |= NO_ENTRY; |
||
186 | tables->flags |= NEED_LOAD_RELOCATABLE; |
||
187 | tables->flags |= NEED_SECTION_RELOCATION; |
||
188 | } |
||
189 | //printk("ELF Read headers Done!\n"); |
||
190 | return entry; |
||
191 | }; |
||
192 | |||
193 | |||
194 | int ELF_read_section_headers(struct file_ops *kf, |
||
195 | struct table_info *tables, |
||
196 | struct section_info *scndata) |
||
197 | { |
||
198 | |||
199 | int bss = -1; |
||
200 | int i, j; |
||
201 | struct elf_section_header h; |
||
202 | int header_size; |
||
203 | int stringtable = -1; |
||
204 | struct elf_rel_info r; |
||
205 | |||
206 | header_size = tables->section_header_size; |
||
207 | if(header_size > sizeof(struct elf_section_header)) |
||
208 | { |
||
209 | printk("Section header size (%d) > sizeof(struct section_header) (%d)\n", |
||
210 | header_size, (int)(sizeof(struct elf_section_header)) ); |
||
211 | |||
212 | header_size = sizeof(struct elf_section_header); |
||
213 | } |
||
214 | |||
215 | for (i = 0; i < tables->num_sections; i++) |
||
216 | { |
||
217 | kf->file_seek( kf->file_offset + tables->section_header + |
||
218 | i * tables->section_header_size, kf->seek_set); |
||
219 | kf->file_read( &h, sizeof(struct elf_section_header)); |
||
220 | |||
221 | #ifdef __ELF_DEBUG__ |
||
222 | printk("Section %d: ", i); |
||
223 | printk("Flags 0x%x: \n", h.sh_flags); |
||
224 | #endif |
||
225 | /* |
||
226 | Set this stuff to 0... |
||
227 | If size == 0 the section must not be loaded |
||
228 | */ |
||
229 | scndata[i].num_reloc = 0; |
||
230 | scndata[i].base = 0; |
||
231 | scndata[i].size = 0; |
||
232 | scndata[i].fileptr = 0; |
||
233 | scndata[i].filesize = 0; |
||
234 | |||
235 | /* If this is a NULL section, skip it!!! */ |
||
236 | if (h.sh_type != SHT_NULL) { |
||
237 | if (tables->section_names != 0) { |
||
238 | #ifdef __ELF_DEBUG__ |
||
239 | printk("[%s]", tables->section_names + h.sh_name); |
||
240 | #endif |
||
241 | if (strcmp(tables->section_names + h.sh_name, ".bss") == 0) { |
||
242 | bss = i; |
||
243 | } |
||
244 | } |
||
245 | #ifdef __ELF_DEBUG__ |
||
246 | printk(" <0x%lx:0x%lx> (0x%lx)\n", |
||
247 | h.sh_addr, |
||
248 | h.sh_addr + h.sh_size, |
||
249 | h.sh_offset); |
||
250 | #endif |
||
251 | |||
252 | if (h.sh_type == SHT_REL) { |
||
253 | #ifdef __ELF_DEBUG__ |
||
254 | printk("\t\tSection %d: relocation info!!!\n", i); |
||
255 | printk("\t\tSymbol table: section number %lu\n", h.sh_link); |
||
256 | printk("\t\tSection to modify: %lu\n", h.sh_info); |
||
257 | printk("\t\tNumber of relocation entries: %lu\n", |
||
258 | h.sh_size / h.sh_entsize); |
||
259 | #endif |
||
260 | if (scndata[h.sh_info].num_reloc != 0) { |
||
261 | printk("Double relocation for section\n"); |
||
262 | printk("%lu?\n", h.sh_info); |
||
263 | return 0; |
||
264 | } |
||
265 | /* So, ...let's load it!!! */ |
||
266 | scndata[h.sh_info].num_reloc = h.sh_size / h.sh_entsize; |
||
267 | //scndata[h.sh_info].reloc = (void *)kf->mem_alloc((h.sh_size / h.sh_entsize) * sizeof(struct reloc_info)); |
||
268 | scndata[h.sh_info].reloc = (void *)malloc((h.sh_size / h.sh_entsize) * sizeof(struct reloc_info)); |
||
269 | if (scndata[h.sh_info].reloc == NULL) { |
||
270 | printk("Failed to allocate space for relocation info...\n"); |
||
271 | return 0; |
||
272 | } |
||
273 | //printk("ELF Allocate space for relocation info OK!\n"); |
||
274 | |||
275 | for (j = 0; j < h.sh_size / h.sh_entsize; j++) { |
||
276 | kf->file_seek( kf->file_offset + h.sh_offset + j * h.sh_entsize, |
||
277 | kf->seek_set); |
||
278 | kf->file_read( &r, sizeof(struct elf_rel_info)); |
||
279 | scndata[h.sh_info].reloc[j].offset = r.r_offset; |
||
280 | scndata[h.sh_info].reloc[j].symbol = r.r_info >> 8; |
||
281 | /* HACKME!!! Unify the relocation types... */ |
||
282 | scndata[h.sh_info].reloc[j].type = (BYTE)r.r_info; |
||
283 | if ((BYTE)r.r_info == R_386_32){ |
||
284 | scndata[h.sh_info].reloc[j].type = REL_TYPE_ELF_ABSOLUTE; |
||
285 | } else if ((BYTE)r.r_info == R_386_PC32) { |
||
286 | scndata[h.sh_info].reloc[j].type = REL_TYPE_RELATIVE; |
||
287 | } |
||
288 | } |
||
289 | } else if (h.sh_type == SHT_RELA) { |
||
290 | printk("Error: unsupported relocation section!!!\n"); |
||
291 | |||
292 | return 0; |
||
293 | } else if ((h.sh_type == SHT_SYMTAB) || (h.sh_type == SHT_DYNSYM)) { |
||
294 | #ifdef __ELF_DEBUG__ |
||
295 | printk("\t\tSection %d: symbol table!!!\n", i); |
||
296 | printk("\t\tString table: section number %lu\n", h.sh_link); |
||
297 | printk("\t\tLast local Symbol + 1: %lu\n", h.sh_info); |
||
298 | #endif |
||
299 | tables->symbol = h.sh_offset; |
||
300 | tables->num_symbols = h.sh_size / h.sh_entsize; |
||
301 | tables->symbol_size = h.sh_size; |
||
302 | if (stringtable != -1) { |
||
303 | printk("Error: double string table!!!\n"); |
||
304 | return 0; |
||
305 | } |
||
306 | stringtable = h.sh_link; |
||
307 | if (stringtable < i) { |
||
308 | printk("Strange... "); |
||
309 | printk("String table (%d) < Symbol Table\n", stringtable); |
||
310 | return 0; |
||
311 | } |
||
312 | } else if (i == stringtable) { |
||
313 | #ifdef __ELF_DEBUG__ |
||
314 | printk("\t\t Section %d: string table!!!\n", i); |
||
315 | #endif |
||
316 | tables->string = h.sh_offset; |
||
317 | tables->string_size = h.sh_size; |
||
318 | stringtable = -1; |
||
319 | } else { |
||
320 | scndata[i].base = h.sh_addr; |
||
321 | scndata[i].size = h.sh_size; |
||
322 | scndata[i].fileptr = h.sh_offset; |
||
323 | if (h.sh_type != SHT_NOBITS) { |
||
324 | #ifdef __ELF_DEBUG__ |
||
325 | printk("BSS?\n"); |
||
326 | #endif |
||
327 | scndata[i].filesize = h.sh_size; |
||
328 | } |
||
329 | } |
||
330 | } else { |
||
331 | #ifdef __ELF_DEBUG__ |
||
332 | printk("NULL Section\n"); |
||
333 | #endif |
||
334 | } |
||
335 | |||
336 | #if 0 |
||
337 | if (h.s_flags & SECT_TEXT) { |
||
338 | printk("Executable section\n"); |
||
339 | } |
||
340 | if (h.s_flags & SECT_INIT_DATA) { |
||
341 | printk("Data section\n"); |
||
342 | } |
||
343 | if (h.s_flags & SECT_UNINIT_DATA) { |
||
344 | printk("BSS section\n"); |
||
345 | scndata[i].filesize = 0; |
||
346 | } |
||
347 | #endif |
||
348 | } |
||
349 | tables->image_base = scndata[0].base; |
||
350 | return bss; |
||
351 | }; |
||
352 | |||
353 | |||
354 | int ELF_read_symbols(struct file_ops *kf, |
||
355 | struct table_info *tables, |
||
356 | struct symbol_info *syms) |
||
357 | { |
||
358 | //printk("ELF read_symbols\n"); |
||
359 | |||
360 | int i; |
||
361 | int entsize; |
||
362 | struct elf_symbol_info symbol; |
||
363 | char *s; |
||
364 | |||
365 | s = (void *)malloc(tables->string_size); |
||
366 | if(s == NULL) |
||
367 | { |
||
368 | printk("Failed to allocate space for string table...\n"); |
||
369 | return 0; |
||
370 | } |
||
371 | |||
372 | tables->string_buffer = (DWORD)s; |
||
373 | kf->file_seek( kf->file_offset + tables->string, kf->seek_set); |
||
374 | kf->file_read( s, tables->string_size); |
||
375 | |||
376 | entsize = tables->symbol_size / tables->num_symbols; |
||
377 | |||
378 | for (i = 0; i < tables->num_symbols; i++) |
||
379 | { |
||
380 | kf->file_seek( kf->file_offset + tables->symbol + i * entsize, |
||
381 | kf->seek_set); |
||
382 | kf->file_read( &symbol, sizeof(struct elf_symbol_info)); |
||
383 | syms[i].name = s + symbol.st_name; |
||
384 | syms[i].section = symbol.st_shndx; |
||
385 | syms[i].offset = symbol.st_value; |
||
386 | |||
387 | if (syms[i].section == SHN_UNDEF) { |
||
388 | /* extern symbol */ |
||
389 | if (symbol.st_name != 0) |
||
390 | syms[i].section = EXTERN_SYMBOL; |
||
391 | else /* Mark the empty entry, external symbol with no name is not used :-) */ |
||
392 | syms[i].section = NULL_SYMBOL; |
||
393 | } |
||
394 | if (syms[i].section == SHN_COMMON) { |
||
395 | /* extern symbol */ |
||
396 | syms[i].section = COMMON_SYMBOL; |
||
397 | syms[i].offset = symbol.st_size; |
||
398 | /* calculate the local_bss_size */ |
||
399 | tables->local_bss_size += syms[i].offset; |
||
400 | } |
||
401 | } |
||
402 | |||
403 | return 1; |
||
404 | }; |
||
405 | |||
406 | int Elf_check(struct file_ops *kf) |
||
407 | { |
||
408 | char signature[4]; |
||
409 | |||
410 | kf->file_offset = kf->file_seek( 0, kf->seek_cur); |
||
411 | kf->file_read(signature, 4); |
||
412 | kf->file_seek( kf->file_offset + 0, kf->seek_set); |
||
413 | |||
414 | if(memcmp(signature, elf_signature, 4)) |
||
415 | { |
||
416 | return 0; |
||
417 | } |
||
418 | |||
419 | return 1; |
||
420 | }; |
||
421 | |||
422 | int ELF_relocate_section(struct file_ops *kf, |
||
423 | DWORD base, |
||
424 | struct table_info *tables, |
||
425 | int n, |
||
426 | struct section_info *s, |
||
427 | int sect, |
||
428 | struct symbol_info *syms, |
||
429 | struct symbol *import) |
||
430 | { |
||
431 | |||
432 | int i, idx; |
||
433 | DWORD address, destination; |
||
434 | int j, done; |
||
435 | DWORD local_bss = tables->local_bss; |
||
436 | struct reloc_info *rel = s[sect].reloc; |
||
437 | |||
438 | /* Setup the common space-uninitialized symbols at the first section relocation |
||
439 | * Pre-calculate the local BSS size (in read_symbols) |
||
440 | * then allocate for each symbol (in load_relocatable) |
||
441 | */ |
||
442 | |||
443 | if(sect == 0) |
||
444 | { |
||
445 | for(i=0; i<tables->num_symbols; i++) |
||
446 | { |
||
447 | if(syms[i].section == COMMON_SYMBOL) |
||
448 | { |
||
449 | j = syms[i].offset; |
||
450 | syms[i].offset = local_bss; |
||
451 | local_bss += j; |
||
452 | } |
||
453 | else if(syms[i].section == EXTERN_SYMBOL) |
||
454 | { |
||
455 | #ifdef __ELF_DEBUG__ |
||
456 | printk("Searching for symbol %s\n", syms[i].name); |
||
457 | #endif |
||
458 | /* Pre-set the external symbol at the same time */ |
||
459 | for(j=0, done=0; import[j].name != 0; j++) |
||
460 | { |
||
461 | if(strcmp(import[j].name, syms[i].name) == 0) |
||
462 | { |
||
463 | syms[i].offset = import[j].address; |
||
464 | done = 1; |
||
465 | break; |
||
466 | } |
||
467 | } |
||
468 | if(done == 0) |
||
469 | { |
||
470 | printk("Symbol %s not found\n", syms[i].name); |
||
471 | return -1; |
||
472 | } |
||
473 | |||
474 | } |
||
475 | } |
||
476 | } |
||
477 | |||
478 | //printk("[COMMON] s[sect].num_reloc = %d\n", s[sect].num_reloc); |
||
479 | |||
480 | for(i=0; i < s[sect].num_reloc; i++) |
||
481 | { |
||
482 | #ifdef __COFF_DEBUG__ |
||
483 | printk("Relocate 0x%lx (index 0x%x): mode %d ", |
||
484 | rel[i].offset, rel[i].symbol, rel[i].type); |
||
485 | #endif |
||
486 | idx = rel[i].symbol; |
||
487 | |||
488 | #ifdef __COFF_DEBUG__ |
||
489 | printk("%s --> 0x%lx (section %d)\n", syms[idx].name, |
||
490 | syms[idx].offset, syms[idx].section); |
||
491 | #endif |
||
492 | |||
493 | switch (rel[i].type) |
||
494 | { |
||
495 | case REL_TYPE_ELF_ABSOLUTE: |
||
496 | destination = s[sect].base + rel[i].offset + base; |
||
497 | // Initial address |
||
498 | address = *((DWORD*)destination); |
||
499 | break; |
||
500 | case REL_TYPE_RELATIVE: |
||
501 | destination = s[sect].base + rel[i].offset + base; |
||
502 | address = 0; |
||
503 | break; |
||
504 | default: |
||
505 | // (Non-)external symbols: only REL32 is supported |
||
506 | printk("Unsupported relocation!\n"); |
||
507 | printk("Relocation Type: %d\n", rel[i].type); |
||
508 | return -1; |
||
509 | } |
||
510 | |||
511 | if(syms[idx].section == COMMON_SYMBOL || syms[idx].section == EXTERN_SYMBOL) |
||
512 | { |
||
513 | if(rel[i].type == REL_TYPE_ELF_ABSOLUTE) |
||
514 | address += syms[idx].offset; |
||
515 | |||
516 | else if(rel[i].type == REL_TYPE_RELATIVE) |
||
517 | address = syms[idx].offset - destination - 4; |
||
518 | } |
||
519 | else if(syms[idx].section >= n) |
||
520 | { |
||
521 | // Check if the section exists ... |
||
522 | printk("Unsupported relocation section\n"); |
||
523 | printk("Section %d > %d\n", syms[idx].section, n); |
||
524 | printk("Value 0x%lx\n", syms[idx].offset); |
||
525 | return -1; |
||
526 | } |
||
527 | else |
||
528 | { |
||
529 | if(rel[i].type == REL_TYPE_ELF_ABSOLUTE) |
||
530 | { |
||
531 | address += base + s[syms[idx].section].base + syms[idx].offset; |
||
532 | } |
||
533 | else if(rel[i].type == REL_TYPE_RELATIVE) |
||
534 | { |
||
535 | address = (s[syms[idx].section].base + syms[idx].offset) - (s[sect].base + rel[i].offset) - 4; |
||
536 | #ifdef __COFF_DEBUG__ |
||
537 | printk("Reloc: 0x%lx + 0x%lx - 0x%lx = 0x%lx ", |
||
538 | syms[idx].offset, |
||
539 | s[syms[idx].section].base, |
||
540 | rel[i].offset , address); |
||
541 | #endif |
||
542 | } |
||
543 | } |
||
544 | |||
545 | #ifdef __COFF_DEBUG__ |
||
546 | printk("0x%lx <--- 0x%lx\n", destination, address); |
||
547 | #endif |
||
548 | *((DWORD*)destination) = address; |
||
549 | } |
||
550 | |||
551 | return 1; |
||
552 | }; |
||
553 | |||
554 | |||
555 | /* Import symbol with suffix `name' |
||
556 | * NOTE: Any symbol with prefix `_' won't be found and be regarded as internal and hidden |
||
557 | */ |
||
558 | DWORD ELF_import_symbol(struct file_ops *kf, |
||
559 | int n, |
||
560 | struct symbol_info *syms, |
||
561 | char *name, |
||
562 | int *sect) |
||
563 | { |
||
564 | //printk("[COMMON] import_symbol...\n"); |
||
565 | |||
566 | int i; |
||
567 | int len = strlen(name); |
||
568 | |||
569 | for(i = 0; i < n ; i++) |
||
570 | { |
||
571 | #ifdef __COFF_DEBUG__ |
||
572 | printk("Checking symbol %d [%d] --- Sect %d\n", i, n, syms[i].section); |
||
573 | #endif |
||
574 | if ((syms[i].section != EXTERN_SYMBOL) && (syms[i].section != COMMON_SYMBOL) && (syms[i].section != NULL_SYMBOL)) |
||
575 | { |
||
576 | #ifdef __COFF_DEBUG__ |
||
577 | printk("Compare %s, %s\n", syms[i].name, name); |
||
578 | #endif |
||
579 | if(syms[i].name[0] != '_') |
||
580 | { |
||
581 | int sym_len = strlen(syms[i].name); |
||
582 | if(sym_len >= len && strcmp(syms[i].name+sym_len-len, name) == 0) |
||
583 | { |
||
584 | #ifdef __COFF_DEBUG__ |
||
585 | printk("Found: %s --- 0x%x : 0x%lx\n", |
||
586 | syms[i].name, syms[i].section, syms[i].offset); |
||
587 | #endif |
||
588 | break; |
||
589 | } |
||
590 | #ifdef __COFF_DEBUG__ |
||
591 | else |
||
592 | { |
||
593 | printk("Cmp failed --- Going to %d\n", i); |
||
594 | } |
||
595 | #endif |
||
596 | } |
||
597 | } |
||
598 | #ifdef __COFF_DEBUG__ |
||
599 | else |
||
600 | { |
||
601 | printk("Skipped symbol --- Going to %d\n", i); |
||
602 | } |
||
603 | #endif |
||
604 | } |
||
605 | |||
606 | if(i < n) |
||
607 | { /* Symbol found */ |
||
608 | *sect = syms[i].section; |
||
609 | return syms[i].offset; |
||
610 | } |
||
611 | else |
||
612 | { |
||
613 | *sect = -1; |
||
614 | printk("Symbol not found!!!\n"); |
||
615 | return 0; |
||
616 | } |
||
617 | }; |
||
618 | |||
619 | |||
620 | |||
621 | DWORD ELF_load_relocatable( struct file_ops *kf, |
||
622 | struct table_info *tables, |
||
623 | int n, |
||
624 | struct section_info *s, |
||
625 | DWORD *size) |
||
626 | { |
||
627 | int i; |
||
628 | DWORD needed_mem = 0; |
||
629 | DWORD local_offset = 0; |
||
630 | BYTE *mem_space, *where_to_place; |
||
631 | |||
632 | // Allocate for the local bss at the mean time |
||
633 | for(i=0; i<n; i++) |
||
634 | { |
||
635 | needed_mem += s[i].size; |
||
636 | } |
||
637 | needed_mem += tables->local_bss_size; |
||
638 | mem_space = (BYTE *)malloc(needed_mem); |
||
639 | if(mem_space == NULL) |
||
640 | { |
||
641 | printk("Unable to allocate memory for the program image\n"); |
||
642 | return 0; |
||
643 | } |
||
644 | memset(mem_space, 0, needed_mem); |
||
645 | |||
646 | #ifdef __ELF_DEBUG__ |
||
647 | printk("Loading relocatable @%p; size 0x%lx\n", mem_space, needed_mem); |
||
648 | #endif |
||
649 | |||
650 | |||
651 | if(tables->local_bss_size != 0) |
||
652 | tables->local_bss = (DWORD)mem_space + needed_mem - tables->local_bss_size; |
||
653 | else |
||
654 | tables->local_bss = 0; |
||
655 | |||
656 | |||
657 | for(i=0; i<n; i++) |
||
658 | { |
||
659 | #ifdef __ELF_DEBUG__ |
||
660 | printk("Section %d\t", i); |
||
661 | #endif |
||
662 | if(s[i].size != 0) |
||
663 | { |
||
664 | #ifdef __ELF_DEBUG__ |
||
665 | printk("Loading @ 0x%lx (0x%lx + 0x%lx)...\n", |
||
666 | (DWORD)mem_space + (DWORD)local_offset, |
||
667 | (DWORD)mem_space, local_offset); |
||
668 | #endif |
||
669 | |||
670 | where_to_place = mem_space + local_offset; |
||
671 | s[i].base = local_offset; |
||
672 | local_offset += s[i].size; |
||
673 | kf->file_seek( kf->file_offset + s[i].fileptr, kf->seek_set); |
||
674 | if(s[i].filesize > 0) |
||
675 | { |
||
676 | kf->file_read( where_to_place, s[i].filesize); |
||
677 | } |
||
678 | } |
||
679 | else |
||
680 | { |
||
681 | #ifdef __ELF_DEBUG__ |
||
682 | printk("Not to be loaded\n"); |
||
683 | #endif |
||
684 | } |
||
685 | } |
||
686 | |||
687 | *size = needed_mem; |
||
688 | return (DWORD)mem_space; |
||
689 | }; |
||
690 | |||
691 | |||
692 | void ELF_free_tables(struct file_ops *kf, |
||
693 | struct table_info *tables, |
||
694 | struct symbol_info *syms, |
||
695 | struct section_info *scndata) |
||
696 | { |
||
697 | int i; |
||
698 | |||
699 | for(i = 0; i < tables->num_sections; i++) |
||
700 | if (scndata[i].num_reloc != 0) |
||
701 | free( scndata[i].reloc); |
||
702 | |||
703 | free(scndata); |
||
704 | if (syms != NULL) free(syms); |
||
705 | if (tables->string_size != 0) free((DWORD*)tables->string_buffer); |
||
706 | if (tables->section_names_size != 0) free(tables->section_names); |
||
707 | }; |
||
708 |