#include #include #include #include #include #include #include extern const char *__progname; static const char *filename = "/home/mouse/esparc/sparc/bin/csh"; static int fd; static Elf32_Ehdr eh; static int nph; static Elf32_Phdr *ph; static int nsh; static Elf32_Shdr *sh; static unsigned int strings; static char *stringdata; static int stringlen; static int symsize; static char *symbuf; static int symstrsize; static char *symstrbuf; static unsigned int elf32_half_to_native(const Elf32_Half *vp) { const unsigned char *p; p = (const void *) vp; switch (eh.e_ident[EI_DATA]) { case ELFDATA2LSB: return(p[0]|(p[1]*0x100)); break; case ELFDATA2MSB: return(p[1]|(p[0]*0x100)); break; } fprintf(stderr,"%s: %s: invalid EI_DATA value %u\n",__progname,filename,eh.e_ident[EI_DATA]); exit(1); } static unsigned int elf32_word_to_native(const Elf32_Word *vp) { const unsigned char *p; p = (const void *) vp; switch (eh.e_ident[EI_DATA]) { case ELFDATA2LSB: return(p[0]|(p[1]*0x100)|(p[2]*0x10000)|(p[3]*0x1000000)); break; case ELFDATA2MSB: return(p[3]|(p[2]*0x100)|(p[1]*0x10000)|(p[0]*0x1000000)); break; } fprintf(stderr,"%s: %s: invalid EI_DATA value %u\n",__progname,filename,eh.e_ident[EI_DATA]); exit(1); } static unsigned int elf32_off_to_native(const Elf32_Off *vp) { const unsigned char *p; p = (const void *) vp; switch (eh.e_ident[EI_DATA]) { case ELFDATA2LSB: return(p[0]|(p[1]*0x100)|(p[2]*0x10000)|(p[3]*0x1000000)); break; case ELFDATA2MSB: return(p[3]|(p[2]*0x100)|(p[1]*0x10000)|(p[0]*0x1000000)); break; } fprintf(stderr,"%s: %s: invalid EI_DATA value %u\n",__progname,filename,eh.e_ident[EI_DATA]); exit(1); } static unsigned int elf32_addr_to_native(const Elf32_Addr *vp) { const unsigned char *p; p = (const void *) vp; switch (eh.e_ident[EI_DATA]) { case ELFDATA2LSB: return(p[0]|(p[1]*0x100)|(p[2]*0x10000)|(p[3]*0x1000000)); break; case ELFDATA2MSB: return(p[3]|(p[2]*0x100)|(p[1]*0x10000)|(p[0]*0x1000000)); break; } fprintf(stderr,"%s: %s: invalid EI_DATA value %u\n",__progname,filename,eh.e_ident[EI_DATA]); exit(1); } static void openit(void) { fd = open(filename,O_RDONLY,0); if (fd < 0) { fprintf(stderr,"%s: %s: %s\n",__progname,filename,strerror(errno)); exit(1); } } static void mustread(off_t at, void *buf, int len) { int n; n = pread(fd,buf,len,at); if (n < 0) { fprintf(stderr,"%s: %s: read: %s\n",__progname,filename,strerror(errno)); exit(1); } if (n != len) { fprintf(stderr,"%s: %s: read %d at %llu got %d\n",__progname,filename,len,(unsigned long long int)at,n); exit(1); } } static void read_headers(void) { mustread(0,&eh,sizeof(eh)); if ( (eh.e_ident[EI_MAG0] != ELFMAG0) || (eh.e_ident[EI_MAG1] != ELFMAG1) || (eh.e_ident[EI_MAG2] != ELFMAG2) || (eh.e_ident[EI_MAG3] != ELFMAG3) ) { fprintf(stderr,"%s: %s: not an ELF file (bad magic)\n",__progname,filename); exit(1); } nph = elf32_half_to_native(&eh.e_phnum); ph = malloc(nph*sizeof(Elf32_Phdr)); mustread(elf32_off_to_native(&eh.e_phoff),ph,nph*sizeof(Elf32_Phdr)); nsh = elf32_half_to_native(&eh.e_shnum); sh = malloc(nsh*sizeof(Elf32_Shdr)); mustread(elf32_off_to_native(&eh.e_shoff),sh,nsh*sizeof(Elf32_Shdr)); strings = elf32_half_to_native(&eh.e_shstrndx); } static void dump_headers(void) { int i; int j; int n; unsigned int u; const char *s; printf("e_ident:"); for (i=0;i= ET_LOOS) && (u <= ET_HIOS)) { printf("OS-specific +%u",u-ET_LOOS); } else if ((u >= ET_LOPROC) && (u <= ET_HIPROC)) { printf("processor-specific +%u",u-ET_LOPROC); } else { printf("unrecognized"); } break; } printf(")\n"); u = elf32_half_to_native(&eh.e_machine); switch (u) { case EM_NONE: s = "NONE"; break; case EM_M32: s = "WE 32100"; break; case EM_SPARC: s = "SPARC"; break; case EM_386: s = "i386"; break; case EM_68K: s = "m68k"; break; case EM_88K: s = "m88k"; break; case EM_486: s = "i486"; break; case EM_860: s = "i860"; break; case EM_MIPS: s = "MIPS I"; break; case EM_S370: s = "System/370"; break; case EM_MIPS_RS3_LE: s = "MIPS RS3k LE"; break; case EM_RS6000: s = "RS/6000"; break; case EM_PARISC: s = "PA-RISC"; break; case EM_NCUBE: s = "NCube"; break; case EM_VPP500: s = "VPP500"; break; case EM_SPARC32PLUS: s = "SPARC32+"; break; case EM_960: s = "i960"; break; case EM_PPC: s = "PowerPC"; break; case EM_PPC64: s = "PPC64"; break; case EM_V800: s = "V800"; break; case EM_FR20: s = "FR20"; break; case EM_RH32: s = "RH-32"; break; case EM_RCE: s = "RCE"; break; case EM_ARM: s = "ARM"; break; case EM_ALPHA: s = "Alpha"; break; case EM_SH: s = "Super-H"; break; case EM_SPARCV9: s = "SPARCv9"; break; case EM_TRICORE: s = "Tricore"; break; case EM_ARC: s = "ARC"; break; case EM_H8_300: s = "H8/300"; break; case EM_H8_300H: s = "H8/300H"; break; case EM_H8S: s = "H8S"; break; case EM_H8_500: s = "H8/500"; break; case EM_IA_64: s = "IA-64"; break; case EM_MIPS_X: s = "MIPS-X"; break; case EM_COLDFIRE: s = "Coldfire"; break; case EM_68HC12: s = "MC68HC12"; break; case EM_MMA: s = "MMA"; break; case EM_PCP: s = "PCP"; break; case EM_NCPU: s = "nCPU"; break; case EM_NDR1: s = "NDR1"; break; case EM_STARCORE: s = "Star*Core"; break; case EM_ME16: s = "ME16"; break; case EM_ST100: s = "ST100"; break; case EM_TINYJ: s = "TinyJ"; break; case EM_X86_64: s = "x86-64"; break; case EM_PDSP: s = "Sony DSP"; break; case EM_PDP10: s = "PDP-10"; break; case EM_PDP11: s = "PDP-11"; break; case EM_FX66: s = "FX66"; break; case EM_ST9PLUS: s = "ST9+"; break; case EM_ST7: s = "ST7"; break; case EM_68HC16: s = "MC68HC16"; break; case EM_68HC11: s = "CM68HC11"; break; case EM_68HC08: s = "MC68HC08"; break; case EM_68HC05: s = "MC68HC05"; break; case EM_SVX: s = "SVx"; break; case EM_ST19: s = "ST19"; break; case EM_VAX: s = "VAX"; break; case EM_CRIS: s = "CRIS"; break; case EM_JAVELIN: s = "JAVELIN"; break; case EM_FIREPATH: s = "FIREPATH"; break; case EM_ZSP: s = "ZSP"; break; case EM_MMIX: s = "MMIX"; break; case EM_HUANY: s = "HUANY"; break; case EM_PRISM: s = "Prism"; break; case EM_AVR: s = "AVR"; break; case EM_FR30: s = "FR30"; break; case EM_D10V: s = "D10V"; break; case EM_D30V: s = "D30V"; break; case EM_V850: s = "v850"; break; case EM_M32R: s = "M32R"; break; case EM_MN10300: s = "MN10300"; break; case EM_MN10200: s = "MN10200"; break; case EM_PJ: s = "picoJava"; break; case EM_OPENRISC: s = "OpenRISC"; break; case EM_ARC_A5: s = "ARC Tangent-A5"; break; case EM_XTENSA: s = "Xtensa"; break; case EM_NS32K: s = "NS32k"; break; case EM_AVR32: s = "NetBSD/avr32"; break; case EM_ALPHA_EXP: s = "Alpha-experimental"; break; default: s = "unrecognized"; break; } printf("e_machine %u (%s)\n",u,s); printf("e_version %u\n",elf32_word_to_native(&eh.e_version)); printf("e_entry %#x\n",elf32_addr_to_native(&eh.e_entry)); printf("e_phoff %#x\n",elf32_off_to_native(&eh.e_phoff)); printf("e_shoff %#x\n",elf32_off_to_native(&eh.e_shoff)); printf("e_flags %#x\n",elf32_word_to_native(&eh.e_flags)); printf("e_ehsize %u (%d)\n",elf32_half_to_native(&eh.e_ehsize),(int)sizeof(Elf32_Ehdr)); printf("e_phentsize %u (%d)\n",elf32_half_to_native(&eh.e_phentsize),(int)sizeof(Elf32_Phdr)); printf("e_phnum %u\n",elf32_half_to_native(&eh.e_phnum)); printf("e_shentsize %u (%d)\n",elf32_half_to_native(&eh.e_shentsize),(int)sizeof(Elf32_Shdr)); printf("e_shnum %u\n",elf32_half_to_native(&eh.e_shnum)); printf("e_shstrndx %u\n",elf32_half_to_native(&eh.e_shstrndx)); n = elf32_half_to_native(&eh.e_phnum); for (i=0;i= PT_LOOS) && (u <= PT_HIOS)) { printf("OS-specific +%u",u-PT_LOOS); } else if ((u >= PT_LOPROC) && (u <= PT_HIPROC)) { printf("processor-specific +%u",u-PT_LOPROC); } else { printf("unrecognized"); } break; } printf(")\n"); printf("\tp_offset %u\n",elf32_off_to_native(&ph[i].p_offset)); printf("\tp_vaddr %u\n",elf32_addr_to_native(&ph[i].p_vaddr)); printf("\tp_paddr %u\n",elf32_addr_to_native(&ph[i].p_paddr)); printf("\tp_filesz %u\n",elf32_word_to_native(&ph[i].p_filesz)); printf("\tp_memsz %u\n",elf32_word_to_native(&ph[i].p_memsz)); printf("\tp_flags %u\n",elf32_word_to_native(&ph[i].p_flags)); printf("\tp_align %u\n",elf32_word_to_native(&ph[i].p_align)); } if (strings < nsh) { stringlen = elf32_word_to_native(&sh[strings].sh_size); stringdata = malloc(stringlen); mustread(elf32_off_to_native(&sh[strings].sh_offset),stringdata,stringlen); } else { stringdata = 0; } n = elf32_half_to_native(&eh.e_shnum); for (i=0;i= SHT_LOOS) && (u <= SHT_HIOS)) { printf("OS-specific +%u",u-SHT_LOOS); } else if ((u >= SHT_LOPROC) && (u <= SHT_HIPROC)) { printf("processor-specific +%u",u-SHT_LOPROC); } else if ((u >= SHT_LOUSER) && (u <= SHT_HIUSER)) { printf("application-specific +%u",u-SHT_LOUSER); } else { printf("unrecognized"); } break; } printf(")\n"); u = elf32_word_to_native(&sh[i].sh_flags); printf("\tsh_flags %u <",u); s = ""; if (u & SHF_WRITE) { printf("WRITE"); s = "|"; } if (u & SHF_ALLOC) { printf("%sALLOC",s); s = "|"; } if (u & SHF_EXECINSTR) { printf("%sEXECINSTR",s); s = "|"; } u &= ~(SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR); if (u) { printf("%s%#x",s,u); } printf(">\n"); printf("\tsh_addr %u\n",elf32_addr_to_native(&sh[i].sh_addr)); printf("\tsh_offset %u\n",elf32_off_to_native(&sh[i].sh_offset)); printf("\tsh_size %u\n",elf32_word_to_native(&sh[i].sh_size)); printf("\tsh_link %u\n",elf32_word_to_native(&sh[i].sh_link)); printf("\tsh_info %u\n",elf32_word_to_native(&sh[i].sh_info)); printf("\tsh_addralign %u\n",elf32_word_to_native(&sh[i].sh_addralign)); printf("\tsh_entsize %u\n",elf32_word_to_native(&sh[i].sh_entsize)); } } static void read_section(Elf32_Shdr *sh, char **bufp, int *sizep) { int s; char *b; s = elf32_word_to_native(&sh->sh_size); b = malloc(s); mustread(elf32_off_to_native(&sh->sh_offset),b,s); *bufp = b; *sizep = s; } static void dump_syms(void) { int i; int shx; int strx; unsigned int u; int n; Elf32_Sym sym; shx = -1; for (i=nsh-1;i>=0;i--) { if (elf32_word_to_native(&sh[i].sh_type) == SHT_SYMTAB) { if (shx < 0) { shx = i; } else { printf("multiple symtab sections\n"); return; } } } if (shx < 0) { printf("No symtab found\n"); return; } u = elf32_word_to_native(&sh[shx].sh_link); if (! u) { printf("symtab section has no link\n"); return; } if (u >= nsh) { printf("symtab link %u out of range\n",u); return; } strx = u; read_section(&sh[shx],&symbuf,&symsize); read_section(&sh[strx],&symstrbuf,&symstrsize); if (symsize % sizeof(Elf32_Sym)) { printf("symtab size %u isn't a multiple of symbol size %d\n",symsize,(int)sizeof(Elf32_Sym)); return; } n = symsize / sizeof(Elf32_Sym); for (i=0;i= STB_LOOS) && (u <= STB_HIOS)) { printf("OS-specific+%u",u-STB_LOOS); } else if ((u >= STB_LOPROC) && (u <= STB_HIPROC)) { printf("CPU-specific+%u",u-STB_LOPROC); } else { printf("?binding=%u",u); break; } break; } printf(", "); u = ELF_ST_TYPE(sym.st_info); switch (u) { case STT_NOTYPE: printf("no type"); break; case STT_OBJECT: printf("object"); break; case STT_FUNC: printf("function"); break; case STT_SECTION: printf("section"); break; case STT_FILE: printf("file"); break; default: if ((u >= STT_LOOS) && (u <= STT_HIOS)) { printf("OS-specific+%u",u-STT_LOOS); } else if ((u >= STT_LOPROC) && (u <= STT_HIPROC)) { printf("CPU-specific+%u",u-STT_LOPROC); } else { printf("?type=%u",u); } break; } printf(")\n"); printf("\tst_other %d\n",sym.st_other); printf("\tst_shndx %d\n",elf32_half_to_native(&sym.st_shndx)); } } int main(void); int main(void) { openit(); read_headers(); dump_headers(); dump_syms(); return(0); }