From 70170b65b6897c4f2e539b1dd2f02500071aa6c0 Mon Sep 17 00:00:00 2001 From: adamdunkels Date: Mon, 18 Dec 2006 11:55:42 +0000 Subject: [PATCH] Removed old elfloader.c and replaced with the current code (previously in elfloader-tmp.c) --- core/loader/elfloader.c | 434 ++++++++++++++++++++-------------------- 1 file changed, 218 insertions(+), 216 deletions(-) diff --git a/core/loader/elfloader.c b/core/loader/elfloader.c index 78f1307a9..b868e5cd5 100644 --- a/core/loader/elfloader.c +++ b/core/loader/elfloader.c @@ -1,77 +1,61 @@ /* * Copyright (c) 2005, Swedish Institute of Computer Science - * All rights reserved. + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * This file is part of the Contiki operating system. * - * @(#)$Id: elfloader.c,v 1.1 2006/06/17 22:41:18 adamdunkels Exp $ + * @(#)$Id: elfloader.c,v 1.2 2006/12/18 11:55:42 adamdunkels Exp $ */ -#include -#include -#include - -#include - #include "contiki.h" -#include "loader/elfloader.h" +#include "loader/elfloader-tmp.h" +#include "loader/elfloader-arch.h" + +#include "cfs/cfs.h" #include "loader/symtab.h" -#include "lib/malloc.h" -#include "dev/rom.h" -#include "dev/xmem.h" +#include +#include +#include #if 0 +#include #define PRINTF(...) printf(__VA_ARGS__) #else #define PRINTF(...) do {} while (0) #endif -#define IMAX(a, b) (((a) > (b)) ? (a) : (b)) - -static char *datamemory; - -#define TEXTADDRESS \ - (((uintptr_t)&_etext + (uintptr_t)&_edata - (uintptr_t)&__data_start \ - + ROM_ERASE_UNIT_SIZE) & ~(ROM_ERASE_UNIT_SIZE - 1)) - #define EI_NIDENT 16 -typedef unsigned long elf32_word; -typedef signed long elf32_sword; -typedef unsigned short elf32_half; -typedef unsigned long elf32_off; -typedef unsigned long elf32_addr; - struct elf32_ehdr { unsigned char e_ident[EI_NIDENT]; /* ident bytes */ - elf32_half e_type; /* file type */ + elf32_half e_type; /* file type */ elf32_half e_machine; /* target machine */ elf32_word e_version; /* file version */ elf32_addr e_entry; /* start address */ @@ -129,12 +113,6 @@ struct elf32_rel { elf32_word r_info; /* Relocation type and symbol index. */ }; -struct elf32_rela { - elf32_addr r_offset; /* Location to be relocated. */ - elf32_word r_info; /* Relocation type and symbol index. */ - elf32_sword r_addend; /* Addend. */ -}; - struct elf32_sym { elf32_word st_name; /* String table index of name. */ elf32_addr st_value; /* Symbol value. */ @@ -149,46 +127,119 @@ struct elf32_sym { struct relevant_section { unsigned char number; - //off_t offset; + unsigned int offset; char *address; }; char elfloader_unknown[30]; /* Name that caused link error. */ +struct process **elfloader_autostart_processes; + static struct relevant_section bss, data, text; -/*static unsigned char bss_sectionno, data_sectionno, text_sectionno;*/ - -static const unsigned char elf_magic_header[] = +const static unsigned char elf_magic_header[] = {0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */ 0x01, /* Only 32-bit objects. */ 0x01, /* Only LSB data. */ 0x01, /* Only ELF version 1. */ }; +/*---------------------------------------------------------------------------*/ +static void +seek_read(int fd, unsigned int offset, char *buf, int len) +{ + cfs_seek(fd, offset); + cfs_read(fd, buf, len); +} +/*---------------------------------------------------------------------------*/ +/* +static void +seek_write(int fd, unsigned int offset, char *buf, int len) +{ + cfs_seek(fd, offset); + cfs_write(fd, buf, len); +} +*/ +/*---------------------------------------------------------------------------*/ +static void * +find_local_symbol(int fd, const char *symbol, + unsigned int symtab, unsigned short symtabsize, + unsigned int strtab) +{ + struct elf32_sym s; + unsigned int a; + char name[30]; + struct relevant_section *sect; + + for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) { + seek_read(fd, a, (char *)&s, sizeof(s)); + + if(s.st_name != 0) { + seek_read(fd, strtab + s.st_name, name, sizeof(name)); + if(strcmp(name, symbol) == 0) { + if(s.st_shndx == bss.number) { + sect = &bss; + } else if(s.st_shndx == data.number) { + sect = &data; + } else if(s.st_shndx == text.number) { + sect = &text; + } else { + return NULL; + } + return &(sect->address[s.st_value]); + } + } + } + return NULL; +} /*---------------------------------------------------------------------------*/ static int -relocate_section(off_t section, unsigned short size, - off_t sectionaddr, - off_t strs, - off_t strtab, - off_t symtab, - char *mem) +relocate_section(int fd, + unsigned int section, unsigned short size, + unsigned int sectionaddr, + unsigned int strs, + unsigned int strtab, + unsigned int symtab, unsigned short symtabsize) { struct elf32_rela rela; struct elf32_sym s; - off_t a; + unsigned int a; char name[30]; char *addr; struct relevant_section *sect; - for(a = section; a < section + size; a += sizeof(struct elf32_rela)) { - xmem_pread(&rela, sizeof(rela), a); - xmem_pread(&s, sizeof(s), - symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info)); - if(s.st_name == 0) { /* Local symbol (static) */ - if(s.st_shndx == bss.number) { + seek_read(fd, a, (char *)&rela, sizeof(rela)); + seek_read(fd, + symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info), + (char *)&s, sizeof(s)); + if(s.st_name != 0) { + seek_read(fd, strtab + s.st_name, name, sizeof(name)); + PRINTF("name: %s\n", name); + addr = (char *)symtab_lookup(name); + /* ADDED */ + if(addr == NULL) { + PRINTF("name not found in global: %s\n", name); + addr = find_local_symbol(fd, name, symtab, symtabsize, strtab); + PRINTF("found address %p\n", addr); + } + if(addr == NULL) { + if(s.st_shndx == bss.number) { + sect = &bss; + } else if(s.st_shndx == data.number) { + sect = &data; + } else if(s.st_shndx == text.number) { + sect = &text; + } else { + PRINTF("elfloader unknown name: '%30s'\n", name); + memcpy(elfloader_unknown, name, sizeof(elfloader_unknown)); + elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; + return ELFLOADER_SYMBOL_NOT_FOUND; + } + addr = sect->address; + } + } else { + if(s.st_shndx == bss.number) { sect = &bss; } else if(s.st_shndx == data.number) { sect = &data; @@ -197,77 +248,70 @@ relocate_section(off_t section, unsigned short size, } else { return ELFLOADER_SEGMENT_NOT_FOUND; } - addr = sect->address + rela.r_addend; - } else { - xmem_pread(name, sizeof(name), strtab + s.st_name); - addr = (char *)symtab_lookup(name); - if(addr != NULL) { /* Global symbol */ - addr += rela.r_addend; - } else { /* Exported symbol */ - if(s.st_shndx == bss.number) { - sect = &bss; - } else if(s.st_shndx == data.number) { - sect = &data; - } else if(s.st_shndx == text.number) { - sect = &text; - } else { - PRINTF("elfloader unkown name: '%30s'\n", name); - memcpy(elfloader_unknown, name, sizeof(elfloader_unknown)); - elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; - return ELFLOADER_SYMBOL_NOT_FOUND; - } - addr = sect->address + s.st_value + rela.r_addend; - } + + addr = sect->address; } - memcpy(&mem[rela.r_offset], &addr, 2); /* Write reloc */ + + elfloader_arch_relocate(fd, sectionaddr, &rela, addr); + } return ELFLOADER_OK; } /*---------------------------------------------------------------------------*/ -typedef void (*PFV)(void); - -struct process *elfloader_loaded_process; -void (*elfloader_fini)(void); - -static PFV -find_init_and_fini(off_t symtab, unsigned short size, off_t strtab) +static void * +find_program_processes(int fd, + unsigned int symtab, unsigned short size, + unsigned int strtab) { struct elf32_sym s; - off_t a; + unsigned int a; char name[30]; - void (*elfloader_init)(void); - - elfloader_init = NULL; - + for(a = symtab; a < symtab + size; a += sizeof(s)) { - xmem_pread(&s, sizeof(s), a); + seek_read(fd, a, (char *)&s, sizeof(s)); if(s.st_name != 0) { - xmem_pread(name, sizeof(name), strtab + s.st_name); - if(strcmp(name, "process_load") == 0) { - elfloader_loaded_process = - *(struct process **)&data.address[s.st_value]; - } else if (strcmp(name, "_init") == 0) { - /* XXX Check segment == text. */ - elfloader_init = (PFV)&text.address[s.st_value]; - } else if (strcmp(name, "_fini") == 0) { - /* XXX Check segment == text. */ - elfloader_fini = (PFV)&text.address[s.st_value]; + seek_read(fd, strtab + s.st_name, name, sizeof(name)); + if(strcmp(name, "autostart_processes") == 0) { + return &data.address[s.st_value]; } } } - return elfloader_init; + return NULL; +/* return find_local_symbol(fd, "autostart_processes", symtab, size, strtab); */ } /*---------------------------------------------------------------------------*/ +void +elfloader_init(void) +{ + elfloader_autostart_processes = NULL; +} +/*---------------------------------------------------------------------------*/ +#if 0 +static void +print_chars(unsigned char *ptr, int num) +{ + int i; + for(i = 0; i < num; ++i) { + PRINTF("%d", ptr[i]); + if(i == num - 1) { + PRINTF("\n"); + } else { + PRINTF(", "); + } + } +} +#endif /* 0 */ +/*---------------------------------------------------------------------------*/ int -elfloader_load(off_t eepromaddr) +elfloader_load(int fd) { struct elf32_ehdr ehdr; struct elf32_shdr shdr; struct elf32_shdr strtable; - off_t strs; - off_t shdrptr; - off_t nameptr; + unsigned int strs; + unsigned int shdrptr; + unsigned int nameptr; char name[12]; int i; @@ -279,35 +323,38 @@ elfloader_load(off_t eepromaddr) unsigned short strtaboff = 0, strtabsize; unsigned short bsssize = 0; + struct process **process; int ret; - void (*elfloader_init)(void); elfloader_unknown[0] = 0; /* The ELF header is located at the start of the buffer. */ - xmem_pread(&ehdr, sizeof(ehdr), eepromaddr); + seek_read(fd, 0, (char *)&ehdr, sizeof(ehdr)); + /* print_chars(ehdr.e_ident, sizeof(elf_magic_header)); + print_chars(elf_magic_header, sizeof(elf_magic_header));*/ /* Make sure that we have a correct and compatible ELF header. */ if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) { + PRINTF("ELF header problems\n"); return ELFLOADER_BAD_ELF_HEADER; } /* Grab the section header. */ - shdrptr = eepromaddr + ehdr.e_shoff; - xmem_pread(&shdr, sizeof(shdr), shdrptr); + shdrptr = ehdr.e_shoff; + seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr)); /* Get the size and number of entries of the section header. */ shdrsize = ehdr.e_shentsize; shdrnum = ehdr.e_shnum; /* The string table section: holds the names of the sections. */ - xmem_pread(&strtable, sizeof(strtable), - eepromaddr + ehdr.e_shoff + shdrsize * ehdr.e_shstrndx); + seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx, + (char *)&strtable, sizeof(strtable)); /* Get a pointer to the actual table of strings. This table holds the names of the sections, not the names of other symbols in the file (these are in the sybtam section). */ - strs = eepromaddr + strtable.sh_offset; + strs = strtable.sh_offset; /* Go through all sections and pick out the relevant ones. The ".text" segment holds the actual code from the ELF file, the @@ -332,24 +379,24 @@ elfloader_load(off_t eepromaddr) bss.number = data.number = text.number = 0; - shdrptr = eepromaddr + ehdr.e_shoff; + shdrptr = ehdr.e_shoff; for(i = 0; i < shdrnum; ++i) { - xmem_pread(&shdr, sizeof(shdr), shdrptr); + seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr)); /* The name of the section is contained in the strings table. */ nameptr = strs + shdr.sh_name; - xmem_pread(name, sizeof(name), nameptr); - + seek_read(fd, nameptr, name, sizeof(name)); + /* Match the name of the section with a predefined set of names (.text, .data, .bss, .rela.text, .rela.data, .symtab, and .strtab). */ - + if(strncmp(name, ".text", 5) == 0) { textoff = shdr.sh_offset; textsize = shdr.sh_size; text.number = i; - //text.offset = eepromaddr + textoff; + text.offset = textoff; } else if(strncmp(name, ".rela.text", 10) == 0) { textrelaoff = shdr.sh_offset; textrelasize = shdr.sh_size; @@ -357,7 +404,7 @@ elfloader_load(off_t eepromaddr) dataoff = shdr.sh_offset; datasize = shdr.sh_size; data.number = i; - //data.offset = eepromaddr + dataoff; + data.offset = dataoff; } else if(strncmp(name, ".rela.data", 10) == 0) { datarelaoff = shdr.sh_offset; datarelasize = shdr.sh_size; @@ -370,16 +417,13 @@ elfloader_load(off_t eepromaddr) } else if(strncmp(name, ".bss", 4) == 0) { bsssize = shdr.sh_size; bss.number = i; - //bss.offset = 0; - } else { - PRINTF("elfloader: unknown '%12s' %d\n", name, shdrsize); + bss.offset = 0; } /* Move on to the next section header. */ shdrptr += shdrsize; } - if(symtabsize == 0) { return ELFLOADER_NO_SYMTAB; } @@ -390,102 +434,60 @@ elfloader_load(off_t eepromaddr) return ELFLOADER_NO_TEXT; } - if(datamemory != NULL) { - free(datamemory); - } + bss.address = (char *)elfloader_arch_allocate_ram(bsssize + datasize); + data.address = (char *)bss.address + bsssize; + text.address = (char *)elfloader_arch_allocate_rom(textsize); - /* We are making semi-permanent allocations, first compact heap! */ - malloc_compact(); - datamemory = malloc(IMAX(textsize, datasize + bsssize)); - if(datamemory == NULL) { - return ELFLOADER_DATA_TO_LARGE; /* XXX or text to large */ - } - - bss.address = (char *)datamemory; - data.address = (char *)datamemory + bsssize; - text.address = (char *)TEXTADDRESS; - - PRINTF("elfloader: copy text segment to RAM %p %p\n", - datamemory, datamemory + textsize); - xmem_pread(datamemory, textsize, eepromaddr + textoff); + + /* If we have text segment relocations, we process them. */ + PRINTF("elfloader: relocate text\n"); if(textrelasize > 0) { - PRINTF("elfloader: relocate text in RAM\n"); - ret = relocate_section(eepromaddr + textrelaoff, textrelasize, - eepromaddr + textoff, + ret = relocate_section(fd, + textrelaoff, textrelasize, + textoff, strs, - eepromaddr + strtaboff, - eepromaddr + symtaboff, - datamemory); + strtaboff, + symtaboff, symtabsize); if(ret != ELFLOADER_OK) { return ret; } } - PRINTF("elfloader: copy text segment to ROM %p %p\n", - text.address, text.address + textsize); - rom_erase((textsize + ROM_ERASE_UNIT_SIZE) & ~(ROM_ERASE_UNIT_SIZE - 1), - (uintptr_t)text.address); - rom_pwrite(datamemory, textsize, (uintptr_t)text.address); - PRINTF("elfloader: copy data segment to RAM %p %p\n", - data.address, data.address + datasize); - xmem_pread(data.address, datasize, eepromaddr + dataoff); + /* If we have any data segment relocations, we process them too. */ + PRINTF("elfloader: relocate data\n"); if(datarelasize > 0) { - PRINTF("elfloader: relocate data segment\n"); - ret = relocate_section(eepromaddr + datarelaoff, datarelasize, - eepromaddr + dataoff, + ret = relocate_section(fd, + datarelaoff, datarelasize, + dataoff, strs, - eepromaddr + strtaboff, - eepromaddr + symtaboff, - data.address); + strtaboff, + symtaboff, symtabsize); if(ret != ELFLOADER_OK) { + PRINTF("elfloader: data failed\n"); return ret; } } - PRINTF("elfloader: zero bss %p %p\n", bss.address, bss.address + bsssize); + /* Write text segment into flash and data segment into RAM. */ + cfs_seek(fd, textoff); + elfloader_arch_write_text(fd, textsize, text.address); + memset(bss.address, 0, bsssize); - datamemory = realloc(datamemory, datasize + bsssize); - if(datamemory != bss.address) { - free(bss.address); - return ELFLOADER_BSS_TO_LARGE; /* XXX realloc moved data */ - } + seek_read(fd, dataoff, data.address, datasize); - /* Find _init, _fini, and loaded_process. */ - elfloader_loaded_process = NULL; - elfloader_fini = NULL; - elfloader_init = find_init_and_fini(eepromaddr + symtaboff, - symtabsize, - eepromaddr + strtaboff); - - if(elfloader_init != NULL) { - PRINTF("init=%p fini=%p\n", elfloader_init, elfloader_fini); - (*elfloader_init)(); - elfloader_loaded_process = NULL; - return ELFLOADER_OK; - } - - if(elfloader_loaded_process != NULL) { - PRINTF("elfloader: launch program\n"); - process_start(elfloader_loaded_process, NULL); - elfloader_fini = NULL; + PRINTF("elfloader: autostart search\n"); + process = find_local_symbol(fd, "autostart_processes", symtaboff, symtabsize, strtaboff); + if(process != NULL) { + PRINTF("elfloader: autostart found\n"); + elfloader_autostart_processes = process; return ELFLOADER_OK; } else { + PRINTF("elfloader: no autostart\n"); + process = find_program_processes(fd, symtaboff, symtabsize, strtaboff); + if(process != NULL) { + PRINTF("elfloader: FOUND PRG\n"); + } return ELFLOADER_NO_STARTPOINT; } } /*---------------------------------------------------------------------------*/ -void -elfloader_unload(void) -{ - if(elfloader_fini != NULL) { - (*elfloader_fini)(); - elfloader_fini = NULL; - } else if(elfloader_loaded_process != NULL) { - process_exit(elfloader_loaded_process); - elfloader_loaded_process = NULL; - } - if(datamemory != NULL) { - free(datamemory); - datamemory = NULL; - } -}