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 + -
显示快捷键?