static int get_file_header(FILE *file) { /* Read in the identity array: */ if (fread(elf_header.e_ident, EI_NIDENT, 1, file) != 1) return 0; /* Determine how to read the rest of the header. */ switch (elf_header.e_ident[EI_DATA]) { default: /* fall through to: */ case ELFDATANONE: /* fall through to: */ case ELFDATA2LSB: byte_get = byte_get_little_endian; byte_put = byte_put_little_endian; break; case ELFDATA2MSB: byte_get = byte_get_big_endian; byte_put = byte_put_big_endian; break; } /* Read in the rest of the header. For now we only support 32 bit and 64 bit ELF files. */ switch (elf_header.e_ident[EI_CLASS]) { default: error(_("Unsupported EI_CLASS: %d\n"), elf_header.e_ident[EI_CLASS]); return 0; case ELFCLASS32: if (fread(ehdr32.e_type, (sizeof(ehdr32) - EI_NIDENT), 1, file) != 1) return 0; elf_header.e_type = (unsigned short)BYTE_GET(ehdr32.e_type); elf_header.e_machine = (unsigned short)BYTE_GET(ehdr32.e_machine); elf_header.e_version = (unsigned long)BYTE_GET(ehdr32.e_version); elf_header.e_entry = BYTE_GET(ehdr32.e_entry); elf_header.e_phoff = BYTE_GET(ehdr32.e_phoff); elf_header.e_shoff = BYTE_GET(ehdr32.e_shoff); elf_header.e_flags = (unsigned long)BYTE_GET(ehdr32.e_flags); elf_header.e_ehsize = (unsigned int)BYTE_GET(ehdr32.e_ehsize); elf_header.e_phentsize = (unsigned int)BYTE_GET(ehdr32.e_phentsize); elf_header.e_phnum = (unsigned int)BYTE_GET(ehdr32.e_phnum); elf_header.e_shentsize = (unsigned int)BYTE_GET(ehdr32.e_shentsize); elf_header.e_shnum = (unsigned int)BYTE_GET(ehdr32.e_shnum); elf_header.e_shstrndx = (unsigned int)BYTE_GET(ehdr32.e_shstrndx); memcpy(&ehdr32, &elf_header, EI_NIDENT); break; case ELFCLASS64: /* If we have been compiled with sizeof(bfd_vma) == 4UL, then we will not be able to cope with the 64bit data found in 64 ELF files. Detect this now and abort before we start overwriting things. */ if (sizeof(bfd_vma) < 8UL) { error(_("This executable has been built without support for a\n\ 64 bit data type and so it cannot process 64 bit ELF files.\n")); return 0; } if (fread(ehdr64.e_type, (sizeof(ehdr64) - EI_NIDENT), 1, file) != 1) return 0; elf_header.e_type = (unsigned short)BYTE_GET(ehdr64.e_type); elf_header.e_machine = (unsigned short)BYTE_GET(ehdr64.e_machine); elf_header.e_version = (unsigned long)BYTE_GET(ehdr64.e_version); elf_header.e_entry = BYTE_GET(ehdr64.e_entry); elf_header.e_phoff = BYTE_GET(ehdr64.e_phoff); elf_header.e_shoff = BYTE_GET(ehdr64.e_shoff); elf_header.e_flags = (unsigned long)BYTE_GET(ehdr64.e_flags); elf_header.e_ehsize = (unsigned int)BYTE_GET(ehdr64.e_ehsize); elf_header.e_phentsize = (unsigned int)BYTE_GET(ehdr64.e_phentsize); elf_header.e_phnum = (unsigned int)BYTE_GET(ehdr64.e_phnum); elf_header.e_shentsize = (unsigned int)BYTE_GET(ehdr64.e_shentsize); elf_header.e_shnum = (unsigned int)BYTE_GET(ehdr64.e_shnum); elf_header.e_shstrndx = (unsigned int)BYTE_GET(ehdr64.e_shstrndx); memcpy(&ehdr64, &elf_header, EI_NIDENT); break; }
//Loading binary application int ac_load_elf(char* filename, char* data_mem, unsigned int data_mem_size) { Elf32_Ehdr ehdr; Elf32_Shdr shdr; Elf32_Phdr phdr; FILE *fd; unsigned int i; /* Most code was taken from the Binutils readelf application */ /* Open up the file for reading */ fd = fopen (filename, "rb"); if (fd == NULL) { AC_ERROR("Opening application file '" << filename << "': " << strerror(errno) << endl); exit(EXIT_FAILURE); } /* Read in the identity array. */ if (fread (ehdr.e_ident, EI_NIDENT, 1, fd) != 1) { AC_ERROR("Error reading file '" << filename << endl); exit(EXIT_FAILURE); } /* Determine how to read the rest of the header. */ switch (ehdr.e_ident[EI_DATA]) { default: /* fall through */ case ELFDATANONE: /* fall through */ case ELFDATA2LSB: byte_get = byte_get_little_endian; // byte_put = byte_put_little_endian; break; case ELFDATA2MSB: byte_get = byte_get_big_endian; // byte_put = byte_put_big_endian; break; } // TODO: Consider the case when the file is not 32-bit /* Get the rest of the header data */ if (fread ((unsigned char *)&ehdr.e_type, sizeof (ehdr) - EI_NIDENT, 1, fd) != 1) { AC_ERROR("Error reading file %s\n" << filename << endl); exit(EXIT_FAILURE); } ehdr.e_type = BYTE_GET (&ehdr.e_type); ehdr.e_machine = BYTE_GET (&ehdr.e_machine); ehdr.e_version = BYTE_GET (&ehdr.e_version); ehdr.e_entry = BYTE_GET (&ehdr.e_entry); ehdr.e_phoff = BYTE_GET (&ehdr.e_phoff); ehdr.e_shoff = BYTE_GET (&ehdr.e_shoff); ehdr.e_flags = BYTE_GET (&ehdr.e_flags); ehdr.e_ehsize = BYTE_GET (&ehdr.e_ehsize); ehdr.e_phentsize = BYTE_GET (&ehdr.e_phentsize); ehdr.e_phnum = BYTE_GET (&ehdr.e_phnum); ehdr.e_shentsize = BYTE_GET (&ehdr.e_shentsize); ehdr.e_shnum = BYTE_GET (&ehdr.e_shnum); ehdr.e_shstrndx = BYTE_GET (&ehdr.e_shstrndx); /* Check if the file is in fact an ELF */ if ( ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3) { fclose(fd); return EXIT_FAILURE; } //Set start address ac_start_addr = ehdr.e_entry; if (ac_start_addr > data_mem_size) { AC_ERROR("the start address of the application is beyond model memory\n"); fclose(fd); exit(EXIT_FAILURE); } if (ehdr.e_type == ET_EXEC) { //It is an ELF file AC_SAY("Reading ELF application file: " << filename << endl); //Get program headers and load segments // lseek(fd, convert_endian(4,ehdr.e_phoff), SEEK_SET); for (i=0; i < ehdr.e_phnum; i++) { //Get program headers and load segments fseek(fd, ehdr.e_phoff + ehdr.e_phentsize*i, SEEK_SET); if (fread(&phdr, sizeof(phdr), 1, fd) != 1) { AC_ERROR("reading ELF program header\n"); fclose(fd); exit(EXIT_FAILURE); } if (BYTE_GET (&phdr.p_type) == PT_LOAD) { Elf32_Word j; Elf32_Addr p_vaddr = BYTE_GET (&phdr.p_vaddr); Elf32_Word p_memsz = BYTE_GET (&phdr.p_memsz); Elf32_Word p_filesz = BYTE_GET (&phdr.p_filesz); Elf32_Off p_offset = BYTE_GET (&phdr.p_offset); //Error if segment greater then memory if (data_mem_size < p_vaddr + p_memsz) { AC_ERROR("not enough memory in ArchC model to load application.\n"); fclose(fd); exit(EXIT_FAILURE); } //Set heap to the end of the segment if (ac_heap_ptr < p_vaddr + p_memsz) ac_heap_ptr = p_vaddr + p_memsz; //Load and correct endian fseek(fd, p_offset, SEEK_SET); for (j=0; j < p_filesz; j+=sizeof(ac_fetch)) { int tmp; fread(&tmp, sizeof(ac_fetch), 1, fd); *(ac_fetch *) (data_mem + p_vaddr + j) = byte_get((unsigned char *)&tmp, sizeof(ac_fetch)); } memset(data_mem + p_vaddr + p_filesz, 0, p_memsz - p_filesz); } } } else if (ehdr.e_type == ET_REL) { AC_SAY("Reading ELF relocatable file: " << filename << endl); // first load the section name string table char *string_table; int shoff = ehdr.e_shoff; short shndx = ehdr.e_shstrndx; short shsize = ehdr.e_shentsize; fseek(fd, shoff+(shndx*shsize), SEEK_SET); if (fread(&shdr, sizeof(shdr), 1, fd) != 1) { AC_ERROR("reading ELF section header\n"); fclose(fd); exit(EXIT_FAILURE); } string_table = (char *) malloc(BYTE_GET (&shdr.sh_size)); fseek(fd, BYTE_GET (&shdr.sh_offset), SEEK_SET); fread(string_table, BYTE_GET (&shdr.sh_size), 1, fd); // load .text, .data and .bss sections for (i=0; i < ehdr.e_shnum; i++) { fseek(fd, shoff + shsize*i, SEEK_SET); if (fread(&shdr, sizeof(shdr), 1, fd) != 1) { AC_ERROR("reading ELF section header\n"); fclose(fd); exit(EXIT_FAILURE); } Elf32_Word name = BYTE_GET (&shdr.sh_name); if (!strcmp(string_table+name, ".text") || !strcmp(string_table+name, ".data") || !strcmp(string_table+name, ".bss")) { // printf("Section %s:\n", string_table+convert_endian(4,shdr.sh_name)); Elf32_Off tshoff = BYTE_GET (&shdr.sh_offset); Elf32_Word tshsize = BYTE_GET (&shdr.sh_size); Elf32_Addr tshaddr = BYTE_GET (&shdr.sh_addr); if (tshsize == 0) { // printf("--- empty ---\n"); continue; } if (data_mem_size < tshaddr + tshsize) { AC_ERROR("not enough memory in ArchC model to load application.\n"); fclose(fd); exit(EXIT_FAILURE); } //Set heap to the end of the segment if (ac_heap_ptr < tshaddr + tshsize) ac_heap_ptr = tshaddr + tshsize; if (!strcmp(string_table+BYTE_GET (&shdr.sh_name), ".bss")) { memset(data_mem + tshaddr, 0, tshsize); //continue; break; // .bss is supposed to be the last one } //Load and correct endian fseek(fd, tshoff, SEEK_SET); for (Elf32_Word j=0; j < tshsize; j+=sizeof(ac_fetch)) { int tmp; fread(&tmp, sizeof(ac_fetch), 1, fd); *(ac_fetch *) (data_mem + tshaddr + j) = byte_get((unsigned char *)&tmp, sizeof(ac_fetch)); // printf("0x%08x %08x \n", tshaddr+j, *(ac_fetch *) (data_mem+tshaddr+j)); } // printf("\n"); } } } //Close file fclose(fd); return EXIT_SUCCESS; }
#include <string.h> #include <assert.h> #include <alloca.h> #include <obj.h> #include <util.h> int obj_relocate (struct obj_file *f, ElfW(Addr) base) { int i, n = BYTE_GET(f->header.e_shnum); int ret = 1; DEBUG("==========================================\n"); DEBUG("obj_relocate start\n"); /* Finalize the addresses of the sections. */ arch_finalize_section_address(f, base); /* And iterate over all of the relocations. */ for (i = 0; i < n; ++i) { struct obj_section *relsec, *symsec, *targsec, *strsec; ElfW(RelM) *rel, *relend; ElfW(Sym) *symtab; const char *strtab; unsigned long nsyms; relsec = f->sections[i]; if (BYTE_GET(relsec->header.sh_type) != SHT_RELM) continue;