Version 0.6.7: Added support for hostname - hostname_get (), hostname_set (); Hostnam...
[ZeXOS.git] / kernel / core / elf.c
blob08d50fcfd59a5c9c198c4748b08bad2222c6f18a
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <system.h>
23 #include <string.h>
24 #include <elf.h>
26 extern unsigned long file_cache_id;
28 /*****************************************************************************
29 get value of symbol #i
30 *****************************************************************************/
31 static int get_elf_sym (unsigned char *image, unsigned i,
32 unsigned *sym_val, unsigned symtab_sect)
34 elf_file_t *file;
35 elf_sect_t *sect;
36 elf_sym_t *sym;
37 char *sym_name;
38 unsigned adr;
39 int err;
41 /* point to symbol table */
42 file = (elf_file_t *) image;
44 if (symtab_sect >= file->num_sects) {
45 kprintf ("bad symbol table section number %d (max %u)\n",
46 symtab_sect, file->num_sects - 1);
48 return -1;
51 sect = (elf_sect_t *) (image + file->shtab_offset + file->shtab_ent_size * symtab_sect);
53 /* get symbol */
54 /*if(i >= sect->size) {
55 kprintf ("offset into symbol table (%u) exceeds symbol "
56 "table size (%lu)\n", i, sect->size);
58 return -1;
59 }*/
61 sym = (elf_sym_t *)(image + sect->offset) + i;
63 /* external symbol */
64 if (sym->section == 0) {
65 /* point to string table for this symbol table */
66 sect = (elf_sect_t *) (image + file->shtab_offset +
67 file->shtab_ent_size * sect->link);
68 /* get symbol name */
69 sym_name = (char *) image + sect->offset + sym->name;
70 kprintf ("symbol: %s\n", sym_name);
71 /* ELF binutils for DJGPP: leading underscore
72 err = lookup_external_symbol(sym_name, sym_val, 1); */
73 /* Linux: no leading underscore */
74 /*err = lookup_external_symbol(sym_name, sym_val, 0);
75 if(err != 0)
76 return err;*/
77 } else {
78 /* internal symbol */
79 sect = (elf_sect_t *) (image + file->shtab_offset + file->shtab_ent_size * sym->section);
80 adr = (unsigned) image + sect->offset;
81 *sym_val = sym->value + adr;
84 return 0;
86 /*****************************************************************************
87 *****************************************************************************/
88 static int do_elf_reloc (unsigned char *image, elf_reloc_t *reloc, elf_sect_t *sect)
90 unsigned t_adr, sym_val;
91 elf_sect_t *t_sect;
92 elf_file_t *file;
93 unsigned long *where;
94 int err;
96 /* get address of target section */
97 file = (elf_file_t *) image;
98 t_sect = (elf_sect_t *) (image + file->shtab_offset + file->shtab_ent_size * sect->info);
99 t_adr = (unsigned) image + t_sect->offset;
101 // kprintf ("t_adr: 0x%x\n", t_adr);
103 /* point to relocation */
104 where = (unsigned long *) (t_adr + reloc->adr);
106 /* get symbol */
107 err = get_elf_sym (image, reloc->symtab_index, &sym_val, sect->link);
109 if(err != 0)
110 return err;
112 switch(reloc->type) {
113 /* absolute reference
114 Both ELF.H and objdump call this "R_386_32" */
115 case 1: /* S + A */
116 *where = sym_val + *where;
117 break;
118 /* EIP-relative reference
119 Both ELF.H and objdump call this "R_386_PC32" */
120 case 2: /* S + A - P */
121 *where = sym_val + *where - (unsigned)where;
122 break;
123 default:
124 kprintf ("unknown/unsupported relocation type %u "
125 "(must be 1 or 2)\n", reloc->type);
126 return -1;
129 return 0;
132 /*****************************************************************************
133 *****************************************************************************/
135 int exec_elf (unsigned char *image, unsigned *entry, unsigned *elf_data, unsigned *elf_data_off, unsigned *elf_bss)
137 unsigned s, r, reloc_size;
139 unsigned char *bss = 0;
140 elf_reloc_t *reloc;
141 elf_sect_t *sect;
142 elf_file_t *file;
143 int err;
145 /* validate */
146 file = (elf_file_t *) image;
148 if (!arch_elf_detect (file))
149 return -1;
151 /* find the BSS and allocate memory for it
152 This must be done BEFORE doing any relocations */
153 for (s = 0; s < file->num_sects; s ++) {
154 sect = (elf_sect_t *)(image + file->shtab_offset +
155 file->shtab_ent_size * s);
157 if(sect->type != 8) /* NOBITS */
158 continue;
160 r = sect->size;
162 if (r < 1) {
163 DPRINT (DBG_ELF, "ELF .bss section is too small (%d bytes)", r);
164 continue;
167 bss = (unsigned char *) sect->virt_adr;
169 if (bss == NULL) {
170 DPRINT (DBG_ELF, "Can't allocate %u bytes for BSS, try alloc smaller block", r);
171 continue;
174 sect->offset = bss - image;
175 break;
178 /* for(s = 0; s < file->num_sects; s++)
180 sect = (elf_sect_t *)(image + file->shtab_offset +
181 file->shtab_ent_size * s);
183 // if (sect->type != 0)
184 // sect->offset -= 0x1000;
186 kprintf ("sect addr: 0x%x - sect->type: %d .. sect->size: 0x%x | sect->vaddr: 0x%x | sect->offset: 0x%x |�sect->flags: 0x%x | sect->es: %d\n", sect, sect->type, sect->size, sect->virt_adr, sect->offset, sect->flags, sect->ent_size);
191 elf_sect_t *rodata = 0;
192 //kprintf ("sect->offset: 0x%x - file->num_sects: %d\n", sect->offset, file->num_sects);
193 /* for each section... */
194 for (s = 0; s < file->num_sects; s ++) {
195 sect = (elf_sect_t *)(image + file->shtab_offset + file->shtab_ent_size * s);
196 //kprintf ("sect->type: %d .. sect->size: %d | sect->offset: 0x%x - vadr: 0x%x - flags: 0x%x - %d\n", sect->type, sect->size, sect->offset, sect->virt_adr, sect->flags, sect->ent_size);
197 if (sect->type == 1) {
198 if (sect->sect_name == 0x17 || sect->sect_name == 0x27) {
199 rodata = sect;
200 break;
202 /*else if (sect->flags == 0x2 && sect->ent_size == 0)
203 rodata = sect;*/
206 /* is it a relocation section?
207 xxx - we don't handle the extra addend for RELA relocations */
208 if(sect->type == 4) /* RELA */
209 reloc_size = 12;
210 else if(sect->type == 9)/* REL */
211 reloc_size = 8;
212 else
213 continue;
215 /* for each relocation... */
216 /*for (r = 0; r < sect->size / reloc_size; r ++) {
217 reloc = (elf_reloc_t *)(image + sect->offset + reloc_size * r);
219 kprintf ("reloc: 0x%x : 0x%x - %d\n", reloc, image, r);
220 err = do_elf_reloc (image, reloc, sect);
222 if(err != 0)
223 return err;
227 if (!rodata) {
228 DPRINT (DBG_ELF, "rodata section does not exist");
229 //return -1;
232 /* find start of .text and make it the entry point */
233 (*entry) = 0;
235 for (s = 0; s < file->num_sects; s ++) {
236 sect = (elf_sect_t *) (image + file->shtab_offset + file->shtab_ent_size * s);
237 //kprintf (">>sect type: %d sect_name: %x virt_addr: 0x%x | ", sect->type, sect->sect_name, sect->virt_adr);
238 if (sect->sect_name != 0x0b && sect->sect_name != 0x1b)
239 continue;
241 (*entry) = (unsigned) sect->virt_adr;
243 break;
246 /*timer_wait (10000);
248 char *scode = (char *) image;
249 kprintf ("scode: 0x%x\n", scode);
251 int i = 0;
252 for (i = 0; i < file_cache_id; i ++) {
253 unsigned s = (unsigned) scode;
254 if ((unsigned) s >= (unsigned) 0x1000) {
256 //if (*scode >= (unsigned) (rodata->virt_adr+image))
257 // continue;
258 unsigned *dd = &scode;
259 kprintf ("meh: 0x%x -", scode);
261 unsigned p = (unsigned) scode;
262 scode = image + p;
264 kprintf (" 0x%x | '%s'\n", scode, scode);
266 //timer_wait (1000);
268 scode ++;
271 /* timer_wait (5000);
273 for (i = 0; i < sect->offset; i ++) {
274 if (*scode >= rodata->virt_adr && *scode <= rodata->virt_adr+0x4000) {
275 kprintf ("meh: 0x%x\n", *scode);
276 unsigned p = (unsigned) *scode;
277 *scode = image + p;
278 kprintf ("meh2: 0x%x | %s\n", *scode, *scode);
279 timer_wait (2000);
281 *scode ++;
285 //rodata->offset = (unsigned) image + rodata->offset;
287 /*kprintf ("image: 0x%x\n", (unsigned) image);
288 kprintf ("*entry: 0x%x\n", (*entry));
289 kprintf ("sect->virt_adr: 0x%x offset: 0x%x\n", sect->virt_adr, sect->offset);*/
291 /* copy rodata section to our memory area section */
292 if (rodata) {
293 kprintf ("rodata->vadr: 0x%x %s\n", rodata->virt_adr, rodata->virt_adr);
294 kprintf ("rodata->offset: 0x%x\n", rodata->offset);
296 //char *rodata_p = (char *) rodata->virt_adr;
297 //memcpy (rodata_p, image+rodata->virt_adr, rodata->offset);
299 *elf_data = (unsigned) rodata->virt_adr;
300 *elf_data_off = (unsigned) rodata->offset;
301 } else {
302 *elf_data = (unsigned) 0;
303 *elf_data_off = (unsigned) 0;
306 *elf_bss = (unsigned) bss;
308 if (!(*entry)) {
309 printf ("ELF -> Can't find section .text, so entry point is unknown\n");
310 return -1;
313 return 0;
316 int flush_elf (char *elf_bss)
318 if (elf_bss)
319 kfree (elf_bss);
320 else
321 return 0;
323 return 1;