elfloader-otf.c

来自「伟大的Contiki工程, 短小精悍 的操作系统, 学习编程不可不看」· C语言 代码 · 共 681 行 · 第 1/2 页

C
681
字号
/* * Copyright (c) 2005, Swedish Institute of Computer Science * Copyright (c) 2007, Simon Berg * 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. * * 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-otf.c,v 1.1 2007/03/07 16:07:26 ksb Exp $ */#include "contiki.h"#include "loader/elfloader-otf.h"#include "loader/elfloader-arch-otf.h"#include "cfs/cfs.h"#include "loader/symtab.h"#include <stddef.h>#include <string.h>#include <stdio.h>#if 0#include <stdio.h>#define PRINTF(...) printf(__VA_ARGS__)#else#define PRINTF(...) do {} while (0)#endif#define EI_NIDENT 16struct elf32_ehdr {  unsigned char e_ident[EI_NIDENT];    /* ident bytes */  elf32_half e_type;                   /* file type */  elf32_half e_machine;                /* target machine */  elf32_word e_version;                /* file version */  elf32_addr e_entry;                  /* start address */  elf32_off e_phoff;                   /* phdr file offset */  elf32_off e_shoff;                   /* shdr file offset */  elf32_word e_flags;                  /* file flags */  elf32_half e_ehsize;                 /* sizeof ehdr */  elf32_half e_phentsize;              /* sizeof phdr */  elf32_half e_phnum;                  /* number phdrs */  elf32_half e_shentsize;              /* sizeof shdr */  elf32_half e_shnum;                  /* number shdrs */  elf32_half e_shstrndx;               /* shdr string index */};/* Values for e_type. */#define ET_NONE         0       /* Unknown type. */#define ET_REL          1       /* Relocatable. */#define ET_EXEC         2       /* Executable. */#define ET_DYN          3       /* Shared object. */#define ET_CORE         4       /* Core file. */struct elf32_shdr {  elf32_word sh_name; 		/* section name */  elf32_word sh_type; 		/* SHT_... */  elf32_word sh_flags; 	        /* SHF_... */  elf32_addr sh_addr; 		/* virtual address */  elf32_off sh_offset; 	        /* file offset */  elf32_word sh_size; 		/* section size */  elf32_word sh_link; 		/* misc info */  elf32_word sh_info; 		/* misc info */  elf32_word sh_addralign; 	/* memory alignment */  elf32_word sh_entsize; 	/* entry size if table */};/* sh_type */#define SHT_NULL        0               /* inactive */#define SHT_PROGBITS    1               /* program defined information */#define SHT_SYMTAB      2               /* symbol table section */#define SHT_STRTAB      3               /* string table section */#define SHT_RELA        4               /* relocation section with addends*/#define SHT_HASH        5               /* symbol hash table section */#define SHT_DYNAMIC     6               /* dynamic section */#define SHT_NOTE        7               /* note section */#define SHT_NOBITS      8               /* no space section */#define SHT_REL         9               /* relation section without addends */#define SHT_SHLIB       10              /* reserved - purpose unknown */#define SHT_DYNSYM      11              /* dynamic symbol table section */#define SHT_LOPROC      0x70000000      /* reserved range for processor */#define SHT_HIPROC      0x7fffffff      /* specific section header types */#define SHT_LOUSER      0x80000000      /* reserved range for application */#define SHT_HIUSER      0xffffffff      /* specific indexes */struct elf32_rel {  elf32_addr      r_offset;       /* Location to be relocated. */  elf32_word      r_info;         /* Relocation type and symbol index. */};struct elf32_sym {  elf32_word      st_name;        /* String table index of name. */  elf32_addr      st_value;       /* Symbol value. */  elf32_word      st_size;        /* Size of associated object. */  unsigned char   st_info;        /* Type and binding information. */  unsigned char   st_other;       /* Reserved (not used). */  elf32_half      st_shndx;       /* Section index of symbol. */};#define ELF32_R_SYM(info)       ((info) >> 8)#define ELF32_R_TYPE(info)      ((unsigned char)(info))struct relevant_section {  unsigned char number;  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, rodata, text;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. */  };/* Copy data from the elf file to a segment */static intcopy_segment_data(int input_fd, unsigned int offset,		  struct elfloader_output *output, unsigned int len){  char buffer[16];  int res;  if (cfs_seek(input_fd, offset) != offset) return ELFLOADER_INPUT_ERROR;  while(len > sizeof(buffer)) {    res = cfs_read(input_fd, buffer, sizeof(buffer));    if (res != sizeof(buffer)) return ELFLOADER_INPUT_ERROR;    res = elfloader_output_write_segment(output, buffer, sizeof(buffer));    if (res != sizeof(buffer)) return ELFLOADER_OUTPUT_ERROR;    len -= sizeof(buffer);  }  res = cfs_read(input_fd, buffer, len);  if (res != len) return ELFLOADER_INPUT_ERROR;  res = elfloader_output_write_segment(output, buffer, len);  if (res != len) return ELFLOADER_OUTPUT_ERROR;  return ELFLOADER_OK;}static intseek_read(int fd, unsigned int offset, char *buf, int len){  if (cfs_seek(fd, offset) != offset) return -1;  return cfs_read(fd, buf, len);}static void *find_local_symbol(int input_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;  int ret;    for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {    ret = seek_read(input_fd, a, (char *)&s, sizeof(s));    if (ret < 0) return NULL;    if(s.st_name != 0) {      ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));      if (ret < 0) return NULL;            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 intrelocate_section(int input_fd,		 struct elfloader_output *output,		 unsigned int section, unsigned short size,		 unsigned int sectionaddr,		 char *sectionbase,		 unsigned int strs,		 unsigned int strtab,		 unsigned int symtab, unsigned short symtabsize,		 unsigned char using_relas){  /* sectionbase added; runtime start address of current section */  struct elf32_rela rela; /* Now used both for rel and rela data! */  int rel_size = 0;  struct elf32_sym s;  unsigned int a;  char name[30];  char *addr;  struct relevant_section *sect;  int ret;  /* determine correct relocation entry sizes */  if(using_relas) {    rel_size = sizeof(struct elf32_rela);  } else {    rel_size = sizeof(struct elf32_rel);  }    for(a = section; a < section + size; a += rel_size) {    ret = seek_read(input_fd, a, (char *)&rela, rel_size);    if (ret < 0) return ELFLOADER_INPUT_ERROR;    ret = seek_read(input_fd,		    (symtab +		     sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info)),		    (char *)&s, sizeof(s));    if (ret < 0) return ELFLOADER_INPUT_ERROR;    if(s.st_name != 0) {      ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));      if (ret < 0) return ELFLOADER_INPUT_ERROR;      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(input_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 == rodata.number) {	  sect = &rodata;	} 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;      } else if(s.st_shndx == rodata.number) {	sect = &rodata;      } else if(s.st_shndx == text.number) {	sect = &text;      } else {	return ELFLOADER_SEGMENT_NOT_FOUND;      }            addr = sect->address;    }    #if 0 /* We don't know how big the relocation is or even if we need to read it.	 Let the architecture dependant code decide */    if (!using_relas) {      /* copy addend to rela structure */      ret = seek_read(fd, sectionaddr + rela.r_offset, &rela.r_addend, 4);      if (ret < 0) return ELFLOADER_INPUT_ERROR;    }#endif    {      /* Copy data up to the next relocation */      unsigned int offset = elfloader_output_segment_offset(output);      if (rela.r_offset < offset) {	PRINTF("elfloader relocation out of offset order\n");	      }      if (rela.r_offset > offset) {	ret = copy_segment_data(input_fd, offset+sectionaddr, output,				rela.r_offset - offset);	if (ret != ELFLOADER_OK) return ret;      }    }    ret = elfloader_arch_relocate(input_fd, output, sectionaddr, sectionbase,				  &rela, addr);    if (ret != ELFLOADER_OK) return ret;  }  return ELFLOADER_OK;}/*---------------------------------------------------------------------------*/static void *find_program_processes(int input_fd,		       unsigned int symtab, unsigned short size,		       unsigned int strtab){  struct elf32_sym s;  unsigned int a;  char name[30];    for(a = symtab; a < symtab + size; a += sizeof(s)) {    seek_read(input_fd, a, (char *)&s, sizeof(s));    if(s.st_name != 0) {      seek_read(input_fd, strtab + s.st_name, name, sizeof(name));      if(strcmp(name, "autostart_processes") == 0) {	return &data.address[s.st_value];      }    }  }  return NULL;/*   return find_local_symbol(fd, "autostart_processes", symtab, size, strtab); */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?