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/>.
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
)
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);
51 sect
= (elf_sect_t
*) (image
+ file
->shtab_offset
+ file
->shtab_ent_size
* symtab_sect
);
54 /*if(i >= sect->size) {
55 kprintf ("offset into symbol table (%u) exceeds symbol "
56 "table size (%lu)\n", i, sect->size);
61 sym
= (elf_sym_t
*)(image
+ sect
->offset
) + i
;
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
);
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);
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
;
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
;
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
);
107 err
= get_elf_sym (image
, reloc
->symtab_index
, &sym_val
, sect
->link
);
112 switch(reloc
->type
) {
113 /* absolute reference
114 Both ELF.H and objdump call this "R_386_32" */
116 *where
= sym_val
+ *where
;
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
;
124 kprintf ("unknown/unsupported relocation type %u "
125 "(must be 1 or 2)\n", reloc
->type
);
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;
146 file
= (elf_file_t
*) image
;
148 if (!arch_elf_detect (file
))
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 */
163 DPRINT (DBG_ELF
, "ELF .bss section is too small (%d bytes)", r
);
167 bss
= (unsigned char *) sect
->virt_adr
;
170 DPRINT (DBG_ELF
, "Can't allocate %u bytes for BSS, try alloc smaller block", r
);
174 sect
->offset
= bss
- image
;
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) {
202 /*else if (sect->flags == 0x2 && sect->ent_size == 0)
206 /* is it a relocation section?
207 xxx - we don't handle the extra addend for RELA relocations */
208 if(sect
->type
== 4) /* RELA */
210 else if(sect
->type
== 9)/* REL */
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);
228 DPRINT (DBG_ELF
, "rodata section does not exist");
232 /* find start of .text and make it the entry point */
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)
241 (*entry
) = (unsigned) sect
->virt_adr
;
246 /*timer_wait (10000);
248 char *scode = (char *) image;
249 kprintf ("scode: 0x%x\n", scode);
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))
258 unsigned *dd = &scode;
259 kprintf ("meh: 0x%x -", scode);
261 unsigned p = (unsigned) scode;
264 kprintf (" 0x%x | '%s'\n", scode, 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;
278 kprintf ("meh2: 0x%x | %s\n", *scode, *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 */
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
;
302 *elf_data
= (unsigned) 0;
303 *elf_data_off
= (unsigned) 0;
306 *elf_bss
= (unsigned) bss
;
309 printf ("ELF -> Can't find section .text, so entry point is unknown\n");
316 int flush_elf (char *elf_bss
)