Annotation of prex-old/boot/common/elf.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005-2006, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * elf.c - ELF file format support
32: */
33:
34: #include <boot.h>
35: #include <prex/bootinfo.h>
36: #include <sys/elf.h>
37: #include <platform.h>
38:
39: extern int nr_img; /* number of images */
40:
41: #define SHF_VALID (SHF_ALLOC | SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE)
42:
43: static char *sect_addr[32]; /* array of section address */
44:
45: static int
46: load_executable(char *img, struct module *m)
47: {
48: Elf32_Ehdr *ehdr;
49: Elf32_Phdr *phdr;
50: u_long phys_base;
51: int i;
52:
53: phys_base = load_base;
54: ehdr = (Elf32_Ehdr *)img;
55: phdr = (Elf32_Phdr *)((u_long)ehdr + ehdr->e_phoff);
56: m->phys = load_base;
57: phys_base = load_base;
58: elf_print("phys addr=%x\n", phys_base);
59:
60: for (i = 0; i < (int)ehdr->e_phnum; i++, phdr++) {
61: if (phdr->p_type != PT_LOAD)
62: continue;
63:
64: elf_print("p_flags=%x\n", (int)phdr->p_flags);
65: elf_print("p_align=%x\n", (int)phdr->p_align);
66: elf_print("p_paddr=%x\n", (int)phdr->p_paddr);
67:
68: if (i >= 2) {
69: elf_print("skipping extra phdr\n");
70: continue;
71: }
72: if (phdr->p_flags & PF_X) {
73: /* Text */
74: m->text = phdr->p_vaddr;
75: m->textsz = (size_t)phdr->p_memsz;
76: } else {
77: /* Data & BSS */
78: m->data = phdr->p_vaddr;
79: m->datasz = (size_t)phdr->p_filesz;
80: m->bsssz =
81: (size_t)(phdr->p_memsz - phdr->p_filesz);
82: load_base = phys_base + (m->data - m->text);
83: }
84: if (phdr->p_filesz > 0) {
85: memcpy((char *)load_base, img + phdr->p_offset,
86: (size_t)phdr->p_filesz);
87: elf_print("load: offset=%x size=%x\n",
88: load_base, (int)phdr->p_filesz);
89: }
90: if (!(phdr->p_flags & PF_X)) {
91: if (m->bsssz > 0) {
92: /* Zero fill BSS */
93: memset((char *)load_base + m->datasz,
94: 0, m->bsssz);
95: }
96: load_base += phdr->p_memsz;
97: }
98: }
99: /* workaround for data/bss size is 0 */
100: if (m->data == 0)
101: load_base = phys_base + m->textsz;
102:
103: load_base = PAGE_ALIGN(load_base);
104: m->size = (size_t)(load_base - m->phys);
105: m->entry = ehdr->e_entry;
106: elf_print("module size=%x entry=%x\n", m->size, m->entry);
107: return 0;
108: }
109:
110: static int
111: relocate_section_rela(Elf32_Sym *sym_table, Elf32_Rela *rela,
112: char *target_sect, int nr_reloc)
113: {
114: Elf32_Sym *sym;
115: Elf32_Addr sym_val;
116: int i;
117:
118: for (i = 0; i < nr_reloc; i++) {
119: sym = &sym_table[ELF32_R_SYM(rela->r_info)];
120: if (sym->st_shndx != STN_UNDEF) {
121: sym_val = (Elf32_Addr)sect_addr[sym->st_shndx]
122: + sym->st_value;
123: if (relocate_rela(rela, sym_val, target_sect) != 0)
124: return -1;
125: } else if (ELF32_ST_BIND(sym->st_info) != STB_WEAK) {
126: printk("Undefined symbol for rela[%x] sym=%x\n",
127: i, sym);
128: return -1;
129: } else {
130: elf_print("Undefined weak symbol for rela[%x]\n", i);
131: }
132: rela++;
133: }
134: return 0;
135: }
136:
137: static int
138: relocate_section_rel(Elf32_Sym *sym_table, Elf32_Rel *rel,
139: char *target_sect, int nr_reloc)
140: {
141: Elf32_Sym *sym;
142: Elf32_Addr sym_val;
143: int i;
144:
145: for (i = 0; i < nr_reloc; i++) {
146: sym = &sym_table[ELF32_R_SYM(rel->r_info)];
147: if (sym->st_shndx != STN_UNDEF) {
148: sym_val = (Elf32_Addr)sect_addr[sym->st_shndx]
149: + sym->st_value;
150: if (relocate_rel(rel, sym_val, target_sect) != 0)
151: return -1;
152: } else if (ELF32_ST_BIND(sym->st_info) != STB_WEAK) {
153: printk("Undefined symbol for rel[%x] sym=%x\n",
154: i, sym);
155: return -1;
156: } else {
157: elf_print("Undefined weak symbol for rel[%x]\n", i);
158: }
159: rel++;
160: }
161: return 0;
162: }
163:
164: static int
165: relocate_section(char *img, Elf32_Shdr *shdr)
166: {
167: Elf32_Sym *sym_table;
168: char *target_sect;
169: int nr_reloc, err;
170:
171: if (shdr->sh_entsize == 0)
172: return 0;
173: if ((target_sect = sect_addr[shdr->sh_info]) == 0)
174: return -1;
175: if ((sym_table = (Elf32_Sym *)sect_addr[shdr->sh_link]) == 0)
176: return -1;
177:
178: nr_reloc = (int)(shdr->sh_size / shdr->sh_entsize);
179: switch (shdr->sh_type) {
180: case SHT_REL:
181: err = relocate_section_rel(sym_table,
182: (Elf32_Rel *)(img + shdr->sh_offset),
183: target_sect, nr_reloc);
184: break;
185:
186: case SHT_RELA:
187: err = relocate_section_rela(sym_table,
188: (Elf32_Rela *)(img + shdr->sh_offset),
189: target_sect, nr_reloc);
190: break;
191:
192: default:
193: err = -1;
194: break;
195: }
196: return err;
197: }
198:
199: static int
200: load_relocatable(char *img, struct module *m)
201: {
202: Elf32_Ehdr *ehdr;
203: Elf32_Shdr *shdr;
204: u_long sect_base, bss_base;
205: int i;
206:
207: ehdr = (Elf32_Ehdr *)img;
208: shdr = (Elf32_Shdr *)((u_long)ehdr + ehdr->e_shoff);
209: bss_base = 0;
210: m->phys = load_base;
211: elf_print("phys addr=%x\n", load_base);
212:
213: /* Copy sections */
214: for (i = 0; i < (int)ehdr->e_shnum; i++, shdr++) {
215: sect_addr[i] = 0;
216: if (shdr->sh_type == SHT_PROGBITS) {
217:
218: elf_print("sh_addr=%x\n", shdr->sh_addr);
219: elf_print("sh_size=%x\n", shdr->sh_size);
220: elf_print("sh_offset=%x\n", shdr->sh_offset);
221: elf_print("sh_flags=%x\n", shdr->sh_flags);
222:
223: switch (shdr->sh_flags & SHF_VALID) {
224: case (SHF_ALLOC | SHF_EXECINSTR):
225: /* Text */
226: m->text = (u_long)phys_to_virt(load_base);
227: break;
228: case (SHF_ALLOC | SHF_WRITE):
229: /* Data */
230: if (m->data == 0)
231: m->data =
232: (u_long)phys_to_virt(load_base + shdr->sh_addr);
233: break;
234: case SHF_ALLOC:
235: /* rodata */
236: /* Note: rodata is treated as text. */
237: break;
238: default:
239: continue;
240: }
241: sect_base = load_base + shdr->sh_addr;
242: memcpy((char *)sect_base, img + shdr->sh_offset,
243: (size_t)shdr->sh_size);
244: elf_print("load: offset=%x size=%x\n",
245: sect_base, (int)shdr->sh_size);
246:
247: sect_addr[i] = (char *)sect_base;
248: } else if (shdr->sh_type == SHT_NOBITS) {
249: /* BSS */
250: m->bsssz = (size_t)shdr->sh_size;
251: sect_base = load_base + shdr->sh_addr;
252: bss_base = sect_base;
253:
254: /* Zero fill BSS */
255: memset((char *)sect_base, 0, (size_t)shdr->sh_size);
256:
257: sect_addr[i] = (char *)sect_base;
258: } else if (shdr->sh_type == SHT_SYMTAB) {
259: /* Symbol table */
260: sect_addr[i] = img + shdr->sh_offset;
261: }
262: }
263: m->textsz = (size_t)(m->data - m->text);
264: m->datasz = (size_t)(bss_base - m->data);
265:
266: load_base = bss_base + m->bsssz;
267: load_base = PAGE_ALIGN(load_base);
268:
269: elf_print("module load_base=%x text=%x\n", load_base, m->text);
270: m->size = (size_t)(load_base - (u_long)virt_to_phys(m->text));
271: m->entry = (u_long)phys_to_virt(ehdr->e_entry + m->phys);
272: elf_print("module size=%x entry=%x\n", m->size, m->entry);
273:
274: /* Process relocation */
275: shdr = (Elf32_Shdr *)((u_long)ehdr + ehdr->e_shoff);
276: for (i = 0; i < (int)ehdr->e_shnum; i++, shdr++) {
277: if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
278: if (relocate_section(img, shdr) != 0)
279: return -1;
280: }
281: }
282: return 0;
283: }
284:
285: /*
286: * Load the program from specified ELF image data stored in memory.
287: * The boot information is filled after loading the program.
288: */
289: int
290: elf_load(char *img, struct module *m)
291: {
292: Elf32_Ehdr *ehdr;
293: Elf32_Phdr *phdr;
294:
295: elf_print("\nelf_load\n");
296:
297: ehdr = (Elf32_Ehdr *)img;
298:
299: /* Check ELF header */
300: if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
301: (ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
302: (ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
303: (ehdr->e_ident[EI_MAG3] != ELFMAG3))
304: return -1;
305:
306: phdr = (Elf32_Phdr *)((u_long)ehdr + ehdr->e_ehsize);
307:
308: if (nr_img == 0) {
309: /* Initialize the load address */
310: load_base = (u_long)phys_to_virt(phdr->p_paddr);
311: if (load_base == 0)
312: return -1;
313: elf_print("kernel base=%x\n", load_base);
314: load_start = load_base;
315: }
316: else if (nr_img == 1) {
317: /* Second image => Driver */
318: elf_print("driver base=%x\n", load_base);
319: }
320: else {
321: /* Other images => Boot tasks */
322: elf_print("task base=%x\n", load_base);
323: }
324:
325: switch (ehdr->e_type) {
326: case ET_EXEC:
327: if (load_executable(img, m) != 0)
328: return -1;
329: break;
330: case ET_REL:
331: if (load_relocatable(img, m) != 0)
332: return -1;
333: break;
334: default:
335: elf_print("Unsupported file type\n");
336: return -1;
337: }
338: nr_img++;
339: return 0;
340: }
CVSweb