static int read_all(struct elf32_info *info, FILE *in) { memset(info, 0, sizeof(info)); if (read_ehdr(info, in) < 0) return -1; if (info->file_ehdr.e_machine != EM_MSP430) printc_err("elf32: warning: unknown machine type: 0x%x 0x%x\n", info->file_ehdr.e_machine, EM_MSP430); if (read_phdr(info, in) < 0) return -1; if (read_shdr(info, in) < 0) return -1; return 0; }
int read_elf(char *filename, struct _memory *memory, uint8_t *cpu_type, struct _symbols *symbols) { FILE *in; uint8_t e_ident[16]; int e_shoff; int e_shentsize; int e_shnum; int e_shstrndx; int n; int start, end; struct _elf32_shdr elf32_shdr; long strtab_offset = 0; get_int16_t get_int16; get_int32_t get_int32; memory_clear(memory); //memset(dirty, 0, memory->size); start = -1; end = -1; in = fopen(filename, "rb"); if (in == 0) { return -1; } memset(e_ident, 0, 16); n = fread(e_ident, 1, 16, in); if (e_ident[0] != 0x7f || e_ident[1] != 'E' || e_ident[2] != 'L' || e_ident[3] != 'F') { //printf("Not an ELF file.\n"); fclose(in); return -2; } #define EI_CLASS 4 // 1=32 bit, 2=64 bit #define EI_DATA 5 // 1=little endian, 2=big endian #define EI_OSABI 7 // 0=SysV, 255=Embedded if (e_ident[EI_CLASS] != 1) // let's let other stuff in || e_ident[7]!=0xff) { printf("ELF Error: e_ident shows incorrect type\n"); fclose(in); return -1; } // EI_DATA if (e_ident[EI_DATA] == 1) { memory->endian = ENDIAN_LITTLE; get_int16 = get_int16_le; get_int32 = get_int32_le; } else if (e_ident[EI_DATA] == 2) { memory->endian = ENDIAN_BIG; get_int16 = get_int16_be; get_int32 = get_int32_be; } else { printf("ELF Error: EI_DATA incorrect data encoding\n"); fclose(in); return -1; } get_int16(in); n = get_int16(in); switch(n) { case 8: case 10: *cpu_type = CPU_TYPE_MIPS; break; case 40: *cpu_type = CPU_TYPE_ARM; break; case 83: *cpu_type = CPU_TYPE_AVR8; break; case 105: *cpu_type = CPU_TYPE_MSP430; break; case 118: *cpu_type = CPU_TYPE_DSPIC; break; default: printf("ELF Error: e_machine unknown\n"); fclose(in); return -1; } fseek(in, 32, SEEK_SET); e_shoff = get_int32(in); fseek(in, 46, SEEK_SET); e_shentsize = get_int16(in); e_shnum = get_int16(in); e_shstrndx = get_int16(in); //printf("e_shoff=%d\n", e_shoff); //printf("e_shentsize=%d\n", e_shentsize); //printf("e_shnum=%d\n", e_shnum); //printf("e_shstrndx=%d\n", e_shstrndx); fseek(in, e_shoff + (e_shstrndx * e_shentsize) + 16, SEEK_SET); int stroffset = get_int32(in); char name[32]; // Need to find .strtab so we can fill in symbol names for (n = 0; n < e_shnum; n++) { fseek(in, e_shoff + (n * e_shentsize), SEEK_SET); read_shdr(in, &elf32_shdr, get_int32); if (elf32_shdr.sh_type == SHT_STRTAB) { read_name(in, name, 32, stroffset + elf32_shdr.sh_name); if (strcmp(name, ".strtab") == 0) { strtab_offset = elf32_shdr.sh_offset; break; } } } for (n = 0; n < e_shnum; n++) { // FIXME - a little inefficient eh? fseek(in, e_shoff + (n * e_shentsize), SEEK_SET); read_shdr(in, &elf32_shdr, get_int32); read_name(in, name, 32, stroffset + elf32_shdr.sh_name); //printf("name=%s\n", name); //int is_text = strncmp(name, ".text", 5) == 0 ? 1 : 0; int is_text = (elf32_shdr.sh_flags & SHF_EXECINSTR) != 0 ? 1 : 0; if (is_text || strncmp(name, ".data", 5) == 0 || strcmp(name, ".vectors") == 0) { if (is_text) { if (start == -1) { start = elf32_shdr.sh_addr; } else if (start > elf32_shdr.sh_addr) { start = elf32_shdr.sh_addr; } if (end == -1) { end = elf32_shdr.sh_addr + elf32_shdr.sh_size - 1; } else if (end < elf32_shdr.sh_addr + elf32_shdr.sh_size) { end = elf32_shdr.sh_addr+elf32_shdr.sh_size - 1; } } long marker = ftell(in); fseek(in, elf32_shdr.sh_offset, SEEK_SET); int n; for (n = 0; n < elf32_shdr.sh_size; n++) { if (elf32_shdr.sh_addr + n >= memory->size) break; memory_write_m(memory, elf32_shdr.sh_addr + n, getc(in)); } fseek(in, marker, SEEK_SET); printf("Loaded %d %s bytes from 0x%04x\n", n, name, elf32_shdr.sh_addr); } else if (elf32_shdr.sh_type == SHT_SYMTAB && symbols != NULL) { long marker = ftell(in); fseek(in, elf32_shdr.sh_offset, SEEK_SET); for (n = 0; n < elf32_shdr.sh_size; n += 16) { char name[128]; struct _elf32_sym elf32_sym; elf32_sym.st_name = get_int32(in); elf32_sym.st_value = get_int32(in); elf32_sym.st_size = get_int32(in); elf32_sym.st_info = getc(in); elf32_sym.st_other = getc(in); elf32_sym.st_shndx = get_int16(in); read_name(in, name, 128, strtab_offset + elf32_sym.st_name); printf("symbol %12s 0x%04x\n", name, elf32_sym.st_value); if (elf32_sym.st_info != STT_NOTYPE && elf32_sym.st_info != STT_SECTION && elf32_sym.st_info != STT_FILE) { symbols_append(symbols, name, elf32_sym.st_value); } } fseek(in, marker, SEEK_SET); } } memory->low_address = start; memory->high_address = end; fclose(in); return start; }